porffor 0.60.8 → 0.60.9
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/compiler/2c.js +2 -2
- package/compiler/assemble.js +13 -0
- package/compiler/builtins/regexp.ts +180 -36
- package/compiler/builtins_precompiled.js +1099 -1099
- package/compiler/codegen.js +28 -21
- package/compiler/cyclone.js +2 -2
- package/compiler/disassemble.js +2 -2
- package/compiler/encoding.js +22 -4
- package/compiler/expression.js +0 -25
- package/compiler/opt.js +15 -15
- package/compiler/precompile.js +2 -2
- package/compiler/wrap.js +4 -1
- package/package.json +2 -2
- package/runtime/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
|
2
|
-
import { number, ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector
|
2
|
+
import { number, ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from './encoding.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
4
|
import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
|
5
5
|
import { TYPES, TYPE_FLAGS, TYPE_NAMES } from './types.js';
|
@@ -41,24 +41,30 @@ const allocBytes = (scope, reason, bytes) => {
|
|
41
41
|
return allocs.get(reason);
|
42
42
|
}
|
43
43
|
|
44
|
-
let
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
bin = {
|
49
|
-
used: 0,
|
50
|
-
page
|
51
|
-
};
|
44
|
+
let startingPtr = 0;
|
45
|
+
while (bytes > 0) {
|
46
|
+
const alloc = Math.min(bytes, pageSize);
|
47
|
+
bytes -= alloc;
|
52
48
|
|
53
|
-
|
54
|
-
|
55
|
-
|
49
|
+
let bin = bins.find(x => (pageSize - x.used) >= alloc);
|
50
|
+
if (!bin) {
|
51
|
+
// new bin
|
52
|
+
const page = pages.size;
|
53
|
+
bin = {
|
54
|
+
used: 0,
|
55
|
+
page
|
56
|
+
};
|
56
57
|
|
57
|
-
|
58
|
-
|
58
|
+
const id = bins.push(bin);
|
59
|
+
pages.set(`#bin: ${id}`, page);
|
60
|
+
}
|
61
|
+
|
62
|
+
if (!startingPtr) startingPtr = pagePtr(bin.page) + bin.used;
|
63
|
+
bin.used += alloc;
|
64
|
+
}
|
59
65
|
|
60
|
-
allocs.set(reason,
|
61
|
-
return
|
66
|
+
allocs.set(reason, startingPtr);
|
67
|
+
return startingPtr;
|
62
68
|
};
|
63
69
|
|
64
70
|
export const allocStr = (scope, str, bytestring) => {
|
@@ -2840,7 +2846,7 @@ const knownType = (scope, type) => {
|
|
2840
2846
|
if (typeof type === 'number') return type;
|
2841
2847
|
|
2842
2848
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2843
|
-
return
|
2849
|
+
return type[0][1];
|
2844
2850
|
}
|
2845
2851
|
|
2846
2852
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -4319,7 +4325,7 @@ const generateUnary = (scope, decl) => {
|
|
4319
4325
|
return [
|
4320
4326
|
...toNumeric(),
|
4321
4327
|
Opcodes.i32_to,
|
4322
|
-
[ Opcodes.i32_const,
|
4328
|
+
[ Opcodes.i32_const, -1 ],
|
4323
4329
|
[ Opcodes.i32_xor ],
|
4324
4330
|
Opcodes.i32_from
|
4325
4331
|
];
|
@@ -5118,14 +5124,14 @@ const generateForIn = (scope, decl) => {
|
|
5118
5124
|
[ Opcodes.local_set, tmp ],
|
5119
5125
|
|
5120
5126
|
// symbol is MSB 2 is set
|
5121
|
-
[ Opcodes.i32_const,
|
5122
|
-
[ Opcodes.i32_const,
|
5127
|
+
[ Opcodes.i32_const, TYPES.string ],
|
5128
|
+
[ Opcodes.i32_const, TYPES.symbol ],
|
5123
5129
|
[ Opcodes.local_get, tmp ],
|
5124
5130
|
number(0x40000000, Valtype.i32),
|
5125
5131
|
[ Opcodes.i32_and ],
|
5126
5132
|
[ Opcodes.select ],
|
5127
5133
|
[ Opcodes.else ], // bytestring
|
5128
|
-
[ Opcodes.i32_const,
|
5134
|
+
[ Opcodes.i32_const, TYPES.bytestring ],
|
5129
5135
|
[ Opcodes.end ]
|
5130
5136
|
]),
|
5131
5137
|
|
@@ -6615,6 +6621,7 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined, v
|
|
6615
6621
|
|
6616
6622
|
const encodeFunc = ({
|
6617
6623
|
[Opcodes.f64_const]: x => x,
|
6624
|
+
[Opcodes.i32_const]: x => x,
|
6618
6625
|
[Opcodes.if]: unsignedLEB128,
|
6619
6626
|
[Opcodes.loop]: unsignedLEB128
|
6620
6627
|
})[inst[0]] ?? signedLEB128;
|
package/compiler/cyclone.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
// cyclone: wasm partial constant evaluator (it is fast and dangerous hence "cyclone")
|
2
|
-
import { number
|
2
|
+
import { number } from './encoding.js';
|
3
3
|
import { Opcodes, Valtype } from './wasmSpec.js';
|
4
4
|
import './prefs.js';
|
5
5
|
|
@@ -123,7 +123,7 @@ export default ({ name, wasm, locals: _locals, params }) => {
|
|
123
123
|
}
|
124
124
|
|
125
125
|
case Opcodes.i32_const: {
|
126
|
-
const n =
|
126
|
+
const n = op[1];
|
127
127
|
push(n);
|
128
128
|
break;
|
129
129
|
}
|
package/compiler/disassemble.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
2
|
-
import {
|
2
|
+
import { read_unsignedLEB128 } from './encoding.js';
|
3
3
|
import { importedFuncs } from './builtins.js';
|
4
4
|
|
5
5
|
const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
|
@@ -74,7 +74,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
|
|
74
74
|
if (inst[0] === Opcodes.f64_const) {
|
75
75
|
out += ` ${inst[1]}`;
|
76
76
|
} else if (inst[0] === Opcodes.i32_const || inst[0] === Opcodes.i64_const) {
|
77
|
-
out += ` ${
|
77
|
+
out += ` ${inst[1]}`;
|
78
78
|
} else if (inst[0] === Opcodes.i32_load || inst[0] === Opcodes.i64_load || inst[0] === Opcodes.f64_load || inst[0] === Opcodes.i32_store || inst[0] === Opcodes.i64_store || inst[0] === Opcodes.f64_store || inst[0] === Opcodes.i32_store16 || inst[0] === Opcodes.i32_load16_u) {
|
79
79
|
out += ` ${inst[1]} ${read_unsignedLEB128(inst.slice(2))}`;
|
80
80
|
} else for (const operand of inst.slice(1)) {
|
package/compiler/encoding.js
CHANGED
@@ -3,10 +3,10 @@ import { Opcodes, Valtype } from './wasmSpec.js';
|
|
3
3
|
export const number = (n, valtype = valtypeBinary) => {
|
4
4
|
if (valtype === Valtype.f64) return [ Opcodes.f64_const, n ];
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
return [
|
7
|
+
valtype === Valtype.i32 ? Opcodes.i32_const : Opcodes.i64_const,
|
8
|
+
n
|
9
|
+
];
|
10
10
|
};
|
11
11
|
|
12
12
|
export const codifyString = str => {
|
@@ -23,6 +23,9 @@ export const encodeVector = data => unsignedLEB128(data.length).concat(data.flat
|
|
23
23
|
|
24
24
|
// todo: this only works with integers within 32 bit range
|
25
25
|
export const signedLEB128 = n => {
|
26
|
+
if (n === Infinity) return signedLEB128(2147483647);
|
27
|
+
if (n === -Infinity) return signedLEB128(-2147483648);
|
28
|
+
|
26
29
|
n |= 0;
|
27
30
|
|
28
31
|
// just input for small numbers (for perf as common)
|
@@ -49,6 +52,9 @@ export const signedLEB128 = n => {
|
|
49
52
|
};
|
50
53
|
|
51
54
|
export const unsignedLEB128 = n => {
|
55
|
+
if (n === Infinity) return unsignedLEB128(4294967295);
|
56
|
+
if (n === -Infinity) return unsignedLEB128(0);
|
57
|
+
|
52
58
|
n |= 0;
|
53
59
|
|
54
60
|
// just input for small numbers (for perf as common)
|
@@ -69,6 +75,9 @@ export const unsignedLEB128 = n => {
|
|
69
75
|
};
|
70
76
|
|
71
77
|
export const unsignedLEB128_length = n => {
|
78
|
+
if (n === Infinity) return unsignedLEB128_length(4294967295);
|
79
|
+
if (n === -Infinity) return unsignedLEB128_length(0);
|
80
|
+
|
72
81
|
if (n < 0) n = n >>> 0;
|
73
82
|
if (n <= 127) return 1;
|
74
83
|
if (n <= 16383) return 2;
|
@@ -85,6 +94,9 @@ export const unsignedLEB128_length = n => {
|
|
85
94
|
};
|
86
95
|
|
87
96
|
export const signedLEB128_length = n => {
|
97
|
+
if (n === Infinity) return signedLEB128_length(2147483647);
|
98
|
+
if (n === -Infinity) return signedLEB128_length(-2147483648);
|
99
|
+
|
88
100
|
if (n >= -64 && n <= 63) return 1;
|
89
101
|
if (n >= -8192 && n <= 8191) return 2;
|
90
102
|
if (n >= -1048576 && n <= 1048575) return 3;
|
@@ -201,6 +213,9 @@ export const read_ieee754_binary64 = buffer => new Float64Array(new Uint8Array(b
|
|
201
213
|
|
202
214
|
// into funcs append to a given existing buffer instead of creating our own for perf
|
203
215
|
export const signedLEB128_into = (n, buffer) => {
|
216
|
+
if (n === Infinity) return signedLEB128_into(2147483647, buffer);
|
217
|
+
if (n === -Infinity) return signedLEB128_into(-2147483648, buffer);
|
218
|
+
|
204
219
|
n |= 0;
|
205
220
|
|
206
221
|
// just input for small numbers (for perf as common)
|
@@ -224,6 +239,9 @@ export const signedLEB128_into = (n, buffer) => {
|
|
224
239
|
};
|
225
240
|
|
226
241
|
export const unsignedLEB128_into = (n, buffer) => {
|
242
|
+
if (n === Infinity) return unsignedLEB128_into(4294967295, buffer);
|
243
|
+
if (n === -Infinity) return unsignedLEB128_into(0, buffer);
|
244
|
+
|
227
245
|
n |= 0;
|
228
246
|
|
229
247
|
// just input for small numbers (for perf as common)
|
package/compiler/expression.js
CHANGED
@@ -46,31 +46,6 @@ export const operatorOpcode = {
|
|
46
46
|
]
|
47
47
|
},
|
48
48
|
|
49
|
-
i64: {
|
50
|
-
'+': Opcodes.i64_add,
|
51
|
-
'-': Opcodes.i64_sub,
|
52
|
-
'*': Opcodes.i64_mul,
|
53
|
-
'/': Opcodes.i64_div_s,
|
54
|
-
'%': Opcodes.i64_rem_s,
|
55
|
-
|
56
|
-
'&': Opcodes.i64_and,
|
57
|
-
'|': Opcodes.i64_or,
|
58
|
-
'^': Opcodes.i64_xor,
|
59
|
-
'<<': Opcodes.i64_shl,
|
60
|
-
'>>': Opcodes.i64_shr_s,
|
61
|
-
'>>>': Opcodes.i64_shr_u,
|
62
|
-
|
63
|
-
'==': Opcodes.i64_eq,
|
64
|
-
'===': Opcodes.i64_eq,
|
65
|
-
'!=': Opcodes.i64_ne,
|
66
|
-
'!==': Opcodes.i64_ne,
|
67
|
-
|
68
|
-
'>': Opcodes.i64_gt_s,
|
69
|
-
'>=': Opcodes.i64_ge_s,
|
70
|
-
'<': Opcodes.i64_lt_s,
|
71
|
-
'<=': Opcodes.i64_le_s
|
72
|
-
},
|
73
|
-
|
74
49
|
f64: {
|
75
50
|
'+': Opcodes.f64_add,
|
76
51
|
'-': Opcodes.f64_sub,
|
package/compiler/opt.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
|
-
import { number
|
2
|
+
import { number } from './encoding.js';
|
3
3
|
import { log } from './log.js';
|
4
4
|
import './prefs.js';
|
5
5
|
|
@@ -177,7 +177,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
177
177
|
// -->
|
178
178
|
// i32.const 0
|
179
179
|
|
180
|
-
wasm[i - 1] = number(
|
180
|
+
wasm[i - 1] = number(lastInst[1], Valtype.i32); // f64.const -> i32.const
|
181
181
|
|
182
182
|
wasm.splice(i, 1); // remove this inst
|
183
183
|
i--;
|
@@ -192,7 +192,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
192
192
|
// -->
|
193
193
|
// f64.const 0
|
194
194
|
|
195
|
-
wasm[i - 1] = number(
|
195
|
+
wasm[i - 1] = number(lastInst[1], Valtype.f64); // i32.const -> f64.const
|
196
196
|
|
197
197
|
wasm.splice(i, 1); // remove this inst
|
198
198
|
i--;
|
@@ -215,18 +215,18 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
215
215
|
continue;
|
216
216
|
}
|
217
217
|
|
218
|
-
if (
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
}
|
218
|
+
// if (i === wasm.length - 1 && inst[0] === Opcodes.return) {
|
219
|
+
// // replace final return, end -> end (wasm has implicit return)
|
220
|
+
// // return
|
221
|
+
// // end
|
222
|
+
// // -->
|
223
|
+
// // end
|
224
|
+
|
225
|
+
// wasm.splice(i, 1); // remove this inst (return)
|
226
|
+
// i--;
|
227
|
+
// // if (Prefs.optLog) log('opt', `removed redundant return at end`);
|
228
|
+
// continue;
|
229
|
+
// }
|
230
230
|
|
231
231
|
// remove unneeded before get with update exprs (n++, etc) when value is unused
|
232
232
|
if (i < wasm.length - 4 && lastInst[1] === inst[1] && lastInst[0] === Opcodes.local_get && inst[0] === Opcodes.local_get && wasm[i + 1][0] === Opcodes.const && [Opcodes.add, Opcodes.sub].includes(wasm[i + 2][0]) && wasm[i + 3][0] === Opcodes.local_set && wasm[i + 3][1] === inst[1] && (wasm[i + 4][0] === Opcodes.drop || wasm[i + 4][0] === Opcodes.br)) {
|
package/compiler/precompile.js
CHANGED
@@ -176,7 +176,7 @@ const compile = async (file, _funcs) => {
|
|
176
176
|
x.usesTag = true;
|
177
177
|
let id;
|
178
178
|
if (y[0] === Opcodes.i32_const && n[1] === 0) {
|
179
|
-
id =
|
179
|
+
id = y[1];
|
180
180
|
wasm[i] = [ 'throw', exceptions[id].constructor, exceptions[id].message ];
|
181
181
|
|
182
182
|
// remove throw inst
|
@@ -244,7 +244,7 @@ ${funcs.map(x => {
|
|
244
244
|
if (Number.isNaN(v) || v === Infinity || v === -Infinity) return v.toString();
|
245
245
|
return v;
|
246
246
|
})
|
247
|
-
.replace(/\["alloc","(.*?)",(.*?)\]/g, (_, reason, valtype) => `
|
247
|
+
.replace(/\["alloc","(.*?)",(.*?)\]/g, (_, reason, valtype) => `[${valtype === Valtype.i32 ? Opcodes.i32_const : Opcodes.f64_const},allocPage(_,'${reason}')]`)
|
248
248
|
.replace(/\["global",(.*?),"(.*?)",(.*?)\]/g, (_, opcode, name, valtype) => `...glbl(${opcode},'${name}',${valtype})`)
|
249
249
|
.replace(/\"local","(.*?)",(.*?)\]/g, (_, name, valtype) => `loc('${name}',${valtype})]`)
|
250
250
|
.replace(/\[16,"(.*?)"]/g, (_, name) => `[16,builtin('${name}')]`)
|
package/compiler/wrap.js
CHANGED
@@ -586,7 +586,10 @@ export default (source, module = undefined, print = str => process.stdout.write(
|
|
586
586
|
}
|
587
587
|
|
588
588
|
times.push(performance.now() - t2);
|
589
|
-
if (Prefs.profileCompiler
|
589
|
+
if (Prefs.profileCompiler) {
|
590
|
+
if (globalThis.onProgress) globalThis.onProgress('instantiated', times[1]);
|
591
|
+
else console.log(`instantiated in ${times[1].toFixed(2)}ms`);
|
592
|
+
}
|
590
593
|
|
591
594
|
const exports = {};
|
592
595
|
const rawValues = Prefs.d;
|
package/package.json
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
{
|
2
2
|
"name": "porffor",
|
3
3
|
"description": "An ahead-of-time JavaScript compiler",
|
4
|
-
"version": "0.60.
|
4
|
+
"version": "0.60.9",
|
5
5
|
"author": "Oliver Medhurst <honk@goose.icu>",
|
6
6
|
"license": "MIT",
|
7
7
|
"scripts": {},
|
8
8
|
"dependencies": {
|
9
9
|
"acorn": "^8.15.0",
|
10
|
-
"node-repl-polyfill": "
|
10
|
+
"node-repl-polyfill": "^0.1.2"
|
11
11
|
},
|
12
12
|
"optionalDependencies": {
|
13
13
|
"@babel/parser": "^7.24.4",
|