porffor 0.37.30 → 0.37.32
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/assemble.js +1 -1
- package/compiler/builtins_precompiled.js +146 -146
- package/compiler/codegen.js +15 -19
- package/compiler/index.js +9 -7
- package/compiler/parse.js +4 -4
- package/compiler/pgo.js +2 -2
- package/compiler/precompile.js +2 -2
- package/compiler/wrap.js +4 -6
- package/package.json +1 -1
- package/rhemyn/compile.js +5 -3
- package/runner/debug.js +1 -1
- package/runner/index.js +2 -2
- package/runner/profile.js +1 -1
- package/runner/repl.js +1 -1
- package/runner/compare.js +0 -34
- package/runner/sizes.js +0 -38
package/compiler/codegen.js
CHANGED
@@ -1733,7 +1733,7 @@ const aliasPrimObjsBC = bc => {
|
|
1733
1733
|
const createThisArg = (scope, decl) => {
|
1734
1734
|
const name = mapName(decl.callee?.name);
|
1735
1735
|
if (decl._new) {
|
1736
|
-
// if precompiling or builtin func, just make
|
1736
|
+
// if precompiling or builtin func, just make it null as unused
|
1737
1737
|
if (globalThis.precompile || Object.hasOwn(builtinFuncs, name)) return [
|
1738
1738
|
...number(NULL),
|
1739
1739
|
...number(TYPES.object, Valtype.i32)
|
@@ -1793,11 +1793,12 @@ const createThisArg = (scope, decl) => {
|
|
1793
1793
|
];
|
1794
1794
|
}
|
1795
1795
|
|
1796
|
-
// do not generate globalThis now,
|
1796
|
+
// undefined do not generate globalThis now,
|
1797
1797
|
// do it dynamically in generateThis in the func later
|
1798
|
+
// (or not for strict mode)
|
1798
1799
|
return [
|
1799
|
-
...number(
|
1800
|
-
...number(TYPES.
|
1800
|
+
...number(UNDEFINED),
|
1801
|
+
...number(TYPES.undefined, Valtype.i32)
|
1801
1802
|
];
|
1802
1803
|
}
|
1803
1804
|
};
|
@@ -2597,27 +2598,22 @@ const generateThis = (scope, decl) => {
|
|
2597
2598
|
];
|
2598
2599
|
}
|
2599
2600
|
|
2600
|
-
// opt: do not check for pure constructors
|
2601
|
-
if (scope._onlyConstr || scope._onlyThisMethod || decl._noGlobalThis) return [
|
2601
|
+
// opt: do not check for pure constructors or strict mode
|
2602
|
+
if ((!globalThis.precompile && scope.strict) || scope._onlyConstr || scope._onlyThisMethod || decl._noGlobalThis) return [
|
2602
2603
|
[ Opcodes.local_get, scope.locals['#this'].idx ],
|
2603
2604
|
...setLastType(scope, [ [ Opcodes.local_get, scope.locals['#this#type'].idx ] ])
|
2604
2605
|
];
|
2605
2606
|
|
2606
2607
|
return [
|
2607
2608
|
// default this to globalThis
|
2608
|
-
[ Opcodes.local_get, scope.locals['#this'].idx ],
|
2609
|
-
|
2610
|
-
[ Opcodes.
|
2609
|
+
[ Opcodes.local_get, scope.locals['#this#type'].idx ],
|
2610
|
+
...number(TYPES.undefined, Valtype.i32),
|
2611
|
+
[ Opcodes.i32_eq ],
|
2611
2612
|
[ Opcodes.if, Blocktype.void ],
|
2612
|
-
|
2613
|
-
|
2614
|
-
|
2615
|
-
[ Opcodes.
|
2616
|
-
...generate(scope, { type: 'Identifier', name: 'globalThis' }),
|
2617
|
-
[ Opcodes.local_set, scope.locals['#this'].idx ],
|
2618
|
-
...getType(scope, 'globalThis'),
|
2619
|
-
[ Opcodes.local_set, scope.locals['#this#type'].idx ],
|
2620
|
-
[ Opcodes.end ],
|
2613
|
+
...generate(scope, { type: 'Identifier', name: 'globalThis' }),
|
2614
|
+
[ Opcodes.local_set, scope.locals['#this'].idx ],
|
2615
|
+
...getType(scope, 'globalThis'),
|
2616
|
+
[ Opcodes.local_set, scope.locals['#this#type'].idx ],
|
2621
2617
|
[ Opcodes.end ],
|
2622
2618
|
|
2623
2619
|
[ Opcodes.local_get, scope.locals['#this'].idx ],
|
@@ -4707,7 +4703,7 @@ const generateLabel = (scope, decl) => {
|
|
4707
4703
|
const generateThrow = (scope, decl) => {
|
4708
4704
|
scope.throws = true;
|
4709
4705
|
|
4710
|
-
const exceptionMode = Prefs.exceptionMode ?? '
|
4706
|
+
const exceptionMode = Prefs.exceptionMode ?? 'stack';
|
4711
4707
|
if (exceptionMode === 'lut') {
|
4712
4708
|
let message = decl.argument.value, constructor = null;
|
4713
4709
|
|
package/compiler/index.js
CHANGED
@@ -52,7 +52,9 @@ const progressClear = () => {
|
|
52
52
|
progressLines = 0;
|
53
53
|
};
|
54
54
|
|
55
|
-
export default (code,
|
55
|
+
export default (code, module = undefined) => {
|
56
|
+
if (module !== undefined) Prefs.module = module;
|
57
|
+
|
56
58
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
57
59
|
|
58
60
|
let target = Prefs.target ?? 'wasm';
|
@@ -82,7 +84,7 @@ export default (code, flags) => {
|
|
82
84
|
|
83
85
|
if (logProgress) progressStart('parsing...');
|
84
86
|
const t0 = performance.now();
|
85
|
-
const program = parse(code
|
87
|
+
const program = parse(code);
|
86
88
|
if (logProgress) progressDone('parsed', t0);
|
87
89
|
|
88
90
|
if (logProgress) progressStart('generating wasm...');
|
@@ -98,7 +100,7 @@ export default (code, flags) => {
|
|
98
100
|
|
99
101
|
if (Prefs.pgo) {
|
100
102
|
if (Prefs.pgoLog) {
|
101
|
-
const oldSize = assemble(funcs, globals, tags, pages, data,
|
103
|
+
const oldSize = assemble(funcs, globals, tags, pages, data, true).byteLength;
|
102
104
|
const t = performance.now();
|
103
105
|
|
104
106
|
pgo.run({ funcs, globals, tags, exceptions, pages, data });
|
@@ -106,7 +108,7 @@ export default (code, flags) => {
|
|
106
108
|
|
107
109
|
console.log(`PGO total time: ${(performance.now() - t).toFixed(2)}ms`);
|
108
110
|
|
109
|
-
const newSize = assemble(funcs, globals, tags, pages, data,
|
111
|
+
const newSize = assemble(funcs, globals, tags, pages, data, true).byteLength;
|
110
112
|
console.log(`PGO size diff: ${oldSize - newSize} bytes (${oldSize} -> ${newSize})\n`);
|
111
113
|
} else {
|
112
114
|
pgo.run({ funcs, globals, tags, exceptions, pages, data });
|
@@ -116,7 +118,7 @@ export default (code, flags) => {
|
|
116
118
|
|
117
119
|
if (Prefs.cyclone) {
|
118
120
|
if (Prefs.cycloneLog) {
|
119
|
-
const oldSize = assemble(funcs, globals, tags, pages, data,
|
121
|
+
const oldSize = assemble(funcs, globals, tags, pages, data, true).byteLength;
|
120
122
|
const t = performance.now();
|
121
123
|
|
122
124
|
for (const x of funcs) {
|
@@ -129,7 +131,7 @@ export default (code, flags) => {
|
|
129
131
|
|
130
132
|
console.log(`cyclone total time: ${(performance.now() - t).toFixed(2)}ms`);
|
131
133
|
|
132
|
-
const newSize = assemble(funcs, globals, tags, pages, data,
|
134
|
+
const newSize = assemble(funcs, globals, tags, pages, data, true).byteLength;
|
133
135
|
console.log(`cyclone size diff: ${oldSize - newSize} bytes (${oldSize} -> ${newSize})\n`);
|
134
136
|
} else {
|
135
137
|
for (const x of funcs) {
|
@@ -171,7 +173,7 @@ export default (code, flags) => {
|
|
171
173
|
const out = { funcs, globals, tags, exceptions, pages, data, times: [ t0, t1, t2, t3 ] };
|
172
174
|
if (globalThis.precompile) return out;
|
173
175
|
|
174
|
-
const wasm = out.wasm = assemble(funcs, globals, tags, pages, data
|
176
|
+
const wasm = out.wasm = assemble(funcs, globals, tags, pages, data);
|
175
177
|
if (logProgress) progressDone('assembled', t3);
|
176
178
|
|
177
179
|
if (Prefs.optFuncs || Prefs.f) logFuncs(funcs, globals, exceptions);
|
package/compiler/parse.js
CHANGED
@@ -25,7 +25,7 @@ await loadParser(types ? '@babel/parser' : undefined);
|
|
25
25
|
|
26
26
|
if (types && !['@babel/parser', 'hermes-parser'].includes(parser)) log.warning('parse', `passed -parse-types with a parser (${parser}) which does not support`);
|
27
27
|
|
28
|
-
export default
|
28
|
+
export default input => {
|
29
29
|
try {
|
30
30
|
const ast = parse(input, {
|
31
31
|
// acorn
|
@@ -33,14 +33,14 @@ export default (input, flags) => {
|
|
33
33
|
|
34
34
|
// meriyah
|
35
35
|
next: true,
|
36
|
-
module:
|
36
|
+
module: Prefs.module,
|
37
37
|
webcompat: true,
|
38
38
|
|
39
39
|
// babel
|
40
|
-
plugins: types
|
40
|
+
plugins: types ? ['estree', 'typescript'] : ['estree'],
|
41
41
|
|
42
42
|
// multiple
|
43
|
-
sourceType:
|
43
|
+
sourceType: Prefs.module ? 'module' : 'script',
|
44
44
|
ranges: false,
|
45
45
|
tokens: false,
|
46
46
|
comments: false,
|
package/compiler/pgo.js
CHANGED
@@ -81,12 +81,12 @@ export const run = obj => {
|
|
81
81
|
|
82
82
|
let activeFunc = null, abort = false;
|
83
83
|
try {
|
84
|
-
obj.wasm = assemble(obj.funcs, obj.globals, obj.tags, obj.pages, obj.data,
|
84
|
+
obj.wasm = assemble(obj.funcs, obj.globals, obj.tags, obj.pages, obj.data, true);
|
85
85
|
|
86
86
|
Prefs._profileCompiler = Prefs.profileCompiler;
|
87
87
|
Prefs.profileCompiler = false;
|
88
88
|
|
89
|
-
const { exports } = wrap(obj,
|
89
|
+
const { exports } = wrap(obj, undefined, {
|
90
90
|
y: n => {
|
91
91
|
activeFunc = n;
|
92
92
|
},
|
package/compiler/precompile.js
CHANGED
@@ -25,7 +25,7 @@ const compile = async (file, _funcs) => {
|
|
25
25
|
first = source.slice(0, source.indexOf('\n'));
|
26
26
|
}
|
27
27
|
|
28
|
-
let args = ['--todo-time=compile', '--truthy=no_nan_negative', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--fast-length', '--parse-types', '--opt-types', '--no-passive-data', '--active-data', '--exception-mode=lut'];
|
28
|
+
let args = ['--module', '--todo-time=compile', '--truthy=no_nan_negative', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--fast-length', '--parse-types', '--opt-types', '--no-passive-data', '--active-data', '--exception-mode=lut'];
|
29
29
|
if (first.startsWith('// @porf')) {
|
30
30
|
args = first.slice('// @porf '.length).split(' ').concat(args);
|
31
31
|
}
|
@@ -34,7 +34,7 @@ const compile = async (file, _funcs) => {
|
|
34
34
|
|
35
35
|
const porfCompile = (await import(`./index.js?_=${Date.now()}`)).default;
|
36
36
|
|
37
|
-
let { funcs, globals, data, exceptions, times } = porfCompile(source
|
37
|
+
let { funcs, globals, data, exceptions, times } = porfCompile(source);
|
38
38
|
|
39
39
|
timing.parse ??= 0;
|
40
40
|
timing.parse += times[1] - times[0];
|
package/compiler/wrap.js
CHANGED
@@ -325,16 +325,14 @@ ${flags & 0b0001 ? ` get func idx: ${get}
|
|
325
325
|
}
|
326
326
|
};
|
327
327
|
|
328
|
-
export default (source,
|
328
|
+
export default (source, module = undefined, customImports = {}, print = str => process.stdout.write(str)) => {
|
329
329
|
const times = [];
|
330
330
|
|
331
331
|
const t1 = performance.now();
|
332
|
-
const { wasm, funcs, globals, tags, exceptions, pages, c } = typeof source === 'object' ? source : compile(source,
|
332
|
+
const { wasm, funcs, globals, tags, exceptions, pages, c } = typeof source === 'object' ? source : compile(source, module);
|
333
333
|
|
334
334
|
globalThis.porfDebugInfo = { funcs, globals };
|
335
335
|
|
336
|
-
// if (process.argv[1].includes('/runner') && source.includes?.('export ')) flags.push('module');
|
337
|
-
|
338
336
|
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
339
337
|
|
340
338
|
times.push(performance.now() - t1);
|
@@ -504,7 +502,7 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
504
502
|
return porfToJSValue({ memory, funcs, pages }, ret[0], ret[1]);
|
505
503
|
} catch (e) {
|
506
504
|
if (e.is && e.is(exceptTag)) {
|
507
|
-
const exceptionMode = Prefs.exceptionMode ?? '
|
505
|
+
const exceptionMode = Prefs.exceptionMode ?? 'stack';
|
508
506
|
if (exceptionMode === 'lut') {
|
509
507
|
const exceptId = e.getArg(exceptTag, 0);
|
510
508
|
const exception = exceptions[exceptId];
|
@@ -541,7 +539,7 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
541
539
|
};
|
542
540
|
}
|
543
541
|
|
544
|
-
if (
|
542
|
+
if (Prefs.decomp) {
|
545
543
|
return { exports, wasm, times, decomps: funcs.map(x => decompile(x.wasm, x.name, x.index, x.locals, x.params, x.returns, funcs, globals, exceptions)), c };
|
546
544
|
}
|
547
545
|
|
package/package.json
CHANGED
package/rhemyn/compile.js
CHANGED
@@ -12,15 +12,17 @@ const Length = 4;
|
|
12
12
|
const Tmp = 5;
|
13
13
|
const QuantifierTmp = 6; // the temporary variable used for quanitifers
|
14
14
|
|
15
|
-
const doesSucceedZero =
|
15
|
+
const doesSucceedZero = node => {
|
16
16
|
for (const n of node.body) {
|
17
|
-
if (n.type ===
|
18
|
-
if (!doesSucceedZero(
|
17
|
+
if (n.type === 'Group') {
|
18
|
+
if (!doesSucceedZero(n)) return false;
|
19
19
|
}
|
20
|
+
|
20
21
|
if (!n.quantifier || n.quantifier[0] > 0) {
|
21
22
|
return false;
|
22
23
|
}
|
23
24
|
}
|
25
|
+
|
24
26
|
return true;
|
25
27
|
}
|
26
28
|
|
package/runner/debug.js
CHANGED
@@ -43,7 +43,7 @@ let lastLine;
|
|
43
43
|
let output = '';
|
44
44
|
|
45
45
|
try {
|
46
|
-
const { exports } = compile(source,
|
46
|
+
const { exports } = compile(source, undefined, {
|
47
47
|
y: n => {
|
48
48
|
if (callStarts[callStarts.length - 1] === n - 1) {
|
49
49
|
// end of call
|
package/runner/index.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
#!/usr/bin/env node
|
2
2
|
import fs from 'node:fs';
|
3
|
-
globalThis.version = '0.37.
|
3
|
+
globalThis.version = '0.37.32+fde2c20c4';
|
4
4
|
|
5
5
|
// deno compat
|
6
6
|
if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
|
@@ -158,7 +158,7 @@ const compile = (await import('../compiler/wrap.js')).default;
|
|
158
158
|
let runStart;
|
159
159
|
let ret;
|
160
160
|
try {
|
161
|
-
const out = compile(source
|
161
|
+
const out = compile(source);
|
162
162
|
runStart = performance.now();
|
163
163
|
if (!process.argv.includes('--no-run')) ret = out.exports.main();
|
164
164
|
|
package/runner/profile.js
CHANGED
package/runner/repl.js
CHANGED
@@ -89,7 +89,7 @@ const run = (source, _context, _filename, callback, run = true) => {
|
|
89
89
|
|
90
90
|
let shouldPrint = !prev;
|
91
91
|
try {
|
92
|
-
const { exports, pages } = compile(toRun,
|
92
|
+
const { exports, pages } = compile(toRun, undefined, {}, str => {
|
93
93
|
if (shouldPrint) process.stdout.write(str);
|
94
94
|
if (str === '-4919') shouldPrint = true;
|
95
95
|
});
|
package/runner/compare.js
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
import { execSync } from 'node:child_process';
|
2
|
-
import fs from 'node:fs';
|
3
|
-
|
4
|
-
const [ commitsAgo, file ] = process.argv.slice(2);
|
5
|
-
const source = fs.readFileSync(file, 'utf8');
|
6
|
-
|
7
|
-
const compileNow = (await import('../compiler/index.js')).default;
|
8
|
-
const wasmNow = compileNow(source).byteLength;
|
9
|
-
|
10
|
-
execSync(`git checkout HEAD~${commitsAgo}`);
|
11
|
-
|
12
|
-
let failed = false;
|
13
|
-
|
14
|
-
fs.writeFileSync('tmp.js', source);
|
15
|
-
try {
|
16
|
-
execSync(`node runner/index.js tmp.js`);
|
17
|
-
} catch {
|
18
|
-
failed = true;
|
19
|
-
} finally {
|
20
|
-
fs.rmSync('tmp.js');
|
21
|
-
execSync(`git checkout main`);
|
22
|
-
}
|
23
|
-
|
24
|
-
console.log();
|
25
|
-
|
26
|
-
if (failed) {
|
27
|
-
console.log(`!! failed to compile then`);
|
28
|
-
process.exit();
|
29
|
-
}
|
30
|
-
|
31
|
-
const wasmThen = Buffer.byteLength(fs.readFileSync('out.wasm'));
|
32
|
-
|
33
|
-
console.log(`now: ${wasmNow} bytes`);
|
34
|
-
console.log(`${commitsAgo} commit${commitsAgo > 1 ? 's' : ''} ago: ${wasmThen} bytes`);
|
package/runner/sizes.js
DELETED
@@ -1,38 +0,0 @@
|
|
1
|
-
import compile from '../compiler/index.js';
|
2
|
-
import fs from 'node:fs';
|
3
|
-
|
4
|
-
// deno compat
|
5
|
-
const textEncoder = new TextEncoder();
|
6
|
-
if (typeof process === 'undefined') globalThis.process = { argv: ['', '', ...Deno.args], stdout: { write: str => Deno.writeAllSync(Deno.stdout, textEncoder.encode(str)) } };
|
7
|
-
|
8
|
-
let csv = `file,porffor i32 -O0,porffor i32 -O1,porffor i32 -O2,porffor i32 -O3,porffor i64 -O0,porffor i64 -O1,porffor i64 -O2,porffor i64 -O3,porffor f64 -O0, porffor f64 -O1, porffor f64 -O2, porffor f64 -O3\n`;
|
9
|
-
const perform = async (file, args) => {
|
10
|
-
process.argv = process.argv.slice(0, 2).concat(args);
|
11
|
-
const source = fs.readFileSync(file, 'utf8');
|
12
|
-
|
13
|
-
const { wasm } = compile(source, []);
|
14
|
-
const size = wasm.byteLength;
|
15
|
-
|
16
|
-
const label = `${file} ${args.join(' ')}`;
|
17
|
-
csv += `${size},`;
|
18
|
-
console.log(label, ' '.repeat(40 - label.length), `${size}b`);
|
19
|
-
};
|
20
|
-
|
21
|
-
const argsValtypes = [ '--valtype=i32', '--valtype=f64' ];
|
22
|
-
const argsOptlevels = [ '-O0', '-O1', '-O2', '-O3' ];
|
23
|
-
|
24
|
-
for (const file of [ 'bench/prime_basic.js', 'bench/fib_iter.js', 'test/math_1.js', 'test/math_3.js', 'test/while_1.js', 'test/for_2.js', 'test/unary_3.js', 'test/updateexp_1.js', 'test/eq_3.js', 'test/empty.js' ]) {
|
25
|
-
const niceFile = file.split('/')[1].slice(0, -3);
|
26
|
-
csv += `${niceFile},`;
|
27
|
-
|
28
|
-
for (const x of argsValtypes) {
|
29
|
-
for (const y of argsOptlevels) {
|
30
|
-
await perform(file, [ x, y ]);
|
31
|
-
}
|
32
|
-
}
|
33
|
-
|
34
|
-
csv = csv.slice(0, -1) + '\n';
|
35
|
-
}
|
36
|
-
|
37
|
-
fs.writeFileSync('sizes.csv', csv);
|
38
|
-
console.log(csv);
|