porffor 0.19.9 → 0.19.11
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/error.js +1 -1
- package/compiler/builtins/symbol.ts +10 -0
- package/compiler/codegen.js +50 -14
- package/compiler/generated_builtins.js +518 -511
- package/compiler/precompile.js +71 -36
- package/compiler/wrap.js +9 -5
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/precompile.js
CHANGED
@@ -11,7 +11,7 @@ globalThis.precompile = true;
|
|
11
11
|
|
12
12
|
const argv = process.argv.slice();
|
13
13
|
|
14
|
-
const compile = async (file,
|
14
|
+
const compile = async (file, _funcs) => {
|
15
15
|
let source = fs.readFileSync(file, 'utf8');
|
16
16
|
let first = source.slice(0, source.indexOf('\n'));
|
17
17
|
|
@@ -32,6 +32,7 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
32
32
|
|
33
33
|
const allocated = new Set();
|
34
34
|
|
35
|
+
const main = funcs.find(x => x.name === 'main');
|
35
36
|
const exports = funcs.filter(x => x.export && x.name !== 'main');
|
36
37
|
for (const x of exports) {
|
37
38
|
if (x.data) {
|
@@ -54,41 +55,65 @@ const compile = async (file, [ _funcs, _globals ]) => {
|
|
54
55
|
return acc;
|
55
56
|
}, {});
|
56
57
|
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
58
|
+
const rewriteWasm = (x, wasm, rewriteLocals = false) => {
|
59
|
+
for (let i = 0; i < wasm.length; i++) {
|
60
|
+
const y = wasm[i];
|
61
|
+
const n = wasm[i + 1];
|
62
|
+
if (y[0] === Opcodes.call) {
|
63
|
+
const f = funcs.find(x => x.index === y[1]);
|
64
|
+
if (!f) continue;
|
65
|
+
|
66
|
+
y[1] = f.name;
|
67
|
+
}
|
68
|
+
|
69
|
+
if (y[0] === Opcodes.global_get || y[0] === Opcodes.global_set) {
|
70
|
+
const global = Object.values(globals).findIndex(x => x.idx === y[1]);
|
71
|
+
const name = Object.keys(globals)[global];
|
72
|
+
const type = globals[name].type;
|
73
|
+
y.splice(0, 10, 'global', y[0], name, type);
|
74
|
+
|
75
|
+
if (!x.globalInits) {
|
76
|
+
x.globalInits = { ...main.globalInits };
|
77
|
+
for (const z in x.globalInits) {
|
78
|
+
rewriteWasm(main, x.globalInits[z], true);
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
|
83
|
+
if (rewriteLocals && (y[0] === Opcodes.local_get || y[0] === Opcodes.local_set || y[0] === Opcodes.local_tee)) {
|
84
|
+
const local = Object.values(x.locals).findIndex(x => x.idx === y[1]);
|
85
|
+
const name = Object.keys(x.locals)[local];
|
86
|
+
const type = x.locals[name].type;
|
87
|
+
y.splice(1, 10, 'local', name, type);
|
88
|
+
}
|
89
|
+
|
90
|
+
if (y[0] === Opcodes.const && (n[0] === Opcodes.local_set || n[0] === Opcodes.local_tee)) {
|
91
|
+
const l = locals[n[1]];
|
92
|
+
if (!l) continue;
|
93
|
+
if (![TYPES.string, TYPES.array, TYPES.bytestring].includes(l.metadata?.type)) continue;
|
94
|
+
if (!x.pages) continue;
|
95
|
+
|
96
|
+
const pageName = [...x.pages.keys()].find(z => z.endsWith(l.name));
|
97
|
+
if (!pageName || allocated.has(pageName)) continue;
|
98
|
+
allocated.add(pageName);
|
99
|
+
|
100
|
+
y.splice(0, 10, 'alloc', pageName, x.pages.get(pageName).type, valtypeBinary);
|
101
|
+
}
|
102
|
+
|
103
|
+
if (y[0] === Opcodes.i32_const && n[0] === Opcodes.throw) {
|
104
|
+
const id = y[1];
|
105
|
+
y.splice(0, 10, 'throw', exceptions[id].constructor, exceptions[id].message);
|
106
|
+
|
107
|
+
// remove throw inst
|
108
|
+
wasm.splice(i + 1, 1);
|
109
|
+
}
|
78
110
|
}
|
111
|
+
};
|
79
112
|
|
80
|
-
|
81
|
-
const id = y[1];
|
82
|
-
y.splice(0, 10, 'throw', exceptions[id].constructor, exceptions[id].message);
|
83
|
-
|
84
|
-
// remove throw inst
|
85
|
-
x.wasm.splice(i + 1, 1);
|
86
|
-
}
|
87
|
-
}
|
113
|
+
rewriteWasm(x, x.wasm);
|
88
114
|
}
|
89
115
|
|
90
116
|
_funcs.push(...exports);
|
91
|
-
_globals.push(...Object.values(globals));
|
92
117
|
};
|
93
118
|
|
94
119
|
const precompile = async () => {
|
@@ -96,14 +121,14 @@ const precompile = async () => {
|
|
96
121
|
|
97
122
|
const dir = join(__dirname, 'builtins');
|
98
123
|
|
99
|
-
let funcs = []
|
124
|
+
let funcs = [];
|
100
125
|
for (const file of fs.readdirSync(dir)) {
|
101
126
|
if (file.endsWith('.d.ts')) continue;
|
102
127
|
|
103
128
|
console.log(`${' '.repeat(12)}${file}`);
|
104
129
|
|
105
130
|
const t = performance.now();
|
106
|
-
await compile(join(dir, file),
|
131
|
+
await compile(join(dir, file), funcs);
|
107
132
|
|
108
133
|
console.log(`\u001b[A${' '.repeat(100)}\r\u001b[90m${`[${(performance.now() - t).toFixed(2)}ms]`.padEnd(12, ' ')}\u001b[0m\u001b[92m${file}\u001b[0m`);
|
109
134
|
}
|
@@ -113,13 +138,23 @@ import { number } from './embedding.js';
|
|
113
138
|
|
114
139
|
export const BuiltinFuncs = function() {
|
115
140
|
${funcs.map(x => {
|
116
|
-
const
|
141
|
+
const rewriteWasm = wasm => {
|
142
|
+
const str = JSON.stringify(wasm.filter(x => x.length && x[0] != null))
|
143
|
+
.replace(/\["alloc","(.*?)","(.*?)",(.*?)\]/g, (_, reason, type, valtype) => `...number(allocPage(scope, '${reason}', '${type}') * pageSize, ${valtype})`)
|
144
|
+
.replace(/\["global",(.*?),"(.*?)",(.*?)\]/g, (_, opcode, name, valtype) => `...glbl(${opcode}, '${name}', ${valtype})`)
|
145
|
+
.replace(/\"local","(.*?)",(.*?)\]/g, (_, name, valtype) => `loc('${name}', ${valtype})]`)
|
146
|
+
.replace(/\[16,"(.*?)"]/g, (_, name) => `[16, builtin('${name}')]`)
|
147
|
+
.replace(/\["throw","(.*?)","(.*?)"\]/g, (_, constructor, message) => `...internalThrow(scope, '${constructor}', \`${message}\`)`);
|
148
|
+
|
149
|
+
return `(scope, {${`${str.includes('allocPage(') ? 'allocPage,' : ''}${str.includes('glbl(') ? 'glbl,' : ''}${str.includes('loc(') ? 'loc,' : ''}${str.includes('builtin(') ? 'builtin,' : ''}${str.includes('internalThrow(') ? 'internalThrow,' : ''}`.slice(0, -1)}}) => ` + str;
|
150
|
+
};
|
151
|
+
|
117
152
|
return ` this.${x.name} = {
|
118
|
-
wasm:
|
153
|
+
wasm: ${rewriteWasm(x.wasm)},
|
119
154
|
params: ${JSON.stringify(x.params)}, typedParams: 1,
|
120
155
|
returns: ${JSON.stringify(x.returns)}, ${x.returnType != null ? `returnType: ${JSON.stringify(x.returnType)}` : 'typedReturns: 1'},
|
121
156
|
locals: ${JSON.stringify(Object.values(x.locals).slice(x.params.length).map(x => x.type))}, localNames: ${JSON.stringify(Object.keys(x.locals))},
|
122
|
-
${x.data && x.data.length > 0 ? ` data: [${x.data.map(x => `[${x.offset ?? 'null'},[${x.bytes.join(',')}]]`).join(',')}],` : ''}
|
157
|
+
${x.globalInits ? ` globalInits: {${Object.keys(x.globalInits).map(y => `${y}: ${rewriteWasm(x.globalInits[y])}`).join(',')}},\n` : ''}${x.data && x.data.length > 0 ? ` data: [${x.data.map(x => `[${x.offset ?? 'null'},[${x.bytes.join(',')}]]`).join(',')}],` : ''}
|
123
158
|
${x.table ? ` table: 1,` : ''}${x.constr ? ` constr: 1,` : ''}${x.hasRestArgument ? ` hasRestArgument: 1,` : ''}
|
124
159
|
};`.replaceAll('\n\n', '\n').replaceAll('\n\n', '\n').replaceAll('\n\n', '\n');
|
125
160
|
}).join('\n')}
|
package/compiler/wrap.js
CHANGED
@@ -114,9 +114,10 @@ const porfToJSValue = ({ memory, funcs, pages }, value, type) => {
|
|
114
114
|
}
|
115
115
|
|
116
116
|
case TYPES.symbol: {
|
117
|
-
const
|
118
|
-
if (!
|
117
|
+
const page = pages.get('bytestring: __Porffor_symbol_descStore/ptr');
|
118
|
+
if (!page) return Symbol();
|
119
119
|
|
120
|
+
const descStore = page.ind * pageSize;
|
120
121
|
const offset = descStore + 4 + ((value - 1) * 9);
|
121
122
|
|
122
123
|
const v = read(Float64Array, memory, offset, 1)[0];
|
@@ -233,12 +234,15 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
233
234
|
|
234
235
|
const printDecomp = (middleIndex, func, funcs, globals, exceptions) => {
|
235
236
|
console.log(`\x1B[35m\x1B[1mporffor backtrace\u001b[0m`);
|
236
|
-
|
237
|
+
|
238
|
+
const strParams = func.params.map(v => invValtype[v]);
|
239
|
+
const strReturns = func.returns.map(v => invValtype[v]);
|
240
|
+
console.log(`\x1B[1m${func.name}\x1B[0m \x1B[90m(${strParams.join(', ')}) -> (${strReturns.join(', ')})\x1B[0m`);
|
237
241
|
|
238
242
|
const surrounding = Prefs.backtraceSurrounding ?? 5;
|
239
243
|
let min = middleIndex - surrounding;
|
240
244
|
let max = middleIndex + surrounding + 1;
|
241
|
-
if (Prefs.
|
245
|
+
if (Prefs.backtraceFunc || middleIndex == -1) {
|
242
246
|
min = 0;
|
243
247
|
max = func.wasm.length;
|
244
248
|
}
|
@@ -378,7 +382,7 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
378
382
|
if (!process.argv.includes('-i')) throw e;
|
379
383
|
if (!(e instanceof WebAssembly.CompileError)) throw e;
|
380
384
|
|
381
|
-
const funcInd = parseInt(e.message.match(/function #([0-9]+)
|
385
|
+
const funcInd = parseInt(e.message.match(/function #([0-9]+)/)?.[1]);
|
382
386
|
const blobOffset = parseInt(e.message.split('@')?.[1]);
|
383
387
|
|
384
388
|
backtrace(funcInd, blobOffset);
|
package/package.json
CHANGED