porffor 0.58.19 → 0.59.1
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/AGENT.md +16 -7
- package/compiler/assemble.js +2 -13
- package/compiler/builtins/regexp.ts +186 -7
- package/compiler/builtins/string.ts +0 -35
- package/compiler/builtins/string_f64.ts +97 -0
- package/compiler/builtins.js +30 -37
- package/compiler/builtins_precompiled.js +381 -369
- package/compiler/codegen.js +60 -15
- package/compiler/pgo.js +21 -43
- package/compiler/wrap.js +3 -8
- package/fuzz/index.js +1 -1
- package/package.json +1 -1
- package/runtime/debug.js +1 -1
- package/runtime/index.js +1 -1
- package/runtime/profile.js +1 -1
- package/runtime/repl.js +1 -1
- package/wow.js +0 -1
package/compiler/codegen.js
CHANGED
@@ -1505,6 +1505,7 @@ const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTy
|
|
1505
1505
|
typeUsed(func, returnType);
|
1506
1506
|
}
|
1507
1507
|
|
1508
|
+
func.jsLength = countLength(func);
|
1508
1509
|
func.wasm = wasm;
|
1509
1510
|
return func;
|
1510
1511
|
};
|
@@ -1822,6 +1823,12 @@ const getNodeType = (scope, node) => {
|
|
1822
1823
|
case '__Porffor_bs': return TYPES.bytestring;
|
1823
1824
|
case '__Porffor_s': return TYPES.string;
|
1824
1825
|
}
|
1826
|
+
|
1827
|
+
return getNodeType(scope, {
|
1828
|
+
type: 'CallExpression',
|
1829
|
+
callee: node.tag,
|
1830
|
+
arguments: []
|
1831
|
+
});
|
1825
1832
|
}
|
1826
1833
|
|
1827
1834
|
if (node.type === 'ThisExpression') {
|
@@ -5760,7 +5767,24 @@ const countLength = (func, name = undefined) => {
|
|
5760
5767
|
|
5761
5768
|
let count = countParams(func, name);
|
5762
5769
|
if (builtinFuncs[name] && name.includes('_prototype_')) count--;
|
5763
|
-
|
5770
|
+
if (func.hasRestArgument) count--;
|
5771
|
+
|
5772
|
+
if (func.internal) {
|
5773
|
+
// some js built-ins have an old non-standard length
|
5774
|
+
const override = ({
|
5775
|
+
Array: 1,
|
5776
|
+
String: 1,
|
5777
|
+
__Object_assign: 2,
|
5778
|
+
__String_fromCharCode: 1,
|
5779
|
+
__String_fromCodePoint: 1,
|
5780
|
+
__Array_prototype_concat: 1,
|
5781
|
+
__Array_prototype_push: 1,
|
5782
|
+
__Array_prototype_unshift: 1,
|
5783
|
+
__String_prototype_concat: 1,
|
5784
|
+
__ByteString_prototype_concat: 1
|
5785
|
+
})[name];
|
5786
|
+
if (override != null) return override;
|
5787
|
+
}
|
5764
5788
|
return count;
|
5765
5789
|
};
|
5766
5790
|
|
@@ -6581,20 +6605,41 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined, v
|
|
6581
6605
|
return cacheAst(decl, intrinsics[decl.tag.name](str));
|
6582
6606
|
}
|
6583
6607
|
|
6584
|
-
|
6585
|
-
|
6586
|
-
|
6587
|
-
|
6588
|
-
|
6589
|
-
|
6590
|
-
|
6591
|
-
|
6592
|
-
|
6593
|
-
|
6594
|
-
|
6595
|
-
|
6596
|
-
|
6597
|
-
|
6608
|
+
const tmp = localTmp(scope, '#tagged_template_strings');
|
6609
|
+
const tmpIdent = {
|
6610
|
+
type: 'Identifier',
|
6611
|
+
name: '#tagged_template_strings',
|
6612
|
+
_type: TYPES.array
|
6613
|
+
};
|
6614
|
+
|
6615
|
+
return [
|
6616
|
+
...generate(scope, {
|
6617
|
+
type: 'ArrayExpression',
|
6618
|
+
elements: quasis.map(x => ({
|
6619
|
+
type: 'Literal',
|
6620
|
+
value: x.value.cooked
|
6621
|
+
}))
|
6622
|
+
}),
|
6623
|
+
[ Opcodes.local_set, tmp ],
|
6624
|
+
|
6625
|
+
...generate(scope, setObjProp(tmpIdent, 'raw', {
|
6626
|
+
type: 'ArrayExpression',
|
6627
|
+
elements: quasis.map(x => ({
|
6628
|
+
type: 'Literal',
|
6629
|
+
value: x.value.raw
|
6630
|
+
}))
|
6631
|
+
})),
|
6632
|
+
[ Opcodes.drop ],
|
6633
|
+
|
6634
|
+
...generate(scope, {
|
6635
|
+
type: 'CallExpression',
|
6636
|
+
callee: decl.tag,
|
6637
|
+
arguments: [
|
6638
|
+
tmpIdent,
|
6639
|
+
...expressions
|
6640
|
+
]
|
6641
|
+
})
|
6642
|
+
];
|
6598
6643
|
};
|
6599
6644
|
|
6600
6645
|
globalThis._uniqId = 0;
|
package/compiler/pgo.js
CHANGED
@@ -1,20 +1,26 @@
|
|
1
1
|
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
2
|
import { number } from './encoding.js';
|
3
|
-
import { createImport, importedFuncs } from './builtins.js';
|
3
|
+
import { createImport, importedFuncs, setImports } from './builtins.js';
|
4
4
|
import assemble from './assemble.js';
|
5
5
|
import wrap from './wrap.js';
|
6
6
|
import * as Havoc from './havoc.js';
|
7
7
|
import './prefs.js';
|
8
|
+
import fs from 'node:fs';
|
8
9
|
|
10
|
+
let activeFunc, localData;
|
9
11
|
export const setup = () => {
|
10
12
|
// enable these prefs by default for pgo
|
11
13
|
for (const x of [
|
12
14
|
'typeswitchUniqueTmp', // use unique tmps for typeswitches
|
13
|
-
'
|
14
|
-
'cyclone', // enable cyclone pre-evaler
|
15
|
+
// 'cyclone', // enable cyclone pre-evaler
|
15
16
|
]) {
|
16
17
|
Prefs[x] = Prefs[x] === false ? false : true;
|
17
18
|
}
|
19
|
+
|
20
|
+
createImport('profileLocalSet', [ Valtype.i32, Valtype.i32, Valtype.f64 ], 0, (activeFunc, i, n) => {
|
21
|
+
if (activeFunc == null) throw 'fail';
|
22
|
+
localData[activeFunc][i].push(n);
|
23
|
+
});
|
18
24
|
};
|
19
25
|
|
20
26
|
export const run = obj => {
|
@@ -34,15 +40,7 @@ export const run = obj => {
|
|
34
40
|
|
35
41
|
time(0, `injecting PGO logging...`);
|
36
42
|
|
37
|
-
let
|
38
|
-
createImport('profile1', [ Valtype.i32 ], 0, n => {
|
39
|
-
activeFunc = n;
|
40
|
-
});
|
41
|
-
createImport('profile2', [ Valtype.i32, Valtype.f64 ], 0, (i, n) => {
|
42
|
-
if (activeFunc == null) throw 'fail';
|
43
|
-
localData[activeFunc][i].push(n);
|
44
|
-
});
|
45
|
-
|
43
|
+
let abort = false;
|
46
44
|
let funcs = [];
|
47
45
|
for (let i = 0; i < wasmFuncs.length; i++) {
|
48
46
|
const { name, internal, params, locals, wasm } = wasmFuncs[i];
|
@@ -55,16 +53,13 @@ export const run = obj => {
|
|
55
53
|
funcs.push({ name, id, locals, params, invLocals });
|
56
54
|
|
57
55
|
wasm.unshift(
|
58
|
-
// mark active func
|
59
|
-
number(i, Valtype.i32),
|
60
|
-
[ Opcodes.call, importedFuncs.profile1 ],
|
61
|
-
|
62
56
|
// log args
|
63
57
|
...params.flatMap((_, i) => [
|
58
|
+
number(id, Valtype.i32),
|
64
59
|
number(i, Valtype.i32),
|
65
60
|
[ Opcodes.local_get, i ],
|
66
61
|
...(invLocals[i].type !== Valtype.f64 ? [ Opcodes.i32_from ] : []),
|
67
|
-
[ Opcodes.call, importedFuncs.
|
62
|
+
[ Opcodes.call, importedFuncs.profileLocalSet ]
|
68
63
|
])
|
69
64
|
);
|
70
65
|
|
@@ -72,49 +67,32 @@ export const run = obj => {
|
|
72
67
|
const inst = wasm[j];
|
73
68
|
if (inst[0] === Opcodes.local_set || inst[0] === Opcodes.local_tee) {
|
74
69
|
wasm.splice(j + 1, 0,
|
70
|
+
number(id, Valtype.i32),
|
75
71
|
number(inst[1], Valtype.i32),
|
76
72
|
[ Opcodes.local_get, inst[1] ],
|
77
73
|
...(invLocals[inst[1]].type !== Valtype.f64 ? [ Opcodes.i32_from ] : []),
|
78
|
-
[ Opcodes.call, importedFuncs.
|
74
|
+
[ Opcodes.call, importedFuncs.profileLocalSet ]
|
79
75
|
);
|
80
76
|
}
|
81
77
|
}
|
82
78
|
}
|
83
79
|
|
84
|
-
|
80
|
+
localData = funcs.map(x => new Array(Object.keys(x.locals).length).fill(0).map(() => []));
|
85
81
|
|
86
82
|
time(0, `injected PGO logging`);
|
87
83
|
time(1, `running with PGO logging...`);
|
88
84
|
|
89
|
-
|
90
85
|
try {
|
91
86
|
obj.wasm = assemble(obj.funcs, obj.globals, obj.tags, obj.pages, obj.data, true);
|
92
87
|
|
93
88
|
Prefs._profileCompiler = Prefs.profileCompiler;
|
94
89
|
Prefs.profileCompiler = false;
|
95
90
|
|
96
|
-
const
|
97
|
-
|
98
|
-
// const pgoInd = process.argv.indexOf('--pgo');
|
99
|
-
// let args = process.argv.slice(pgoInd);
|
100
|
-
// args = args.slice(args.findIndex(x => !x.startsWith('-')) + 1);
|
101
|
-
|
102
|
-
// const str = args[ind - 1];
|
103
|
-
// if (pgoInd === -1 || !str) {
|
104
|
-
// if (Prefs.pgoLog) console.log('\nPGO warning: script was expecting arguments, please specify args to use for PGO after --pgo arg');
|
105
|
-
// return -1;
|
106
|
-
// }
|
107
|
-
|
108
|
-
// writeByteStr(exports.$, outPtr, str);
|
109
|
-
// return str.length;
|
110
|
-
return -1;
|
111
|
-
},
|
112
|
-
readFile: (pathPtr, outPtr) => {
|
113
|
-
return -1;
|
114
|
-
}
|
115
|
-
}, () => {});
|
116
|
-
|
91
|
+
const priorImports = { ...importedFuncs };
|
92
|
+
const { exports } = wrap(obj, undefined, () => {});
|
117
93
|
exports.main();
|
94
|
+
|
95
|
+
setImports(priorImports);
|
118
96
|
} catch (e) {
|
119
97
|
throw e;
|
120
98
|
}
|
@@ -242,8 +220,8 @@ export const run = obj => {
|
|
242
220
|
consts.push(number(c, valtype));
|
243
221
|
}
|
244
222
|
|
245
|
-
log += ` ${x.name}: replaced ${targets.length} locals with consts\n`;
|
246
|
-
if (targets.length > 0) Havoc.localsToConsts(wasmFunc, targets, consts, { localKeys: x.localKeys });
|
223
|
+
// log += ` ${x.name}: replaced ${targets.length} locals with consts\n`;
|
224
|
+
// if (targets.length > 0) Havoc.localsToConsts(wasmFunc, targets, consts, { localKeys: x.localKeys });
|
247
225
|
}
|
248
226
|
|
249
227
|
time(3, 'optimized using PGO data\n' + log);
|
package/compiler/wrap.js
CHANGED
@@ -481,10 +481,9 @@ export { createImport };
|
|
481
481
|
*
|
482
482
|
* @param {string} source - JavaScript source code to compile
|
483
483
|
* @param {boolean} module - If the source is a module or not (default: false)
|
484
|
-
* @param {object} customImports - Custom imports
|
485
484
|
* @param {(str: string) => void} print - Function to use for printing (used by console.log etc)
|
486
485
|
*/
|
487
|
-
export default (source, module = undefined,
|
486
|
+
export default (source, module = undefined, print = str => process.stdout.write(str)) => {
|
488
487
|
createImport('print', 1, 0, i => print(i.toString()));
|
489
488
|
createImport('printChar', 1, 0, i => print(String.fromCharCode(i)));
|
490
489
|
createImport('time', 0, 1, () => performance.now());
|
@@ -512,12 +511,6 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
512
511
|
}
|
513
512
|
});
|
514
513
|
|
515
|
-
for (const x in customImports) {
|
516
|
-
const custom = customImports[x];
|
517
|
-
// todo: make a simpler api for just js functions at some point using function.length etc
|
518
|
-
createImport(x, custom.params, custom.returns, custom.js, custom.c);
|
519
|
-
}
|
520
|
-
|
521
514
|
const times = [];
|
522
515
|
|
523
516
|
const t1 = performance.now();
|
@@ -575,6 +568,8 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
575
568
|
instance = new WebAssembly.Instance(module, {
|
576
569
|
'': Object.keys(importedFuncs).reduce((acc, y) => {
|
577
570
|
const x = importedFuncs[y];
|
571
|
+
if (!x.import) return acc;
|
572
|
+
|
578
573
|
acc[x.import] = x.js ?? (() => {});
|
579
574
|
return acc;
|
580
575
|
}, {})
|
package/fuzz/index.js
CHANGED
package/package.json
CHANGED
package/runtime/debug.js
CHANGED
@@ -109,7 +109,7 @@ createImport('profile2', 1, 0, n => {
|
|
109
109
|
});
|
110
110
|
|
111
111
|
try {
|
112
|
-
const { exports } = compile(source, undefined,
|
112
|
+
const { exports } = compile(source, undefined, s => output += s);
|
113
113
|
exports.main();
|
114
114
|
} catch (e) {
|
115
115
|
console.error(e);
|
package/runtime/index.js
CHANGED
package/runtime/profile.js
CHANGED
@@ -94,7 +94,7 @@ globalThis.compileCallback = ({ funcs }) => {
|
|
94
94
|
};
|
95
95
|
|
96
96
|
console.log('Compiling...');
|
97
|
-
const { exports } = compile(source, undefined,
|
97
|
+
const { exports } = compile(source, undefined, () => {});
|
98
98
|
|
99
99
|
// --- Execution with Progress Spinner ---
|
100
100
|
|
package/runtime/repl.js
CHANGED
@@ -95,7 +95,7 @@ const run = (source, _context, _filename, callback, run = true) => {
|
|
95
95
|
|
96
96
|
let shouldPrint = !prev;
|
97
97
|
try {
|
98
|
-
const { exports, pages } = compile(toRun, undefined,
|
98
|
+
const { exports, pages } = compile(toRun, undefined, str => {
|
99
99
|
if (shouldPrint) process.stdout.write(str);
|
100
100
|
if (str === '-4919') shouldPrint = true;
|
101
101
|
});
|
package/wow.js
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
(false ? 42 : 42) + (false ? null : 'G9vBsCA4GzkqlZN')
|