porffor 0.14.0-ec7daba95 → 0.14.0-eca486960

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.
@@ -56,14 +56,13 @@ i32.store8 0 12`;
56
56
  };
57
57
 
58
58
 
59
- // todo: this should be a getter somehow not a method
60
- export const __Set_prototype_size = (_this: Set) => {
59
+ export const __Set_prototype_size$get = (_this: Set) => {
61
60
  return Porffor.wasm.i32.load(_this, 0, 0);
62
61
  };
63
62
 
64
63
  export const __Set_prototype_values = (_this: Set) => {
65
64
  // todo: this should return an iterator not array
66
- const size: number = __Set_prototype_size(_this);
65
+ const size: number = Porffor.wasm.i32.load(_this, 0, 0);
67
66
 
68
67
  const out: any[] = __Porffor_allocate();
69
68
  for (let i: number = 0; i < size; i++) {
@@ -79,7 +78,7 @@ export const __Set_prototype_keys = (_this: Set) => {
79
78
  };
80
79
 
81
80
  export const __Set_prototype_has = (_this: Set, value: any) => {
82
- const size: number = __Set_prototype_size(_this);
81
+ const size: number = Porffor.wasm.i32.load(_this, 0, 0);
83
82
 
84
83
  for (let i: number = 0; i < size; i++) {
85
84
  if (__Porffor_set_read(_this, i) === value) return true;
@@ -89,7 +88,7 @@ export const __Set_prototype_has = (_this: Set, value: any) => {
89
88
  };
90
89
 
91
90
  export const __Set_prototype_add = (_this: Set, value: any) => {
92
- const size: number = __Set_prototype_size(_this);
91
+ const size: number = Porffor.wasm.i32.load(_this, 0, 0);
93
92
 
94
93
  // check if already in set
95
94
  for (let i: number = 0; i < size; i++) {
@@ -107,7 +106,7 @@ export const __Set_prototype_add = (_this: Set, value: any) => {
107
106
  };
108
107
 
109
108
  export const __Set_prototype_delete = (_this: Set, value: any) => {
110
- const size: number = __Set_prototype_size(_this);
109
+ const size: number = Porffor.wasm.i32.load(_this, 0, 0);
111
110
 
112
111
  // check if already in set
113
112
  for (let i: number = 0; i < size; i++) {
@@ -19,7 +19,7 @@ export const Symbol = (description: any): Symbol => {
19
19
  };
20
20
 
21
21
  // todo: this should be a getter somehow not a method
22
- export const __Symbol_prototype_description = (_this: Symbol) => {
22
+ export const __Symbol_prototype_description$get = (_this: Symbol) => {
23
23
  const description: bytestring = __Porffor_symbol_descStore(false,
24
24
  Porffor.wasm`local.get ${_this}` - 1);
25
25
  return description;
@@ -140,6 +140,9 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
140
140
  case 'ArrayExpression':
141
141
  return generateArray(scope, decl, global, name);
142
142
 
143
+ case 'ObjectExpression':
144
+ return generateObject(scope, decl, global, name);
145
+
143
146
  case 'MemberExpression':
144
147
  return generateMember(scope, decl, global, name);
145
148
 
@@ -200,19 +203,11 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
200
203
 
201
204
  __Porffor_bs: str => [
202
205
  ...makeString(scope, str, global, name, true),
203
-
204
- ...(name ? setType(scope, name, TYPES.bytestring) : [
205
- ...number(TYPES.bytestring, Valtype.i32),
206
- ...setLastType(scope)
207
- ])
206
+ ...(name ? setType(scope, name, TYPES.bytestring) : setLastType(scope, TYPES.bytestring))
208
207
  ],
209
208
  __Porffor_s: str => [
210
209
  ...makeString(scope, str, global, name, false),
211
-
212
- ...(name ? setType(scope, name, TYPES.string) : [
213
- ...number(TYPES.string, Valtype.i32),
214
- ...setLastType(scope)
215
- ])
210
+ ...(name ? setType(scope, name, TYPES.string) : setLastType(scope, TYPES.string))
216
211
  ],
217
212
  };
218
213
 
@@ -400,13 +395,11 @@ const performLogicOp = (scope, op, left, right, leftType, rightType) => {
400
395
  [ Opcodes.if, Valtype.i32 ],
401
396
  ...right,
402
397
  // note type
403
- ...rightType,
404
- ...setLastType(scope),
398
+ ...setLastType(scope, rightType),
405
399
  [ Opcodes.else ],
406
400
  [ Opcodes.local_get, localTmp(scope, 'logictmpi', Valtype.i32) ],
407
401
  // note type
408
- ...leftType,
409
- ...setLastType(scope),
402
+ ...setLastType(scope, leftType),
410
403
  [ Opcodes.end ],
411
404
  Opcodes.i32_from
412
405
  ];
@@ -419,13 +412,11 @@ const performLogicOp = (scope, op, left, right, leftType, rightType) => {
419
412
  [ Opcodes.if, valtypeBinary ],
420
413
  ...right,
421
414
  // note type
422
- ...rightType,
423
- ...setLastType(scope),
415
+ ...setLastType(scope, rightType),
424
416
  [ Opcodes.else ],
425
417
  [ Opcodes.local_get, localTmp(scope, 'logictmp') ],
426
418
  // note type
427
- ...leftType,
428
- ...setLastType(scope),
419
+ ...setLastType(scope, leftType),
429
420
  [ Opcodes.end ]
430
421
  ];
431
422
  };
@@ -1194,9 +1185,10 @@ const getLastType = scope => {
1194
1185
  return [ [ Opcodes.local_get, localTmp(scope, '#last_type', Valtype.i32) ] ];
1195
1186
  };
1196
1187
 
1197
- const setLastType = scope => {
1198
- return [ [ Opcodes.local_set, localTmp(scope, '#last_type', Valtype.i32) ] ];
1199
- };
1188
+ const setLastType = (scope, type = []) => [
1189
+ ...(typeof type === 'number' ? number(type, Valtype.i32) : type),
1190
+ [ Opcodes.local_set, localTmp(scope, '#last_type', Valtype.i32) ]
1191
+ ];
1200
1192
 
1201
1193
  const getNodeType = (scope, node) => {
1202
1194
  const ret = (() => {
@@ -1352,22 +1344,27 @@ const getNodeType = (scope, node) => {
1352
1344
  }
1353
1345
 
1354
1346
  if (node.type === 'MemberExpression') {
1355
- // hack: if something.name, string type
1356
- if (node.property.name === 'name') {
1357
- if (hasFuncWithName(node.object.name)) {
1358
- return TYPES.bytestring;
1359
- } else {
1360
- return TYPES.undefined;
1361
- }
1347
+ const name = node.property.name;
1348
+
1349
+ if (name === 'length') {
1350
+ if (hasFuncWithName(node.object.name)) return TYPES.number;
1351
+ if (Prefs.fastLength) return TYPES.number;
1362
1352
  }
1363
1353
 
1364
- // hack: if something.length, number type
1365
- if (node.property.name === 'length') return TYPES.number;
1366
1354
 
1367
- // ts hack
1368
- if (scope.locals[node.object.name]?.metadata?.type === TYPES.string) return TYPES.string;
1369
- if (scope.locals[node.object.name]?.metadata?.type === TYPES.bytestring) return TYPES.bytestring;
1370
- if (scope.locals[node.object.name]?.metadata?.type === TYPES.array) return TYPES.number;
1355
+ const objectKnownType = knownType(scope, getNodeType(scope, node.object));
1356
+ if (objectKnownType != null) {
1357
+ if (name === 'length') {
1358
+ if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(objectKnownType)) return TYPES.number;
1359
+ else return TYPES.undefined;
1360
+ }
1361
+
1362
+ if (node.computed) {
1363
+ if (objectKnownType === TYPES.string) return TYPES.string;
1364
+ if (objectKnownType === TYPES.bytestring) return TYPES.bytestring;
1365
+ if (objectKnownType === TYPES.array) return TYPES.number;
1366
+ }
1367
+ }
1371
1368
 
1372
1369
  if (scope.locals['#last_type']) return getLastType(scope);
1373
1370
 
@@ -1561,16 +1558,10 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1561
1558
  out.splice(out.length - 1, 1);
1562
1559
 
1563
1560
  const finalStatement = parsed.body[parsed.body.length - 1];
1564
- out.push(
1565
- ...getNodeType(scope, finalStatement),
1566
- ...setLastType(scope)
1567
- );
1561
+ out.push(...setLastType(scope, getNodeType(scope, finalStatement)));
1568
1562
  } else if (countLeftover(out) === 0) {
1569
1563
  out.push(...number(UNDEFINED));
1570
- out.push(
1571
- ...number(TYPES.undefined, Valtype.i32),
1572
- ...setLastType(scope)
1573
- );
1564
+ out.push(...setLastType(scope, TYPES.undefined));
1574
1565
  }
1575
1566
 
1576
1567
  // if (lastInst && lastInst[0] === Opcodes.drop) {
@@ -1622,8 +1613,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1622
1613
  [ Opcodes.call, idx ],
1623
1614
  Opcodes.i32_from_u,
1624
1615
 
1625
- ...number(TYPES.boolean, Valtype.i32),
1626
- ...setLastType(scope)
1616
+ ...setLastType(scope, TYPES.boolean)
1627
1617
  ];
1628
1618
  }
1629
1619
 
@@ -1695,9 +1685,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1695
1685
  if (protoFunc.noArgRetLength && decl.arguments.length === 0) {
1696
1686
  protoBC[x] = [
1697
1687
  ...RTArrayUtil.getLength(getPointer),
1698
-
1699
- ...number(TYPES.number, Valtype.i32),
1700
- ...setLastType(scope)
1688
+ ...setLastType(scope, TYPES.number)
1701
1689
  ];
1702
1690
  continue;
1703
1691
  }
@@ -1730,9 +1718,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1730
1718
  protoBC[x] = [
1731
1719
  [ Opcodes.block, unusedValue && optUnused ? Blocktype.void : valtypeBinary ],
1732
1720
  ...protoOut,
1733
-
1734
- ...number(protoFunc.returnType ?? TYPES.number, Valtype.i32),
1735
- ...setLastType(scope),
1721
+ ...setLastType(scope, protoFunc.returnType ?? TYPES.number),
1736
1722
  [ Opcodes.end ]
1737
1723
  ];
1738
1724
  }
@@ -1901,6 +1887,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
1901
1887
  const arg = args[i];
1902
1888
  out = out.concat(generate(scope, arg));
1903
1889
 
1890
+ // todo: this should be used instead of the too many args thing above (by removing that)
1904
1891
  if (i >= paramCount) {
1905
1892
  // over param count of func, drop arg
1906
1893
  out.push([ Opcodes.drop ]);
@@ -1985,8 +1972,11 @@ const knownType = (scope, type) => {
1985
1972
  const idx = type[0][1];
1986
1973
 
1987
1974
  // type idx = var idx + 1
1988
- const v = Object.values(scope.locals).find(x => x.idx === idx - 1);
1989
- if (v.metadata?.type != null) return v.metadata.type;
1975
+ const name = Object.values(scope.locals).find(x => x.idx === idx)?.name;
1976
+ if (name) {
1977
+ const local = scope.locals[name];
1978
+ if (local.metadata?.type != null) return v.metadata.type;
1979
+ }
1990
1980
  }
1991
1981
 
1992
1982
  return null;
@@ -2117,6 +2107,17 @@ const typeSwitch = (scope, type, bc, returns = valtypeBinary) => {
2117
2107
  return out;
2118
2108
  };
2119
2109
 
2110
+ const typeIsOneOf = (type, types, valtype = Valtype.i32) => {
2111
+ const out = [];
2112
+
2113
+ for (let i = 0; i < types.length; i++) {
2114
+ out.push(...type, ...number(types[i], valtype), valtype === Valtype.f64 ? [ Opcodes.f64_eq ] : [ Opcodes.i32_eq ]);
2115
+ if (i !== 0) out.push([ Opcodes.i32_or ]);
2116
+ }
2117
+
2118
+ return out;
2119
+ };
2120
+
2120
2121
  const allocVar = (scope, name, global = false, type = true) => {
2121
2122
  const target = global ? globals : scope.locals;
2122
2123
 
@@ -2133,7 +2134,7 @@ const allocVar = (scope, name, global = false, type = true) => {
2133
2134
 
2134
2135
  if (type) {
2135
2136
  let typeIdx = global ? globalInd++ : scope.localInd++;
2136
- target[name + '#type'] = { idx: typeIdx, type: Valtype.i32 };
2137
+ target[name + '#type'] = { idx: typeIdx, type: Valtype.i32, name };
2137
2138
  }
2138
2139
 
2139
2140
  return idx;
@@ -2611,21 +2612,16 @@ const generateConditional = (scope, decl) => {
2611
2612
  out.push([ Opcodes.if, valtypeBinary ]);
2612
2613
  depth.push('if');
2613
2614
 
2614
- out.push(...generate(scope, decl.consequent));
2615
-
2616
- // note type
2617
2615
  out.push(
2618
- ...getNodeType(scope, decl.consequent),
2619
- ...setLastType(scope)
2616
+ ...generate(scope, decl.consequent),
2617
+ ...setLastType(scope, getNodeType(scope, decl.consequent))
2620
2618
  );
2621
2619
 
2622
2620
  out.push([ Opcodes.else ]);
2623
- out.push(...generate(scope, decl.alternate));
2624
2621
 
2625
- // note type
2626
2622
  out.push(
2627
- ...getNodeType(scope, decl.alternate),
2628
- ...setLastType(scope)
2623
+ ...generate(scope, decl.alternate),
2624
+ ...setLastType(scope, getNodeType(scope, decl.alternate))
2629
2625
  );
2630
2626
 
2631
2627
  out.push([ Opcodes.end ]);
@@ -3225,7 +3221,21 @@ const generateArray = (scope, decl, global = false, name = '$undeclared', initEm
3225
3221
  return makeArray(scope, decl, global, name, initEmpty, valtype)[0];
3226
3222
  };
3227
3223
 
3228
- export const generateMember = (scope, decl, _global, _name) => {
3224
+ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
3225
+ if (decl.properties.length > 0) return todo(scope, 'objects are not supported yet', true);
3226
+
3227
+ return [
3228
+ ...number(1),
3229
+ ...setLastType(scope, TYPES.object)
3230
+ ];
3231
+ };
3232
+
3233
+ const withType = (scope, wasm, type) => [
3234
+ ...wasm,
3235
+ ...setLastType(scope, type)
3236
+ ];
3237
+
3238
+ const generateMember = (scope, decl, _global, _name) => {
3229
3239
  const name = decl.object.name;
3230
3240
  const pointer = scope.arrays?.get(name);
3231
3241
 
@@ -3239,9 +3249,9 @@ export const generateMember = (scope, decl, _global, _name) => {
3239
3249
  // eg: __String_prototype_toLowerCase -> toLowerCase
3240
3250
  if (nameProp.startsWith('__')) nameProp = nameProp.split('_').pop();
3241
3251
 
3242
- return makeString(scope, nameProp, _global, _name, true);
3252
+ return withType(scope, makeString(scope, nameProp, _global, _name, true), TYPES.bytestring);
3243
3253
  } else {
3244
- return generate(scope, DEFAULT_VALUE);
3254
+ return withType(scope, number(0), TYPES.undefined);
3245
3255
  }
3246
3256
  }
3247
3257
 
@@ -3251,7 +3261,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3251
3261
  if (func) {
3252
3262
  const userFunc = funcIndex[name] && !importedFuncs[name] && !builtinFuncs[name] && !internalConstrs[name];
3253
3263
  const typedParams = userFunc || builtinFuncs[name]?.typedParams;
3254
- return number(typedParams ? func.params.length / 2 : func.params.length);
3264
+ return withType(scope, number(typedParams ? func.params.length / 2 : func.params.length), TYPES.number);
3255
3265
  }
3256
3266
 
3257
3267
  if (builtinFuncs[name + '$constructor']) {
@@ -3261,24 +3271,88 @@ export const generateMember = (scope, decl, _global, _name) => {
3261
3271
  const constructorFunc = builtinFuncs[name + '$constructor'];
3262
3272
  const constructorParams = constructorFunc.typedParams ? (constructorFunc.params.length / 2) : constructorFunc.params.length;
3263
3273
 
3264
- return number(Math.max(regularParams, constructorParams));
3274
+ return withType(scope, number(Math.max(regularParams, constructorParams)), TYPES.number);
3275
+ }
3276
+
3277
+ if (builtinFuncs[name]) return withType(scope, number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length), TYPES.number);
3278
+ if (importedFuncs[name]) return withType(scope, number(importedFuncs[name].params), TYPES.number);
3279
+ if (internalConstrs[name]) return withType(scope, number(internalConstrs[name].length ?? 0), TYPES.number);
3280
+
3281
+ if (Prefs.fastLength) {
3282
+ // presume valid length object
3283
+ return [
3284
+ ...(aotPointer ? number(0, Valtype.i32) : [
3285
+ ...generate(scope, decl.object),
3286
+ Opcodes.i32_to_u
3287
+ ]),
3288
+
3289
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
3290
+ Opcodes.i32_from_u
3291
+ ];
3265
3292
  }
3266
3293
 
3267
- if (builtinFuncs[name]) return number(builtinFuncs[name].typedParams ? (builtinFuncs[name].params.length / 2) : builtinFuncs[name].params.length);
3268
- if (importedFuncs[name]) return number(importedFuncs[name].params);
3269
- if (internalConstrs[name]) return number(internalConstrs[name].length ?? 0);
3294
+ const type = getNodeType(scope, decl.object);
3295
+ const known = knownType(scope, type);
3296
+ if (known != null) {
3297
+ if ([ TYPES.string, TYPES.bytestring, TYPES.array ].includes(known)) return [
3298
+ ...(aotPointer ? number(0, Valtype.i32) : [
3299
+ ...generate(scope, decl.object),
3300
+ Opcodes.i32_to_u
3301
+ ]),
3302
+
3303
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
3304
+ Opcodes.i32_from_u
3305
+ ];
3306
+
3307
+ return number(0);
3308
+ }
3270
3309
 
3271
3310
  return [
3272
- ...(aotPointer ? number(0, Valtype.i32) : [
3273
- ...generate(scope, decl.object),
3274
- Opcodes.i32_to_u
3275
- ]),
3311
+ ...typeIsOneOf(getNodeType(scope, decl.object), [ TYPES.string, TYPES.bytestring, TYPES.array ]),
3312
+ [ Opcodes.if, valtypeBinary ],
3313
+ ...(aotPointer ? number(0, Valtype.i32) : [
3314
+ ...generate(scope, decl.object),
3315
+ Opcodes.i32_to_u
3316
+ ]),
3276
3317
 
3277
- [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128((aotPointer ? pointer : 0)) ],
3278
- Opcodes.i32_from_u
3318
+ [ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, ...unsignedLEB128(aotPointer ? pointer : 0) ],
3319
+ Opcodes.i32_from_u,
3320
+
3321
+ ...setLastType(scope, TYPES.number),
3322
+ [ Opcodes.else ],
3323
+ ...number(0),
3324
+ ...setLastType(scope, TYPES.undefined),
3325
+ [ Opcodes.end ]
3279
3326
  ];
3280
3327
  }
3281
3328
 
3329
+ // todo: generate this array procedurally during builtinFuncs creation
3330
+ if (['size', 'description'].includes(decl.property.name)) {
3331
+ const bc = {};
3332
+ const cands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + decl.property.name + '$get'));
3333
+
3334
+ if (cands.length > 0) {
3335
+ for (const x of cands) {
3336
+ const type = TYPES[x.split('_prototype_')[0].slice(2).toLowerCase()];
3337
+ if (type == null) continue;
3338
+
3339
+ bc[type] = generateCall(scope, {
3340
+ callee: {
3341
+ type: 'Identifier',
3342
+ name: x
3343
+ },
3344
+ arguments: [ decl.object ],
3345
+ _protoInternalCall: true
3346
+ });
3347
+ }
3348
+ }
3349
+
3350
+ return typeSwitch(scope, getNodeType(scope, decl.object), {
3351
+ ...bc,
3352
+ default: withType(scope, number(0), TYPES.undefined)
3353
+ }, valtypeBinary);
3354
+ }
3355
+
3282
3356
  const object = generate(scope, decl.object);
3283
3357
  const property = generate(scope, decl.property);
3284
3358
 
@@ -3309,9 +3383,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3309
3383
 
3310
3384
  // read from memory
3311
3385
  [ Opcodes.load, Math.log2(ValtypeSize[valtype]) - 1, ...unsignedLEB128((aotPointer ? pointer : 0) + ValtypeSize.i32) ],
3312
-
3313
- ...number(TYPES.number, Valtype.i32),
3314
- ...setLastType(scope)
3386
+ ...setLastType(scope, TYPES.number)
3315
3387
  ],
3316
3388
 
3317
3389
  [TYPES.string]: [
@@ -3341,9 +3413,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3341
3413
 
3342
3414
  // return new string (page)
3343
3415
  ...number(newPointer),
3344
-
3345
- ...number(TYPES.string, Valtype.i32),
3346
- ...setLastType(scope)
3416
+ ...setLastType(scope, TYPES.string)
3347
3417
  ],
3348
3418
  [TYPES.bytestring]: [
3349
3419
  // setup new/out array
@@ -3369,9 +3439,7 @@ export const generateMember = (scope, decl, _global, _name) => {
3369
3439
 
3370
3440
  // return new string (page)
3371
3441
  ...number(newPointer),
3372
-
3373
- ...number(TYPES.bytestring, Valtype.i32),
3374
- ...setLastType(scope)
3442
+ ...setLastType(scope, TYPES.bytestring)
3375
3443
  ],
3376
3444
 
3377
3445
  default: internalThrow(scope, 'TypeError', 'Member expression is not supported for non-string non-array yet', true)
@@ -3396,7 +3464,7 @@ const objectHack = node => {
3396
3464
  if (!objectName) objectName = objectHack(node.object)?.name?.slice?.(2);
3397
3465
 
3398
3466
  // if .name or .length, give up (hack within a hack!)
3399
- if (['name', 'length'].includes(node.property.name)) {
3467
+ if (['name', 'length', 'size', 'description'].includes(node.property.name)) {
3400
3468
  node.object = objectHack(node.object);
3401
3469
  return;
3402
3470
  }
@@ -1225,7 +1225,7 @@ export const BuiltinFuncs = function() {
1225
1225
  locals: [127],
1226
1226
  localNames: ["_this","_this#type","index","index#type","value","value#type","offset"],
1227
1227
  };
1228
- this.__Set_prototype_size = {
1228
+ this.__Set_prototype_size$get = {
1229
1229
  wasm: (scope, {}) => [[32,0],[252,2],[40,0,0],[183],[65,0],[15]],
1230
1230
  params: [124,127],
1231
1231
  typedParams: true,
@@ -1235,13 +1235,13 @@ export const BuiltinFuncs = function() {
1235
1235
  localNames: ["_this","_this#type"],
1236
1236
  };
1237
1237
  this.__Set_prototype_values = {
1238
- wasm: (scope, {builtin,}) => [[32,0],[65,20],[16, builtin('__Set_prototype_size')],[33,3],[33,2],[16, builtin('__Porffor_allocate')],[33,4],[68,0,0,0,0,0,0,0,0],[33,5],[3,64],[32,5],[32,2],[99],[4,64],[32,0],[65,20],[32,5],[65,0],[16, builtin('__Porffor_set_read')],[33,3],[33,6],[32,3],[33,7],[32,4],[252,3],[34,9],[40,1,0],[34,8],[65,8],[108],[32,9],[106],[32,6],[57,2,4],[32,9],[32,8],[65,1],[106],[54,1,0],[65,0],[33,3],[32,5],[68,0,0,0,0,0,0,240,63],[160],[33,5],[12,1],[11],[11],[32,4],[65,16],[15]],
1238
+ wasm: (scope, {builtin,}) => [[32,0],[252,2],[40,0,0],[183],[33,2],[16, builtin('__Porffor_allocate')],[33,3],[68,0,0,0,0,0,0,0,0],[33,4],[3,64],[32,4],[32,2],[99],[4,64],[32,0],[65,20],[32,4],[65,0],[16, builtin('__Porffor_set_read')],[33,7],[33,5],[32,7],[33,6],[32,3],[252,3],[34,9],[40,1,0],[34,8],[65,8],[108],[32,9],[106],[32,5],[57,2,4],[32,9],[32,8],[65,1],[106],[54,1,0],[65,0],[33,7],[32,4],[68,0,0,0,0,0,0,240,63],[160],[33,4],[12,1],[11],[11],[32,3],[65,16],[15]],
1239
1239
  params: [124,127],
1240
1240
  typedParams: true,
1241
1241
  returns: [124,127],
1242
1242
  typedReturns: true,
1243
- locals: [124,127,124,124,124,127,127,127],
1244
- localNames: ["_this","_this#type","size","#last_type","out","i","val","val#type","__proto_length_cache","__proto_pointer_cache"],
1243
+ locals: [124,124,124,124,127,127,127,127],
1244
+ localNames: ["_this","_this#type","size","out","i","val","val#type","#last_type","__proto_length_cache","__proto_pointer_cache"],
1245
1245
  };
1246
1246
  this.__Set_prototype_keys = {
1247
1247
  wasm: (scope, {builtin,}) => [[32,0],[65,20],[16, builtin('__Set_prototype_values')],[34,2],[15]],
@@ -1253,31 +1253,31 @@ export const BuiltinFuncs = function() {
1253
1253
  localNames: ["_this","_this#type","#last_type"],
1254
1254
  };
1255
1255
  this.__Set_prototype_has = {
1256
- wasm: (scope, {builtin,}) => [[32,0],[65,20],[16, builtin('__Set_prototype_size')],[33,5],[33,4],[68,0,0,0,0,0,0,0,0],[33,6],[3,64],[32,6],[32,4],[99],[4,64],[32,0],[65,20],[32,6],[65,0],[16, builtin('__Porffor_set_read')],[33,5],[32,2],[97],[32,5],[32,3],[70],[113],[4,64],[68,0,0,0,0,0,0,240,63],[65,1],[15],[11],[32,6],[68,0,0,0,0,0,0,240,63],[160],[33,6],[12,1],[11],[11],[68,0,0,0,0,0,0,0,0],[65,1],[15]],
1256
+ wasm: (scope, {builtin,}) => [[32,0],[252,2],[40,0,0],[183],[33,4],[68,0,0,0,0,0,0,0,0],[33,5],[3,64],[32,5],[32,4],[99],[4,64],[2,64],[2,127,"string_only"],[32,0],[65,20],[32,5],[65,0],[16, builtin('__Porffor_set_read')],[33,6],[34,7,"string_only"],[32,2],[34,8,"string_only"],[32,6,"string_only|start"],[65,2],[70],[32,3],[65,2],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[65,2],[108],[33,13],[3,64],[32,12],[32,9],[106],[47,0,4],[32,12],[32,11],[106],[47,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,2],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11],[32,6],[65,18],[70],[32,3],[65,18],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[33,13],[3,64],[32,12],[32,9],[106],[45,0,4],[32,12],[32,11],[106],[45,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,1],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11,"string_only|end"],[97],[11,"string_only"],[32,6],[32,3],[70],[113],[4,64],[68,0,0,0,0,0,0,240,63],[65,1],[15],[11],[11],[32,5],[68,0,0,0,0,0,0,240,63],[160],[33,5],[12,1],[11],[11],[68,0,0,0,0,0,0,0,0],[65,1],[15]],
1257
1257
  params: [124,127,124,127],
1258
1258
  typedParams: true,
1259
1259
  returns: [124,127],
1260
1260
  typedReturns: true,
1261
- locals: [124,127,124],
1262
- localNames: ["_this","_this#type","value","value#type","size","#last_type","i"],
1261
+ locals: [124,124,127,124,124,127,127,127,127,127],
1262
+ localNames: ["_this","_this#type","value","value#type","size","i","#last_type","__tmpop_left","__tmpop_right","compare_left_pointer","compare_left_length","compare_right_pointer","compare_index","compare_index_end"],
1263
1263
  };
1264
1264
  this.__Set_prototype_add = {
1265
- wasm: (scope, {builtin,}) => [[32,0],[65,20],[16, builtin('__Set_prototype_size')],[33,5],[33,4],[68,0,0,0,0,0,0,0,0],[33,6],[3,64],[32,6],[32,4],[99],[4,64],[32,0],[65,20],[32,6],[65,0],[16, builtin('__Porffor_set_read')],[33,5],[32,2],[97],[32,5],[32,3],[70],[113],[4,64],[32,0],[65,20],[15],[11],[32,6],[68,0,0,0,0,0,0,240,63],[160],[33,6],[12,1],[11],[11],[32,0],[252,2],[32,4],[68,0,0,0,0,0,0,240,63],[160],[252,2],[54,0,0],[32,0],[65,20],[32,4],[65,0],[32,2],[32,3],[16, builtin('__Porffor_set_write')],[26],[32,0],[65,20],[15]],
1265
+ wasm: (scope, {builtin,}) => [[32,0],[252,2],[40,0,0],[183],[33,4],[68,0,0,0,0,0,0,0,0],[33,5],[3,64],[32,5],[32,4],[99],[4,64],[2,64],[2,127,"string_only"],[32,0],[65,20],[32,5],[65,0],[16, builtin('__Porffor_set_read')],[33,6],[34,7,"string_only"],[32,2],[34,8,"string_only"],[32,6,"string_only|start"],[65,2],[70],[32,3],[65,2],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[65,2],[108],[33,13],[3,64],[32,12],[32,9],[106],[47,0,4],[32,12],[32,11],[106],[47,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,2],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11],[32,6],[65,18],[70],[32,3],[65,18],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[33,13],[3,64],[32,12],[32,9],[106],[45,0,4],[32,12],[32,11],[106],[45,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,1],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11,"string_only|end"],[97],[11,"string_only"],[32,6],[32,3],[70],[113],[4,64],[32,0],[65,20],[15],[11],[11],[32,5],[68,0,0,0,0,0,0,240,63],[160],[33,5],[12,1],[11],[11],[32,0],[252,2],[32,4],[68,0,0,0,0,0,0,240,63],[160],[252,2],[54,0,0],[32,0],[65,20],[32,4],[65,0],[32,2],[32,3],[16, builtin('__Porffor_set_write')],[26],[32,0],[65,20],[15]],
1266
1266
  params: [124,127,124,127],
1267
1267
  typedParams: true,
1268
1268
  returns: [124,127],
1269
1269
  typedReturns: true,
1270
- locals: [124,127,124],
1271
- localNames: ["_this","_this#type","value","value#type","size","#last_type","i"],
1270
+ locals: [124,124,127,124,124,127,127,127,127,127],
1271
+ localNames: ["_this","_this#type","value","value#type","size","i","#last_type","__tmpop_left","__tmpop_right","compare_left_pointer","compare_left_length","compare_right_pointer","compare_index","compare_index_end"],
1272
1272
  };
1273
1273
  this.__Set_prototype_delete = {
1274
- wasm: (scope, {builtin,}) => [[32,0],[65,20],[16, builtin('__Set_prototype_size')],[33,5],[33,4],[68,0,0,0,0,0,0,0,0],[33,6],[3,64],[32,6],[32,4],[99],[4,64],[32,0],[65,20],[32,6],[65,0],[16, builtin('__Porffor_set_read')],[33,5],[32,2],[97],[32,5],[32,3],[70],[113],[4,64],[32,0],[252,2],[32,4],[68,0,0,0,0,0,0,240,63],[161],[252,2],[54,0,0],[32,6],[252,3],[65,9],[108],[32,0],[252,3],[106],[65,4],[106],[34,7],[32,7],[65,9],[106],[32,4],[32,6],[161],[252,3],[65,1],[107],[65,9],[108],[252,10,0,0],[68,0,0,0,0,0,0,240,63],[65,1],[15],[11],[32,6],[68,0,0,0,0,0,0,240,63],[160],[33,6],[12,1],[11],[11],[68,0,0,0,0,0,0,0,0],[65,1],[15]],
1274
+ wasm: (scope, {builtin,}) => [[32,0],[252,2],[40,0,0],[183],[33,4],[68,0,0,0,0,0,0,0,0],[33,5],[3,64],[32,5],[32,4],[99],[4,64],[2,64],[2,127,"string_only"],[32,0],[65,20],[32,5],[65,0],[16, builtin('__Porffor_set_read')],[33,6],[34,7,"string_only"],[32,2],[34,8,"string_only"],[32,6,"string_only|start"],[65,2],[70],[32,3],[65,2],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[65,2],[108],[33,13],[3,64],[32,12],[32,9],[106],[47,0,4],[32,12],[32,11],[106],[47,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,2],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11],[32,6],[65,18],[70],[32,3],[65,18],[70],[113],[4,64],[32,7],[252,3],[34,9],[32,8],[252,3],[34,11],[71],[4,127],[32,9],[40,2,0],[34,10],[32,11],[40,2,0],[71],[4,64],[65,0],[12,1],[11],[65,0],[33,12],[32,10],[33,13],[3,64],[32,12],[32,9],[106],[45,0,4],[32,12],[32,11],[106],[45,0,4],[71],[4,64],[65,0],[12,2],[11],[32,12],[65,1],[106],[34,12],[32,13],[71],[13,0],[11],[65,1],[5],[65,1],[11],[12,1],[11,"string_only|end"],[97],[11,"string_only"],[32,6],[32,3],[70],[113],[4,64],[32,0],[252,2],[32,4],[68,0,0,0,0,0,0,240,63],[161],[252,2],[54,0,0],[32,5],[252,3],[65,9],[108],[32,0],[252,3],[106],[65,4],[106],[34,14],[32,14],[65,9],[106],[32,4],[32,5],[161],[252,3],[65,1],[107],[65,9],[108],[252,10,0,0],[68,0,0,0,0,0,0,240,63],[65,1],[15],[11],[11],[32,5],[68,0,0,0,0,0,0,240,63],[160],[33,5],[12,1],[11],[11],[68,0,0,0,0,0,0,0,0],[65,1],[15]],
1275
1275
  params: [124,127,124,127],
1276
1276
  typedParams: true,
1277
1277
  returns: [124,127],
1278
1278
  typedReturns: true,
1279
- locals: [124,127,124,127],
1280
- localNames: ["_this","_this#type","value","value#type","size","#last_type","i","offset"],
1279
+ locals: [124,124,127,124,124,127,127,127,127,127,127],
1280
+ localNames: ["_this","_this#type","value","value#type","size","i","#last_type","__tmpop_left","__tmpop_right","compare_left_pointer","compare_left_length","compare_right_pointer","compare_index","compare_index_end","offset"],
1281
1281
  };
1282
1282
  this.__Set_prototype_clear = {
1283
1283
  wasm: (scope, {}) => [[32,0],[252,2],[65,0],[54,0,0],[68,0,0,0,0,0,0,0,0],[65,3],[15]],
@@ -1640,7 +1640,7 @@ export const BuiltinFuncs = function() {
1640
1640
  locals: [127],
1641
1641
  localNames: ["description","description#type","#last_type"],
1642
1642
  };
1643
- this.__Symbol_prototype_description = {
1643
+ this.__Symbol_prototype_description$get = {
1644
1644
  wasm: (scope, {builtin,}) => [[68,0,0,0,0,0,0,0,0],[65,1],[32,0],[68,0,0,0,0,0,0,240,63],[161],[65,0],[16, builtin('__Porffor_symbol_descStore')],[33,3],[34,2],[65,18],[15]],
1645
1645
  params: [124,127],
1646
1646
  typedParams: true,
@@ -18,7 +18,7 @@ const compile = async (file, [ _funcs, _globals ]) => {
18
18
  first = source.slice(0, source.indexOf('\n'));
19
19
  }
20
20
 
21
- let args = ['--bytestring', '--todo-time=compile', '--no-aot-pointer-opt', '--no-indirect-calls', '--no-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--parse-types', '--opt-types'];
21
+ let args = ['--bytestring', '--todo-time=compile', '--no-indirect-calls', '--no-treeshake-wasm-imports', '--no-rm-unused-types', '--scoped-page-names', '--funsafe-no-unlikely-proto-checks', '--fast-length', '--parse-types', '--opt-types'];
22
22
  if (first.startsWith('// @porf')) {
23
23
  args = args.concat(first.slice('// @porf '.length).split(' '));
24
24
  }
package/compiler/prefs.js CHANGED
@@ -1,4 +1,4 @@
1
- const onByDefault = [ 'bytestring', 'aotPointerOpt', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls' ];
1
+ const onByDefault = [ 'bytestring', 'treeshakeWasmImports', 'alwaysMemory', 'indirectCalls' ];
2
2
 
3
3
  let cache = {};
4
4
  const obj = new Proxy({}, {
package/compiler/wrap.js CHANGED
@@ -103,40 +103,12 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
103
103
  times.push(performance.now() - t1);
104
104
  if (Prefs.profileCompiler) console.log(bold(`compiled in ${times[0].toFixed(2)}ms`));
105
105
 
106
- const t2 = performance.now();
107
-
108
- let instance;
109
- try {
110
- let wasmEngine = WebAssembly;
111
- if (Prefs.asur) {
112
- log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
113
- wasmEngine = await import('../asur/index.js');
114
- }
115
-
116
- 0, { instance } = await wasmEngine.instantiate(wasm, {
117
- '': {
118
- p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
119
- c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
120
- t: () => performance.now(),
121
- u: () => performance.timeOrigin,
122
- y: () => {},
123
- z: () => {},
124
- ...customImports
125
- }
126
- });
127
- } catch (e) {
128
- // only backtrace for runner, not test262/etc
129
- if (!process.argv[1].includes('/runner')) throw e;
130
-
131
- const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
132
- const blobOffset = parseInt(e.message.split('@')?.[1]);
133
-
134
- if (!funcInd) throw e;
106
+ const backtrace = (funcInd, blobOffset) => {
107
+ if (funcInd == null || blobOffset == null) return false;
135
108
 
136
109
  // convert blob offset -> function wasm offset.
137
110
  // this is not good code and is somewhat duplicated
138
111
  // I just want it to work for debugging, I don't care about perf/yes
139
-
140
112
  const func = funcs.find(x => x.index === funcInd);
141
113
  const locals = Object.values(func.locals).sort((a, b) => a.idx - b.idx).slice(func.params.length).sort((a, b) => a.idx - b.idx);
142
114
 
@@ -154,7 +126,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
154
126
 
155
127
  if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
156
128
 
157
- const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 40));
129
+ const toFind = encodeVector(localDecl).concat(func.wasm.flat().filter(x => x != null && x <= 0xff).slice(0, 60));
158
130
 
159
131
  let i = 0;
160
132
  for (; i < wasm.length; i++) {
@@ -169,7 +141,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
169
141
  if (!mismatch) break;
170
142
  }
171
143
 
172
- if (i === wasm.length) throw e;
144
+ if (i === wasm.length) return false;
173
145
 
174
146
  const offset = (blobOffset - i) + encodeVector(localDecl).length;
175
147
 
@@ -180,7 +152,7 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
180
152
  if (cumLen === offset) break;
181
153
  }
182
154
 
183
- if (cumLen !== offset) throw e;
155
+ if (cumLen !== offset) return false;
184
156
 
185
157
  i -= 1;
186
158
 
@@ -205,6 +177,38 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
205
177
  console.log(decomp.join('\n'));
206
178
  console.log('\x1B[90m...\x1B[0m\n');
207
179
 
180
+ return true;
181
+ };
182
+
183
+ const t2 = performance.now();
184
+
185
+ let instance;
186
+ try {
187
+ let wasmEngine = WebAssembly;
188
+ if (Prefs.asur) {
189
+ log.warning('wrap', 'using our !experimental! asur wasm engine instead of host to run');
190
+ wasmEngine = await import('../asur/index.js');
191
+ }
192
+
193
+ 0, { instance } = await wasmEngine.instantiate(wasm, {
194
+ '': {
195
+ p: valtype === 'i64' ? i => print(Number(i).toString()) : i => print(i.toString()),
196
+ c: valtype === 'i64' ? i => print(String.fromCharCode(Number(i))) : i => print(String.fromCharCode(i)),
197
+ t: () => performance.now(),
198
+ u: () => performance.timeOrigin,
199
+ y: () => {},
200
+ z: () => {},
201
+ ...customImports
202
+ }
203
+ });
204
+ } catch (e) {
205
+ // only backtrace for runner, not test262/etc
206
+ if (!process.argv[1].includes('/runner')) throw e;
207
+
208
+ const funcInd = parseInt(e.message.match(/function #([0-9]+) /)?.[1]);
209
+ const blobOffset = parseInt(e.message.split('@')?.[1]);
210
+
211
+ backtrace(funcInd, blobOffset);
208
212
  throw e;
209
213
  }
210
214
 
@@ -249,6 +253,17 @@ export default async (source, flags = [ 'module' ], customImports = {}, print =
249
253
  throw new constructor(exception.message);
250
254
  }
251
255
 
256
+ if (e instanceof WebAssembly.RuntimeError) {
257
+ // only backtrace for runner, not test262/etc
258
+ if (!process.argv[1].includes('/runner')) throw e;
259
+
260
+ const match = e.stack.match(/wasm-function\[([0-9]+)\]:([0-9a-z]+)/) ?? [];
261
+ const funcInd = parseInt(match[1]);
262
+ const blobOffset = parseInt(match[2]);
263
+
264
+ backtrace(funcInd, blobOffset);
265
+ }
266
+
252
267
  throw e;
253
268
  }
254
269
  };
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.14.0-ec7daba95",
4
+ "version": "0.14.0-eca486960",
5
5
  "author": "CanadaHonk",
6
6
  "license": "MIT",
7
7
  "scripts": {