porffor 0.16.0-a2e115b05 → 0.16.0-a7bc359af
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 +1 -1
- package/compiler/assemble.js +5 -4
- package/compiler/builtins.js +2 -2
- package/compiler/codegen.js +15 -29
- package/compiler/cyclone.js +535 -0
- package/compiler/decompile.js +3 -1
- package/compiler/havoc.js +93 -0
- package/compiler/index.js +89 -6
- package/compiler/opt.js +1 -37
- package/compiler/parse.js +1 -1
- package/compiler/pgo.js +207 -0
- package/compiler/precompile.js +3 -1
- package/compiler/prefs.js +6 -1
- package/compiler/wrap.js +53 -12
- package/no_pgo.txt +923 -0
- package/package.json +3 -5
- package/pgo.txt +916 -0
- package/runner/index.js +21 -11
- /package/runner/{profiler.js → profile.js} +0 -0
package/CONTRIBUTING.md
CHANGED
@@ -26,7 +26,7 @@ You can also swap out `node` in the alias to use another runtime like Deno (`den
|
|
26
26
|
|
27
27
|
### Precompile
|
28
28
|
|
29
|
-
**If you update any file inside `compiler/builtins` you will need to do this for it to update inside Porffor otherwise your changes will have no effect.** Run
|
29
|
+
**If you update any file inside `compiler/builtins` you will need to do this for it to update inside Porffor otherwise your changes will have no effect.** Run `./porf precompile` to precompile. It may error during this, if so, you might have an error in your code or there could be a compiler error with Porffor (feel free to ask for help as soon as you encounter any errors with it).
|
30
30
|
|
31
31
|
<br>
|
32
32
|
|
package/compiler/assemble.js
CHANGED
@@ -21,7 +21,7 @@ const chHint = (topTier, baselineTier, strategy) => {
|
|
21
21
|
return (strategy | (baselineTier << 2) | (topTier << 4));
|
22
22
|
};
|
23
23
|
|
24
|
-
export default (funcs, globals, tags, pages, data, flags) => {
|
24
|
+
export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) => {
|
25
25
|
const types = [], typeCache = {};
|
26
26
|
|
27
27
|
const optLevel = parseInt(process.argv.find(x => x.startsWith('-O'))?.[2] ?? 1);
|
@@ -44,7 +44,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
44
44
|
|
45
45
|
let importFuncs = [];
|
46
46
|
|
47
|
-
if (optLevel < 1 || !Prefs.treeshakeWasmImports) {
|
47
|
+
if (optLevel < 1 || !Prefs.treeshakeWasmImports || noTreeshake) {
|
48
48
|
importFuncs = importedFuncs;
|
49
49
|
} else {
|
50
50
|
let imports = new Map();
|
@@ -94,7 +94,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
94
94
|
|
95
95
|
const importSection = importFuncs.length === 0 ? [] : createSection(
|
96
96
|
Section.import,
|
97
|
-
encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(
|
97
|
+
encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(typeof x.params === 'object' ? x.params : new Array(x.params).fill(valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
|
98
98
|
);
|
99
99
|
|
100
100
|
const funcSection = createSection(
|
@@ -116,7 +116,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
116
116
|
] ])
|
117
117
|
);
|
118
118
|
|
119
|
-
if (pages.has('func argc lut')) {
|
119
|
+
if (pages.has('func argc lut') && !data.addedFuncArgcLut) {
|
120
120
|
// generate func argc lut data
|
121
121
|
const bytes = [];
|
122
122
|
for (let i = 0; i < funcs.length; i++) {
|
@@ -128,6 +128,7 @@ export default (funcs, globals, tags, pages, data, flags) => {
|
|
128
128
|
offset: pages.get('func argc lut').ind * pageSize,
|
129
129
|
bytes
|
130
130
|
});
|
131
|
+
data.addedFuncArgcLut = true;
|
131
132
|
}
|
132
133
|
|
133
134
|
// const t0 = performance.now();
|
package/compiler/builtins.js
CHANGED
@@ -32,13 +32,13 @@ export const importedFuncs = [
|
|
32
32
|
{
|
33
33
|
name: 'profile1',
|
34
34
|
import: 'y',
|
35
|
-
params:
|
35
|
+
params: [ Valtype.i32 ],
|
36
36
|
returns: 0
|
37
37
|
},
|
38
38
|
{
|
39
39
|
name: 'profile2',
|
40
40
|
import: 'z',
|
41
|
-
params:
|
41
|
+
params: [ Valtype.i32 ],
|
42
42
|
returns: 0
|
43
43
|
},
|
44
44
|
{
|
package/compiler/codegen.js
CHANGED
@@ -1807,7 +1807,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1807
1807
|
f64_store: { imms: 2, args: [ true, false ], returns: 0 },
|
1808
1808
|
|
1809
1809
|
// value
|
1810
|
-
i32_const: { imms: 1, args: [], returns:
|
1810
|
+
i32_const: { imms: 1, args: [], returns: 0 },
|
1811
1811
|
};
|
1812
1812
|
|
1813
1813
|
const opName = name.slice('__Porffor_wasm_'.length);
|
@@ -1999,8 +1999,8 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
1999
1999
|
}
|
2000
2000
|
|
2001
2001
|
if (valtypeBinary !== Valtype.i32 && (
|
2002
|
-
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32)
|
2003
|
-
(importedFuncs[name] && name.startsWith('profile'))
|
2002
|
+
(builtinFuncs[name] && builtinFuncs[name].params[i * (typedParams ? 2 : 1)] === Valtype.i32)
|
2003
|
+
// (importedFuncs[name] && name.startsWith('profile'))
|
2004
2004
|
)) {
|
2005
2005
|
out.push(Opcodes.i32_to);
|
2006
2006
|
}
|
@@ -2115,7 +2115,6 @@ const brTable = (input, bc, returns) => {
|
|
2115
2115
|
}
|
2116
2116
|
|
2117
2117
|
for (let i = 0; i < count; i++) {
|
2118
|
-
// if (i === 0) out.push([ Opcodes.block, returns, 'br table start' ]);
|
2119
2118
|
if (i === 0) out.push([ Opcodes.block, returns ]);
|
2120
2119
|
else out.push([ Opcodes.block, Blocktype.void ]);
|
2121
2120
|
}
|
@@ -2149,10 +2148,8 @@ const brTable = (input, bc, returns) => {
|
|
2149
2148
|
[ Opcodes.br_table, ...encodeVector(table), 0 ]
|
2150
2149
|
);
|
2151
2150
|
|
2152
|
-
//
|
2153
|
-
// (
|
2154
|
-
// dm me and if you are correct and the first person
|
2155
|
-
// I will somehow shout you out or something
|
2151
|
+
// sort the wrong way and then reverse
|
2152
|
+
// so strings ('default') are at the start before any numbers
|
2156
2153
|
const orderedBc = keys.sort((a, b) => b - a).reverse();
|
2157
2154
|
|
2158
2155
|
br = count - 1;
|
@@ -2178,10 +2175,10 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
|
|
2178
2175
|
return bc[known] ?? bc.default;
|
2179
2176
|
}
|
2180
2177
|
|
2181
|
-
if (Prefs.
|
2178
|
+
if (Prefs.typeswitchBrtable)
|
2182
2179
|
return brTable(type, bc, returns);
|
2183
2180
|
|
2184
|
-
const tmp = localTmp(scope, '#typeswitch_tmp', Valtype.i32);
|
2181
|
+
const tmp = localTmp(scope, '#typeswitch_tmp' + (Prefs.typeswitchUniqueTmp ? randId() : ''), Valtype.i32);
|
2185
2182
|
const out = [
|
2186
2183
|
...type,
|
2187
2184
|
[ Opcodes.local_set, tmp ],
|
@@ -2563,7 +2560,7 @@ const generateUnary = (scope, decl) => {
|
|
2563
2560
|
// * -1
|
2564
2561
|
|
2565
2562
|
if (decl.prefix && decl.argument.type === 'Literal' && typeof decl.argument.value === 'number') {
|
2566
|
-
// if
|
2563
|
+
// if -n, just return that as a const
|
2567
2564
|
return number(-1 * decl.argument.value);
|
2568
2565
|
}
|
2569
2566
|
|
@@ -2575,14 +2572,14 @@ const generateUnary = (scope, decl) => {
|
|
2575
2572
|
case '!':
|
2576
2573
|
const arg = decl.argument;
|
2577
2574
|
if (arg.type === 'UnaryExpression' && arg.operator === '!') {
|
2578
|
-
// !!x -> is x truthy
|
2575
|
+
// opt: !!x -> is x truthy
|
2579
2576
|
return truthy(scope, generate(scope, arg.argument), getNodeType(scope, arg.argument), false, false);
|
2580
2577
|
}
|
2578
|
+
|
2581
2579
|
// !=
|
2582
|
-
return falsy(scope, generate(scope,
|
2580
|
+
return falsy(scope, generate(scope, arg), getNodeType(scope, arg), false, false);
|
2583
2581
|
|
2584
2582
|
case '~':
|
2585
|
-
// todo: does not handle Infinity properly (should convert to 0) (but opt const converting saves us sometimes)
|
2586
2583
|
return [
|
2587
2584
|
...generate(scope, decl.argument),
|
2588
2585
|
Opcodes.i32_to,
|
@@ -3270,7 +3267,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
3270
3267
|
firstAssign = true;
|
3271
3268
|
|
3272
3269
|
// todo: can we just have 1 undeclared array? probably not? but this is not really memory efficient
|
3273
|
-
const uniqueName = name === '$undeclared' ? name +
|
3270
|
+
const uniqueName = name === '$undeclared' ? name + randId() : name;
|
3274
3271
|
|
3275
3272
|
let page;
|
3276
3273
|
if (Prefs.scopedPageNames) page = allocPage(scope, `${getAllocType(itemType)}: ${scope.name}/${uniqueName}`, itemType);
|
@@ -3502,7 +3499,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3502
3499
|
}
|
3503
3500
|
|
3504
3501
|
if (builtinFuncs[name]) return withType(scope, number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length), TYPES.number);
|
3505
|
-
if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params), TYPES.number);
|
3502
|
+
if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params.length ?? importedFuncs[name].params), TYPES.number);
|
3506
3503
|
if (internalConstrs[name]) return withType(scope, number(internalConstrs[name].length ?? 0), TYPES.number);
|
3507
3504
|
|
3508
3505
|
if (Prefs.fastLength) {
|
@@ -3658,7 +3655,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
3658
3655
|
});
|
3659
3656
|
};
|
3660
3657
|
|
3661
|
-
const randId = () => Math.random().toString(16).slice(
|
3658
|
+
const randId = () => Math.random().toString(16).slice(1, -2).padEnd(12, '0');
|
3662
3659
|
|
3663
3660
|
const objectHack = node => {
|
3664
3661
|
if (!node) return node;
|
@@ -3710,7 +3707,7 @@ const generateFunc = (scope, decl) => {
|
|
3710
3707
|
if (decl.async) return todo(scope, 'async functions are not supported');
|
3711
3708
|
if (decl.generator) return todo(scope, 'generator functions are not supported');
|
3712
3709
|
|
3713
|
-
const name = decl.id ? decl.id.name : `
|
3710
|
+
const name = decl.id ? decl.id.name : `anonymous${randId()}`;
|
3714
3711
|
const params = decl.params ?? [];
|
3715
3712
|
|
3716
3713
|
// TODO: share scope/locals between !!!
|
@@ -3971,19 +3968,8 @@ export default program => {
|
|
3971
3968
|
data = [];
|
3972
3969
|
currentFuncIndex = importedFuncs.length;
|
3973
3970
|
|
3974
|
-
globalThis.valtype = 'f64';
|
3975
|
-
|
3976
|
-
const valtypeOpt = process.argv.find(x => x.startsWith('--valtype='));
|
3977
|
-
if (valtypeOpt) valtype = valtypeOpt.split('=')[1];
|
3978
|
-
|
3979
|
-
globalThis.valtypeBinary = Valtype[valtype];
|
3980
|
-
|
3981
3971
|
const valtypeInd = ['i32', 'i64', 'f64'].indexOf(valtype);
|
3982
3972
|
|
3983
|
-
globalThis.pageSize = PageSize;
|
3984
|
-
const pageSizeOpt = process.argv.find(x => x.startsWith('--page-size='));
|
3985
|
-
if (pageSizeOpt) pageSize = parseInt(pageSizeOpt.split('=')[1]) * 1024;
|
3986
|
-
|
3987
3973
|
// set generic opcodes for current valtype
|
3988
3974
|
Opcodes.const = [ Opcodes.i32_const, Opcodes.i64_const, Opcodes.f64_const ][valtypeInd];
|
3989
3975
|
Opcodes.eq = [ Opcodes.i32_eq, Opcodes.i64_eq, Opcodes.f64_eq ][valtypeInd];
|