porffor 0.2.0-fde989a → 0.14.0-0d97d1e6a
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 +256 -0
- package/LICENSE +20 -20
- package/README.md +131 -86
- package/asur/README.md +2 -0
- package/asur/index.js +1262 -0
- package/byg/index.js +216 -0
- package/compiler/2c.js +2 -53
- package/compiler/{sections.js → assemble.js} +95 -21
- 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/boolean.ts +18 -0
- package/compiler/builtins/crypto.ts +120 -0
- package/compiler/builtins/date.ts +2067 -0
- package/compiler/builtins/escape.ts +141 -0
- package/compiler/builtins/function.ts +5 -0
- package/compiler/builtins/int.ts +145 -0
- package/compiler/builtins/number.ts +529 -0
- package/compiler/builtins/object.ts +4 -0
- package/compiler/builtins/porffor.d.ts +60 -0
- package/compiler/builtins/set.ts +187 -0
- package/compiler/builtins/string.ts +1080 -0
- package/compiler/builtins/symbol.ts +61 -0
- package/compiler/builtins.js +440 -285
- package/compiler/{codeGen.js → codegen.js} +1116 -489
- package/compiler/decompile.js +3 -4
- package/compiler/embedding.js +22 -22
- package/compiler/encoding.js +94 -10
- package/compiler/expression.js +1 -1
- package/compiler/generated_builtins.js +1670 -0
- package/compiler/index.js +27 -43
- package/compiler/log.js +6 -3
- package/compiler/opt.js +55 -41
- package/compiler/parse.js +38 -30
- package/compiler/precompile.js +120 -0
- package/compiler/prefs.js +31 -0
- package/compiler/prototype.js +31 -46
- package/compiler/types.js +38 -0
- package/compiler/wasmSpec.js +33 -8
- package/compiler/wrap.js +107 -71
- package/package.json +9 -5
- package/porf +2 -0
- package/rhemyn/compile.js +46 -27
- package/rhemyn/parse.js +322 -320
- package/rhemyn/test/parse.js +58 -58
- package/runner/compare.js +33 -34
- package/runner/debug.js +117 -0
- package/runner/index.js +78 -11
- package/runner/profiler.js +75 -0
- package/runner/repl.js +40 -13
- package/runner/sizes.js +37 -37
- package/runner/version.js +10 -8
- package/compiler/builtins/base64.js +0 -92
- package/filesize.cmd +0 -2
- 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/tmp.c +0 -661
- package/util/enum.js +0 -20
@@ -0,0 +1,31 @@
|
|
1
|
+
const onByDefault = [ 'bytestring', 'aotPointerOpt', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls' ];
|
2
|
+
|
3
|
+
let cache = {};
|
4
|
+
const obj = new Proxy({}, {
|
5
|
+
get(_, p) {
|
6
|
+
// intentionally misses with undefined values cached
|
7
|
+
if (cache[p]) return cache[p];
|
8
|
+
|
9
|
+
const ret = (() => {
|
10
|
+
// fooBar -> foo-bar
|
11
|
+
const name = p[0] === '_' ? p : p.replace(/[A-Z]/g, c => `-${c.toLowerCase()}`);
|
12
|
+
const prefix = name.length === 1 ? '-' : '--';
|
13
|
+
if (process.argv.includes(prefix + name)) return true;
|
14
|
+
if (process.argv.includes(prefix + 'no-' + name)) return false;
|
15
|
+
|
16
|
+
const valArg = process.argv.find(x => x.startsWith(`${prefix}${name}=`));
|
17
|
+
if (valArg) return valArg.slice(name.length + 1 + prefix.length);
|
18
|
+
|
19
|
+
if (onByDefault.includes(p)) return true;
|
20
|
+
return undefined;
|
21
|
+
})();
|
22
|
+
|
23
|
+
// do not cache in web demo as args are changed live
|
24
|
+
if (!globalThis.document) cache[p] = ret;
|
25
|
+
return ret;
|
26
|
+
}
|
27
|
+
});
|
28
|
+
|
29
|
+
obj.uncache = () => cache = {};
|
30
|
+
|
31
|
+
export default obj;
|
package/compiler/prototype.js
CHANGED
@@ -1,34 +1,20 @@
|
|
1
|
-
import { Opcodes, Blocktype, Valtype, ValtypeSize
|
2
|
-
import { number } from
|
3
|
-
import { unsignedLEB128 } from
|
4
|
-
import { UNDEFINED } from
|
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
|
-
_bytestring: 0x12
|
21
|
-
};
|
1
|
+
import { Opcodes, Blocktype, Valtype, ValtypeSize } from './wasmSpec.js';
|
2
|
+
import { number } from './embedding.js';
|
3
|
+
import { unsignedLEB128 } from './encoding.js';
|
4
|
+
import { UNDEFINED } from './builtins.js';
|
5
|
+
import { TYPES } from './types.js';
|
6
|
+
import Prefs from './prefs.js';
|
22
7
|
|
23
8
|
// todo: turn these into built-ins once arrays and these become less hacky
|
24
9
|
|
25
10
|
export const PrototypeFuncs = function() {
|
26
|
-
const noUnlikelyChecks =
|
27
|
-
|
28
|
-
|
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; }, {});
|
29
15
|
else zeroChecks = {};
|
30
16
|
|
31
|
-
this[TYPES.
|
17
|
+
this[TYPES.array] = {
|
32
18
|
// lX = local accessor of X ({ get, set }), iX = local index of X, wX = wasm ops of X
|
33
19
|
at: (pointer, length, wIndex, iTmp) => [
|
34
20
|
...wIndex,
|
@@ -148,7 +134,7 @@ export const PrototypeFuncs = function() {
|
|
148
134
|
shift: (pointer, length) => [
|
149
135
|
// if length == 0, noop
|
150
136
|
...length.getCachedI32(),
|
151
|
-
Opcodes.i32_eqz,
|
137
|
+
[ Opcodes.i32_eqz ],
|
152
138
|
[ Opcodes.if, Blocktype.void ],
|
153
139
|
...number(UNDEFINED),
|
154
140
|
[ Opcodes.br, 1 ],
|
@@ -267,10 +253,10 @@ export const PrototypeFuncs = function() {
|
|
267
253
|
]
|
268
254
|
};
|
269
255
|
|
270
|
-
this[TYPES.
|
271
|
-
this[TYPES.
|
272
|
-
this[TYPES.
|
273
|
-
this[TYPES.
|
256
|
+
this[TYPES.array].at.local = Valtype.i32;
|
257
|
+
this[TYPES.array].push.noArgRetLength = true;
|
258
|
+
this[TYPES.array].fill.local = valtypeBinary;
|
259
|
+
this[TYPES.array].fill.returnType = TYPES.array;
|
274
260
|
|
275
261
|
this[TYPES.string] = {
|
276
262
|
at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
|
@@ -342,8 +328,8 @@ export const PrototypeFuncs = function() {
|
|
342
328
|
...number(0, Valtype.i32), // base 0 for store later
|
343
329
|
|
344
330
|
...wIndex,
|
345
|
-
|
346
331
|
Opcodes.i32_to,
|
332
|
+
|
347
333
|
...number(ValtypeSize.i16, Valtype.i32),
|
348
334
|
[ Opcodes.i32_mul ],
|
349
335
|
|
@@ -383,7 +369,7 @@ export const PrototypeFuncs = function() {
|
|
383
369
|
|
384
370
|
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
385
371
|
[ Opcodes.if, Blocktype.void ],
|
386
|
-
...number(NaN),
|
372
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
387
373
|
[ Opcodes.br, 1 ],
|
388
374
|
[ Opcodes.end ],
|
389
375
|
|
@@ -489,10 +475,10 @@ export const PrototypeFuncs = function() {
|
|
489
475
|
this[TYPES.string].isWellFormed.local2 = Valtype.i32;
|
490
476
|
this[TYPES.string].isWellFormed.returnType = TYPES.boolean;
|
491
477
|
|
492
|
-
if (
|
493
|
-
this[TYPES.
|
478
|
+
if (Prefs.bytestring) {
|
479
|
+
this[TYPES.bytestring] = {
|
494
480
|
at: (pointer, length, wIndex, iTmp, _, arrayShell) => {
|
495
|
-
const [ newOut, newPointer ] = arrayShell(1, '
|
481
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
496
482
|
|
497
483
|
return [
|
498
484
|
// setup new/out array
|
@@ -548,7 +534,7 @@ export const PrototypeFuncs = function() {
|
|
548
534
|
|
549
535
|
// todo: out of bounds properly
|
550
536
|
charAt: (pointer, length, wIndex, _1, _2, arrayShell) => {
|
551
|
-
const [ newOut, newPointer ] = arrayShell(1, '
|
537
|
+
const [ newOut, newPointer ] = arrayShell(1, 'i8');
|
552
538
|
|
553
539
|
return [
|
554
540
|
// setup new/out array
|
@@ -558,7 +544,6 @@ export const PrototypeFuncs = function() {
|
|
558
544
|
...number(0, Valtype.i32), // base 0 for store later
|
559
545
|
|
560
546
|
...wIndex,
|
561
|
-
|
562
547
|
Opcodes.i32_to,
|
563
548
|
|
564
549
|
...pointer,
|
@@ -597,7 +582,7 @@ export const PrototypeFuncs = function() {
|
|
597
582
|
|
598
583
|
...(noUnlikelyChecks ? [] : [ [ Opcodes.i32_or ] ]),
|
599
584
|
[ Opcodes.if, Blocktype.void ],
|
600
|
-
...number(NaN),
|
585
|
+
...number(valtype === 'i32' ? -1 : NaN),
|
601
586
|
[ Opcodes.br, 1 ],
|
602
587
|
[ Opcodes.end ],
|
603
588
|
|
@@ -621,14 +606,14 @@ export const PrototypeFuncs = function() {
|
|
621
606
|
}
|
622
607
|
};
|
623
608
|
|
624
|
-
this[TYPES.
|
625
|
-
this[TYPES.
|
626
|
-
this[TYPES.
|
627
|
-
this[TYPES.
|
628
|
-
this[TYPES.
|
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;
|
629
614
|
|
630
|
-
this[TYPES.
|
631
|
-
this[TYPES.
|
632
|
-
this[TYPES.
|
615
|
+
this[TYPES.bytestring].isWellFormed.local = Valtype.i32;
|
616
|
+
this[TYPES.bytestring].isWellFormed.local2 = Valtype.i32;
|
617
|
+
this[TYPES.bytestring].isWellFormed.returnType = TYPES.boolean;
|
633
618
|
}
|
634
619
|
};
|
@@ -0,0 +1,38 @@
|
|
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');
|
38
|
+
registerInternalType('Set');
|
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');
|
@@ -12,6 +21,11 @@ export const Valtype = {
|
|
12
21
|
v128: 0x7b
|
13
22
|
};
|
14
23
|
|
24
|
+
export const Reftype = {
|
25
|
+
funcref: 0x70,
|
26
|
+
externref: 0x6f
|
27
|
+
};
|
28
|
+
|
15
29
|
export const Blocktype = {
|
16
30
|
void: 0x40,
|
17
31
|
};
|
@@ -32,17 +46,16 @@ export const Opcodes = {
|
|
32
46
|
throw: 0x08,
|
33
47
|
rethrow: 0x09,
|
34
48
|
|
35
|
-
call: 0x10,
|
36
|
-
call_indirect: 0x11,
|
37
|
-
return_call: 0x12,
|
38
|
-
return_call_indirect: 0x13,
|
39
|
-
|
40
49
|
end: 0x0b,
|
41
50
|
br: 0x0c,
|
42
51
|
br_if: 0x0d,
|
43
52
|
br_table: 0x0e,
|
44
53
|
return: 0x0f,
|
54
|
+
|
45
55
|
call: 0x10,
|
56
|
+
call_indirect: 0x11,
|
57
|
+
return_call: 0x12,
|
58
|
+
return_call_indirect: 0x13,
|
46
59
|
|
47
60
|
drop: 0x1a,
|
48
61
|
|
@@ -62,13 +75,22 @@ export const Opcodes = {
|
|
62
75
|
i32_load16_s: 0x2e,
|
63
76
|
i32_load16_u: 0x2f,
|
64
77
|
|
65
|
-
|
66
|
-
|
78
|
+
i64_load8_s: 0x30,
|
79
|
+
i64_load8_u: 0x31,
|
80
|
+
i64_load16_s: 0x32,
|
81
|
+
i64_load16_u: 0x33,
|
67
82
|
|
68
83
|
i32_store: 0x36,
|
69
84
|
i64_store: 0x37,
|
70
85
|
f64_store: 0x39,
|
71
86
|
|
87
|
+
i32_store8: 0x3a,
|
88
|
+
i32_store16: 0x3b,
|
89
|
+
|
90
|
+
i64_store8: 0x3c,
|
91
|
+
i64_store16: 0x3d,
|
92
|
+
|
93
|
+
memory_size: 0x3f,
|
72
94
|
memory_grow: 0x40,
|
73
95
|
|
74
96
|
i32_const: 0x41,
|
@@ -100,6 +122,8 @@ export const Opcodes = {
|
|
100
122
|
i32_shl: 0x74,
|
101
123
|
i32_shr_s: 0x75,
|
102
124
|
i32_shr_u: 0x76,
|
125
|
+
i32_rotl: 0x77,
|
126
|
+
i32_rotr: 0x78,
|
103
127
|
|
104
128
|
i64_eqz: 0x50,
|
105
129
|
i64_eq: 0x51,
|
@@ -123,6 +147,7 @@ export const Opcodes = {
|
|
123
147
|
i64_shr_s: 0x87,
|
124
148
|
i64_shr_u: 0x88,
|
125
149
|
i64_rotl: 0x89,
|
150
|
+
i64_rotr: 0x8a,
|
126
151
|
|
127
152
|
f64_eq: 0x61,
|
128
153
|
f64_ne: 0x62,
|
package/compiler/wrap.js
CHANGED
@@ -1,26 +1,91 @@
|
|
1
|
+
import { encodeVector, encodeLocal } from './encoding.js';
|
2
|
+
import { importedFuncs } from './builtins.js';
|
1
3
|
import compile from './index.js';
|
2
4
|
import decompile from './decompile.js';
|
3
|
-
import {
|
4
|
-
|
5
|
+
import { TYPES } from './types.js';
|
6
|
+
import { log } from './log.js';
|
7
|
+
import Prefs from './prefs.js';
|
5
8
|
|
6
9
|
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
7
10
|
|
8
|
-
const
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
11
|
+
const porfToJSValue = ({ memory, funcs, pages }, value, type) => {
|
12
|
+
switch (type) {
|
13
|
+
case TYPES.boolean: return Boolean(value);
|
14
|
+
case TYPES.undefined: return undefined;
|
15
|
+
case TYPES.object: return value === 0 ? null : {};
|
16
|
+
|
17
|
+
case TYPES.function: {
|
18
|
+
let func;
|
19
|
+
if (value < 0) {
|
20
|
+
func = importedFuncs[value + importedFuncs.length];
|
21
|
+
} else {
|
22
|
+
func = funcs.find(x => ((x.originalIndex ?? x.index) - importedFuncs.length) === value);
|
23
|
+
}
|
24
|
+
|
25
|
+
if (!func) return function () {};
|
26
|
+
|
27
|
+
// make fake empty func for repl/etc
|
28
|
+
return {[func.name]() {}}[func.name];
|
29
|
+
}
|
30
|
+
|
31
|
+
case TYPES.string: {
|
32
|
+
const length = (new Int32Array(memory.buffer, value, 1))[0];
|
33
|
+
return Array.from(new Uint16Array(memory.buffer, value + 4, length)).map(x => String.fromCharCode(x)).join('');
|
34
|
+
}
|
35
|
+
|
36
|
+
case TYPES.bytestring: {
|
37
|
+
const length = (new Int32Array(memory.buffer, value, 1))[0];
|
38
|
+
return Array.from(new Uint8Array(memory.buffer, value + 4, length)).map(x => String.fromCharCode(x)).join('');
|
39
|
+
}
|
40
|
+
|
41
|
+
case TYPES.array: {
|
42
|
+
const length = (new Int32Array(memory.buffer, value, 1))[0];
|
43
|
+
|
44
|
+
// have to slice because of memory alignment (?)
|
45
|
+
const buf = memory.buffer.slice(value + 4, value + 4 + 8 * length);
|
46
|
+
return Array.from(new Float64Array(buf, 0, length));
|
47
|
+
}
|
48
|
+
|
49
|
+
case TYPES.date: {
|
50
|
+
const t = (new Float64Array(memory.buffer, value, 1))[0];
|
51
|
+
return new Date(t);
|
52
|
+
}
|
53
|
+
|
54
|
+
case TYPES.set: {
|
55
|
+
const size = (new Int32Array(memory.buffer, value, 1))[0];
|
56
|
+
|
57
|
+
const out = new Set();
|
58
|
+
for (let i = 0; i < size; i++) {
|
59
|
+
const offset = value + 4 + (i * 9);
|
60
|
+
|
61
|
+
// have to slice because of memory alignment (?)
|
62
|
+
const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
|
63
|
+
const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
|
64
|
+
|
65
|
+
// console.log(`reading value at index ${i}...`)
|
66
|
+
// console.log(' memory:', Array.from(new Uint8Array(memory.buffer, offset, 9)).map(x => x.toString(16).padStart(2, '0')).join(' '));
|
67
|
+
// console.log(' read:', { value: v, type: t }, '\n');
|
68
|
+
|
69
|
+
out.add(porfToJSValue({ memory, funcs, pages }, v, t));
|
70
|
+
}
|
71
|
+
|
72
|
+
return out;
|
73
|
+
}
|
74
|
+
|
75
|
+
case TYPES.symbol: {
|
76
|
+
const descStore = pages.get('bytestring: __Porffor_symbol_descStore/ptr').ind * pageSize;
|
77
|
+
const offset = descStore + 4 + ((value - 1) * 9);
|
78
|
+
|
79
|
+
const v = (new Float64Array(memory.buffer.slice(offset, offset + 8), 0, 1))[0];
|
80
|
+
const t = (new Uint8Array(memory.buffer, offset + 8, 1))[0];
|
81
|
+
|
82
|
+
const desc = porfToJSValue({ memory, funcs, pages }, v, t);
|
83
|
+
|
84
|
+
return Symbol(desc);
|
85
|
+
}
|
86
|
+
|
87
|
+
default: return value;
|
88
|
+
}
|
24
89
|
};
|
25
90
|
|
26
91
|
export default async (source, flags = [ 'module' ], customImports = {}, print = str => process.stdout.write(str)) => {
|
@@ -29,22 +94,33 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
29
94
|
const t1 = performance.now();
|
30
95
|
const { wasm, funcs, globals, tags, exceptions, pages, c } = compile(source, flags);
|
31
96
|
|
97
|
+
globalThis.porfDebugInfo = { funcs, globals };
|
98
|
+
|
32
99
|
if (source.includes('export function')) flags.push('module');
|
33
100
|
|
34
|
-
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
101
|
+
// (await import('node:fs')).writeFileSync('out.wasm', Buffer.from(wasm));
|
35
102
|
|
36
103
|
times.push(performance.now() - t1);
|
37
|
-
if (
|
104
|
+
if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
|
38
105
|
|
39
106
|
const t2 = performance.now();
|
40
107
|
|
41
108
|
let instance;
|
42
109
|
try {
|
43
|
-
|
110
|
+
let wasmEngine = WebAssembly;
|
111
|
+
if (Prefs.asur) {
|
112
|
+
log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
|
113
|
+
wasmEngine = await import('../asur/index.js');
|
114
|
+
}
|
115
|
+
|
116
|
+
0, { instance } = await wasmEngine.instantiate(wasm, {
|
44
117
|
'': {
|
45
118
|
p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
|
46
119
|
c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
|
47
|
-
t:
|
120
|
+
t: () => performance.now(),
|
121
|
+
u: () => performance.timeOrigin,
|
122
|
+
y: () => {},
|
123
|
+
z: () => {},
|
48
124
|
...customImports
|
49
125
|
}
|
50
126
|
});
|
@@ -52,8 +128,10 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
52
128
|
// only backtrace for runner, not test262/etc
|
53
129
|
if (!process.argv[1].includes('/runner')) throw e;
|
54
130
|
|
55
|
-
const funcInd = parseInt(e.message.match(/function #([0-9]+) /)[1]);
|
56
|
-
const blobOffset = parseInt(e.message.split('@')[1]);
|
131
|
+
const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
|
132
|
+
const blobOffset = parseInt(e.message.split('@')?.[1]);
|
133
|
+
|
134
|
+
if (!funcInd) throw e;
|
57
135
|
|
58
136
|
// convert blob offset -> function wasm offset.
|
59
137
|
// this is not good code and is somewhat duplicated
|
@@ -131,7 +209,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
131
209
|
}
|
132
210
|
|
133
211
|
times.push(performance.now() - t2);
|
134
|
-
if (
|
212
|
+
if (Prefs.profileCompiler) console.log(`instantiated in ${times[1].toFixed(2)}ms`);
|
135
213
|
|
136
214
|
const exports = {};
|
137
215
|
|
@@ -151,54 +229,12 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
|
|
151
229
|
|
152
230
|
exports[func.name] = function() {
|
153
231
|
try {
|
154
|
-
const
|
155
|
-
|
156
|
-
if (_ret == null) return undefined;
|
157
|
-
|
158
|
-
const [ ret, type ] = _ret;
|
232
|
+
const ret = exp.apply(this, arguments);
|
233
|
+
if (ret == null) return undefined;
|
159
234
|
|
160
|
-
|
235
|
+
if (Prefs.rawValue) return { value: ret[0], type: ret[1] };
|
161
236
|
|
162
|
-
|
163
|
-
case 'boolean': return Boolean(ret);
|
164
|
-
case 'undefined': return undefined;
|
165
|
-
case 'object': return ret === 0 ? null : {};
|
166
|
-
|
167
|
-
case '_array': {
|
168
|
-
const pointer = ret;
|
169
|
-
const length = new Int32Array(memory.buffer, pointer, 1);
|
170
|
-
|
171
|
-
// have to slice because of memory alignment
|
172
|
-
const buf = memory.buffer.slice(pointer + 4, pointer + 4 + 8 * length);
|
173
|
-
|
174
|
-
return Array.from(new Float64Array(buf));
|
175
|
-
}
|
176
|
-
|
177
|
-
case 'string': {
|
178
|
-
const pointer = ret;
|
179
|
-
const length = new Int32Array(memory.buffer, pointer, 1);
|
180
|
-
|
181
|
-
return Array.from(new Uint16Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
182
|
-
}
|
183
|
-
|
184
|
-
case '_bytestring': {
|
185
|
-
const pointer = ret;
|
186
|
-
const length = new Int32Array(memory.buffer, pointer, 1);
|
187
|
-
|
188
|
-
return Array.from(new Uint8Array(memory.buffer, pointer + 4, length)).map(x => String.fromCharCode(x)).join('');
|
189
|
-
}
|
190
|
-
|
191
|
-
case 'function': {
|
192
|
-
// wasm func index, including all imports
|
193
|
-
const func = funcs.find(x => (x.originalIndex ?? x.index) === ret);
|
194
|
-
if (!func) return ret;
|
195
|
-
|
196
|
-
// make fake empty func for repl/etc
|
197
|
-
return {[func.name]() {}}[func.name];
|
198
|
-
}
|
199
|
-
|
200
|
-
default: return ret;
|
201
|
-
}
|
237
|
+
return porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]);
|
202
238
|
} catch (e) {
|
203
239
|
if (e.is && e.is(exceptTag)) {
|
204
240
|
const exceptId = e.getArg(exceptTag, 0);
|
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.
|
4
|
+
"version": "0.14.0-0d97d1e6a",
|
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
CHANGED