porffor 0.2.0-f2bbe1f → 0.2.0-f549952
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CONTRIBUTING.md +248 -0
- package/LICENSE +20 -20
- package/README.md +154 -89
- package/asur/README.md +2 -0
- package/asur/index.js +1262 -0
- package/byg/index.js +237 -0
- package/compiler/2c.js +317 -72
- package/compiler/{sections.js → assemble.js} +63 -15
- package/compiler/builtins/annexb_string.js +72 -0
- package/compiler/builtins/annexb_string.ts +18 -0
- package/compiler/builtins/array.ts +145 -0
- package/compiler/builtins/base64.ts +76 -0
- package/compiler/builtins/crypto.ts +120 -0
- package/compiler/builtins/date.ts +2071 -0
- package/compiler/builtins/escape.ts +141 -0
- package/compiler/builtins/int.ts +147 -0
- package/compiler/builtins/number.ts +527 -0
- package/compiler/builtins/porffor.d.ts +59 -0
- package/compiler/builtins/string.ts +1055 -0
- package/compiler/builtins/tostring.ts +45 -0
- package/compiler/builtins.js +449 -269
- package/compiler/{codeGen.js → codegen.js} +1153 -418
- package/compiler/decompile.js +0 -1
- package/compiler/embedding.js +22 -22
- package/compiler/encoding.js +108 -10
- package/compiler/generated_builtins.js +1481 -0
- package/compiler/index.js +36 -34
- package/compiler/log.js +6 -3
- package/compiler/opt.js +51 -36
- package/compiler/parse.js +33 -23
- package/compiler/precompile.js +128 -0
- package/compiler/prefs.js +27 -0
- package/compiler/prototype.js +177 -37
- package/compiler/types.js +37 -0
- package/compiler/wasmSpec.js +30 -7
- package/compiler/wrap.js +56 -40
- package/package.json +9 -5
- package/porf +4 -0
- package/rhemyn/compile.js +46 -27
- package/rhemyn/parse.js +322 -320
- package/rhemyn/test/parse.js +58 -58
- package/runner/compare.js +34 -34
- package/runner/debug.js +122 -0
- package/runner/index.js +91 -11
- package/runner/profiler.js +102 -0
- package/runner/repl.js +42 -9
- package/runner/sizes.js +37 -37
- package/compiler/builtins/base64.js +0 -92
- package/runner/info.js +0 -89
- package/runner/profile.js +0 -46
- package/runner/results.json +0 -1
- package/runner/transform.js +0 -15
- package/util/enum.js +0 -20
package/compiler/prototype.js
CHANGED
@@ -2,29 +2,16 @@ import { Opcodes, Blocktype, Valtype, ValtypeSize, PageSize } from "./wasmSpec.j
|
|
2
2
|
import { number } from "./embedding.js";
|
3
3
|
import { unsignedLEB128 } from "./encoding.js";
|
4
4
|
import { UNDEFINED } from "./builtins.js";
|
5
|
-
|
6
|
-
|
7
|
-
const TYPES = {
|
8
|
-
number: 0x00,
|
9
|
-
boolean: 0x01,
|
10
|
-
string: 0x02,
|
11
|
-
undefined: 0x03,
|
12
|
-
object: 0x04,
|
13
|
-
function: 0x05,
|
14
|
-
symbol: 0x06,
|
15
|
-
bigint: 0x07,
|
16
|
-
|
17
|
-
// these are not "typeof" types but tracked internally
|
18
|
-
_array: 0x10,
|
19
|
-
_regexp: 0x11
|
20
|
-
};
|
5
|
+
import Prefs from './prefs.js';
|
6
|
+
import { TYPES } from './types.js';
|
21
7
|
|
22
8
|
// todo: turn these into built-ins once arrays and these become less hacky
|
23
9
|
|
24
10
|
export const PrototypeFuncs = function() {
|
25
|
-
const noUnlikelyChecks =
|
26
|
-
|
27
|
-
|
11
|
+
const noUnlikelyChecks = Prefs.funsafeNoUnlikelyProtoChecks;
|
12
|
+
|
13
|
+
let zeroChecks;
|
14
|
+
if (Prefs.zeroChecks) zeroChecks = Prefs.zeroChecks.split('=')[1].split(',').reduce((acc, x) => { acc[x.toLowerCase()] = true; return acc; }, {});
|
28
15
|
else zeroChecks = {};
|
29
16
|
|
30
17
|
this[TYPES._array] = {
|
@@ -71,7 +58,7 @@ export const PrototypeFuncs = function() {
|
|
71
58
|
],
|
72
59
|
|
73
60
|
// todo: only for 1 argument
|
74
|
-
push: (pointer, length, wNewMember) => [
|
61
|
+
push: (pointer, length, wNewMember, _1, _2, _3, unusedValue) => [
|
75
62
|
// get memory offset of array at last index (length)
|
76
63
|
...length.getCachedI32(),
|
77
64
|
...number(ValtypeSize[valtype], Valtype.i32),
|
@@ -92,22 +79,28 @@ export const PrototypeFuncs = function() {
|
|
92
79
|
...number(1, Valtype.i32),
|
93
80
|
[ Opcodes.i32_add ],
|
94
81
|
|
95
|
-
...
|
96
|
-
|
82
|
+
...(unusedValue() ? [] : [
|
83
|
+
...length.setCachedI32(),
|
84
|
+
...length.getCachedI32(),
|
85
|
+
])
|
97
86
|
]),
|
98
87
|
|
99
|
-
...
|
100
|
-
|
88
|
+
...(unusedValue() ? [] : [
|
89
|
+
...length.getCachedI32(),
|
90
|
+
Opcodes.i32_from_u
|
91
|
+
])
|
101
92
|
|
102
93
|
// ...length.get()
|
103
94
|
],
|
104
95
|
|
105
|
-
pop: (pointer, length) => [
|
96
|
+
pop: (pointer, length, _1, _2, _3, _4, unusedValue) => [
|
106
97
|
// if length == 0, noop
|
107
98
|
...length.getCachedI32(),
|
108
99
|
[ Opcodes.i32_eqz ],
|
109
100
|
[ Opcodes.if, Blocktype.void ],
|
110
|
-
...
|
101
|
+
...(unusedValue() ? [] : [
|
102
|
+
...number(UNDEFINED),
|
103
|
+
]),
|
111
104
|
[ Opcodes.br, 1 ],
|
112
105
|
[ Opcodes.end ],
|
113
106
|
|
@@ -119,25 +112,29 @@ export const PrototypeFuncs = function() {
|
|
119
112
|
...number(1, Valtype.i32),
|
120
113
|
[ Opcodes.i32_sub ],
|
121
114
|
|
122
|
-
...
|
123
|
-
|
115
|
+
...(unusedValue() ? [] : [
|
116
|
+
...length.setCachedI32(),
|
117
|
+
...length.getCachedI32(),
|
118
|
+
])
|
124
119
|
]),
|
125
120
|
|
126
121
|
// load last element
|
127
|
-
...
|
128
|
-
|
129
|
-
|
122
|
+
...(unusedValue() ? [] : [
|
123
|
+
...length.getCachedI32(),
|
124
|
+
...number(ValtypeSize[valtype], Valtype.i32),
|
125
|
+
[ Opcodes.i32_mul ],
|
130
126
|
|
131
|
-
|
132
|
-
|
127
|
+
...pointer,
|
128
|
+
[ Opcodes.i32_add ],
|
133
129
|
|
134
|
-
|
130
|
+
[ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128(ValtypeSize.i32) ]
|
131
|
+
])
|
135
132
|
],
|
136
133
|
|
137
134
|
shift: (pointer, length) => [
|
138
135
|
// if length == 0, noop
|
139
136
|
...length.getCachedI32(),
|
140
|
-
Opcodes.i32_eqz,
|
137
|
+
[ Opcodes.i32_eqz ],
|
141
138
|
[ Opcodes.if, Blocktype.void ],
|
142
139
|
...number(UNDEFINED),
|
143
140
|
[ Opcodes.br, 1 ],
|
@@ -331,8 +328,8 @@ export const PrototypeFuncs = function() {
|
|
331
328
|
...number(0, Valtype.i32), // base 0 for store later
|
332
329
|
|
333
330
|
...wIndex,
|
334
|
-
|
335
331
|
Opcodes.i32_to,
|
332
|
+
|
336
333
|
...number(ValtypeSize.i16, Valtype.i32),
|
337
334
|
[ Opcodes.i32_mul ],
|
338
335
|
|
@@ -372,7 +369,7 @@ export const PrototypeFuncs = function() {
|
|
372
369
|
|
373
370
|
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
374
371
|
[ Opcodes.if, Blocktype.void ],
|
375
|
-
...number(NaN),
|
372
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
376
373
|
[ Opcodes.br, 1 ],
|
377
374
|
[ Opcodes.end ],
|
378
375
|
|
@@ -472,8 +469,151 @@ export const PrototypeFuncs = function() {
|
|
472
469
|
this[TYPES.string].at.returnType = TYPES.string;
|
473
470
|
this[TYPES.string].charAt.returnType = TYPES.string;
|
474
471
|
this[TYPES.string].charCodeAt.local = Valtype.i32;
|
472
|
+
this[TYPES.string].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
475
473
|
|
476
474
|
this[TYPES.string].isWellFormed.local = Valtype.i32;
|
477
475
|
this[TYPES.string].isWellFormed.local2 = Valtype.i32;
|
478
476
|
this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
|
477
|
+
|
478
|
+
if (Prefs.bytestring) {
|
479
|
+
this[TYPES._bytestring] = {
|
480
|
+
at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
|
481
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
482
|
+
|
483
|
+
return [
|
484
|
+
// setup new/out array
|
485
|
+
...newOut,
|
486
|
+
[ Opcodes.drop ],
|
487
|
+
|
488
|
+
...number(0, Valtype.i32), // base 0 for store later
|
489
|
+
|
490
|
+
...wIndex,
|
491
|
+
Opcodes.i32_to_u,
|
492
|
+
[ Opcodes.local_tee, iTmp ],
|
493
|
+
|
494
|
+
// if index < 0: access index + array length
|
495
|
+
...number(0, Valtype.i32),
|
496
|
+
[ Opcodes.i32_lt_s ],
|
497
|
+
[ Opcodes.if, Blocktype.void ],
|
498
|
+
[ Opcodes.local_get, iTmp ],
|
499
|
+
...length.getCachedI32(),
|
500
|
+
[ Opcodes.i32_add ],
|
501
|
+
[ Opcodes.local_set, iTmp ],
|
502
|
+
[ Opcodes.end ],
|
503
|
+
|
504
|
+
// if still < 0 or >= length: return undefined
|
505
|
+
[ Opcodes.local_get, iTmp ],
|
506
|
+
...number(0, Valtype.i32),
|
507
|
+
[ Opcodes.i32_lt_s ],
|
508
|
+
|
509
|
+
[ Opcodes.local_get, iTmp ],
|
510
|
+
...length.getCachedI32(),
|
511
|
+
[ Opcodes.i32_ge_s ],
|
512
|
+
[ Opcodes.i32_or ],
|
513
|
+
|
514
|
+
[ Opcodes.if, Blocktype.void ],
|
515
|
+
...number(UNDEFINED),
|
516
|
+
[ Opcodes.br, 1 ],
|
517
|
+
[ Opcodes.end ],
|
518
|
+
|
519
|
+
[ Opcodes.local_get, iTmp ],
|
520
|
+
|
521
|
+
...pointer,
|
522
|
+
[ Opcodes.i32_add ],
|
523
|
+
|
524
|
+
// load current string ind {arg}
|
525
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
526
|
+
|
527
|
+
// store to new string ind 0
|
528
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
529
|
+
|
530
|
+
// return new string (pointer)
|
531
|
+
...number(newPointer)
|
532
|
+
];
|
533
|
+
},
|
534
|
+
|
535
|
+
// todo: out of bounds properly
|
536
|
+
charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
|
537
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
538
|
+
|
539
|
+
return [
|
540
|
+
// setup new/out array
|
541
|
+
...newOut,
|
542
|
+
[ Opcodes.drop ],
|
543
|
+
|
544
|
+
...number(0, Valtype.i32), // base 0 for store later
|
545
|
+
|
546
|
+
...wIndex,
|
547
|
+
Opcodes.i32_to,
|
548
|
+
|
549
|
+
...pointer,
|
550
|
+
[ Opcodes.i32_add ],
|
551
|
+
|
552
|
+
// load current string ind {arg}
|
553
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
554
|
+
|
555
|
+
// store to new string ind 0
|
556
|
+
[ Opcodes.i32_store8, 0, ...unsignedLEB128(newPointer + ValtypeSize.i32) ],
|
557
|
+
|
558
|
+
// return new string (page)
|
559
|
+
...number(newPointer)
|
560
|
+
];
|
561
|
+
},
|
562
|
+
|
563
|
+
charCodeAt: (pointer, length, wIndex, iTmp) => {
|
564
|
+
return [
|
565
|
+
...wIndex,
|
566
|
+
Opcodes.i32_to,
|
567
|
+
|
568
|
+
...(zeroChecks.charcodeat ? [] : [
|
569
|
+
[ Opcodes.local_set, iTmp ],
|
570
|
+
|
571
|
+
// index < 0
|
572
|
+
...(noUnlikelyChecks ? [] : [
|
573
|
+
[ Opcodes.local_get, iTmp ],
|
574
|
+
...number(0, Valtype.i32),
|
575
|
+
[ Opcodes.i32_lt_s ],
|
576
|
+
]),
|
577
|
+
|
578
|
+
// index >= length
|
579
|
+
[ Opcodes.local_get, iTmp ],
|
580
|
+
...length.getCachedI32(),
|
581
|
+
[ Opcodes.i32_ge_s ],
|
582
|
+
|
583
|
+
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
584
|
+
[ Opcodes.if, Blocktype.void ],
|
585
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
586
|
+
[ Opcodes.br, 1 ],
|
587
|
+
[ Opcodes.end ],
|
588
|
+
|
589
|
+
[ Opcodes.local_get, iTmp ],
|
590
|
+
]),
|
591
|
+
|
592
|
+
...pointer,
|
593
|
+
[ Opcodes.i32_add ],
|
594
|
+
|
595
|
+
// load current string ind {arg}
|
596
|
+
[ Opcodes.i32_load8_u, 0, ...unsignedLEB128(ValtypeSize.i32) ],
|
597
|
+
Opcodes.i32_from_u
|
598
|
+
];
|
599
|
+
},
|
600
|
+
|
601
|
+
isWellFormed: () => {
|
602
|
+
return [
|
603
|
+
// we know it must be true as it is a bytestring lol
|
604
|
+
...number(1)
|
605
|
+
]
|
606
|
+
}
|
607
|
+
};
|
608
|
+
|
609
|
+
this[TYPES._bytestring].at.local = Valtype.i32;
|
610
|
+
this[TYPES._bytestring].at.returnType = TYPES._bytestring;
|
611
|
+
this[TYPES._bytestring].charAt.returnType = TYPES._bytestring;
|
612
|
+
this[TYPES._bytestring].charCodeAt.local = Valtype.i32;
|
613
|
+
this[TYPES._bytestring].charCodeAt.noPointerCache = zeroChecks.charcodeat;
|
614
|
+
|
615
|
+
this[TYPES._bytestring].isWellFormed.local = Valtype.i32;
|
616
|
+
this[TYPES._bytestring].isWellFormed.local2 = Valtype.i32;
|
617
|
+
this[TYPES._bytestring].isWellFormed.returnType = TYPES.boolean;
|
618
|
+
}
|
479
619
|
};
|
@@ -0,0 +1,37 @@
|
|
1
|
+
export const TYPES = {
|
2
|
+
number: 0x00,
|
3
|
+
boolean: 0x01,
|
4
|
+
string: 0x02,
|
5
|
+
undefined: 0x03,
|
6
|
+
object: 0x04,
|
7
|
+
function: 0x05,
|
8
|
+
symbol: 0x06,
|
9
|
+
bigint: 0x07
|
10
|
+
};
|
11
|
+
|
12
|
+
export const TYPE_NAMES = {
|
13
|
+
[TYPES.number]: 'Number',
|
14
|
+
[TYPES.boolean]: 'Boolean',
|
15
|
+
[TYPES.string]: 'String',
|
16
|
+
[TYPES.undefined]: 'undefined',
|
17
|
+
[TYPES.object]: 'Object',
|
18
|
+
[TYPES.function]: 'Function',
|
19
|
+
[TYPES.symbol]: 'Symbol',
|
20
|
+
[TYPES.bigint]: 'BigInt'
|
21
|
+
};
|
22
|
+
|
23
|
+
export const INTERNAL_TYPE_BASE = 0x10;
|
24
|
+
let internalTypeIndex = INTERNAL_TYPE_BASE;
|
25
|
+
const registerInternalType = name => {
|
26
|
+
const n = internalTypeIndex++;
|
27
|
+
TYPES['_' + name.toLowerCase()] = n;
|
28
|
+
TYPE_NAMES[n] = name;
|
29
|
+
};
|
30
|
+
|
31
|
+
// note: when adding a new internal type, please also add a deserializer to wrap.js
|
32
|
+
// (it is okay to add a throw todo deserializer for wips)
|
33
|
+
|
34
|
+
registerInternalType('Array');
|
35
|
+
registerInternalType('RegExp');
|
36
|
+
registerInternalType('ByteString');
|
37
|
+
registerInternalType('Date');
|
package/compiler/wasmSpec.js
CHANGED
@@ -1,4 +1,13 @@
|
|
1
|
-
|
1
|
+
const enumify = (...args) => {
|
2
|
+
const obj = {};
|
3
|
+
|
4
|
+
for (let i = 0; i < args.length; i++) {
|
5
|
+
obj[i] = args[i];
|
6
|
+
obj[args[i]] = i;
|
7
|
+
}
|
8
|
+
|
9
|
+
return obj;
|
10
|
+
};
|
2
11
|
|
3
12
|
export const Section = enumify('custom', 'type', 'import', 'func', 'table', 'memory', 'global', 'export', 'start', 'element', 'code', 'data', 'data_count', 'tag');
|
4
13
|
export const ExportDesc = enumify('func', 'table', 'mem', 'global', 'tag');
|
@@ -32,17 +41,16 @@ export const Opcodes = {
|
|
32
41
|
throw: 0x08,
|
33
42
|
rethrow: 0x09,
|
34
43
|
|
35
|
-
call: 0x10,
|
36
|
-
call_indirect: 0x11,
|
37
|
-
return_call: 0x12,
|
38
|
-
return_call_indirect: 0x13,
|
39
|
-
|
40
44
|
end: 0x0b,
|
41
45
|
br: 0x0c,
|
42
46
|
br_if: 0x0d,
|
43
47
|
br_table: 0x0e,
|
44
48
|
return: 0x0f,
|
49
|
+
|
45
50
|
call: 0x10,
|
51
|
+
call_indirect: 0x11,
|
52
|
+
return_call: 0x12,
|
53
|
+
return_call_indirect: 0x13,
|
46
54
|
|
47
55
|
drop: 0x1a,
|
48
56
|
|
@@ -57,15 +65,27 @@ export const Opcodes = {
|
|
57
65
|
i64_load: 0x29,
|
58
66
|
f64_load: 0x2b,
|
59
67
|
|
68
|
+
i32_load8_s: 0x2c,
|
69
|
+
i32_load8_u: 0x2d,
|
60
70
|
i32_load16_s: 0x2e,
|
61
71
|
i32_load16_u: 0x2f,
|
62
72
|
|
63
|
-
|
73
|
+
i64_load8_s: 0x30,
|
74
|
+
i64_load8_u: 0x31,
|
75
|
+
i64_load16_s: 0x32,
|
76
|
+
i64_load16_u: 0x33,
|
64
77
|
|
65
78
|
i32_store: 0x36,
|
66
79
|
i64_store: 0x37,
|
67
80
|
f64_store: 0x39,
|
68
81
|
|
82
|
+
i32_store8: 0x3a,
|
83
|
+
i32_store16: 0x3b,
|
84
|
+
|
85
|
+
i64_store8: 0x3c,
|
86
|
+
i64_store16: 0x3d,
|
87
|
+
|
88
|
+
memory_size: 0x3f,
|
69
89
|
memory_grow: 0x40,
|
70
90
|
|
71
91
|
i32_const: 0x41,
|
@@ -97,6 +117,8 @@ export const Opcodes = {
|
|
97
117
|
i32_shl: 0x74,
|
98
118
|
i32_shr_s: 0x75,
|
99
119
|
i32_shr_u: 0x76,
|
120
|
+
i32_rotl: 0x77,
|
121
|
+
i32_rotr: 0x78,
|
100
122
|
|
101
123
|
i64_eqz: 0x50,
|
102
124
|
i64_eq: 0x51,
|
@@ -120,6 +142,7 @@ export const Opcodes = {
|
|
120
142
|
i64_shr_s: 0x87,
|
121
143
|
i64_shr_u: 0x88,
|
122
144
|
i64_rotl: 0x89,
|
145
|
+
i64_rotr: 0x8a,
|
123
146
|
|
124
147
|
f64_eq: 0x61,
|
125
148
|
f64_ne: 0x62,
|
package/compiler/wrap.js
CHANGED
@@ -1,55 +1,56 @@
|
|
1
1
|
import compile from './index.js';
|
2
2
|
import decompile from './decompile.js';
|
3
3
|
import { encodeVector, encodeLocal } from './encoding.js';
|
4
|
-
|
4
|
+
import Prefs from './prefs.js';
|
5
|
+
import { log } from './log.js';
|
6
|
+
import { TYPES } from './types.js';
|
5
7
|
|
6
8
|
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
7
9
|
|
8
|
-
const typeBase = 0x00;
|
9
|
-
const internalTypeBase = 0x10;
|
10
|
-
const TYPES = {
|
11
|
-
[typeBase]: 'number',
|
12
|
-
[typeBase + 1]: 'boolean',
|
13
|
-
[typeBase + 2]: 'string',
|
14
|
-
[typeBase + 3]: 'undefined',
|
15
|
-
[typeBase + 4]: 'object',
|
16
|
-
[typeBase + 5]: 'function',
|
17
|
-
[typeBase + 6]: 'symbol',
|
18
|
-
[typeBase + 7]: 'bigint',
|
19
|
-
|
20
|
-
// internal
|
21
|
-
[internalTypeBase]: '_array',
|
22
|
-
[internalTypeBase + 1]: '_regexp'
|
23
|
-
};
|
24
|
-
|
25
10
|
export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
|
26
11
|
const times = [];
|
27
12
|
|
28
13
|
const t1 = performance.now();
|
29
14
|
const { wasm, funcs, globals, tags, exceptions, pages, c } = compile(source, flags);
|
30
15
|
|
16
|
+
globalThis.porfDebugInfo = { funcs, globals };
|
17
|
+
|
31
18
|
if (source.includes('export function')) flags.push('module');
|
32
19
|
|
33
|
-
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
20
|
+
// (await import('node:fs')).writeFileSync('out.wasm', Buffer.from(wasm));
|
34
21
|
|
35
22
|
times.push(performance.now() - t1);
|
36
|
-
if (
|
23
|
+
if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
|
37
24
|
|
38
25
|
const t2 = performance.now();
|
39
26
|
|
40
27
|
let instance;
|
41
28
|
try {
|
42
|
-
|
29
|
+
let wasmEngine = WebAssembly;
|
30
|
+
if (Prefs.asur) {
|
31
|
+
log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
|
32
|
+
wasmEngine = await import('../asur/index.js');
|
33
|
+
}
|
34
|
+
|
35
|
+
0, { instance } = await wasmEngine.instantiate(wasm, {
|
43
36
|
'': {
|
44
37
|
p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
|
45
38
|
c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
|
46
|
-
t:
|
39
|
+
t: () => performance.now(),
|
40
|
+
u: () => performance.timeOrigin,
|
41
|
+
y: () => {},
|
42
|
+
z: () => {},
|
47
43
|
...customImports
|
48
44
|
}
|
49
45
|
});
|
50
46
|
} catch (e) {
|
51
|
-
|
52
|
-
|
47
|
+
// only backtrace for runner, not test262/etc
|
48
|
+
if (!process.argv[1].includes('/runner')) throw e;
|
49
|
+
|
50
|
+
const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
|
51
|
+
const blobOffset = parseInt(e.message.split('@')?.[1]);
|
52
|
+
|
53
|
+
if (!funcInd) throw e;
|
53
54
|
|
54
55
|
// convert blob offset -> function wasm offset.
|
55
56
|
// this is not good code and is somewhat duplicated
|
@@ -127,7 +128,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
127
128
|
}
|
128
129
|
|
129
130
|
times.push(performance.now() - t2);
|
130
|
-
if (
|
131
|
+
if (Prefs.profileCompiler) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
|
131
132
|
|
132
133
|
const exports = {};
|
133
134
|
|
@@ -155,14 +156,31 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
155
156
|
|
156
157
|
// if (ret >= typeBase && ret <= typeBase + 8) return ret > (typeBase + 7) ? 'object' : TYPES[ret];
|
157
158
|
|
158
|
-
switch (
|
159
|
-
case
|
160
|
-
case
|
161
|
-
case
|
159
|
+
switch (type) {
|
160
|
+
case TYPES.boolean: return Boolean(ret);
|
161
|
+
case TYPES.undefined: return undefined;
|
162
|
+
case TYPES.object: return ret === 0 ? null : {};
|
163
|
+
|
164
|
+
case TYPES.string: {
|
165
|
+
const pointer = ret;
|
166
|
+
const length = (new Int32Array(memory.buffer, pointer, 1))[0];
|
167
|
+
|
168
|
+
return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
169
|
+
}
|
170
|
+
|
171
|
+
case TYPES.function: {
|
172
|
+
// wasm func index, including all imports
|
173
|
+
const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
|
174
|
+
// if (!func) return ret;
|
175
|
+
if (!func) return function () {};
|
176
|
+
|
177
|
+
// make fake empty func for repl/etc
|
178
|
+
return {[func.name]() {}}[func.name];
|
179
|
+
}
|
162
180
|
|
163
|
-
case
|
181
|
+
case TYPES._array: {
|
164
182
|
const pointer = ret;
|
165
|
-
const length = new Int32Array(memory.buffer, pointer, 1);
|
183
|
+
const length = (new Int32Array(memory.buffer, pointer, 1))[0];
|
166
184
|
|
167
185
|
// have to slice because of memory alignment
|
168
186
|
const buf = memory.buffer.slice(pointer + 4, pointer + 4 + 8 * length);
|
@@ -170,20 +188,18 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
170
188
|
return Array.from(new Float64Array(buf));
|
171
189
|
}
|
172
190
|
|
173
|
-
case
|
191
|
+
case TYPES._bytestring: {
|
174
192
|
const pointer = ret;
|
175
|
-
const length = new Int32Array(memory.buffer, pointer, 1);
|
193
|
+
const length = (new Int32Array(memory.buffer, pointer, 1))[0];
|
176
194
|
|
177
|
-
return Array.from(new
|
195
|
+
return Array.from(new Uint8Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
178
196
|
}
|
179
197
|
|
180
|
-
case
|
181
|
-
|
182
|
-
const
|
183
|
-
if (!func) return ret;
|
198
|
+
case TYPES._date: {
|
199
|
+
const pointer = ret;
|
200
|
+
const value = (new Float64Array(memory.buffer, pointer, 1))[0];
|
184
201
|
|
185
|
-
|
186
|
-
return {[func.name]() {}}[func.name];
|
202
|
+
return new Date(value);
|
187
203
|
}
|
188
204
|
|
189
205
|
default: return ret;
|
package/package.json
CHANGED
@@ -1,21 +1,25 @@
|
|
1
1
|
{
|
2
2
|
"name": "porffor",
|
3
3
|
"description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
|
4
|
-
"version": "0.2.0-
|
4
|
+
"version": "0.2.0-f549952",
|
5
5
|
"author": "CanadaHonk",
|
6
6
|
"license": "MIT",
|
7
|
+
"scripts": {
|
8
|
+
"precompile": "node ./compiler/precompile.js"
|
9
|
+
},
|
7
10
|
"dependencies": {
|
8
|
-
"acorn": "^8.
|
11
|
+
"acorn": "^8.11.3",
|
12
|
+
"node-repl-polyfill": "^0.1.1"
|
9
13
|
},
|
10
14
|
"optionalDependencies": {
|
11
|
-
"@babel/parser": "^7.
|
15
|
+
"@babel/parser": "^7.24.4",
|
12
16
|
"hermes-parser": "^0.18.2",
|
13
17
|
"meriyah": "^4.3.9"
|
14
18
|
},
|
15
19
|
"bin": {
|
16
20
|
"porf": "./runner/index.js"
|
17
21
|
},
|
18
|
-
"main": "./
|
22
|
+
"main": "./compiler/wrap.js",
|
19
23
|
"type": "module",
|
20
24
|
"repository": {
|
21
25
|
"type": "git",
|
@@ -25,4 +29,4 @@
|
|
25
29
|
"url": "https://github.com/CanadaHonk/porffor/issues"
|
26
30
|
},
|
27
31
|
"homepage": "https://porffor.goose.icu"
|
28
|
-
}
|
32
|
+
}
|
package/porf
ADDED