porffor 0.30.13 → 0.31.0
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/2c.js +16 -16
- package/compiler/allocators.js +1 -0
- package/compiler/assemble.js +12 -5
- package/compiler/builtins/_internal_object.ts +35 -12
- package/compiler/builtins/arraybuffer.ts +5 -1
- package/compiler/builtins/object.ts +24 -11
- package/compiler/builtins_objects.js +20 -5
- package/compiler/builtins_precompiled.js +522 -514
- package/compiler/codegen.js +127 -64
- package/compiler/cyclone.js +3 -3
- package/compiler/precompile.js +2 -5
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -1218,7 +1218,7 @@ const generateBinaryExp = (scope, decl, _global, _name) => {
|
|
1218
1218
|
type: 'CallExpression',
|
1219
1219
|
callee: {
|
1220
1220
|
type: 'Identifier',
|
1221
|
-
name: '
|
1221
|
+
name: '__Porffor_object_in'
|
1222
1222
|
},
|
1223
1223
|
arguments: [
|
1224
1224
|
decl.right,
|
@@ -1327,12 +1327,8 @@ const asmFunc = (name, { wasm, params = [], typedParams = false, locals: localTy
|
|
1327
1327
|
locals[nameParam(i)] = { idx: i, type: allLocals[i] };
|
1328
1328
|
}
|
1329
1329
|
|
1330
|
-
for (const x
|
1331
|
-
|
1332
|
-
if (offset != null) offset += pages.size * pageSize;
|
1333
|
-
|
1334
|
-
const bytes = x[1];
|
1335
|
-
data.push({ offset, bytes });
|
1330
|
+
for (const x in _data) {
|
1331
|
+
data.push({ page: x, bytes: _data[x] });
|
1336
1332
|
}
|
1337
1333
|
|
1338
1334
|
const func = {
|
@@ -1515,6 +1511,7 @@ const setLastType = (scope, type = []) => [
|
|
1515
1511
|
|
1516
1512
|
const getNodeType = (scope, node) => {
|
1517
1513
|
const ret = (() => {
|
1514
|
+
if (node._type) return node._type;
|
1518
1515
|
if (node.type === 'Literal') {
|
1519
1516
|
if (node.regex) return TYPES.regexp;
|
1520
1517
|
|
@@ -1675,10 +1672,7 @@ const getNodeType = (scope, node) => {
|
|
1675
1672
|
|
1676
1673
|
const objectKnownType = knownType(scope, getNodeType(scope, node.object));
|
1677
1674
|
if (objectKnownType != null) {
|
1678
|
-
if (name === 'length')
|
1679
|
-
if (typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1680
|
-
else return TYPES.undefined;
|
1681
|
-
}
|
1675
|
+
if (name === 'length' && typeHasFlag(objectKnownType, TYPE_FLAGS.length)) return TYPES.number;
|
1682
1676
|
|
1683
1677
|
if (node.computed) {
|
1684
1678
|
if (objectKnownType === TYPES.string) return TYPES.string;
|
@@ -3221,12 +3215,7 @@ const generateVarDstr = (scope, kind, pattern, init, defaultValue, global) => {
|
|
3221
3215
|
},
|
3222
3216
|
arguments: [
|
3223
3217
|
{ type: 'Identifier', name: tmpName },
|
3224
|
-
{ type: 'Literal', value: i }
|
3225
|
-
{
|
3226
|
-
type: 'MemberExpression',
|
3227
|
-
object: { type: 'Identifier', name: tmpName, },
|
3228
|
-
property: { type: 'Identifier', name: 'length', }
|
3229
|
-
}
|
3218
|
+
{ type: 'Literal', value: i }
|
3230
3219
|
],
|
3231
3220
|
_protoInternalCall: true
|
3232
3221
|
}, undefined, global)
|
@@ -3419,15 +3408,16 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
3419
3408
|
const op = decl.operator.slice(0, -1) || '=';
|
3420
3409
|
|
3421
3410
|
// hack: .length setter
|
3422
|
-
if (type === 'MemberExpression' && decl.left.property.name === 'length') {
|
3411
|
+
if (type === 'MemberExpression' && decl.left.property.name === 'length' && !decl._internalAssign) {
|
3423
3412
|
const newValueTmp = localTmp(scope, '__length_setter_tmp');
|
3424
|
-
const pointerTmp =
|
3413
|
+
const pointerTmp = localTmp(scope, '__member_setter_ptr_tmp', Valtype.i32);
|
3425
3414
|
|
3426
|
-
|
3415
|
+
const out = [
|
3427
3416
|
...generate(scope, decl.left.object),
|
3428
|
-
Opcodes.i32_to_u
|
3429
|
-
|
3417
|
+
Opcodes.i32_to_u
|
3418
|
+
];
|
3430
3419
|
|
3420
|
+
const lengthTypeWasm = [
|
3431
3421
|
...(op === '=' ? generate(scope, decl.right) : performOp(scope, op, [
|
3432
3422
|
[ Opcodes.local_get, pointerTmp ],
|
3433
3423
|
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
@@ -3440,6 +3430,33 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
3440
3430
|
|
3441
3431
|
[ Opcodes.local_get, newValueTmp ]
|
3442
3432
|
];
|
3433
|
+
|
3434
|
+
const type = getNodeType(scope, decl.left.object);
|
3435
|
+
const known = knownType(scope, type);
|
3436
|
+
if (known != null && typeHasFlag(known, TYPE_FLAGS.length)) return [
|
3437
|
+
...out,
|
3438
|
+
...(!pointerTmp ? [] : [ [ Opcodes.local_tee, pointerTmp ] ]),
|
3439
|
+
|
3440
|
+
...lengthTypeWasm
|
3441
|
+
];
|
3442
|
+
|
3443
|
+
return [
|
3444
|
+
...out,
|
3445
|
+
[ Opcodes.local_set, pointerTmp ],
|
3446
|
+
|
3447
|
+
...type,
|
3448
|
+
...number(TYPE_FLAGS.length, Valtype.i32),
|
3449
|
+
[ Opcodes.i32_and ],
|
3450
|
+
[ Opcodes.if, valtypeBinary ],
|
3451
|
+
[ Opcodes.local_get, pointerTmp ],
|
3452
|
+
...lengthTypeWasm,
|
3453
|
+
[ Opcodes.else ],
|
3454
|
+
...generate(scope, {
|
3455
|
+
...decl,
|
3456
|
+
_internalAssign: true
|
3457
|
+
}),
|
3458
|
+
[ Opcodes.end ]
|
3459
|
+
];
|
3443
3460
|
}
|
3444
3461
|
|
3445
3462
|
// arr[i]
|
@@ -4951,7 +4968,7 @@ const compileBytes = (val, itemType) => {
|
|
4951
4968
|
}
|
4952
4969
|
};
|
4953
4970
|
|
4954
|
-
const makeData = (scope, elements,
|
4971
|
+
const makeData = (scope, elements, page = null, itemType, initEmpty) => {
|
4955
4972
|
const length = elements.length;
|
4956
4973
|
|
4957
4974
|
// if length is 0 memory/data will just be 0000... anyway
|
@@ -4965,8 +4982,7 @@ const makeData = (scope, elements, offset = null, itemType, initEmpty) => {
|
|
4965
4982
|
bytes.push(...compileBytes(elements[i], itemType));
|
4966
4983
|
}
|
4967
4984
|
|
4968
|
-
const obj = { bytes };
|
4969
|
-
if (offset != null) obj.offset = offset;
|
4985
|
+
const obj = { bytes, page };
|
4970
4986
|
|
4971
4987
|
const idx = data.push(obj) - 1;
|
4972
4988
|
|
@@ -5068,7 +5084,7 @@ const makeArray = (scope, decl, global = false, name = '$undeclared', initEmpty
|
|
5068
5084
|
(!globalThis.precompile || !global)
|
5069
5085
|
) {
|
5070
5086
|
if (Prefs.activeData && firstAssign) {
|
5071
|
-
makeData(scope, elements,
|
5087
|
+
makeData(scope, elements, allocator.lastName, itemType, initEmpty);
|
5072
5088
|
|
5073
5089
|
// local value as pointer
|
5074
5090
|
return [ number(rawPtr, intOut ? Valtype.i32 : valtypeBinary), pointer ];
|
@@ -5363,6 +5379,7 @@ const countLength = (func, name = undefined) => {
|
|
5363
5379
|
};
|
5364
5380
|
|
5365
5381
|
const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) => {
|
5382
|
+
let final = [], finalEnd, extraBC = {};
|
5366
5383
|
const name = decl.object.name;
|
5367
5384
|
|
5368
5385
|
// hack: .name
|
@@ -5375,6 +5392,12 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5375
5392
|
return withType(scope, makeString(scope, nameProp, _global, _name, true), TYPES.bytestring);
|
5376
5393
|
}
|
5377
5394
|
|
5395
|
+
const object = decl.object;
|
5396
|
+
const property = getMemberProperty(decl);
|
5397
|
+
|
5398
|
+
// generate now so type is gotten correctly later (it gets cached)
|
5399
|
+
generate(scope, object);
|
5400
|
+
|
5378
5401
|
// hack: .length
|
5379
5402
|
if (decl.property.name === 'length') {
|
5380
5403
|
// todo: support optional
|
@@ -5389,7 +5412,7 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5389
5412
|
}
|
5390
5413
|
|
5391
5414
|
const out = [
|
5392
|
-
...generate(scope,
|
5415
|
+
...generate(scope, object),
|
5393
5416
|
Opcodes.i32_to_u,
|
5394
5417
|
];
|
5395
5418
|
|
@@ -5403,25 +5426,21 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5403
5426
|
];
|
5404
5427
|
}
|
5405
5428
|
|
5406
|
-
const type = getNodeType(scope,
|
5429
|
+
const type = getNodeType(scope, object);
|
5407
5430
|
const known = knownType(scope, type);
|
5408
|
-
if (known != null && known
|
5409
|
-
|
5410
|
-
...out,
|
5411
|
-
|
5412
|
-
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
5413
|
-
Opcodes.i32_from_u
|
5414
|
-
];
|
5431
|
+
if (known != null && typeHasFlag(known, TYPE_FLAGS.length)) return [
|
5432
|
+
...out,
|
5415
5433
|
|
5416
|
-
|
5417
|
-
|
5434
|
+
[ Opcodes.i32_load, Math.log2(ValtypeSize.i32) - 1, 0 ],
|
5435
|
+
Opcodes.i32_from_u
|
5436
|
+
];
|
5418
5437
|
|
5419
5438
|
const tmp = localTmp(scope, '#length_tmp', Valtype.i32);
|
5420
|
-
|
5439
|
+
final = [
|
5421
5440
|
...out,
|
5422
5441
|
[ Opcodes.local_set, tmp ],
|
5423
5442
|
|
5424
|
-
...getNodeType(scope,
|
5443
|
+
...getNodeType(scope, object),
|
5425
5444
|
...number(TYPE_FLAGS.length, Valtype.i32),
|
5426
5445
|
[ Opcodes.i32_and ],
|
5427
5446
|
[ Opcodes.if, valtypeBinary ],
|
@@ -5431,22 +5450,14 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5431
5450
|
|
5432
5451
|
...setLastType(scope, TYPES.number),
|
5433
5452
|
[ Opcodes.else ],
|
5434
|
-
...getNodeType(scope, decl.object),
|
5435
|
-
...number(TYPES.function, Valtype.i32),
|
5436
|
-
[ Opcodes.i32_eq ],
|
5437
|
-
[ Opcodes.if, Blocktype.void ],
|
5438
|
-
[ Opcodes.local_get, tmp ],
|
5439
|
-
[ Opcodes.call, includeBuiltin(scope, '__Porffor_funcLut_length').index ],
|
5440
|
-
Opcodes.i32_from_u,
|
5441
|
-
|
5442
|
-
...setLastType(scope, TYPES.number),
|
5443
|
-
[ Opcodes.br, 1 ],
|
5444
|
-
[ Opcodes.end ],
|
5445
|
-
|
5446
|
-
...number(0),
|
5447
|
-
...setLastType(scope, TYPES.undefined),
|
5448
5453
|
[ Opcodes.end ]
|
5449
5454
|
];
|
5455
|
+
|
5456
|
+
if (known != null) {
|
5457
|
+
final = [];
|
5458
|
+
} else {
|
5459
|
+
finalEnd = final.pop();
|
5460
|
+
}
|
5450
5461
|
}
|
5451
5462
|
|
5452
5463
|
// todo: generate this array procedurally during builtinFuncs creation
|
@@ -5455,33 +5466,67 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5455
5466
|
const bc = {};
|
5456
5467
|
const cands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + decl.property.name + '$get'));
|
5457
5468
|
|
5469
|
+
localTmp(scope, '#member_obj');
|
5470
|
+
localTmp(scope, '#member_obj#type', Valtype.i32);
|
5471
|
+
|
5472
|
+
const known = knownType(scope, getNodeType(scope, object));
|
5458
5473
|
if (cands.length > 0) {
|
5459
5474
|
for (const x of cands) {
|
5460
5475
|
const type = TYPES[x.split('_prototype_')[0].slice(2).toLowerCase()];
|
5461
5476
|
if (type == null) continue;
|
5462
5477
|
|
5478
|
+
if (type === known) return generateCall(scope, {
|
5479
|
+
callee: {
|
5480
|
+
type: 'Identifier',
|
5481
|
+
name: x
|
5482
|
+
},
|
5483
|
+
arguments: [ object ],
|
5484
|
+
_protoInternalCall: true
|
5485
|
+
});
|
5486
|
+
|
5463
5487
|
bc[type] = generateCall(scope, {
|
5464
5488
|
callee: {
|
5465
5489
|
type: 'Identifier',
|
5466
5490
|
name: x
|
5467
5491
|
},
|
5468
|
-
arguments: [
|
5492
|
+
arguments: [
|
5493
|
+
{ type: 'Identifier', name: '#member_obj' }
|
5494
|
+
],
|
5469
5495
|
_protoInternalCall: true
|
5470
5496
|
});
|
5471
5497
|
}
|
5472
5498
|
}
|
5473
5499
|
|
5474
|
-
|
5475
|
-
...bc,
|
5476
|
-
default: withType(scope, number(0), TYPES.undefined)
|
5477
|
-
}, valtypeBinary);
|
5500
|
+
if (known == null) extraBC = bc;
|
5478
5501
|
}
|
5479
5502
|
|
5480
|
-
|
5481
|
-
|
5503
|
+
if (decl.property.name === '__proto__') {
|
5504
|
+
// todo: support optional
|
5505
|
+
const bc = {};
|
5506
|
+
const prototypes = Object.keys(builtinVars).filter(x => x.endsWith('_prototype'));
|
5482
5507
|
|
5483
|
-
|
5484
|
-
|
5508
|
+
const known = knownType(scope, getNodeType(scope, decl.object));
|
5509
|
+
for (const x of prototypes) {
|
5510
|
+
const type = TYPES[x.split('_prototype')[0].slice(2).toLowerCase()];
|
5511
|
+
if (type == null) continue;
|
5512
|
+
|
5513
|
+
// do not __proto__ primitive hack for objects
|
5514
|
+
if (type === TYPES.object) continue;
|
5515
|
+
|
5516
|
+
const ident = {
|
5517
|
+
type: 'Identifier',
|
5518
|
+
name: x
|
5519
|
+
};
|
5520
|
+
|
5521
|
+
bc[type] = [
|
5522
|
+
...generateIdent(scope, ident),
|
5523
|
+
...setLastType(scope, getNodeType(scope, ident))
|
5524
|
+
];
|
5525
|
+
if (type === known) return bc[type];
|
5526
|
+
}
|
5527
|
+
|
5528
|
+
if (known == null) extraBC = bc;
|
5529
|
+
}
|
5485
5530
|
|
5486
5531
|
// todo/perf: use i32 object (and prop?) locals
|
5487
5532
|
const objectWasm = [ [ Opcodes.local_get, localTmp(scope, '#member_obj') ] ];
|
@@ -5668,7 +5713,9 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5668
5713
|
default: [
|
5669
5714
|
...number(0),
|
5670
5715
|
...setLastType(scope, TYPES.undefined)
|
5671
|
-
]
|
5716
|
+
],
|
5717
|
+
|
5718
|
+
...extraBC
|
5672
5719
|
});
|
5673
5720
|
|
5674
5721
|
if (decl.optional) {
|
@@ -5676,6 +5723,10 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5676
5723
|
[ Opcodes.block, valtypeBinary ],
|
5677
5724
|
...(_objectWasm ? _objectWasm : generate(scope, object)),
|
5678
5725
|
[ Opcodes.local_tee, localTmp(scope, '#member_obj') ],
|
5726
|
+
...(scope.locals['#member_obj#type'] ? [
|
5727
|
+
...getNodeType(scope, object),
|
5728
|
+
[ Opcodes.local_set, localTmp(scope, '#member_obj#type', Valtype.i32) ],
|
5729
|
+
] : []),
|
5679
5730
|
|
5680
5731
|
...nullish(scope, [], getNodeType(scope, object), false, true),
|
5681
5732
|
[ Opcodes.if, Blocktype.void ],
|
@@ -5695,12 +5746,22 @@ const generateMember = (scope, decl, _global, _name, _objectWasm = undefined) =>
|
|
5695
5746
|
out.unshift(
|
5696
5747
|
...(_objectWasm ? _objectWasm : generate(scope, object)),
|
5697
5748
|
[ Opcodes.local_set, localTmp(scope, '#member_obj') ],
|
5749
|
+
...(scope.locals['#member_obj#type'] ? [
|
5750
|
+
...getNodeType(scope, object),
|
5751
|
+
[ Opcodes.local_set, localTmp(scope, '#member_obj#type', Valtype.i32) ],
|
5752
|
+
] : []),
|
5698
5753
|
|
5699
5754
|
...generate(scope, property, false, '#member_prop'),
|
5700
5755
|
[ Opcodes.local_set, localTmp(scope, '#member_prop') ]
|
5701
5756
|
);
|
5702
5757
|
}
|
5703
5758
|
|
5759
|
+
if (final.length > 0) {
|
5760
|
+
final = final.concat(out);
|
5761
|
+
final.push(finalEnd);
|
5762
|
+
return final;
|
5763
|
+
}
|
5764
|
+
|
5704
5765
|
return out;
|
5705
5766
|
};
|
5706
5767
|
|
@@ -5716,7 +5777,9 @@ const objectHack = node => {
|
|
5716
5777
|
if (node.computed || node.optional) return;
|
5717
5778
|
|
5718
5779
|
// hack: block these properties as they can be accessed on functions
|
5719
|
-
if (node.property.name
|
5780
|
+
if (node.property.name === 'length' || node.property.name === 'name' || node.property.name === 'call') return;
|
5781
|
+
|
5782
|
+
if (node.property.name === '__proto__') return;
|
5720
5783
|
|
5721
5784
|
let objectName = node.object.name;
|
5722
5785
|
|
package/compiler/cyclone.js
CHANGED
@@ -53,7 +53,7 @@ export default wasm => {
|
|
53
53
|
const replaceOp = newOp => {
|
54
54
|
op.splice(0, op.length, ...newOp);
|
55
55
|
};
|
56
|
-
const replaceVal = (val, valtype) => replaceOp(number(val, valtype));
|
56
|
+
const replaceVal = (val, valtype) => replaceOp(number(val, valtype)[0]);
|
57
57
|
|
58
58
|
const empty = () => {
|
59
59
|
stack = [];
|
@@ -511,7 +511,7 @@ export default wasm => {
|
|
511
511
|
|
512
512
|
// convert f64.const -> i32.const
|
513
513
|
const n = wasm[i - 1][1];
|
514
|
-
wasm.splice(i - 1, 1, number(n, Valtype.i32));
|
514
|
+
wasm.splice(i - 1, 1, number(n, Valtype.i32)[0]);
|
515
515
|
|
516
516
|
// convert math op from f64 to i32
|
517
517
|
wasm[i][0] = f64ToI32Op[wasm[i][0]];
|
@@ -551,7 +551,7 @@ export default wasm => {
|
|
551
551
|
|
552
552
|
// convert f64.const -> i32.const
|
553
553
|
const n = wasm[i - 2][1];
|
554
|
-
wasm.splice(i - 2, 1, number(n, Valtype.i32));
|
554
|
+
wasm.splice(i - 2, 1, number(n, Valtype.i32)[0]);
|
555
555
|
|
556
556
|
// convert math op from f64 to i32
|
557
557
|
wasm[i - 1][0] = f64ToI32Op[wasm[i - 1][0]];
|
package/compiler/precompile.js
CHANGED
@@ -66,10 +66,7 @@ const compile = async (file, _funcs) => {
|
|
66
66
|
const exports = funcs.filter(x => x.export && x.name !== 'main');
|
67
67
|
for (const x of exports) {
|
68
68
|
if (x.data) {
|
69
|
-
x.data = x.data.
|
70
|
-
for (const y in x.data) {
|
71
|
-
if (x.data[y].offset != null) x.data[y].offset -= x.data[0].offset;
|
72
|
-
}
|
69
|
+
x.data = x.data.reduce((acc, x) => { acc[data[x].page] = data[x].bytes; return acc; }, {});
|
73
70
|
}
|
74
71
|
|
75
72
|
if (x.exceptions) {
|
@@ -226,7 +223,7 @@ ${funcs.map(x => {
|
|
226
223
|
wasm:${rewriteWasm(x.wasm)},
|
227
224
|
params:${JSON.stringify(x.params)},typedParams:1,returns:${JSON.stringify(x.returns)},${x.returnType != null ? `returnType:${JSON.stringify(x.returnType)}` : 'typedReturns:1'},
|
228
225
|
locals:${JSON.stringify(locals.slice(x.params.length).map(x => x[1].type))},localNames:${JSON.stringify(locals.map(x => x[0]))},
|
229
|
-
${x.globalInits ? `globalInits:{${Object.keys(x.globalInits).map(y => `${y}:${rewriteWasm(x.globalInits[y])}`).join(',')}},` : ''}${x.data && x.data.length > 0 ? `data
|
226
|
+
${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)},` : ''}
|
230
227
|
${x.table ? `table:1,` : ''}${x.constr ? `constr:1,` : ''}${x.hasRestArgument ? `hasRestArgument:1,` : ''}
|
231
228
|
};`.replaceAll('\n\n', '\n').replaceAll('\n\n', '\n').replaceAll('\n\n', '\n');
|
232
229
|
}).join('\n')}
|
package/package.json
CHANGED