porffor 0.48.3 → 0.48.5
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 +105 -132
- package/compiler/builtins/__internal_object.ts +2 -5
- package/compiler/builtins/array.ts +2 -2
- package/compiler/builtins/date.ts +1 -2
- package/compiler/builtins/error.js +7 -11
- package/compiler/builtins/function.ts +2 -6
- package/compiler/builtins/json.ts +11 -14
- package/compiler/builtins/object.ts +10 -27
- package/compiler/builtins/promise.ts +4 -17
- package/compiler/builtins/set.ts +1 -5
- package/compiler/builtins/weakref.ts +1 -5
- package/compiler/builtins/z_map.ts +1 -5
- package/compiler/builtins/z_weakmap.ts +1 -5
- package/compiler/builtins/z_weakset.ts +1 -5
- package/compiler/builtins.js +2 -15
- package/compiler/builtins_precompiled.js +103 -97
- package/compiler/codegen.js +138 -130
- package/compiler/precompile.js +1 -1
- package/compiler/types.js +1 -1
- package/compiler/wasmSpec.js +1 -2
- package/compiler/wrap.js +2 -4
- package/package.json +1 -1
- package/runner/index.js +1 -13
package/compiler/codegen.js
CHANGED
@@ -31,7 +31,7 @@ const todo = (scope, msg, expectsValue = undefined) => {
|
|
31
31
|
throw new TodoError(msg);
|
32
32
|
|
33
33
|
case 'runtime':
|
34
|
-
return internalThrow(scope, '
|
34
|
+
return internalThrow(scope, 'TodoError', msg, expectsValue);
|
35
35
|
}
|
36
36
|
};
|
37
37
|
|
@@ -389,6 +389,8 @@ const generateIdent = (scope, decl) => {
|
|
389
389
|
if (builtinVars[name].floatOnly && valtype[0] === 'i') throw new Error(`Cannot use ${unhackName(name)} with integer valtype`);
|
390
390
|
|
391
391
|
let wasm = builtinVars[name];
|
392
|
+
if (wasm.usesImports) scope.usesImports = true;
|
393
|
+
|
392
394
|
if (typeof wasm === 'function') wasm = asmFuncToAsm(scope, wasm);
|
393
395
|
return wasm.slice();
|
394
396
|
}
|
@@ -1207,7 +1209,7 @@ const asmFuncToAsm = (scope, func) => {
|
|
1207
1209
|
});
|
1208
1210
|
};
|
1209
1211
|
|
1210
|
-
const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], data: _data = [], table = false, constr = false, hasRestArgument = false, usesTag = false, usedTypes = [] } = {}) => {
|
1212
|
+
const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTypes = [], globals: globalTypes = [], globalInits = [], returns = [], returnType, localNames = [], globalNames = [], data: _data = [], table = false, constr = false, hasRestArgument = false, usesTag = false, usesImports = false, usedTypes = [] } = {}) => {
|
1211
1213
|
if (wasm == null) { // called with no builtin
|
1212
1214
|
log.warning('codegen', `${name} has no built-in!`);
|
1213
1215
|
wasm = [];
|
@@ -1282,6 +1284,7 @@ const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTy
|
|
1282
1284
|
|
1283
1285
|
if (hasRestArgument) func.hasRestArgument = true;
|
1284
1286
|
if (usesTag) ensureTag();
|
1287
|
+
if (usesImports) func.usesImports = true;
|
1285
1288
|
|
1286
1289
|
for (const x of usedTypes) typeUsed(func, x);
|
1287
1290
|
|
@@ -2271,155 +2274,158 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2271
2274
|
}
|
2272
2275
|
|
2273
2276
|
let idx;
|
2274
|
-
if (Object.hasOwn(funcIndex, name))
|
2275
|
-
|
2276
|
-
|
2277
|
-
|
2278
|
-
|
2279
|
-
|
2280
|
-
|
2281
|
-
|
2282
|
-
|
2283
|
-
|
2284
|
-
|
2285
|
-
|
2286
|
-
|
2287
|
-
|
2288
|
-
|
2289
|
-
|
2290
|
-
|
2291
|
-
|
2292
|
-
|
2293
|
-
|
2294
|
-
|
2295
|
-
|
2296
|
-
|
2297
|
-
|
2298
|
-
|
2299
|
-
|
2300
|
-
|
2301
|
-
|
2302
|
-
|
2303
|
-
|
2304
|
-
|
2305
|
-
|
2306
|
-
|
2307
|
-
|
2308
|
-
|
2309
|
-
|
2310
|
-
|
2277
|
+
if (Object.hasOwn(funcIndex, name)) {
|
2278
|
+
idx = funcIndex[name];
|
2279
|
+
} else if (Object.hasOwn(importedFuncs, name)) {
|
2280
|
+
idx = importedFuncs[name];
|
2281
|
+
scope.usesImports = true;
|
2282
|
+
} else if (Object.hasOwn(builtinFuncs, name)) {
|
2283
|
+
if (builtinFuncs[name].floatOnly && valtype !== 'f64') throw new Error(`Cannot use built-in ${unhackName(name)} with integer valtype`);
|
2284
|
+
if (decl._new && !builtinFuncs[name].constr) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a constructor`, true);
|
2285
|
+
|
2286
|
+
includeBuiltin(scope, name);
|
2287
|
+
idx = funcIndex[name];
|
2288
|
+
} else if (Object.hasOwn(internalConstrs, name)) {
|
2289
|
+
if (decl._new && internalConstrs[name].notConstr) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a constructor`, true);
|
2290
|
+
return internalConstrs[name].generate(scope, decl, _global, _name);
|
2291
|
+
} else if (!decl._new && name && name.startsWith('__Porffor_wasm_')) {
|
2292
|
+
const wasmOps = {
|
2293
|
+
// pointer, align, offset
|
2294
|
+
i32_load: { imms: 2, args: [ true ], returns: 1 },
|
2295
|
+
// pointer, value, align, offset
|
2296
|
+
i32_store: { imms: 2, args: [ true, true ], returns: 0 },
|
2297
|
+
// pointer, align, offset
|
2298
|
+
i32_load8_u: { imms: 2, args: [ true ], returns: 1 },
|
2299
|
+
// pointer, value, align, offset
|
2300
|
+
i32_store8: { imms: 2, args: [ true, true ], returns: 0 },
|
2301
|
+
// pointer, align, offset
|
2302
|
+
i32_load16_u: { imms: 2, args: [ true ], returns: 1 },
|
2303
|
+
// pointer, value, align, offset
|
2304
|
+
i32_store16: { imms: 2, args: [ true, true ], returns: 0 },
|
2305
|
+
|
2306
|
+
// pointer, align, offset
|
2307
|
+
f64_load: { imms: 2, args: [ true ], returns: 0 }, // 0 due to not i32
|
2308
|
+
// pointer, value, align, offset
|
2309
|
+
f64_store: { imms: 2, args: [ true, false ], returns: 0 },
|
2310
|
+
|
2311
|
+
// value
|
2312
|
+
i32_const: { imms: 1, args: [], returns: 0 },
|
2313
|
+
|
2314
|
+
// dst, src, size, _, _
|
2315
|
+
memory_copy: { imms: 2, args: [ true, true, true ], returns: 0 }
|
2316
|
+
};
|
2311
2317
|
|
2312
|
-
|
2318
|
+
const opName = name.slice('__Porffor_wasm_'.length);
|
2313
2319
|
|
2314
|
-
|
2315
|
-
|
2320
|
+
if (wasmOps[opName]) {
|
2321
|
+
const op = wasmOps[opName];
|
2316
2322
|
|
2317
|
-
|
2318
|
-
|
2319
|
-
|
2323
|
+
const argOut = [];
|
2324
|
+
for (let i = 0; i < op.args.length; i++) {
|
2325
|
+
if (!op.args[i]) globalThis.noi32F64CallConv = true;
|
2320
2326
|
|
2321
|
-
|
2322
|
-
|
2323
|
-
|
2324
|
-
|
2327
|
+
argOut.push(
|
2328
|
+
...generate(scope, decl.arguments[i]),
|
2329
|
+
...(op.args[i] ? [ Opcodes.i32_to ] : [])
|
2330
|
+
);
|
2325
2331
|
|
2326
|
-
|
2327
|
-
|
2332
|
+
globalThis.noi32F64CallConv = false;
|
2333
|
+
}
|
2328
2334
|
|
2329
|
-
|
2330
|
-
|
2335
|
+
// literals only
|
2336
|
+
const imms = decl.arguments.slice(op.args.length).map(x => x.value);
|
2331
2337
|
|
2332
|
-
|
2333
|
-
|
2338
|
+
let opcode = Opcodes[opName];
|
2339
|
+
if (!Array.isArray(opcode)) opcode = [ opcode ];
|
2334
2340
|
|
2335
|
-
|
2336
|
-
|
2337
|
-
|
2338
|
-
|
2339
|
-
|
2340
|
-
|
2341
|
-
|
2342
|
-
|
2341
|
+
return [
|
2342
|
+
...argOut,
|
2343
|
+
[ ...opcode, ...imms ],
|
2344
|
+
...(new Array(op.returns).fill(Opcodes.i32_from))
|
2345
|
+
];
|
2346
|
+
}
|
2347
|
+
} else {
|
2348
|
+
if (!Prefs.indirectCalls) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true);
|
2343
2349
|
|
2344
|
-
|
2345
|
-
|
2350
|
+
funcs.table = true;
|
2351
|
+
scope.table = true;
|
2346
2352
|
|
2347
|
-
|
2348
|
-
|
2349
|
-
|
2350
|
-
|
2351
|
-
|
2353
|
+
let args = decl.arguments;
|
2354
|
+
const wrapperArgc = Prefs.indirectWrapperArgc ?? 8;
|
2355
|
+
if (args.length < wrapperArgc) {
|
2356
|
+
args = args.concat(new Array(wrapperArgc - args.length).fill(DEFAULT_VALUE()));
|
2357
|
+
}
|
2352
2358
|
|
2353
|
-
|
2354
|
-
|
2355
|
-
|
2356
|
-
|
2359
|
+
for (let i = 0; i < args.length; i++) {
|
2360
|
+
const arg = args[i];
|
2361
|
+
out = out.concat(generate(scope, arg), valtypeBinary === Valtype.i32 && scope.locals[arg.name]?.type !== Valtype.f64 ? [ [ Opcodes.f64_convert_i32_s ] ] : [], getNodeType(scope, arg));
|
2362
|
+
}
|
2357
2363
|
|
2358
|
-
|
2359
|
-
|
2364
|
+
let knownThis = undefined, getCallee = undefined;
|
2365
|
+
const calleeLocal = localTmp(scope, '#indirect_callee');
|
2360
2366
|
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2367
|
+
// hack: this should be more thorough, Function.bind, etc
|
2368
|
+
if (decl.callee.type === 'MemberExpression' && !decl._new) {
|
2369
|
+
const thisLocal = localTmp(scope, '#indirect_caller');
|
2370
|
+
const thisLocalType = localTmp(scope, '#indirect_caller#type', Valtype.i32);
|
2365
2371
|
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2374
|
-
|
2372
|
+
knownThis = [
|
2373
|
+
[ Opcodes.local_get, thisLocal ],
|
2374
|
+
[ Opcodes.local_get, thisLocalType ]
|
2375
|
+
];
|
2376
|
+
getCallee = [
|
2377
|
+
...generate(scope, decl.callee.object),
|
2378
|
+
[ Opcodes.local_set, thisLocal ],
|
2379
|
+
...getNodeType(scope, decl.callee.object),
|
2380
|
+
[ Opcodes.local_set, thisLocalType ],
|
2375
2381
|
|
2376
|
-
|
2377
|
-
|
2378
|
-
|
2379
|
-
|
2380
|
-
|
2381
|
-
|
2382
|
-
|
2383
|
-
|
2384
|
-
|
2382
|
+
...generate(scope, {
|
2383
|
+
type: 'MemberExpression',
|
2384
|
+
object: { type: 'Identifier', name: '#indirect_caller' },
|
2385
|
+
property: decl.callee.property,
|
2386
|
+
computed: decl.callee.computed,
|
2387
|
+
optional: decl.callee.optional
|
2388
|
+
})
|
2389
|
+
];
|
2390
|
+
}
|
2385
2391
|
|
2386
|
-
|
2387
|
-
|
2388
|
-
|
2389
|
-
|
2390
|
-
|
2391
|
-
|
2392
|
-
|
2393
|
-
|
2394
|
-
|
2395
|
-
|
2392
|
+
let callee = decl.callee, callAsNew = decl._new;
|
2393
|
+
if (callee.type === 'Super') {
|
2394
|
+
// call super constructor with direct super() call
|
2395
|
+
callee = getObjProp(callee, 'constructor');
|
2396
|
+
callAsNew = true;
|
2397
|
+
knownThis = [
|
2398
|
+
...generate(scope, { type: 'ThisExpression' }),
|
2399
|
+
...getNodeType(scope, { type: 'ThisExpression' })
|
2400
|
+
];
|
2401
|
+
}
|
2396
2402
|
|
2397
|
-
|
2398
|
-
|
2399
|
-
|
2400
|
-
|
2403
|
+
const newTargetWasm = decl._newTargetWasm ?? createNewTarget(scope, decl, [
|
2404
|
+
[ Opcodes.local_get, calleeLocal ]
|
2405
|
+
], callAsNew);
|
2406
|
+
const thisWasm = decl._thisWasm ?? knownThis ?? createThisArg(scope, decl);
|
2401
2407
|
|
2402
|
-
|
2403
|
-
|
2404
|
-
|
2408
|
+
return [
|
2409
|
+
...(getCallee ? getCallee : generate(scope, callee)),
|
2410
|
+
[ Opcodes.local_set, calleeLocal ],
|
2405
2411
|
|
2406
|
-
|
2407
|
-
|
2408
|
-
|
2409
|
-
|
2410
|
-
|
2412
|
+
...typeSwitch(scope, getNodeType(scope, callee), {
|
2413
|
+
[TYPES.function]: () => [
|
2414
|
+
...forceDuoValtype(scope, newTargetWasm, Valtype.f64),
|
2415
|
+
...forceDuoValtype(scope, thisWasm, Valtype.f64),
|
2416
|
+
...out,
|
2411
2417
|
|
2412
|
-
|
2413
|
-
|
2414
|
-
|
2415
|
-
|
2416
|
-
|
2418
|
+
[ Opcodes.local_get, calleeLocal ],
|
2419
|
+
Opcodes.i32_to_u,
|
2420
|
+
[ Opcodes.call_indirect, args.length + 2, 0 ],
|
2421
|
+
...setLastType(scope)
|
2422
|
+
],
|
2417
2423
|
|
2418
|
-
|
2419
|
-
|
2420
|
-
|
2421
|
-
|
2422
|
-
|
2424
|
+
default: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, Valtype.f64)
|
2425
|
+
}, Valtype.f64),
|
2426
|
+
...(valtypeBinary === Valtype.i32 && scope.returns[0] !== Valtype.f64 ? [ [ Opcodes.f64_convert_i32_s ] ] : [])
|
2427
|
+
];
|
2428
|
+
}
|
2423
2429
|
|
2424
2430
|
const func = funcByIndex(idx);
|
2425
2431
|
|
@@ -6426,6 +6432,8 @@ const internalConstrs = {
|
|
6426
6432
|
|
6427
6433
|
__Porffor_printStatic: {
|
6428
6434
|
generate: (scope, decl) => {
|
6435
|
+
scope.usesImports = true;
|
6436
|
+
|
6429
6437
|
const str = decl.arguments[0].value;
|
6430
6438
|
return printStaticStr(str);
|
6431
6439
|
},
|
package/compiler/precompile.js
CHANGED
@@ -251,7 +251,7 @@ params:${JSON.stringify(x.params)},typedParams:1,returns:${JSON.stringify(x.retu
|
|
251
251
|
locals:${JSON.stringify(locals.slice(x.params.length).map(x => x[1].type))},localNames:${JSON.stringify(locals.map(x => x[0]))},
|
252
252
|
${usedTypes.length > 0 ? `usedTypes:${JSON.stringify(usedTypes)},` : ''}
|
253
253
|
${x.globalInits ? `globalInits:{${Object.keys(x.globalInits).map(y => `${y}:${rewriteWasm(x.globalInits[y])}`).join(',')}},` : ''}${x.data && Object.keys(x.data).length > 0 ? `data:${JSON.stringify(x.data)},` : ''}
|
254
|
-
${x.table ? `table:1,` : ''}${x.constr ? `constr:1,` : ''}${x.hasRestArgument ? `hasRestArgument:1,` : ''}${x.usesTag ? `usesTag:1,` : ''}
|
254
|
+
${x.table ? `table:1,` : ''}${x.constr ? `constr:1,` : ''}${x.hasRestArgument ? `hasRestArgument:1,` : ''}${x.usesTag ? `usesTag:1,` : ''}${x.usesImports ? `usesImports:1,` : ''}
|
255
255
|
}`.replaceAll('\n\n', '\n').replaceAll('\n\n', '\n').replaceAll('\n\n', '\n');
|
256
256
|
}).join('\n')}
|
257
257
|
}`;
|
package/compiler/types.js
CHANGED
@@ -87,7 +87,7 @@ registerInternalType('RangeError');
|
|
87
87
|
registerInternalType('EvalError');
|
88
88
|
registerInternalType('URIError');
|
89
89
|
registerInternalType('Test262Error');
|
90
|
-
registerInternalType('
|
90
|
+
registerInternalType('TodoError');
|
91
91
|
|
92
92
|
registerInternalType('__Porffor_Generator');
|
93
93
|
registerInternalType('__Porffor_AsyncGenerator');
|
package/compiler/wasmSpec.js
CHANGED
@@ -226,8 +226,7 @@ export const Opcodes = {
|
|
226
226
|
export const FuncType = 0x60;
|
227
227
|
export const Empty = 0x00;
|
228
228
|
|
229
|
-
export const Magic = [0x00, 0x61, 0x73, 0x6d];
|
230
|
-
export const ModuleVersion = [0x01, 0x00, 0x00, 0x00];
|
229
|
+
export const Magic = [ 0x00, 0x61, 0x73, 0x6d, 0x01, 0x00, 0x00, 0x00 ];
|
231
230
|
|
232
231
|
export const PageSize = 65536; // 64KiB (1024 * 8)
|
233
232
|
|
package/compiler/wrap.js
CHANGED
@@ -8,8 +8,6 @@ import './prefs.js';
|
|
8
8
|
|
9
9
|
const fs = (typeof process?.version !== 'undefined' ? (await import('node:fs')) : undefined);
|
10
10
|
|
11
|
-
const bold = x => `\u001b[1m${x}\u001b[0m`;
|
12
|
-
|
13
11
|
const checkOOB = (memory, ptr) => ptr >= memory.buffer.byteLength;
|
14
12
|
|
15
13
|
let dv;
|
@@ -315,7 +313,7 @@ ${flags & 0b0001 ? ` get func idx: ${get}
|
|
315
313
|
case TYPES.evalerror:
|
316
314
|
case TYPES.urierror:
|
317
315
|
case TYPES.test262error:
|
318
|
-
case TYPES.
|
316
|
+
case TYPES.todoerror: {
|
319
317
|
const obj = porfToJSValue({ memory, funcs, pages }, value, TYPES.object);
|
320
318
|
const err = new (globalThis[TYPE_NAMES[type]] ?? Error)(obj.message);
|
321
319
|
|
@@ -352,7 +350,7 @@ export default (source, module = undefined, customImports = {}, print = str => p
|
|
352
350
|
// fs.writeFileSync('out.wasm', Buffer.from(wasm));
|
353
351
|
|
354
352
|
times.push(performance.now() - t1);
|
355
|
-
if (Prefs.profileCompiler && !globalThis.onProgress) console.log(
|
353
|
+
if (Prefs.profileCompiler && !globalThis.onProgress) console.log(`\u001b[1mcompiled in ${times[0].toFixed(2)}ms\u001b[0m`);
|
356
354
|
|
357
355
|
const printDecomp = (middleIndex, func, funcs, globals, exceptions) => {
|
358
356
|
console.log(`\x1B[35m\x1B[1mporffor backtrace\u001b[0m`);
|
package/package.json
CHANGED
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.48.
|
3
|
+
globalThis.version = '0.48.5';
|
4
4
|
|
5
5
|
// deno compat
|
6
6
|
if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
|
@@ -9,18 +9,6 @@ if (typeof process === 'undefined' && typeof Deno !== 'undefined') {
|
|
9
9
|
|
10
10
|
const start = performance.now();
|
11
11
|
|
12
|
-
if (process.argv.includes('--compile-hints')) {
|
13
|
-
const v8 = await import('node:v8');
|
14
|
-
v8.setFlagsFromString(`--experimental-wasm-compilation-hints`);
|
15
|
-
|
16
|
-
// see also these flags:
|
17
|
-
// --experimental-wasm-branch-hinting
|
18
|
-
// --experimental-wasm-extended-const
|
19
|
-
// --experimental-wasm-inlining (?)
|
20
|
-
// --experimental-wasm-js-inlining (?)
|
21
|
-
// --experimental-wasm-return-call (on by default)
|
22
|
-
}
|
23
|
-
|
24
12
|
if (process.argv.includes('--help')) {
|
25
13
|
// description + version
|
26
14
|
console.log(`\x1B[1m\x1B[35mPorffor\x1B[0m is a JavaScript engine/runtime/compiler. \x1B[90m(${globalThis.version})\x1B[0m`);
|