porffor 0.20.2 → 0.20.4
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/builtins/console.ts +70 -13
- package/compiler/generated_builtins.js +45 -32
- package/compiler/opt.js +0 -94
- package/compiler/precompile.js +4 -2
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/opt.js
CHANGED
@@ -4,14 +4,6 @@ import { read_signedLEB128, read_ieee754_binary64 } from './encoding.js';
|
|
4
4
|
import { log } from './log.js';
|
5
5
|
import Prefs from './prefs.js';
|
6
6
|
|
7
|
-
const performWasmOp = (op, a, b) => {
|
8
|
-
switch (op) {
|
9
|
-
case Opcodes.add: return a + b;
|
10
|
-
case Opcodes.sub: return a - b;
|
11
|
-
case Opcodes.mul: return a * b;
|
12
|
-
}
|
13
|
-
};
|
14
|
-
|
15
7
|
export default (funcs, globals, pages, tags, exceptions) => {
|
16
8
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
17
9
|
if (optLevel === 0) return;
|
@@ -114,21 +106,12 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
114
106
|
while (runs > 0) {
|
115
107
|
runs--;
|
116
108
|
|
117
|
-
let getCount = {}, setCount = {};
|
118
|
-
for (const x in f.locals) {
|
119
|
-
getCount[f.locals[x].idx] = 0;
|
120
|
-
setCount[f.locals[x].idx] = 0;
|
121
|
-
}
|
122
|
-
|
123
109
|
// main pass
|
124
110
|
for (let i = 0; i < wasm.length; i++) {
|
125
111
|
let inst = wasm[i];
|
126
112
|
inst = [ ...inst ];
|
127
113
|
wasm[i] = inst;
|
128
114
|
|
129
|
-
if (inst[0] === Opcodes.local_get) getCount[inst[1]]++;
|
130
|
-
if (inst[0] === Opcodes.local_set || inst[0] === Opcodes.local_tee) setCount[inst[1]]++;
|
131
|
-
|
132
115
|
// if (inst[0] === Opcodes.throw) {
|
133
116
|
// tagUse[inst[1]]++;
|
134
117
|
|
@@ -267,7 +250,6 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
267
250
|
lastInst[0] = Opcodes.local_tee; // replace last inst opcode (set -> tee)
|
268
251
|
wasm.splice(i, 1); // remove this inst (get)
|
269
252
|
|
270
|
-
getCount[inst[1]]--;
|
271
253
|
i--;
|
272
254
|
// if (Prefs.optLog) log('opt', `consolidated set, get -> tee`);
|
273
255
|
continue;
|
@@ -280,8 +262,6 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
280
262
|
// -->
|
281
263
|
//
|
282
264
|
|
283
|
-
getCount[lastInst[1]]--;
|
284
|
-
|
285
265
|
wasm.splice(i - 1, 2); // remove this inst and last
|
286
266
|
i -= 2;
|
287
267
|
continue;
|
@@ -294,8 +274,6 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
294
274
|
// -->
|
295
275
|
// local.set 0
|
296
276
|
|
297
|
-
getCount[lastInst[1]]--;
|
298
|
-
|
299
277
|
lastInst[0] = Opcodes.local_set; // change last op
|
300
278
|
|
301
279
|
wasm.splice(i, 1); // remove this inst
|
@@ -427,78 +405,6 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
427
405
|
continue;
|
428
406
|
}
|
429
407
|
}
|
430
|
-
|
431
|
-
if (optLevel < 2) continue;
|
432
|
-
|
433
|
-
if (Prefs.optLog) log('opt', `get counts: ${Object.keys(f.locals).map(x => `${x} (${f.locals[x].idx}): ${getCount[f.locals[x].idx]}`).join(', ')}`);
|
434
|
-
|
435
|
-
// remove unneeded var: remove pass
|
436
|
-
// locals only got once. we don't need to worry about sets/else as these are only candidates and we will check for matching set + get insts in wasm
|
437
|
-
let unneededCandidates = Object.keys(getCount).filter(x => getCount[x] === 0 || (getCount[x] === 1 && setCount[x] === 0)).map(x => parseInt(x));
|
438
|
-
if (Prefs.optLog) log('opt', `found unneeded locals candidates: ${unneededCandidates.join(', ')} (${unneededCandidates.length}/${Object.keys(getCount).length})`);
|
439
|
-
|
440
|
-
// note: disabled for now due to instability
|
441
|
-
if (unneededCandidates.length > 0 && false) for (let i = 0; i < wasm.length; i++) {
|
442
|
-
if (i < 1) continue;
|
443
|
-
|
444
|
-
const inst = wasm[i];
|
445
|
-
const lastInst = wasm[i - 1];
|
446
|
-
|
447
|
-
if (lastInst[1] === inst[1] && lastInst[0] === Opcodes.local_set && inst[0] === Opcodes.local_get && unneededCandidates.includes(inst[1])) {
|
448
|
-
// local.set N
|
449
|
-
// local.get N
|
450
|
-
// -->
|
451
|
-
// <nothing>
|
452
|
-
|
453
|
-
wasm.splice(i - 1, 2); // remove insts
|
454
|
-
i -= 2;
|
455
|
-
delete f.locals[Object.keys(f.locals)[inst[1]]]; // remove from locals
|
456
|
-
if (Prefs.optLog) log('opt', `removed redundant local (get set ${inst[1]})`);
|
457
|
-
}
|
458
|
-
|
459
|
-
if (inst[0] === Opcodes.local_tee && unneededCandidates.includes(inst[1])) {
|
460
|
-
// local.tee N
|
461
|
-
// -->
|
462
|
-
// <nothing>
|
463
|
-
|
464
|
-
wasm.splice(i, 1); // remove inst
|
465
|
-
i--;
|
466
|
-
|
467
|
-
const localName = Object.keys(f.locals)[inst[1]];
|
468
|
-
const removedIdx = f.locals[localName].idx;
|
469
|
-
delete f.locals[localName]; // remove from locals
|
470
|
-
|
471
|
-
// fix locals index for locals after
|
472
|
-
for (const x in f.locals) {
|
473
|
-
const local = f.locals[x];
|
474
|
-
if (local.idx > removedIdx) local.idx--;
|
475
|
-
}
|
476
|
-
|
477
|
-
for (const inst of wasm) {
|
478
|
-
if ((inst[0] === Opcodes.local_get || inst[0] === Opcodes.local_set || inst[0] === Opcodes.local_tee) && inst[1] > removedIdx) inst[1]--;
|
479
|
-
}
|
480
|
-
|
481
|
-
unneededCandidates.splice(unneededCandidates.indexOf(inst[1]), 1);
|
482
|
-
unneededCandidates = unneededCandidates.map(x => x > removedIdx ? (x - 1) : x);
|
483
|
-
|
484
|
-
if (Prefs.optLog) log('opt', `removed redundant local ${localName} (tee ${inst[1]})`);
|
485
|
-
}
|
486
|
-
}
|
487
|
-
|
488
|
-
const useCount = {};
|
489
|
-
for (const x in f.locals) useCount[f.locals[x].idx] = 0;
|
490
|
-
|
491
|
-
const localIdxs = Object.values(f.locals).map(x => x.idx);
|
492
|
-
// remove unused locals (cleanup)
|
493
|
-
for (const x in useCount) {
|
494
|
-
if (useCount[x] === 0) {
|
495
|
-
const name = Object.keys(f.locals)[localIdxs.indexOf(parseInt(x))];
|
496
|
-
if (Prefs.optLog) log('opt', `removed internal local ${x} (${name})`);
|
497
|
-
delete f.locals[name];
|
498
|
-
}
|
499
|
-
}
|
500
|
-
|
501
|
-
if (Prefs.optLog) log('opt', `final use counts: ${Object.keys(f.locals).map(x => `${x} (${f.locals[x].idx}): ${useCount[f.locals[x].idx]}`).join(', ')}`);
|
502
408
|
}
|
503
409
|
}
|
504
410
|
|
package/compiler/precompile.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import { Opcodes } from './wasmSpec.js';
|
2
|
+
import { read_unsignedLEB128 } from './encoding.js';
|
2
3
|
import { TYPES } from './types.js';
|
3
4
|
|
4
5
|
import process from 'node:process';
|
@@ -68,10 +69,11 @@ const compile = async (file, _funcs) => {
|
|
68
69
|
const y = wasm[i];
|
69
70
|
const n = wasm[i + 1];
|
70
71
|
if (y[0] === Opcodes.call) {
|
71
|
-
const
|
72
|
+
const idx = read_unsignedLEB128(y.slice(1));
|
73
|
+
const f = funcs.find(x => x.index === idx);
|
72
74
|
if (!f) continue;
|
73
75
|
|
74
|
-
y
|
76
|
+
y.splice(1, 10, f.name);
|
75
77
|
}
|
76
78
|
|
77
79
|
if (y[0] === Opcodes.global_get || y[0] === Opcodes.global_set) {
|
package/package.json
CHANGED