porffor 0.34.8 → 0.34.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/compiler/assemble.js +50 -27
- package/compiler/builtins/__internal_object.ts +7 -2
- package/compiler/builtins/_internal_object.ts +24 -0
- package/compiler/builtins/date.ts +3 -11
- package/compiler/builtins_precompiled.js +8 -3
- package/compiler/codegen.js +38 -9
- package/compiler/decompile.js +1 -1
- package/compiler/precompile.js +1 -0
- package/package.json +1 -1
- package/runner/index.js +1 -1
package/compiler/assemble.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Valtype, FuncType, ExportDesc, Section, Magic, ModuleVersion, Opcodes, PageSize, Reftype } from './wasmSpec.js';
|
2
|
-
import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128, unsignedLEB128_into, signedLEB128_into, ieee754_binary64_into } from './encoding.js';
|
2
|
+
import { encodeVector, encodeString, encodeLocal, unsignedLEB128, signedLEB128, unsignedLEB128_into, signedLEB128_into, ieee754_binary64, ieee754_binary64_into } from './encoding.js';
|
3
3
|
import { importedFuncs } from './builtins.js';
|
4
4
|
import { log } from './log.js';
|
5
5
|
import {} from './prefs.js';
|
@@ -72,6 +72,14 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
72
72
|
return typeCache[hash] = idx;
|
73
73
|
};
|
74
74
|
|
75
|
+
let t = performance.now();
|
76
|
+
const time = msg => {
|
77
|
+
if (!Prefs.profileAssemble) return;
|
78
|
+
|
79
|
+
console.log(`${' '.repeat(50)}\r[${(performance.now() - t).toFixed(2)}ms] ${msg}`);
|
80
|
+
t = performance.now();
|
81
|
+
};
|
82
|
+
|
75
83
|
let importFuncs = [], importDelta = 0;
|
76
84
|
if (optLevel < 1 || !Prefs.treeshakeWasmImports || noTreeshake) {
|
77
85
|
importFuncs = importedFuncs;
|
@@ -81,7 +89,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
81
89
|
// tree shake imports
|
82
90
|
for (const f of funcs) {
|
83
91
|
for (const inst of f.wasm) {
|
84
|
-
if ((inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) && inst[1] < importedFuncs.length) {
|
92
|
+
if ((inst[0] === Opcodes.call /* || inst[0] === Opcodes.return_call */) && inst[1] < importedFuncs.length) {
|
85
93
|
const idx = inst[1];
|
86
94
|
const func = importedFuncs[idx];
|
87
95
|
|
@@ -95,24 +103,25 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
95
103
|
importDelta = importedFuncs.length - importFuncs.length;
|
96
104
|
}
|
97
105
|
|
98
|
-
// fix call indexes for non-imports
|
99
|
-
// also fix call_indirect types
|
100
|
-
// also encode call indexes
|
101
106
|
for (const f of funcs) {
|
102
107
|
f.asmIndex = f.index - importDelta;
|
103
108
|
}
|
104
109
|
|
110
|
+
time('treeshake import funcs');
|
111
|
+
|
105
112
|
if (Prefs.optLog) log('assemble', `treeshake: using ${importFuncs.length}/${importedFuncs.length} imports`);
|
106
113
|
|
107
114
|
const importSection = importFuncs.length === 0 ? [] : createSection(
|
108
115
|
Section.import,
|
109
116
|
encodeVector(importFuncs.map(x => [ 0, ...encodeString(x.import), ExportDesc.func, getType(typeof x.params === 'object' ? x.params : new Array(x.params).fill(valtypeBinary), new Array(x.returns).fill(valtypeBinary)) ]))
|
110
117
|
);
|
118
|
+
time('import section');
|
111
119
|
|
112
120
|
const funcSection = createSection(
|
113
121
|
Section.func,
|
114
122
|
encodeVector(funcs.map(x => getType(x.params, x.returns))) // type indexes
|
115
123
|
);
|
124
|
+
time('func section');
|
116
125
|
|
117
126
|
const nameSection = Prefs.d ? customSection('name', encodeNames(funcs)) : [];
|
118
127
|
|
@@ -120,6 +129,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
120
129
|
Section.table,
|
121
130
|
encodeVector([ [ Reftype.funcref, 0x00, ...unsignedLEB128(funcs.length) ] ])
|
122
131
|
);
|
132
|
+
time('table section');
|
123
133
|
|
124
134
|
const elementSection = !funcs.table ? [] : createSection(
|
125
135
|
Section.element,
|
@@ -129,6 +139,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
129
139
|
...encodeVector(funcs.map(x => unsignedLEB128(x.asmIndex)))
|
130
140
|
] ])
|
131
141
|
);
|
142
|
+
time('element section');
|
132
143
|
|
133
144
|
if (pages.has('func lut')) {
|
134
145
|
const offset = pages.get('func lut').ind * pageSize;
|
@@ -181,8 +192,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
181
192
|
});
|
182
193
|
data.addedFuncArgcLut = true;
|
183
194
|
}
|
184
|
-
|
185
|
-
// const t0 = performance.now();
|
195
|
+
time('func lut');
|
186
196
|
|
187
197
|
// specially optimized assembly for globals as this version is much (>5x) faster than traditional createSection()
|
188
198
|
const globalsValues = Object.values(globals);
|
@@ -224,17 +234,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
224
234
|
unsignedLEB128_into(data.length, globalSection);
|
225
235
|
globalSection = globalSection.concat(data);
|
226
236
|
}
|
227
|
-
|
228
|
-
// if (Prefs.profileCompiler) {
|
229
|
-
// const log = console.log;
|
230
|
-
// console.log = function () {
|
231
|
-
// log.apply(this, arguments);
|
232
|
-
// console.log = log;
|
233
|
-
// console.log(` a. assembled global section in ${(performance.now() - t0).toFixed(2)}ms\n`);
|
234
|
-
// };
|
235
|
-
// }
|
236
|
-
|
237
|
-
const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, ...unsignedLEB128(x.asmIndex) ]);
|
237
|
+
time('global section');
|
238
238
|
|
239
239
|
if (Prefs.alwaysMemory && pages.size === 0) pages.set('--always-memory', 0);
|
240
240
|
if (optLevel === 0) pages.set('O0 precaution', 0);
|
@@ -244,9 +244,13 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
244
244
|
Section.memory,
|
245
245
|
encodeVector([ [ 0x00, ...unsignedLEB128(Math.ceil((pages.size * pageSize) / PageSize)) ] ])
|
246
246
|
);
|
247
|
+
time('memory section');
|
248
|
+
|
249
|
+
const exports = funcs.filter(x => x.export).map((x, i) => [ ...encodeString(x.name === 'main' ? 'm' : x.name), ExportDesc.func, ...unsignedLEB128(x.asmIndex) ]);
|
247
250
|
|
248
251
|
// export memory if used
|
249
252
|
if (usesMemory) exports.unshift([ ...encodeString('$'), ExportDesc.mem, 0x00 ]);
|
253
|
+
time('gen exports');
|
250
254
|
|
251
255
|
const tagSection = tags.length === 0 ? [] : createSection(
|
252
256
|
Section.tag,
|
@@ -255,16 +259,20 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
255
259
|
|
256
260
|
// export first tag if used
|
257
261
|
if (tags.length !== 0) exports.unshift([ ...encodeString('0'), ExportDesc.tag, 0x00 ]);
|
262
|
+
time('tag section');
|
258
263
|
|
259
264
|
const exportSection = createSection(
|
260
265
|
Section.export,
|
261
266
|
encodeVector(exports)
|
262
267
|
);
|
268
|
+
time('export section');
|
263
269
|
|
264
270
|
const codeSection = createSection(
|
265
271
|
Section.code,
|
266
272
|
encodeVector(funcs.map(x => {
|
267
|
-
|
273
|
+
// time(x.name);
|
274
|
+
const locals = Object.values(x.locals).sort((a, b) => a.idx - b.idx).slice(x.params.length);
|
275
|
+
// time(' locals gen');
|
268
276
|
|
269
277
|
let localDecl = [], typeCount = 0, lastType;
|
270
278
|
for (let i = 0; i < locals.length; i++) {
|
@@ -279,6 +287,7 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
279
287
|
}
|
280
288
|
|
281
289
|
if (typeCount !== 0) localDecl.push(encodeLocal(typeCount, lastType));
|
290
|
+
// time(' localDecl gen');
|
282
291
|
|
283
292
|
const makeAssembled = Prefs.d;
|
284
293
|
let wasm = [], wasmNonFlat = [];
|
@@ -287,7 +296,8 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
287
296
|
|
288
297
|
// encode local/global ops as unsigned leb128 from raw number
|
289
298
|
if (
|
290
|
-
(o[0] === Opcodes.local_get || o[0] === Opcodes.local_set || o[0] === Opcodes.local_tee || o[0] === Opcodes.global_get || o[0] === Opcodes.global_set) &&
|
299
|
+
// (o[0] === Opcodes.local_get || o[0] === Opcodes.local_set || o[0] === Opcodes.local_tee || o[0] === Opcodes.global_get || o[0] === Opcodes.global_set) &&
|
300
|
+
(o[0] >= Opcodes.local_get && o[0] <= Opcodes.global_set) &&
|
291
301
|
o[1] > 127
|
292
302
|
) {
|
293
303
|
const n = o[1];
|
@@ -298,14 +308,17 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
298
308
|
// encode f64.const ops as ieee754 from raw number
|
299
309
|
if (o[0] === Opcodes.f64_const) {
|
300
310
|
const n = o[1];
|
301
|
-
o = [ o[0] ];
|
302
|
-
ieee754_binary64_into(n, o);
|
311
|
+
// o = [ o[0] ];
|
312
|
+
// ieee754_binary64_into(n, o);
|
313
|
+
o = ieee754_binary64(n);
|
314
|
+
if (o.length === 8) o.unshift(Opcodes.f64_const);
|
303
315
|
}
|
304
316
|
|
305
317
|
// encode call ops as unsigned leb128 from raw number
|
306
|
-
if ((o[0] === Opcodes.call || o[0] === Opcodes.return_call) && o[1] >= importedFuncs.length) {
|
318
|
+
if ((o[0] === Opcodes.call /* || o[0] === Opcodes.return_call */) && o[1] >= importedFuncs.length) {
|
307
319
|
const n = o[1] - importDelta;
|
308
|
-
o = [ o[0] ];
|
320
|
+
// o = [ o[0] ];
|
321
|
+
o = [ Opcodes.call ];
|
309
322
|
unsignedLEB128_into(n, o);
|
310
323
|
}
|
311
324
|
|
@@ -334,27 +347,35 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
334
347
|
|
335
348
|
if (makeAssembled) wasmNonFlat.push(o);
|
336
349
|
}
|
350
|
+
// time(' wasm transform');
|
337
351
|
|
338
352
|
if (makeAssembled) {
|
339
353
|
x.assembled = { localDecl, wasm, wasmNonFlat };
|
340
354
|
}
|
341
355
|
|
342
|
-
|
356
|
+
let out = unsignedLEB128(localDecl.length)
|
357
|
+
.concat(localDecl.flat(), wasm, Opcodes.end);
|
358
|
+
|
359
|
+
out.unshift(...unsignedLEB128(out.length));
|
360
|
+
|
361
|
+
// time(' finish');
|
362
|
+
return out;
|
343
363
|
}))
|
344
364
|
);
|
365
|
+
time('code section');
|
345
366
|
|
346
367
|
const typeSection = createSection(
|
347
368
|
Section.type,
|
348
369
|
encodeVector(types)
|
349
370
|
);
|
371
|
+
time('type section');
|
350
372
|
|
351
373
|
const dataSection = data.length === 0 ? [] : createSection(
|
352
374
|
Section.data,
|
353
375
|
encodeVector(data.map(x => {
|
354
376
|
if (Prefs.d && x.bytes.length > PageSize) log.warning('assemble', `data (${x.page}) has more bytes than Wasm page size! (${x.bytes.length})`);
|
355
377
|
|
356
|
-
const bytes =
|
357
|
-
|
378
|
+
const bytes = unsignedLEB128(x.bytes.length).concat(x.bytes);
|
358
379
|
if (x.page != null) {
|
359
380
|
// type: active
|
360
381
|
let offset = pages.get(x.page).ind * pageSize;
|
@@ -368,11 +389,13 @@ export default (funcs, globals, tags, pages, data, flags, noTreeshake = false) =
|
|
368
389
|
return bytes;
|
369
390
|
}))
|
370
391
|
);
|
392
|
+
time('data section');
|
371
393
|
|
372
394
|
const dataCountSection = data.length === 0 ? [] : createSection(
|
373
395
|
Section.data_count,
|
374
396
|
unsignedLEB128(data.length)
|
375
397
|
);
|
398
|
+
time('datacount section');
|
376
399
|
|
377
400
|
if (Prefs.sections) console.log({
|
378
401
|
typeSection: typeSection.map(x => x.toString(16)),
|
@@ -5,8 +5,13 @@ export const __Porffor_object_getObject = (obj: any): any => {
|
|
5
5
|
let underlying: object = underlyingFuncObjs.get(funcI32);
|
6
6
|
if (underlying == null) {
|
7
7
|
underlying = {};
|
8
|
-
|
9
|
-
|
8
|
+
|
9
|
+
const proto = {};
|
10
|
+
const key1: bytestring = 'prototype';
|
11
|
+
__Porffor_object_expr_initWithFlags(underlying, key1, proto, 0b1000);
|
12
|
+
|
13
|
+
const key2: bytestring = 'constructor';
|
14
|
+
__Porffor_object_expr_initWithFlags(proto, key2, obj, 0b1010);
|
10
15
|
|
11
16
|
underlyingFuncObjs.set(funcI32, underlying);
|
12
17
|
}
|
@@ -572,6 +572,30 @@ export const __Porffor_object_expr_init = (obj: any, key: any, value: any): void
|
|
572
572
|
0, 12);
|
573
573
|
};
|
574
574
|
|
575
|
+
export const __Porffor_object_expr_initWithFlags = (obj: any, key: any, value: any, flags: i32): void => {
|
576
|
+
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_getObject(obj);
|
577
|
+
let entryPtr: i32 = __Porffor_object_lookup(obj, key);
|
578
|
+
if (entryPtr == -1) {
|
579
|
+
// add new entry
|
580
|
+
// bump size +1
|
581
|
+
const size: i32 = Porffor.wasm.i32.load(obj, 0, 0);
|
582
|
+
Porffor.wasm.i32.store(obj, size + 1, 0, 0);
|
583
|
+
|
584
|
+
// entryPtr = current end of object
|
585
|
+
entryPtr = Porffor.wasm`local.get ${obj}` + 5 + size * 14;
|
586
|
+
|
587
|
+
__Porffor_object_writeKey(entryPtr, key);
|
588
|
+
}
|
589
|
+
|
590
|
+
// write new value value (lol)
|
591
|
+
Porffor.wasm.f64.store(entryPtr, value, 0, 4);
|
592
|
+
|
593
|
+
// write new tail (value type + flags)
|
594
|
+
Porffor.wasm.i32.store16(entryPtr,
|
595
|
+
flags + (Porffor.wasm`local.get ${value+1}` << 8),
|
596
|
+
0, 12);
|
597
|
+
};
|
598
|
+
|
575
599
|
// used for { get foo() {} }
|
576
600
|
export const __Porffor_object_expr_get = (obj: any, key: any, get: any): void => {
|
577
601
|
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) obj = __Porffor_object_getObject(obj);
|
@@ -1746,9 +1746,7 @@ export const __ecma262_ToDateString = (tv: number) => {
|
|
1746
1746
|
out.length = 0;
|
1747
1747
|
|
1748
1748
|
// 1. If tv is NaN, return "Invalid Date".
|
1749
|
-
if (Number.isNaN(tv))
|
1750
|
-
return out = 'Invalid Date';
|
1751
|
-
}
|
1749
|
+
if (Number.isNaN(tv)) return out = 'Invalid Date';
|
1752
1750
|
|
1753
1751
|
// 2. Let t be LocalTime(tv).
|
1754
1752
|
const t: number = __ecma262_LocalTime(tv);
|
@@ -1788,10 +1786,7 @@ export const __Date_prototype_toTimeString = (_this: Date) => {
|
|
1788
1786
|
let out: bytestring = Porffor.allocateBytes(27);
|
1789
1787
|
out.length = 0;
|
1790
1788
|
|
1791
|
-
if (Number.isNaN(tv))
|
1792
|
-
out = 'Invalid Date';
|
1793
|
-
return out;
|
1794
|
-
}
|
1789
|
+
if (Number.isNaN(tv)) return out = 'Invalid Date';
|
1795
1790
|
|
1796
1791
|
// 5. Let t be LocalTime(tv).
|
1797
1792
|
const t: number = __ecma262_LocalTime(tv);
|
@@ -1816,10 +1811,7 @@ export const __Date_prototype_toDateString = (_this: Date) => {
|
|
1816
1811
|
let out: bytestring = Porffor.allocateBytes(20);
|
1817
1812
|
out.length = 0;
|
1818
1813
|
|
1819
|
-
if (Number.isNaN(tv))
|
1820
|
-
out = 'Invalid Date';
|
1821
|
-
return out;
|
1822
|
-
}
|
1814
|
+
if (Number.isNaN(tv)) return out = 'Invalid Date';
|
1823
1815
|
|
1824
1816
|
// 5. Let t be LocalTime(tv).
|
1825
1817
|
const t: number = __ecma262_LocalTime(tv);
|
@@ -3,10 +3,10 @@ import { number } from './embedding.js';
|
|
3
3
|
|
4
4
|
export const BuiltinFuncs = function() {
|
5
5
|
this.__Porffor_object_getObject = {
|
6
|
-
wasm:(_,{glbl,builtin
|
6
|
+
wasm:(_,{allocPage,glbl,builtin})=>[[32,1],[184],[68,6],[97],[4,64],[32,0],[33,2],...glbl(35,'underlyingFuncObjs',124),[33,4],[65,20],[33,5],[32,4],[32,5],[32,2],[65,1],[16,builtin('__Map_prototype_get')],[26],[34,3],[68,0],[97],[4,64],[16,builtin('__Porffor_allocate')],[184],[33,3],[16,builtin('__Porffor_allocate')],[184],[33,7],[65,7],[33,8],...number(allocPage(_,'bytestring: __Porffor_object_getObject/key1','i8'),124),[33,9],[32,3],[252,2],[65,7],[32,9],[252,2],[65,195,1],[32,7],[32,8],[65,8],[65,1],[16,builtin('__Porffor_object_expr_initWithFlags')],[33,6],[183],[26],...number(allocPage(_,'bytestring: __Porffor_object_getObject/key2','i8'),124),[33,10],[32,7],[252,2],[32,8],[32,10],[252,2],[65,195,1],[32,0],[32,1],[65,10],[65,1],[16,builtin('__Porffor_object_expr_initWithFlags')],[33,6],[183],[26],...glbl(35,'underlyingFuncObjs',124),[33,4],[65,20],[33,5],[32,4],[32,5],[32,2],[65,1],[32,3],[65,7],[16,builtin('__Map_prototype_set')],[33,6],[26],[11],[32,3],[65,7],[15],[11],[32,0],[32,1],[15]],
|
7
7
|
params:[124,127],typedParams:1,returns:[124,127],typedReturns:1,
|
8
|
-
locals:[124,124,124,127,127,124,127,124,124
|
9
|
-
globalInits:{underlyingFuncObjs:(_,{glbl,builtin})=>[[68,1],[65,6],[16,builtin('__Porffor_allocate')],[184],[65,7],[68,0],[65,128,1],[16,builtin('Map')],[26],...glbl(36,'underlyingFuncObjs',124)]},
|
8
|
+
locals:[124,124,124,127,127,124,127,124,124],localNames:["obj","obj#type","funcI32","underlying","#proto_target","#proto_target#type","#last_type","proto","proto#type","key1","key2"],
|
9
|
+
globalInits:{underlyingFuncObjs:(_,{glbl,builtin})=>[[68,1],[65,6],[16,builtin('__Porffor_allocate')],[184],[65,7],[68,0],[65,128,1],[16,builtin('Map')],[26],...glbl(36,'underlyingFuncObjs',124)]},data:{"bytestring: __Porffor_object_getObject/key1":[9,0,0,0,112,114,111,116,111,116,121,112,101],"bytestring: __Porffor_object_getObject/key2":[11,0,0,0,99,111,110,115,116,114,117,99,116,111,114]},
|
10
10
|
};
|
11
11
|
this.__Porffor_strcmp = {
|
12
12
|
wasm:()=>[[32,0],[32,2],[70],[4,64],[65,1],[65,2],[15],[11],[32,0],[40,0,0],[33,4],[32,2],[40,0,0],[33,5],[32,4],[32,5],[71],[4,64],[65,0],[65,2],[15],[11],[32,1],[65,195,1],[70],[4,64],[32,3],[65,195,1],[70],[4,64],[65,0],[33,6],[3,64],[32,6],[32,4],[72],[4,64],[32,0],[32,6],[106],[45,0,4],[32,2],[32,6],[106],[45,0,4],[71],[4,64],[65,0],[65,2],[15],[11],[32,6],[65,1],[106],[33,6],[12,1],[11],[11],[65,1],[65,2],[15],[5],[65,0],[33,6],[3,64],[32,6],[32,4],[72],[4,64],[32,0],[32,6],[106],[45,0,4],[32,2],[32,6],[65,2],[108],[106],[47,0,4],[71],[4,64],[65,0],[65,2],[15],[11],[32,6],[65,1],[106],[33,6],[12,1],[11],[11],[65,1],[65,2],[15],[11],[5],[32,3],[65,195,1],[70],[4,64],[65,0],[33,6],[3,64],[32,6],[32,4],[72],[4,64],[32,0],[32,6],[65,2],[108],[106],[47,0,4],[32,2],[32,6],[106],[45,0,4],[71],[4,64],[65,0],[65,2],[15],[11],[32,6],[65,1],[106],[33,6],[12,1],[11],[11],[65,1],[65,2],[15],[5],[65,0],[33,6],[3,64],[32,6],[32,4],[72],[4,64],[32,0],[32,6],[65,2],[108],[106],[47,0,4],[32,2],[32,6],[65,2],[108],[106],[47,0,4],[71],[4,64],[65,0],[65,2],[15],[11],[32,6],[65,1],[106],[33,6],[12,1],[11],[11],[65,1],[65,2],[15],[11],[11],[65,0],[65,128,1],[15]],
|
@@ -105,6 +105,11 @@ wasm:(_,{builtin})=>[[32,1],[65,7],[71],[4,64],[32,0],[184],[32,1],[16,builtin('
|
|
105
105
|
params:[127,127,127,127,124,127],typedParams:1,returns:[127,127],typedReturns:1,
|
106
106
|
locals:[127,127,127],localNames:["obj","obj#type","key","key#type","value","value#type","#last_type","entryPtr","size"],
|
107
107
|
};
|
108
|
+
this.__Porffor_object_expr_initWithFlags = {
|
109
|
+
wasm:(_,{builtin})=>[[32,1],[65,7],[71],[4,64],[32,0],[184],[32,1],[16,builtin('__Porffor_object_getObject')],[33,8],[252,2],[34,0],[32,8],[33,1],[26],[11],[32,0],[32,1],[32,2],[32,3],[16,builtin('__Porffor_object_lookup')],[26],[34,9],[65,127],[70],[4,64],[32,0],[40,0,0],[33,10],[32,0],[32,10],[65,1],[106],[54,0,0],[32,0],[65,5],[106],[32,10],[65,14],[108],[106],[34,9],[65,1],[32,2],[32,3],[16,builtin('__Porffor_object_writeKey')],[33,8],[26],[11],[32,9],[32,4],[57,0,4],[32,9],[32,6],[32,5],[65,8],[116],[106],[59,0,12],[65,0],[65,128,1],[15]],
|
110
|
+
params:[127,127,127,127,124,127,127,127],typedParams:1,returns:[127,127],typedReturns:1,
|
111
|
+
locals:[127,127,127],localNames:["obj","obj#type","key","key#type","value","value#type","flags","flags#type","#last_type","entryPtr","size"],
|
112
|
+
};
|
108
113
|
this.__Porffor_object_expr_get = {
|
109
114
|
wasm:(_,{builtin})=>[[32,1],[65,7],[71],[4,64],[32,0],[184],[32,1],[16,builtin('__Porffor_object_getObject')],[33,6],[252,2],[34,0],[32,6],[33,1],[26],[11],[32,0],[32,1],[32,2],[32,3],[16,builtin('__Porffor_object_lookup')],[26],[33,7],[65,0],[33,8],[65,128,1],[33,9],[32,7],[65,127],[70],[4,64],[32,0],[40,0,0],[33,10],[32,0],[32,10],[65,1],[106],[54,0,0],[32,0],[65,5],[106],[32,10],[65,14],[108],[106],[34,7],[65,1],[32,2],[32,3],[16,builtin('__Porffor_object_writeKey')],[33,6],[26],[5],[32,7],[65,1],[16,builtin('__Porffor_object_accessorSet')],[33,9],[33,8],[11],[32,7],[32,4],[32,5],[32,8],[32,9],[16,builtin('__Porffor_object_packAccessor')],[33,6],[57,0,4],[32,7],[65,15],[65,1],[65,8],[116],[106],[59,0,12],[65,0],[65,128,1],[15]],
|
110
115
|
params:[127,127,127,127,127,127],typedParams:1,returns:[127,127],typedReturns:1,
|
package/compiler/codegen.js
CHANGED
@@ -102,7 +102,7 @@ const generate = (scope, decl, global = false, name = undefined, valueUnused = f
|
|
102
102
|
return cacheAst(decl, generateNew(scope, decl, global, name));
|
103
103
|
|
104
104
|
case 'ThisExpression':
|
105
|
-
return cacheAst(decl, generateThis(scope, decl
|
105
|
+
return cacheAst(decl, generateThis(scope, decl));
|
106
106
|
|
107
107
|
case 'Literal':
|
108
108
|
return cacheAst(decl, generateLiteral(scope, decl, global, name));
|
@@ -2629,7 +2629,7 @@ const generateNew = (scope, decl, _global, _name) => generateCall(scope, {
|
|
2629
2629
|
_new: true
|
2630
2630
|
}, _global, _name);
|
2631
2631
|
|
2632
|
-
const generateThis = (scope, decl
|
2632
|
+
const generateThis = (scope, decl) => {
|
2633
2633
|
if (!scope.constr) {
|
2634
2634
|
// this in a non-constructor context is a reference to globalThis
|
2635
2635
|
return [
|
@@ -2639,7 +2639,7 @@ const generateThis = (scope, decl, _global, _name) => {
|
|
2639
2639
|
}
|
2640
2640
|
|
2641
2641
|
// opt: do not check for pure constructors
|
2642
|
-
if (scope._onlyConstr) return [
|
2642
|
+
if (scope._onlyConstr || scope._onlyThisMethod || decl._noGlobalThis) return [
|
2643
2643
|
[ Opcodes.local_get, scope.locals['#this'].idx ],
|
2644
2644
|
...setLastType(scope, [ [ Opcodes.local_get, scope.locals['#this#type'].idx ] ])
|
2645
2645
|
];
|
@@ -5163,7 +5163,7 @@ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
|
5163
5163
|
|
5164
5164
|
for (const x of decl.properties) {
|
5165
5165
|
// method, shorthand are made into useful values by parser for us :)
|
5166
|
-
|
5166
|
+
let { type, argument, computed, kind, key, value } = x;
|
5167
5167
|
|
5168
5168
|
if (type === 'SpreadElement') {
|
5169
5169
|
out.push(
|
@@ -5189,6 +5189,18 @@ const generateObject = (scope, decl, global = false, name = '$undeclared') => {
|
|
5189
5189
|
value: key.name
|
5190
5190
|
};
|
5191
5191
|
|
5192
|
+
if (isFuncType(value.type)) {
|
5193
|
+
let id = value.id;
|
5194
|
+
|
5195
|
+
// todo: support computed names properly
|
5196
|
+
if (typeof k.value === 'string') id ??= {
|
5197
|
+
type: 'Identifier',
|
5198
|
+
name: k.value
|
5199
|
+
};
|
5200
|
+
|
5201
|
+
value = { ...value, id };
|
5202
|
+
}
|
5203
|
+
|
5192
5204
|
out.push(
|
5193
5205
|
[ Opcodes.local_get, tmp ],
|
5194
5206
|
...number(TYPES.object, Valtype.i32),
|
@@ -5695,7 +5707,7 @@ const generateClass = (scope, decl) => {
|
|
5695
5707
|
body: []
|
5696
5708
|
}
|
5697
5709
|
}),
|
5698
|
-
id: root
|
5710
|
+
id: root
|
5699
5711
|
};
|
5700
5712
|
|
5701
5713
|
const [ func, out ] = generateFunc(scope, {
|
@@ -5759,11 +5771,28 @@ const generateClass = (scope, decl) => {
|
|
5759
5771
|
outArr = func.wasm;
|
5760
5772
|
outOp = 'unshift';
|
5761
5773
|
object = {
|
5762
|
-
type: 'ThisExpression'
|
5774
|
+
type: 'ThisExpression',
|
5775
|
+
_noGlobalThis: true
|
5763
5776
|
};
|
5764
5777
|
outScope = func;
|
5765
5778
|
}
|
5766
5779
|
|
5780
|
+
if (isFuncType(value.type) && type === 'MethodDefinition') {
|
5781
|
+
let id = value.id;
|
5782
|
+
|
5783
|
+
// todo: support computed names properly
|
5784
|
+
if (typeof k.value === 'string') id ??= {
|
5785
|
+
type: 'Identifier',
|
5786
|
+
name: k.value
|
5787
|
+
};
|
5788
|
+
|
5789
|
+
value = {
|
5790
|
+
...value,
|
5791
|
+
id,
|
5792
|
+
_onlyThisMethod: true
|
5793
|
+
};
|
5794
|
+
}
|
5795
|
+
|
5767
5796
|
outArr[outOp](
|
5768
5797
|
...generate(outScope, object),
|
5769
5798
|
Opcodes.i32_to_u,
|
@@ -5884,7 +5913,7 @@ const generateFunc = (scope, decl, outUnused = false) => {
|
|
5884
5913
|
(decl.type && decl.type !== 'ArrowFunctionExpression' && decl.type !== 'Program') &&
|
5885
5914
|
// not async or generator
|
5886
5915
|
!decl.async && !decl.generator,
|
5887
|
-
_onlyConstr: decl._onlyConstr,
|
5916
|
+
_onlyConstr: decl._onlyConstr, _onlyThisMethod: decl._onlyThisMethod,
|
5888
5917
|
strict: scope.strict,
|
5889
5918
|
|
5890
5919
|
generate() {
|
@@ -5941,7 +5970,7 @@ const generateFunc = (scope, decl, outUnused = false) => {
|
|
5941
5970
|
// todo: wrap in try and reject thrown value once supported
|
5942
5971
|
}
|
5943
5972
|
|
5944
|
-
if (!globalThis.precompile && func.constr) {
|
5973
|
+
if (!globalThis.precompile && func.constr && !func._onlyThisMethod) {
|
5945
5974
|
wasm.unshift(
|
5946
5975
|
// opt: do not check for pure constructors
|
5947
5976
|
...(func._onlyConstr ? [] : [
|
@@ -5951,7 +5980,7 @@ const generateFunc = (scope, decl, outUnused = false) => {
|
|
5951
5980
|
[ Opcodes.if, Blocktype.void ],
|
5952
5981
|
]),
|
5953
5982
|
// set prototype of this ;)
|
5954
|
-
...generate(func, setObjProp({ type: 'ThisExpression' }, '__proto__', getObjProp(func.name, 'prototype'))),
|
5983
|
+
...generate(func, setObjProp({ type: 'ThisExpression', _noGlobalThis: true }, '__proto__', getObjProp(func.name, 'prototype'))),
|
5955
5984
|
...(func._onlyConstr ? [] : [ [ Opcodes.end ] ])
|
5956
5985
|
);
|
5957
5986
|
}
|
package/compiler/decompile.js
CHANGED
@@ -99,7 +99,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
|
|
99
99
|
|
100
100
|
if (inst[0] === Opcodes.call || inst[0] === Opcodes.return_call) {
|
101
101
|
const idx = inst[1];
|
102
|
-
const callFunc = funcs.find(x =>
|
102
|
+
const callFunc = funcs.find(x => x.index === idx);
|
103
103
|
if (callFunc) out += ` ;; $${callFunc.name} ${makeSignature(callFunc.params, callFunc.returns)}`;
|
104
104
|
if (globalThis.importFuncs && idx < importFuncs.length) {
|
105
105
|
const importFunc = importFuncs[idx];
|
package/compiler/precompile.js
CHANGED
@@ -59,6 +59,7 @@ const compile = async (file, _funcs) => {
|
|
59
59
|
const paramOverrides = {
|
60
60
|
__Porffor_object_set: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
|
61
61
|
__Porffor_object_expr_init: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32 ],
|
62
|
+
__Porffor_object_expr_initWithFlags: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32, Valtype.i32, Valtype.i32 ],
|
62
63
|
__Porffor_object_define: [ Valtype.i32, Valtype.i32, Valtype.i32, Valtype.i32, Valtype.f64, Valtype.i32, Valtype.i32, Valtype.i32 ],
|
63
64
|
};
|
64
65
|
|
package/package.json
CHANGED