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.
@@ -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, '__Porffor_TodoError', msg, expectsValue);
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)) idx = funcIndex[name];
2275
- else if (Object.hasOwn(importedFuncs, name)) idx = importedFuncs[name];
2276
- else if (Object.hasOwn(builtinFuncs, name)) {
2277
- if (builtinFuncs[name].floatOnly && valtype !== 'f64') throw new Error(`Cannot use built-in ${unhackName(name)} with integer valtype`);
2278
- if (decl._new && !builtinFuncs[name].constr) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a constructor`, true);
2279
-
2280
- includeBuiltin(scope, name);
2281
- idx = funcIndex[name];
2282
- } else if (Object.hasOwn(internalConstrs, name)) {
2283
- if (decl._new && internalConstrs[name].notConstr) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a constructor`, true);
2284
- return internalConstrs[name].generate(scope, decl, _global, _name);
2285
- } else if (!decl._new && name && name.startsWith('__Porffor_wasm_')) {
2286
- const wasmOps = {
2287
- // pointer, align, offset
2288
- i32_load: { imms: 2, args: [ true ], returns: 1 },
2289
- // pointer, value, align, offset
2290
- i32_store: { imms: 2, args: [ true, true ], returns: 0 },
2291
- // pointer, align, offset
2292
- i32_load8_u: { imms: 2, args: [ true ], returns: 1 },
2293
- // pointer, value, align, offset
2294
- i32_store8: { imms: 2, args: [ true, true ], returns: 0 },
2295
- // pointer, align, offset
2296
- i32_load16_u: { imms: 2, args: [ true ], returns: 1 },
2297
- // pointer, value, align, offset
2298
- i32_store16: { imms: 2, args: [ true, true ], returns: 0 },
2299
-
2300
- // pointer, align, offset
2301
- f64_load: { imms: 2, args: [ true ], returns: 0 }, // 0 due to not i32
2302
- // pointer, value, align, offset
2303
- f64_store: { imms: 2, args: [ true, false ], returns: 0 },
2304
-
2305
- // value
2306
- i32_const: { imms: 1, args: [], returns: 0 },
2307
-
2308
- // dst, src, size, _, _
2309
- memory_copy: { imms: 2, args: [ true, true, true ], returns: 0 }
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
- const opName = name.slice('__Porffor_wasm_'.length);
2318
+ const opName = name.slice('__Porffor_wasm_'.length);
2313
2319
 
2314
- if (wasmOps[opName]) {
2315
- const op = wasmOps[opName];
2320
+ if (wasmOps[opName]) {
2321
+ const op = wasmOps[opName];
2316
2322
 
2317
- const argOut = [];
2318
- for (let i = 0; i < op.args.length; i++) {
2319
- if (!op.args[i]) globalThis.noi32F64CallConv = true;
2323
+ const argOut = [];
2324
+ for (let i = 0; i < op.args.length; i++) {
2325
+ if (!op.args[i]) globalThis.noi32F64CallConv = true;
2320
2326
 
2321
- argOut.push(
2322
- ...generate(scope, decl.arguments[i]),
2323
- ...(op.args[i] ? [ Opcodes.i32_to ] : [])
2324
- );
2327
+ argOut.push(
2328
+ ...generate(scope, decl.arguments[i]),
2329
+ ...(op.args[i] ? [ Opcodes.i32_to ] : [])
2330
+ );
2325
2331
 
2326
- globalThis.noi32F64CallConv = false;
2327
- }
2332
+ globalThis.noi32F64CallConv = false;
2333
+ }
2328
2334
 
2329
- // literals only
2330
- const imms = decl.arguments.slice(op.args.length).map(x => x.value);
2335
+ // literals only
2336
+ const imms = decl.arguments.slice(op.args.length).map(x => x.value);
2331
2337
 
2332
- let opcode = Opcodes[opName];
2333
- if (!Array.isArray(opcode)) opcode = [ opcode ];
2338
+ let opcode = Opcodes[opName];
2339
+ if (!Array.isArray(opcode)) opcode = [ opcode ];
2334
2340
 
2335
- return [
2336
- ...argOut,
2337
- [ ...opcode, ...imms ],
2338
- ...(new Array(op.returns).fill(Opcodes.i32_from))
2339
- ];
2340
- }
2341
- } else {
2342
- if (!Prefs.indirectCalls) return internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, true);
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
- funcs.table = true;
2345
- scope.table = true;
2350
+ funcs.table = true;
2351
+ scope.table = true;
2346
2352
 
2347
- let args = decl.arguments;
2348
- const wrapperArgc = Prefs.indirectWrapperArgc ?? 8;
2349
- if (args.length < wrapperArgc) {
2350
- args = args.concat(new Array(wrapperArgc - args.length).fill(DEFAULT_VALUE()));
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
- for (let i = 0; i < args.length; i++) {
2354
- const arg = args[i];
2355
- out = out.concat(generate(scope, arg), valtypeBinary === Valtype.i32 && scope.locals[arg.name]?.type !== Valtype.f64 ? [ [ Opcodes.f64_convert_i32_s ] ] : [], getNodeType(scope, arg));
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
- let knownThis = undefined, getCallee = undefined;
2359
- const calleeLocal = localTmp(scope, '#indirect_callee');
2364
+ let knownThis = undefined, getCallee = undefined;
2365
+ const calleeLocal = localTmp(scope, '#indirect_callee');
2360
2366
 
2361
- // hack: this should be more thorough, Function.bind, etc
2362
- if (decl.callee.type === 'MemberExpression' && !decl._new) {
2363
- const thisLocal = localTmp(scope, '#indirect_caller');
2364
- const thisLocalType = localTmp(scope, '#indirect_caller#type', Valtype.i32);
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
- knownThis = [
2367
- [ Opcodes.local_get, thisLocal ],
2368
- [ Opcodes.local_get, thisLocalType ]
2369
- ];
2370
- getCallee = [
2371
- ...generate(scope, decl.callee.object),
2372
- [ Opcodes.local_set, thisLocal ],
2373
- ...getNodeType(scope, decl.callee.object),
2374
- [ Opcodes.local_set, thisLocalType ],
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
- ...generate(scope, {
2377
- type: 'MemberExpression',
2378
- object: { type: 'Identifier', name: '#indirect_caller' },
2379
- property: decl.callee.property,
2380
- computed: decl.callee.computed,
2381
- optional: decl.callee.optional
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
- let callee = decl.callee, callAsNew = decl._new;
2387
- if (callee.type === 'Super') {
2388
- // call super constructor with direct super() call
2389
- callee = getObjProp(callee, 'constructor');
2390
- callAsNew = true;
2391
- knownThis = [
2392
- ...generate(scope, { type: 'ThisExpression' }),
2393
- ...getNodeType(scope, { type: 'ThisExpression' })
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
- const newTargetWasm = decl._newTargetWasm ?? createNewTarget(scope, decl, [
2398
- [ Opcodes.local_get, calleeLocal ]
2399
- ], callAsNew);
2400
- const thisWasm = decl._thisWasm ?? knownThis ?? createThisArg(scope, decl);
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
- return [
2403
- ...(getCallee ? getCallee : generate(scope, callee)),
2404
- [ Opcodes.local_set, calleeLocal ],
2408
+ return [
2409
+ ...(getCallee ? getCallee : generate(scope, callee)),
2410
+ [ Opcodes.local_set, calleeLocal ],
2405
2411
 
2406
- ...typeSwitch(scope, getNodeType(scope, callee), {
2407
- [TYPES.function]: () => [
2408
- ...forceDuoValtype(scope, newTargetWasm, Valtype.f64),
2409
- ...forceDuoValtype(scope, thisWasm, Valtype.f64),
2410
- ...out,
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
- [ Opcodes.local_get, calleeLocal ],
2413
- Opcodes.i32_to_u,
2414
- [ Opcodes.call_indirect, args.length + 2, 0 ],
2415
- ...setLastType(scope)
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
- default: internalThrow(scope, 'TypeError', `${unhackName(name)} is not a function`, Valtype.f64)
2419
- }, Valtype.f64),
2420
- ...(valtypeBinary === Valtype.i32 && scope.returns[0] !== Valtype.f64 ? [ [ Opcodes.f64_convert_i32_s ] ] : [])
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
  },
@@ -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('__Porffor_TodoError');
90
+ registerInternalType('TodoError');
91
91
 
92
92
  registerInternalType('__Porffor_Generator');
93
93
  registerInternalType('__Porffor_AsyncGenerator');
@@ -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.__porffor_todoerror: {
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(bold(`compiled in ${times[0].toFixed(2)}ms`));
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
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "porffor",
3
3
  "description": "a basic experimental wip aot optimizing js -> wasm engine/compiler/runtime in js",
4
- "version": "0.48.3",
4
+ "version": "0.48.5",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {},
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';
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`);