porffor 0.55.22 → 0.55.24
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/allocator.js +1 -1
- package/compiler/builtins/_internal_object.ts +568 -285
- package/compiler/builtins/bigint.ts +2 -2
- package/compiler/builtins/console.ts +1 -1
- package/compiler/builtins/function.ts +1 -1
- package/compiler/builtins/object.ts +46 -51
- package/compiler/builtins/object_prototypeWithHidden.js +47 -0
- package/compiler/builtins/reflect.ts +4 -4
- package/compiler/builtins/z_ecma262.ts +3 -0
- package/compiler/builtins_precompiled.js +575 -554
- package/compiler/codegen.js +86 -216
- package/compiler/precompile.js +6 -5
- package/compiler/prototype.js +80 -66
- package/compiler/wrap.js +3 -4
- package/package.json +1 -1
- package/r.cjs +30 -6
- package/runner/flamegraph.js +13 -13
- package/runner/index.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -848,13 +848,6 @@ const truthy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMod
|
|
848
848
|
] ] ] : []),
|
849
849
|
|
850
850
|
[ 'default', def ]
|
851
|
-
|
852
|
-
// [ [ TYPES.boolean, TYPES.number, TYPES.object, TYPES.undefined, TYPES.empty ], def ],
|
853
|
-
// [ 'default', [
|
854
|
-
// // other types are always truthy
|
855
|
-
// ...(!useTmp ? [ [ Opcodes.drop ] ] : []),
|
856
|
-
// number(1, intOut ? Valtype.i32 : valtypeBinary)
|
857
|
-
// ] ]
|
858
851
|
], intOut ? Valtype.i32 : valtypeBinary)
|
859
852
|
];
|
860
853
|
};
|
@@ -921,13 +914,6 @@ const falsy = (scope, wasm, type, intIn = false, intOut = false, forceTruthyMode
|
|
921
914
|
] ] ] : []),
|
922
915
|
|
923
916
|
[ 'default', def ]
|
924
|
-
|
925
|
-
// [ [ TYPES.boolean, TYPES.number, TYPES.object, TYPES.undefined, TYPES.empty ], def ],
|
926
|
-
// [ 'default', [
|
927
|
-
// // other types are always truthy
|
928
|
-
// ...(!useTmp ? [ [ Opcodes.drop ] ] : []),
|
929
|
-
// number(0, intOut ? Valtype.i32 : valtypeBinary)
|
930
|
-
// ] ]
|
931
917
|
], intOut ? Valtype.i32 : valtypeBinary)
|
932
918
|
];
|
933
919
|
};
|
@@ -1539,7 +1525,7 @@ const getNodeType = (scope, node) => {
|
|
1539
1525
|
return getType(scope, node.name);
|
1540
1526
|
}
|
1541
1527
|
|
1542
|
-
if (node.type === 'ObjectExpression') {
|
1528
|
+
if (node.type === 'ObjectExpression' || node.type === 'Super') {
|
1543
1529
|
return TYPES.object;
|
1544
1530
|
}
|
1545
1531
|
|
@@ -1571,24 +1557,6 @@ const getNodeType = (scope, node) => {
|
|
1571
1557
|
if (Object.hasOwn(builtinFuncs, name) && builtinFuncs[name].returnType != null) return builtinFuncs[name].returnType;
|
1572
1558
|
if (Object.hasOwn(internalConstrs, name) && internalConstrs[name].type != null) return internalConstrs[name].type;
|
1573
1559
|
|
1574
|
-
// check if this is a prototype function
|
1575
|
-
// if so and there is only one impl (eg charCodeAt)
|
1576
|
-
// or all impls have the same return type
|
1577
|
-
// use that return type as that is the only possibility
|
1578
|
-
// (if non-matching type it would error out)
|
1579
|
-
if (name.startsWith('__')) {
|
1580
|
-
const spl = name.slice(2).split('_');
|
1581
|
-
|
1582
|
-
const func = spl[spl.length - 1];
|
1583
|
-
const protoFuncs = Object.keys(prototypeFuncs).filter(x => x != TYPES.bytestring && prototypeFuncs[x][func] != null);
|
1584
|
-
if (
|
1585
|
-
protoFuncs.length === 1 ||
|
1586
|
-
(protoFuncs.length > 1 && protoFuncs.every(x => x.returnType === protoFuncs[0].returnType))
|
1587
|
-
) {
|
1588
|
-
if (protoFuncs[0].returnType != null) return protoFuncs[0].returnType;
|
1589
|
-
}
|
1590
|
-
}
|
1591
|
-
|
1592
1560
|
if (name.startsWith('__Porffor_wasm_')) {
|
1593
1561
|
// todo: return undefined for non-returning ops
|
1594
1562
|
return TYPES.number;
|
@@ -1741,7 +1709,6 @@ const getNodeType = (scope, node) => {
|
|
1741
1709
|
if (guess != null) out.guess = typeof guess === 'number' ? [ number(guess, Valtype.i32) ] : guess;
|
1742
1710
|
|
1743
1711
|
typeUsed(scope, knownType(scope, out));
|
1744
|
-
|
1745
1712
|
return out;
|
1746
1713
|
};
|
1747
1714
|
|
@@ -1860,29 +1827,6 @@ const createNewTarget = (scope, decl, idx = 0, force = false) => {
|
|
1860
1827
|
];
|
1861
1828
|
};
|
1862
1829
|
|
1863
|
-
const makeObject = (scope, obj) => {
|
1864
|
-
const properties = [];
|
1865
|
-
for (const x in obj) {
|
1866
|
-
properties.push({
|
1867
|
-
type: 'Property',
|
1868
|
-
method: false,
|
1869
|
-
shorthand: false,
|
1870
|
-
computed: false,
|
1871
|
-
key: {
|
1872
|
-
type: 'Identifier',
|
1873
|
-
name: x
|
1874
|
-
},
|
1875
|
-
value: obj[x],
|
1876
|
-
kind: 'init'
|
1877
|
-
});
|
1878
|
-
}
|
1879
|
-
|
1880
|
-
return generate(scope, {
|
1881
|
-
type: 'ObjectExpression',
|
1882
|
-
properties
|
1883
|
-
});
|
1884
|
-
};
|
1885
|
-
|
1886
1830
|
const getObjProp = (obj, prop) => {
|
1887
1831
|
if (typeof obj === 'string') obj = {
|
1888
1832
|
type: 'Identifier',
|
@@ -1932,8 +1876,6 @@ const aliasPrimObjsBC = bc => {
|
|
1932
1876
|
const add = (x, y) => {
|
1933
1877
|
if (bc[x] == null) return;
|
1934
1878
|
|
1935
|
-
// bc[`${x},${y}`] = original;
|
1936
|
-
|
1937
1879
|
// intentionally duplicate to avoid extra bc for prim objs as rarely used
|
1938
1880
|
bc[y] = bc[x];
|
1939
1881
|
};
|
@@ -1967,32 +1909,22 @@ const createThisArg = (scope, decl) => {
|
|
1967
1909
|
number(TYPES.object, Valtype.i32)
|
1968
1910
|
];
|
1969
1911
|
|
1970
|
-
// create new object with
|
1912
|
+
// create new object with prototype set to callee prototype
|
1971
1913
|
const tmp = localTmp(scope, '#this_create_tmp');
|
1972
1914
|
const proto = getObjProp(decl.callee, 'prototype');
|
1973
1915
|
|
1974
1916
|
return [
|
1975
|
-
|
1917
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_allocate').index ],
|
1918
|
+
Opcodes.i32_from_u,
|
1976
1919
|
[ Opcodes.local_tee, tmp ],
|
1977
1920
|
Opcodes.i32_to_u,
|
1978
|
-
|
1979
1921
|
number(TYPES.object, Valtype.i32),
|
1980
1922
|
|
1981
|
-
...generate(scope, {
|
1982
|
-
type: 'Literal',
|
1983
|
-
value: '__proto__'
|
1984
|
-
}),
|
1985
|
-
Opcodes.i32_to_u,
|
1986
|
-
number(TYPES.bytestring, Valtype.i32),
|
1987
|
-
|
1988
1923
|
...generate(scope, proto),
|
1924
|
+
Opcodes.i32_to_u,
|
1989
1925
|
...getNodeType(scope, proto),
|
1990
1926
|
|
1991
|
-
|
1992
|
-
number(0b1000, Valtype.i32),
|
1993
|
-
number(TYPES.number, Valtype.i32),
|
1994
|
-
|
1995
|
-
[ Opcodes.call, includeBuiltin(scope, '__Porffor_object_expr_initWithFlags').index ],
|
1927
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_object_setPrototype').index ],
|
1996
1928
|
|
1997
1929
|
[ Opcodes.local_get, tmp ],
|
1998
1930
|
number(TYPES.object, Valtype.i32)
|
@@ -2353,30 +2285,34 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2353
2285
|
const protoLocal2 = protoFunc.local2 ? localTmp(scope, `__${protoName}_tmp2`, protoFunc.local2) : -1;
|
2354
2286
|
|
2355
2287
|
let optUnused = false;
|
2356
|
-
const protoOut = protoFunc(
|
2357
|
-
|
2358
|
-
|
2359
|
-
|
2360
|
-
|
2361
|
-
|
2362
|
-
|
2363
|
-
|
2364
|
-
|
2365
|
-
|
2366
|
-
|
2367
|
-
|
2368
|
-
|
2369
|
-
|
2370
|
-
|
2371
|
-
|
2372
|
-
|
2373
|
-
|
2288
|
+
const protoOut = protoFunc({
|
2289
|
+
pointer: getPointer,
|
2290
|
+
length: {
|
2291
|
+
getCachedI32: () => [ [ Opcodes.local_get, lengthLocal ] ],
|
2292
|
+
setCachedI32: () => [ [ Opcodes.local_set, lengthLocal ] ],
|
2293
|
+
get: () => ArrayUtil.getLength(getPointer),
|
2294
|
+
getI32: () => ArrayUtil.getLengthI32(getPointer),
|
2295
|
+
set: value => ArrayUtil.setLength(getPointer, value),
|
2296
|
+
setI32: value => ArrayUtil.setLengthI32(getPointer, value)
|
2297
|
+
},
|
2298
|
+
arg: generate(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
|
2299
|
+
argType: getNodeType(scope, decl.arguments[0] ?? DEFAULT_VALUE()),
|
2300
|
+
iTmp: protoLocal,
|
2301
|
+
iTmp2: protoLocal2,
|
2302
|
+
alloc: bytes => [
|
2303
|
+
number(bytes, Valtype.i32),
|
2304
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_allocateBytes').index ]
|
2305
|
+
],
|
2306
|
+
unusedValue: () => {
|
2307
|
+
optUnused = true;
|
2308
|
+
return unusedValue;
|
2309
|
+
},
|
2310
|
+
setType: type => setLastType(scope, type)
|
2374
2311
|
});
|
2375
2312
|
|
2376
2313
|
return [
|
2377
2314
|
[ Opcodes.block, unusedValue ? Blocktype.void : valtypeBinary ],
|
2378
2315
|
...protoOut,
|
2379
|
-
...(unusedValue && optUnused ? [] : (protoFunc.returnType != null ? setLastType(scope, protoFunc.returnType) : setLastType(scope))),
|
2380
2316
|
...(unusedValue && !optUnused ? [ [ Opcodes.drop ] ] : []),
|
2381
2317
|
[ Opcodes.end ]
|
2382
2318
|
];
|
@@ -2774,8 +2710,19 @@ const generateThis = (scope, decl) => {
|
|
2774
2710
|
];
|
2775
2711
|
};
|
2776
2712
|
|
2777
|
-
const generateSuper = (scope, decl) => generate(scope,
|
2778
|
-
|
2713
|
+
const generateSuper = (scope, decl) => generate(scope, {
|
2714
|
+
type: 'CallExpression',
|
2715
|
+
callee: { type: 'Identifier', name: '__Porffor_object_getPrototype' },
|
2716
|
+
arguments: [
|
2717
|
+
{
|
2718
|
+
type: 'CallExpression',
|
2719
|
+
callee: { type: 'Identifier', name: '__Porffor_object_getPrototype' },
|
2720
|
+
arguments: [
|
2721
|
+
{ type: 'ThisExpression', _noGlobalThis: true }
|
2722
|
+
]
|
2723
|
+
}
|
2724
|
+
]
|
2725
|
+
});
|
2779
2726
|
|
2780
2727
|
// bad hack for undefined and null working without additional logic
|
2781
2728
|
const DEFAULT_VALUE = () => ({
|
@@ -3160,8 +3107,6 @@ const extractTypeAnnotation = decl => {
|
|
3160
3107
|
const typeName = type;
|
3161
3108
|
type = typeAnnoToPorfType(type);
|
3162
3109
|
|
3163
|
-
// if (decl.name) console.log(decl.name, { type, elementType });
|
3164
|
-
|
3165
3110
|
return { type, typeName, elementType };
|
3166
3111
|
};
|
3167
3112
|
|
@@ -3587,6 +3532,8 @@ const memberTmpNames = scope => {
|
|
3587
3532
|
|
3588
3533
|
// COCTC: cross-object compile-time cache
|
3589
3534
|
const coctcOffset = prop => {
|
3535
|
+
if (!Prefs.coctc) return 0;
|
3536
|
+
|
3590
3537
|
if (typeof prop === 'object') {
|
3591
3538
|
if (
|
3592
3539
|
prop.computed || prop.optional ||
|
@@ -3727,7 +3674,7 @@ const generateAssign = (scope, decl, _global, _name, valueUnused = false) => {
|
|
3727
3674
|
// todo/perf: use i32 object (and prop?) locals
|
3728
3675
|
const { objectTmp, propertyTmp, objectGet, propertyGet } = memberTmpNames(scope);
|
3729
3676
|
|
3730
|
-
const useCoctc =
|
3677
|
+
const useCoctc = coctcOffset(decl.left) > 0;
|
3731
3678
|
if (useCoctc) valueUnused = false;
|
3732
3679
|
|
3733
3680
|
// opt: do not mark prototype funcs as referenced to optimize this in them
|
@@ -4173,7 +4120,7 @@ const generateUnary = (scope, decl) => {
|
|
4173
4120
|
const property = getProperty(decl.argument);
|
4174
4121
|
if (property.value === 'length' || property.value === 'name') scope.noFastFuncMembers = true;
|
4175
4122
|
|
4176
|
-
const useCoctc =
|
4123
|
+
const useCoctc = coctcOffset(decl.argument) > 0;
|
4177
4124
|
const objectTmp = useCoctc && localTmp(scope, '#coctc_object', Valtype.i32);
|
4178
4125
|
|
4179
4126
|
const out = [
|
@@ -4887,7 +4834,7 @@ const generateForIn = (scope, decl) => {
|
|
4887
4834
|
|
4888
4835
|
// get length
|
4889
4836
|
[ Opcodes.local_get, pointer ],
|
4890
|
-
[ Opcodes.
|
4837
|
+
[ Opcodes.i32_load16_u, 0, 0 ],
|
4891
4838
|
[ Opcodes.local_tee, length ],
|
4892
4839
|
|
4893
4840
|
[ Opcodes.if, Blocktype.void ]
|
@@ -4920,7 +4867,7 @@ const generateForIn = (scope, decl) => {
|
|
4920
4867
|
|
4921
4868
|
// read key
|
4922
4869
|
[ Opcodes.local_get, pointer ],
|
4923
|
-
[ Opcodes.i32_load, 0,
|
4870
|
+
[ Opcodes.i32_load, 0, 12 ],
|
4924
4871
|
[ Opcodes.local_tee, tmp ],
|
4925
4872
|
|
4926
4873
|
...setType(scope, tmpName, [
|
@@ -4952,7 +4899,7 @@ const generateForIn = (scope, decl) => {
|
|
4952
4899
|
// todo/perf: do not read key for non-enumerables
|
4953
4900
|
// only run body if entry is enumerable
|
4954
4901
|
[ Opcodes.local_get, pointer ],
|
4955
|
-
[ Opcodes.i32_load8_u, 0,
|
4902
|
+
[ Opcodes.i32_load8_u, 0, 24 ],
|
4956
4903
|
[ Opcodes.i32_const, 0b0100 ],
|
4957
4904
|
[ Opcodes.i32_and ],
|
4958
4905
|
[ Opcodes.if, Blocktype.void ],
|
@@ -4960,9 +4907,9 @@ const generateForIn = (scope, decl) => {
|
|
4960
4907
|
[ Opcodes.drop ],
|
4961
4908
|
[ Opcodes.end ],
|
4962
4909
|
|
4963
|
-
// increment pointer by
|
4910
|
+
// increment pointer by 18
|
4964
4911
|
[ Opcodes.local_get, pointer ],
|
4965
|
-
number(
|
4912
|
+
number(18, Valtype.i32),
|
4966
4913
|
[ Opcodes.i32_add ],
|
4967
4914
|
[ Opcodes.local_set, pointer ],
|
4968
4915
|
|
@@ -5694,7 +5641,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
5694
5641
|
|
5695
5642
|
const out = [
|
5696
5643
|
...generate(scope, object),
|
5697
|
-
Opcodes.i32_to_u
|
5644
|
+
Opcodes.i32_to_u
|
5698
5645
|
];
|
5699
5646
|
|
5700
5647
|
if (Prefs.fastLength) {
|
@@ -5721,7 +5668,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
5721
5668
|
...out,
|
5722
5669
|
[ Opcodes.local_set, tmp ],
|
5723
5670
|
|
5724
|
-
...
|
5671
|
+
...type,
|
5725
5672
|
number(TYPE_FLAGS.length, Valtype.i32),
|
5726
5673
|
[ Opcodes.i32_and ],
|
5727
5674
|
[ Opcodes.if, valtypeBinary ],
|
@@ -5743,6 +5690,8 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
5743
5690
|
|
5744
5691
|
// todo/perf: use i32 object (and prop?) locals
|
5745
5692
|
const { objectTmp, propertyTmp, objectGet, propertyGet } = memberTmpNames(scope);
|
5693
|
+
const type = getNodeType(scope, object);
|
5694
|
+
const known = knownType(scope, type);
|
5746
5695
|
|
5747
5696
|
// todo: generate this array procedurally during builtinFuncs creation
|
5748
5697
|
if (['size', 'description', 'byteLength', 'byteOffset', 'buffer', 'detached', 'resizable', 'growable', 'maxByteLength'].includes(decl.property.name)) {
|
@@ -5750,7 +5699,6 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
5750
5699
|
const bc = {};
|
5751
5700
|
const cands = Object.keys(builtinFuncs).filter(x => x.startsWith('__') && x.endsWith('_prototype_' + decl.property.name + '$get'));
|
5752
5701
|
|
5753
|
-
const known = knownType(scope, getNodeType(scope, object));
|
5754
5702
|
if (cands.length > 0) {
|
5755
5703
|
for (const x of cands) {
|
5756
5704
|
const type = TYPES[x.split('_prototype_')[0].slice(2).toLowerCase()];
|
@@ -5786,64 +5734,10 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
5786
5734
|
if (known == null) extraBC = bc;
|
5787
5735
|
}
|
5788
5736
|
|
5789
|
-
|
5790
|
-
// todo: support optional
|
5791
|
-
const bc = {};
|
5792
|
-
const prototypes = Object.keys(builtinVars).filter(x => x.endsWith('_prototype'));
|
5793
|
-
|
5794
|
-
const known = knownType(scope, getNodeType(scope, decl.object));
|
5795
|
-
for (const x of prototypes) {
|
5796
|
-
let type = TYPES[x.split('_prototype')[0].slice(2).toLowerCase()];
|
5797
|
-
if (type == null) continue;
|
5798
|
-
|
5799
|
-
// do not __proto__ primitive hack for objects or functions
|
5800
|
-
if (type === TYPES.object || type === TYPES.function) continue;
|
5801
|
-
|
5802
|
-
// hack: do not support primitives for Object.prototype.isPrototypeOf
|
5803
|
-
if (scope.name === '__Object_prototype_isPrototypeOf') {
|
5804
|
-
switch (type) {
|
5805
|
-
case TYPES.boolean:
|
5806
|
-
type = TYPES.booleanobject;
|
5807
|
-
break;
|
5808
|
-
|
5809
|
-
case TYPES.number:
|
5810
|
-
type = TYPES.numberobject;
|
5811
|
-
break;
|
5812
|
-
|
5813
|
-
case TYPES.string:
|
5814
|
-
type = TYPES.stringobject;
|
5815
|
-
break;
|
5816
|
-
|
5817
|
-
case TYPES.bytestring:
|
5818
|
-
continue;
|
5819
|
-
}
|
5820
|
-
}
|
5821
|
-
|
5822
|
-
const ident = {
|
5823
|
-
type: 'Identifier',
|
5824
|
-
name: x
|
5825
|
-
};
|
5826
|
-
|
5827
|
-
// hack: bytestrings should return string prototype
|
5828
|
-
if (type === TYPES.bytestring) ident.name = '__String_prototype';
|
5829
|
-
|
5830
|
-
bc[type] = () => [
|
5831
|
-
...generate(scope, ident),
|
5832
|
-
...setLastType(scope, getNodeType(scope, ident))
|
5833
|
-
];
|
5834
|
-
if (type === known) return bc[type]();
|
5835
|
-
}
|
5836
|
-
|
5837
|
-
if (known == null) {
|
5838
|
-
aliasPrimObjsBC(bc);
|
5839
|
-
extraBC = bc;
|
5840
|
-
}
|
5841
|
-
}
|
5842
|
-
|
5843
|
-
const useCoctc = Prefs.coctc && coctcOffset(decl) > 0;
|
5737
|
+
const useCoctc = coctcOffset(decl) > 0;
|
5844
5738
|
const coctcObjTmp = useCoctc && localTmp(scope, '#coctc_obj' + uniqId(), Valtype.i32);
|
5845
5739
|
|
5846
|
-
const out = typeSwitch(scope,
|
5740
|
+
const out = typeSwitch(scope, type, {
|
5847
5741
|
...(decl.computed ? {
|
5848
5742
|
[TYPES.array]: () => [
|
5849
5743
|
propertyGet,
|
@@ -6009,22 +5903,17 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
6009
5903
|
}),
|
6010
5904
|
} : {}),
|
6011
5905
|
|
6012
|
-
[TYPES.undefined]: internalThrow(scope, 'TypeError',
|
5906
|
+
[TYPES.undefined]: internalThrow(scope, 'TypeError', `Cannot read property of undefined`, true),
|
6013
5907
|
|
6014
|
-
// default: internalThrow(scope, 'TypeError', 'Unsupported member expression object', true)
|
6015
5908
|
default: () => [
|
6016
|
-
|
6017
|
-
|
6018
|
-
|
6019
|
-
|
6020
|
-
|
6021
|
-
|
6022
|
-
|
6023
|
-
|
6024
|
-
|
6025
|
-
objectGet,
|
6026
|
-
Opcodes.i32_to,
|
6027
|
-
...getNodeType(scope, object),
|
5909
|
+
...(useCoctc && known === TYPES.object ? [
|
5910
|
+
[ Opcodes.local_get, coctcObjTmp ],
|
5911
|
+
number(TYPES.object, Valtype.i32)
|
5912
|
+
] : [
|
5913
|
+
objectGet,
|
5914
|
+
Opcodes.i32_to,
|
5915
|
+
...type
|
5916
|
+
]),
|
6028
5917
|
|
6029
5918
|
...toPropertyKey(scope, [ propertyGet ], getNodeType(scope, property), decl.computed, true),
|
6030
5919
|
|
@@ -6044,7 +5933,7 @@ const generateMember = (scope, decl, _global, _name) => {
|
|
6044
5933
|
...generate(scope, object),
|
6045
5934
|
[ Opcodes.local_tee, objectTmp ],
|
6046
5935
|
|
6047
|
-
...nullish(scope, [],
|
5936
|
+
...nullish(scope, [], type, false, true),
|
6048
5937
|
[ Opcodes.if, Blocktype.void ],
|
6049
5938
|
...setLastType(scope, TYPES.undefined),
|
6050
5939
|
number(0),
|
@@ -6164,10 +6053,25 @@ const generateClass = (scope, decl) => {
|
|
6164
6053
|
// class Foo {}
|
6165
6054
|
// class Bar extends Foo {}
|
6166
6055
|
// Bar.__proto__ = Foo
|
6167
|
-
|
6168
|
-
|
6056
|
+
...generate(scope, {
|
6057
|
+
type: 'CallExpression',
|
6058
|
+
callee: { type: 'Identifier', name: '__Porffor_object_setPrototype' },
|
6059
|
+
arguments: [
|
6060
|
+
root,
|
6061
|
+
decl.superClass
|
6062
|
+
]
|
6063
|
+
}),
|
6169
6064
|
[ Opcodes.drop ],
|
6170
|
-
|
6065
|
+
|
6066
|
+
// Bar.prototype.__proto__ = Foo.prototype
|
6067
|
+
...generate(scope, {
|
6068
|
+
type: 'CallExpression',
|
6069
|
+
callee: { type: 'Identifier', name: '__Porffor_object_setPrototype' },
|
6070
|
+
arguments: [
|
6071
|
+
proto,
|
6072
|
+
getObjProp(decl.superClass, 'prototype')
|
6073
|
+
]
|
6074
|
+
}),
|
6171
6075
|
[ Opcodes.drop ]
|
6172
6076
|
);
|
6173
6077
|
}
|
@@ -6354,7 +6258,7 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined, v
|
|
6354
6258
|
return funcIndex[x];
|
6355
6259
|
}
|
6356
6260
|
|
6357
|
-
return scope.locals[x]?.idx ?? globals[x].
|
6261
|
+
return scope.locals[x]?.idx ?? globals[x]?.idx ?? (log.warning('codegen', `unknown immediate in Porffor.wasm: ${x}`) || 0);
|
6358
6262
|
}
|
6359
6263
|
|
6360
6264
|
return n;
|
@@ -6428,7 +6332,6 @@ const objectHack = node => {
|
|
6428
6332
|
|
6429
6333
|
// hack: block these properties as they can be accessed on functions
|
6430
6334
|
if (node.object.name !== 'Porffor' && (node.property.name === 'length' || node.property.name === 'name' || node.property.name === 'call')) return abortOut;
|
6431
|
-
|
6432
6335
|
if (node.property.name === '__proto__') return abortOut;
|
6433
6336
|
|
6434
6337
|
let objectName = node.object.name;
|
@@ -7035,39 +6938,6 @@ export default program => {
|
|
7035
6938
|
f.wasm = f.returns.map(x => number(0, x));
|
7036
6939
|
}
|
7037
6940
|
|
7038
|
-
// // remove never generated functions
|
7039
|
-
// let indexDelta = 0;
|
7040
|
-
// const funcRemap = new Map();
|
7041
|
-
// for (let i = 0; i < funcs.length; i++) {
|
7042
|
-
// const f = funcs[i];
|
7043
|
-
// if (f.internal || f.wasm) {
|
7044
|
-
// if (indexDelta) {
|
7045
|
-
// funcRemap.set(f.index, f.index - indexDelta);
|
7046
|
-
// f.index -= indexDelta;
|
7047
|
-
// }
|
7048
|
-
// continue;
|
7049
|
-
// }
|
7050
|
-
|
7051
|
-
// funcs.splice(i--, 1);
|
7052
|
-
// indexDelta++;
|
7053
|
-
// }
|
7054
|
-
|
7055
|
-
// // remap call ops
|
7056
|
-
// if (indexDelta) for (let i = 0; i < funcs.length; i++) {
|
7057
|
-
// const wasm = funcs[i].wasm;
|
7058
|
-
// for (let j = 0; j < wasm.length; j++) {
|
7059
|
-
// const op = wasm[j];
|
7060
|
-
// if (op[0] === Opcodes.call) {
|
7061
|
-
// let idx = op[1];
|
7062
|
-
// wasm[j] = [ Opcodes.call, funcRemap.get(idx) ?? idx ];
|
7063
|
-
// }
|
7064
|
-
|
7065
|
-
// if (op[0] === Opcodes.const && op[2] === 'funcref') {
|
7066
|
-
// wasm[j] = [ Opcodes.const, funcRemap.get(op[1] + importedFuncs.length) - importedFuncs.length ];
|
7067
|
-
// }
|
7068
|
-
// }
|
7069
|
-
// }
|
7070
|
-
|
7071
6941
|
// add indirect funcs to end of funcs
|
7072
6942
|
for (let i = 0; i < indirectFuncs.length; i++) {
|
7073
6943
|
const f = indirectFuncs[i];
|
package/compiler/precompile.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
2
|
import { read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
|
3
|
-
import { TYPES } from './types.js';
|
3
|
+
import { TYPES, TYPE_NAMES } from './types.js';
|
4
4
|
import { log } from './log.js';
|
5
5
|
|
6
6
|
import process from 'node:process';
|
@@ -41,7 +41,7 @@ const compile = async (file, _funcs) => {
|
|
41
41
|
let first = source.slice(0, source.indexOf('\n'));
|
42
42
|
|
43
43
|
if (first.startsWith('export default')) {
|
44
|
-
source = await (await import('file://' + file)).default();
|
44
|
+
source = await (await import('file://' + file)).default({ TYPES, TYPE_NAMES });
|
45
45
|
first = source.slice(0, source.indexOf('\n'));
|
46
46
|
}
|
47
47
|
|
@@ -155,11 +155,10 @@ const compile = async (file, _funcs) => {
|
|
155
155
|
}
|
156
156
|
|
157
157
|
if (n[0] === Opcodes.throw) {
|
158
|
-
if (!bodyHasTopLevelThrow && depth === 0) log.warning('codegen', `top-level throw in ${x.name}`);
|
159
|
-
|
160
158
|
x.usesTag = true;
|
159
|
+
let id;
|
161
160
|
if (y[0] === Opcodes.i32_const && n[1] === 0) {
|
162
|
-
|
161
|
+
id = read_signedLEB128(y.slice(1));
|
163
162
|
y.splice(0, 10, 'throw', exceptions[id].constructor, exceptions[id].message);
|
164
163
|
|
165
164
|
// remove throw inst
|
@@ -167,6 +166,8 @@ const compile = async (file, _funcs) => {
|
|
167
166
|
} else {
|
168
167
|
n[1]--;
|
169
168
|
}
|
169
|
+
|
170
|
+
if (!bodyHasTopLevelThrow && depth === 0) log.warning('codegen', `top-level throw in ${x.name} (${exceptions[id].constructor}: ${exceptions[id].message})`);
|
170
171
|
}
|
171
172
|
|
172
173
|
if (n[0] === Opcodes.catch) {
|