porffor 0.60.7 → 0.60.9
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/README.md +1 -3
- package/compiler/2c.js +2 -2
- package/compiler/assemble.js +16 -3
- package/compiler/builtins/regexp.ts +180 -36
- package/compiler/builtins.js +348 -6
- package/compiler/builtins_precompiled.js +1099 -1099
- package/compiler/codegen.js +78 -12
- package/compiler/cyclone.js +2 -2
- package/compiler/disassemble.js +2 -2
- package/compiler/encoding.js +22 -4
- package/compiler/expression.js +0 -25
- package/compiler/opt.js +15 -15
- package/compiler/precompile.js +3 -3
- package/compiler/wrap.js +4 -1
- package/package.json +2 -2
- package/runtime/index.js +1 -1
- package/AGENTS.md +0 -20
- package/compiler/allocator.js +0 -65
- package/compiler/builtins_objects.js +0 -349
package/compiler/codegen.js
CHANGED
@@ -1,13 +1,78 @@
|
|
1
1
|
import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
|
2
|
-
import { number, ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector
|
2
|
+
import { number, ieee754_binary64, signedLEB128, unsignedLEB128, encodeVector } from './encoding.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
4
|
import { BuiltinFuncs, BuiltinVars, importedFuncs, NULL, UNDEFINED } from './builtins.js';
|
5
5
|
import { TYPES, TYPE_FLAGS, TYPE_NAMES } from './types.js';
|
6
6
|
import parse from './parse.js';
|
7
7
|
import { log } from './log.js';
|
8
|
-
import { allocPage, allocStr } from './allocator.js';
|
9
8
|
import './prefs.js';
|
10
9
|
|
10
|
+
const pagePtr = ind => {
|
11
|
+
if (ind === 0) return 16;
|
12
|
+
return ind * pageSize;
|
13
|
+
};
|
14
|
+
|
15
|
+
const allocPage = (scope, name) => {
|
16
|
+
if (!name.startsWith('#')) {
|
17
|
+
name = `${scope.name}/${name}`;
|
18
|
+
if (globalThis.precompile) name = `${globalThis.precompile}/${name}`;
|
19
|
+
}
|
20
|
+
|
21
|
+
if (pages.has(name)) {
|
22
|
+
return pagePtr(pages.get(name));
|
23
|
+
}
|
24
|
+
|
25
|
+
const ind = pages.size;
|
26
|
+
pages.set(name, ind);
|
27
|
+
|
28
|
+
scope.pages ??= new Map();
|
29
|
+
scope.pages.set(name, ind);
|
30
|
+
|
31
|
+
return pagePtr(ind);
|
32
|
+
};
|
33
|
+
|
34
|
+
const allocBytes = (scope, reason, bytes) => {
|
35
|
+
bytes += 2; // overallocate by 2 bytes to ensure null termination
|
36
|
+
|
37
|
+
const allocs = pages.allocs ??= new Map();
|
38
|
+
const bins = pages.bins ??= [];
|
39
|
+
|
40
|
+
if (allocs.has(reason)) {
|
41
|
+
return allocs.get(reason);
|
42
|
+
}
|
43
|
+
|
44
|
+
let startingPtr = 0;
|
45
|
+
while (bytes > 0) {
|
46
|
+
const alloc = Math.min(bytes, pageSize);
|
47
|
+
bytes -= alloc;
|
48
|
+
|
49
|
+
let bin = bins.find(x => (pageSize - x.used) >= alloc);
|
50
|
+
if (!bin) {
|
51
|
+
// new bin
|
52
|
+
const page = pages.size;
|
53
|
+
bin = {
|
54
|
+
used: 0,
|
55
|
+
page
|
56
|
+
};
|
57
|
+
|
58
|
+
const id = bins.push(bin);
|
59
|
+
pages.set(`#bin: ${id}`, page);
|
60
|
+
}
|
61
|
+
|
62
|
+
if (!startingPtr) startingPtr = pagePtr(bin.page) + bin.used;
|
63
|
+
bin.used += alloc;
|
64
|
+
}
|
65
|
+
|
66
|
+
allocs.set(reason, startingPtr);
|
67
|
+
return startingPtr;
|
68
|
+
};
|
69
|
+
|
70
|
+
export const allocStr = (scope, str, bytestring) => {
|
71
|
+
// basic string interning for ~free
|
72
|
+
const bytes = 4 + str.length * (bytestring ? 1 : 2);
|
73
|
+
return allocBytes(scope, str, bytes);
|
74
|
+
};
|
75
|
+
|
11
76
|
const todo = (scope, msg, expectsValue = undefined) => {
|
12
77
|
msg = `todo: ${msg}`;
|
13
78
|
|
@@ -1465,10 +1530,10 @@ const asmFuncToAsm = (scope, func, extra) => func(scope, {
|
|
1465
1530
|
wasm.push(Opcodes.i32_to_u);
|
1466
1531
|
return wasm;
|
1467
1532
|
},
|
1468
|
-
allocPage
|
1533
|
+
allocPage,
|
1469
1534
|
allocLargePage: (scope, name) => {
|
1470
|
-
const _ = allocPage(
|
1471
|
-
allocPage(
|
1535
|
+
const _ = allocPage(scope, name);
|
1536
|
+
allocPage(scope, name + '#2');
|
1472
1537
|
|
1473
1538
|
return _;
|
1474
1539
|
}
|
@@ -2781,7 +2846,7 @@ const knownType = (scope, type) => {
|
|
2781
2846
|
if (typeof type === 'number') return type;
|
2782
2847
|
|
2783
2848
|
if (type.length === 1 && type[0][0] === Opcodes.i32_const) {
|
2784
|
-
return
|
2849
|
+
return type[0][1];
|
2785
2850
|
}
|
2786
2851
|
|
2787
2852
|
if (typedInput && type.length === 1 && type[0][0] === Opcodes.local_get) {
|
@@ -4260,7 +4325,7 @@ const generateUnary = (scope, decl) => {
|
|
4260
4325
|
return [
|
4261
4326
|
...toNumeric(),
|
4262
4327
|
Opcodes.i32_to,
|
4263
|
-
[ Opcodes.i32_const,
|
4328
|
+
[ Opcodes.i32_const, -1 ],
|
4264
4329
|
[ Opcodes.i32_xor ],
|
4265
4330
|
Opcodes.i32_from
|
4266
4331
|
];
|
@@ -5059,14 +5124,14 @@ const generateForIn = (scope, decl) => {
|
|
5059
5124
|
[ Opcodes.local_set, tmp ],
|
5060
5125
|
|
5061
5126
|
// symbol is MSB 2 is set
|
5062
|
-
[ Opcodes.i32_const,
|
5063
|
-
[ Opcodes.i32_const,
|
5127
|
+
[ Opcodes.i32_const, TYPES.string ],
|
5128
|
+
[ Opcodes.i32_const, TYPES.symbol ],
|
5064
5129
|
[ Opcodes.local_get, tmp ],
|
5065
5130
|
number(0x40000000, Valtype.i32),
|
5066
5131
|
[ Opcodes.i32_and ],
|
5067
5132
|
[ Opcodes.select ],
|
5068
5133
|
[ Opcodes.else ], // bytestring
|
5069
|
-
[ Opcodes.i32_const,
|
5134
|
+
[ Opcodes.i32_const, TYPES.bytestring ],
|
5070
5135
|
[ Opcodes.end ]
|
5071
5136
|
]),
|
5072
5137
|
|
@@ -5582,7 +5647,7 @@ const makeString = (scope, str, bytestring = true) => {
|
|
5582
5647
|
if (c > 0xFF) bytestring = false;
|
5583
5648
|
}
|
5584
5649
|
|
5585
|
-
const ptr = allocStr(
|
5650
|
+
const ptr = allocStr(scope, str, bytestring);
|
5586
5651
|
makeData(scope, elements, str, bytestring ? 'i8' : 'i16');
|
5587
5652
|
|
5588
5653
|
return [ number(ptr) ];
|
@@ -5598,7 +5663,7 @@ const generateArray = (scope, decl, global = false, name = '$undeclared', static
|
|
5598
5663
|
if (staticAlloc || decl._staticAlloc) {
|
5599
5664
|
const uniqueName = name === '$undeclared' ? name + uniqId() : name;
|
5600
5665
|
|
5601
|
-
const ptr = allocPage(
|
5666
|
+
const ptr = allocPage(scope, uniqueName);
|
5602
5667
|
pointer = number(ptr, Valtype.i32);
|
5603
5668
|
|
5604
5669
|
scope.arrays ??= new Map();
|
@@ -6556,6 +6621,7 @@ const generateTaggedTemplate = (scope, decl, global = false, name = undefined, v
|
|
6556
6621
|
|
6557
6622
|
const encodeFunc = ({
|
6558
6623
|
[Opcodes.f64_const]: x => x,
|
6624
|
+
[Opcodes.i32_const]: x => x,
|
6559
6625
|
[Opcodes.if]: unsignedLEB128,
|
6560
6626
|
[Opcodes.loop]: unsignedLEB128
|
6561
6627
|
})[inst[0]] ?? signedLEB128;
|
package/compiler/cyclone.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
// cyclone: wasm partial constant evaluator (it is fast and dangerous hence "cyclone")
|
2
|
-
import { number
|
2
|
+
import { number } from './encoding.js';
|
3
3
|
import { Opcodes, Valtype } from './wasmSpec.js';
|
4
4
|
import './prefs.js';
|
5
5
|
|
@@ -123,7 +123,7 @@ export default ({ name, wasm, locals: _locals, params }) => {
|
|
123
123
|
}
|
124
124
|
|
125
125
|
case Opcodes.i32_const: {
|
126
|
-
const n =
|
126
|
+
const n = op[1];
|
127
127
|
push(n);
|
128
128
|
break;
|
129
129
|
}
|
package/compiler/disassemble.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
2
|
-
import {
|
2
|
+
import { read_unsignedLEB128 } from './encoding.js';
|
3
3
|
import { importedFuncs } from './builtins.js';
|
4
4
|
|
5
5
|
const inv = (obj, keyMap = x => x) => Object.keys(obj).reduce((acc, x) => { acc[keyMap(obj[x])] = x; return acc; }, {});
|
@@ -74,7 +74,7 @@ export default (wasm, name = '', ind = 0, locals = {}, params = [], returns = []
|
|
74
74
|
if (inst[0] === Opcodes.f64_const) {
|
75
75
|
out += ` ${inst[1]}`;
|
76
76
|
} else if (inst[0] === Opcodes.i32_const || inst[0] === Opcodes.i64_const) {
|
77
|
-
out += ` ${
|
77
|
+
out += ` ${inst[1]}`;
|
78
78
|
} else if (inst[0] === Opcodes.i32_load || inst[0] === Opcodes.i64_load || inst[0] === Opcodes.f64_load || inst[0] === Opcodes.i32_store || inst[0] === Opcodes.i64_store || inst[0] === Opcodes.f64_store || inst[0] === Opcodes.i32_store16 || inst[0] === Opcodes.i32_load16_u) {
|
79
79
|
out += ` ${inst[1]} ${read_unsignedLEB128(inst.slice(2))}`;
|
80
80
|
} else for (const operand of inst.slice(1)) {
|
package/compiler/encoding.js
CHANGED
@@ -3,10 +3,10 @@ import { Opcodes, Valtype } from './wasmSpec.js';
|
|
3
3
|
export const number = (n, valtype = valtypeBinary) => {
|
4
4
|
if (valtype === Valtype.f64) return [ Opcodes.f64_const, n ];
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
6
|
+
return [
|
7
|
+
valtype === Valtype.i32 ? Opcodes.i32_const : Opcodes.i64_const,
|
8
|
+
n
|
9
|
+
];
|
10
10
|
};
|
11
11
|
|
12
12
|
export const codifyString = str => {
|
@@ -23,6 +23,9 @@ export const encodeVector = data => unsignedLEB128(data.length).concat(data.flat
|
|
23
23
|
|
24
24
|
// todo: this only works with integers within 32 bit range
|
25
25
|
export const signedLEB128 = n => {
|
26
|
+
if (n === Infinity) return signedLEB128(2147483647);
|
27
|
+
if (n === -Infinity) return signedLEB128(-2147483648);
|
28
|
+
|
26
29
|
n |= 0;
|
27
30
|
|
28
31
|
// just input for small numbers (for perf as common)
|
@@ -49,6 +52,9 @@ export const signedLEB128 = n => {
|
|
49
52
|
};
|
50
53
|
|
51
54
|
export const unsignedLEB128 = n => {
|
55
|
+
if (n === Infinity) return unsignedLEB128(4294967295);
|
56
|
+
if (n === -Infinity) return unsignedLEB128(0);
|
57
|
+
|
52
58
|
n |= 0;
|
53
59
|
|
54
60
|
// just input for small numbers (for perf as common)
|
@@ -69,6 +75,9 @@ export const unsignedLEB128 = n => {
|
|
69
75
|
};
|
70
76
|
|
71
77
|
export const unsignedLEB128_length = n => {
|
78
|
+
if (n === Infinity) return unsignedLEB128_length(4294967295);
|
79
|
+
if (n === -Infinity) return unsignedLEB128_length(0);
|
80
|
+
|
72
81
|
if (n < 0) n = n >>> 0;
|
73
82
|
if (n <= 127) return 1;
|
74
83
|
if (n <= 16383) return 2;
|
@@ -85,6 +94,9 @@ export const unsignedLEB128_length = n => {
|
|
85
94
|
};
|
86
95
|
|
87
96
|
export const signedLEB128_length = n => {
|
97
|
+
if (n === Infinity) return signedLEB128_length(2147483647);
|
98
|
+
if (n === -Infinity) return signedLEB128_length(-2147483648);
|
99
|
+
|
88
100
|
if (n >= -64 && n <= 63) return 1;
|
89
101
|
if (n >= -8192 && n <= 8191) return 2;
|
90
102
|
if (n >= -1048576 && n <= 1048575) return 3;
|
@@ -201,6 +213,9 @@ export const read_ieee754_binary64 = buffer => new Float64Array(new Uint8Array(b
|
|
201
213
|
|
202
214
|
// into funcs append to a given existing buffer instead of creating our own for perf
|
203
215
|
export const signedLEB128_into = (n, buffer) => {
|
216
|
+
if (n === Infinity) return signedLEB128_into(2147483647, buffer);
|
217
|
+
if (n === -Infinity) return signedLEB128_into(-2147483648, buffer);
|
218
|
+
|
204
219
|
n |= 0;
|
205
220
|
|
206
221
|
// just input for small numbers (for perf as common)
|
@@ -224,6 +239,9 @@ export const signedLEB128_into = (n, buffer) => {
|
|
224
239
|
};
|
225
240
|
|
226
241
|
export const unsignedLEB128_into = (n, buffer) => {
|
242
|
+
if (n === Infinity) return unsignedLEB128_into(4294967295, buffer);
|
243
|
+
if (n === -Infinity) return unsignedLEB128_into(0, buffer);
|
244
|
+
|
227
245
|
n |= 0;
|
228
246
|
|
229
247
|
// just input for small numbers (for perf as common)
|
package/compiler/expression.js
CHANGED
@@ -46,31 +46,6 @@ export const operatorOpcode = {
|
|
46
46
|
]
|
47
47
|
},
|
48
48
|
|
49
|
-
i64: {
|
50
|
-
'+': Opcodes.i64_add,
|
51
|
-
'-': Opcodes.i64_sub,
|
52
|
-
'*': Opcodes.i64_mul,
|
53
|
-
'/': Opcodes.i64_div_s,
|
54
|
-
'%': Opcodes.i64_rem_s,
|
55
|
-
|
56
|
-
'&': Opcodes.i64_and,
|
57
|
-
'|': Opcodes.i64_or,
|
58
|
-
'^': Opcodes.i64_xor,
|
59
|
-
'<<': Opcodes.i64_shl,
|
60
|
-
'>>': Opcodes.i64_shr_s,
|
61
|
-
'>>>': Opcodes.i64_shr_u,
|
62
|
-
|
63
|
-
'==': Opcodes.i64_eq,
|
64
|
-
'===': Opcodes.i64_eq,
|
65
|
-
'!=': Opcodes.i64_ne,
|
66
|
-
'!==': Opcodes.i64_ne,
|
67
|
-
|
68
|
-
'>': Opcodes.i64_gt_s,
|
69
|
-
'>=': Opcodes.i64_ge_s,
|
70
|
-
'<': Opcodes.i64_lt_s,
|
71
|
-
'<=': Opcodes.i64_le_s
|
72
|
-
},
|
73
|
-
|
74
49
|
f64: {
|
75
50
|
'+': Opcodes.f64_add,
|
76
51
|
'-': Opcodes.f64_sub,
|
package/compiler/opt.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { Opcodes, Valtype } from './wasmSpec.js';
|
2
|
-
import { number
|
2
|
+
import { number } from './encoding.js';
|
3
3
|
import { log } from './log.js';
|
4
4
|
import './prefs.js';
|
5
5
|
|
@@ -177,7 +177,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
177
177
|
// -->
|
178
178
|
// i32.const 0
|
179
179
|
|
180
|
-
wasm[i - 1] = number(
|
180
|
+
wasm[i - 1] = number(lastInst[1], Valtype.i32); // f64.const -> i32.const
|
181
181
|
|
182
182
|
wasm.splice(i, 1); // remove this inst
|
183
183
|
i--;
|
@@ -192,7 +192,7 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
192
192
|
// -->
|
193
193
|
// f64.const 0
|
194
194
|
|
195
|
-
wasm[i - 1] = number(
|
195
|
+
wasm[i - 1] = number(lastInst[1], Valtype.f64); // i32.const -> f64.const
|
196
196
|
|
197
197
|
wasm.splice(i, 1); // remove this inst
|
198
198
|
i--;
|
@@ -215,18 +215,18 @@ export default (funcs, globals, pages, tags, exceptions) => {
|
|
215
215
|
continue;
|
216
216
|
}
|
217
217
|
|
218
|
-
if (
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
}
|
218
|
+
// if (i === wasm.length - 1 && inst[0] === Opcodes.return) {
|
219
|
+
// // replace final return, end -> end (wasm has implicit return)
|
220
|
+
// // return
|
221
|
+
// // end
|
222
|
+
// // -->
|
223
|
+
// // end
|
224
|
+
|
225
|
+
// wasm.splice(i, 1); // remove this inst (return)
|
226
|
+
// i--;
|
227
|
+
// // if (Prefs.optLog) log('opt', `removed redundant return at end`);
|
228
|
+
// continue;
|
229
|
+
// }
|
230
230
|
|
231
231
|
// remove unneeded before get with update exprs (n++, etc) when value is unused
|
232
232
|
if (i < wasm.length - 4 && lastInst[1] === inst[1] && lastInst[0] === Opcodes.local_get && inst[0] === Opcodes.local_get && wasm[i + 1][0] === Opcodes.const && [Opcodes.add, Opcodes.sub].includes(wasm[i + 2][0]) && wasm[i + 3][0] === Opcodes.local_set && wasm[i + 3][1] === inst[1] && (wasm[i + 4][0] === Opcodes.drop || wasm[i + 4][0] === Opcodes.br)) {
|
package/compiler/precompile.js
CHANGED
@@ -57,7 +57,7 @@ const compile = async (file, _funcs) => {
|
|
57
57
|
first = source.slice(0, source.indexOf('\n'));
|
58
58
|
}
|
59
59
|
|
60
|
-
let args = ['--module', '--todo-time=compile', '--truthy=no_nan_negative', '--no-rm-unused-types', '--
|
60
|
+
let args = ['--module', '--todo-time=compile', '--truthy=no_nan_negative', '--no-rm-unused-types', '--fast-length', '--parse-types', '--opt-types', '--no-passive-data', '--active-data', '--no-treeshake-wasm-imports', '--no-coctc'];
|
61
61
|
if (first.startsWith('// @porf')) {
|
62
62
|
args = first.slice('// @porf '.length).split(' ').concat(args);
|
63
63
|
}
|
@@ -176,7 +176,7 @@ const compile = async (file, _funcs) => {
|
|
176
176
|
x.usesTag = true;
|
177
177
|
let id;
|
178
178
|
if (y[0] === Opcodes.i32_const && n[1] === 0) {
|
179
|
-
id =
|
179
|
+
id = y[1];
|
180
180
|
wasm[i] = [ 'throw', exceptions[id].constructor, exceptions[id].message ];
|
181
181
|
|
182
182
|
// remove throw inst
|
@@ -244,7 +244,7 @@ ${funcs.map(x => {
|
|
244
244
|
if (Number.isNaN(v) || v === Infinity || v === -Infinity) return v.toString();
|
245
245
|
return v;
|
246
246
|
})
|
247
|
-
.replace(/\["alloc","(.*?)",(.*?)\]/g, (_, reason, valtype) => `
|
247
|
+
.replace(/\["alloc","(.*?)",(.*?)\]/g, (_, reason, valtype) => `[${valtype === Valtype.i32 ? Opcodes.i32_const : Opcodes.f64_const},allocPage(_,'${reason}')]`)
|
248
248
|
.replace(/\["global",(.*?),"(.*?)",(.*?)\]/g, (_, opcode, name, valtype) => `...glbl(${opcode},'${name}',${valtype})`)
|
249
249
|
.replace(/\"local","(.*?)",(.*?)\]/g, (_, name, valtype) => `loc('${name}',${valtype})]`)
|
250
250
|
.replace(/\[16,"(.*?)"]/g, (_, name) => `[16,builtin('${name}')]`)
|
package/compiler/wrap.js
CHANGED
@@ -586,7 +586,10 @@ export default (source, module = undefined, print = str => process.stdout.write(
|
|
586
586
|
}
|
587
587
|
|
588
588
|
times.push(performance.now() - t2);
|
589
|
-
if (Prefs.profileCompiler
|
589
|
+
if (Prefs.profileCompiler) {
|
590
|
+
if (globalThis.onProgress) globalThis.onProgress('instantiated', times[1]);
|
591
|
+
else console.log(`instantiated in ${times[1].toFixed(2)}ms`);
|
592
|
+
}
|
590
593
|
|
591
594
|
const exports = {};
|
592
595
|
const rawValues = Prefs.d;
|
package/package.json
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
{
|
2
2
|
"name": "porffor",
|
3
3
|
"description": "An ahead-of-time JavaScript compiler",
|
4
|
-
"version": "0.60.
|
4
|
+
"version": "0.60.9",
|
5
5
|
"author": "Oliver Medhurst <honk@goose.icu>",
|
6
6
|
"license": "MIT",
|
7
7
|
"scripts": {},
|
8
8
|
"dependencies": {
|
9
9
|
"acorn": "^8.15.0",
|
10
|
-
"node-repl-polyfill": "
|
10
|
+
"node-repl-polyfill": "^0.1.2"
|
11
11
|
},
|
12
12
|
"optionalDependencies": {
|
13
13
|
"@babel/parser": "^7.24.4",
|
package/runtime/index.js
CHANGED
package/AGENTS.md
DELETED
@@ -1,20 +0,0 @@
|
|
1
|
-
you are an assistant coder for Porffor - an early javascript and typescript to webassembly and native ahead-of-time compiler. the codebase is written in js and ts.
|
2
|
-
|
3
|
-
- built-ins apis (Date, String.prototype, etc) are written in ts inside `compiler/builtins`
|
4
|
-
- once you update a file inside that directory, you MUST run `./porf precompile` to compile to make your changes effective
|
5
|
-
- test your work using the test262 tools available, iterate independently but do not get stuck on one chain of thought or approach. paths for test262 tools should be relative to the 'test262/test' directory (e.g., 'built-ins/RegExp' NOT 'test262/test/built-ins/RegExp').
|
6
|
-
- to get an overview of the most failing directories, use the command: `node test262/fails.cjs`
|
7
|
-
- to just evaluate code in the engine, use the command: `./porf -p "..."`
|
8
|
-
- after finishing, check if your work/diff could be simplified
|
9
|
-
- always use single quotes (unless double is required)
|
10
|
-
- 2-space indentation, LF line endings, no trailing whitespace
|
11
|
-
- built-in APIs in `compiler/builtins/` written in TypeScript
|
12
|
-
- inline code in built-ins, avoid helper functions
|
13
|
-
- use semicolons
|
14
|
-
- do not use trailing commas
|
15
|
-
- use const/let, avoid var
|
16
|
-
- follow existing naming: camelCase for variables, PascalCase for types
|
17
|
-
- when possible, do not concat strings and instead write to them directly using wasm memory
|
18
|
-
- there are no closures, you cannot use locals between functions. use arguments or globals if really necessary
|
19
|
-
- The user prefers that prototype functions not have explicit return types in this codebase.
|
20
|
-
- The user prefers not to use global variables in built-in functions.
|
package/compiler/allocator.js
DELETED
@@ -1,65 +0,0 @@
|
|
1
|
-
import './prefs.js';
|
2
|
-
|
3
|
-
const pagePtr = ind => {
|
4
|
-
if (ind === 0) return 16;
|
5
|
-
return ind * pageSize;
|
6
|
-
};
|
7
|
-
|
8
|
-
export const nameToReason = (scope, name) => {
|
9
|
-
let scopeName = scope.name;
|
10
|
-
if (globalThis.precompile && scopeName === '#main') scopeName = globalThis.precompile;
|
11
|
-
|
12
|
-
return `${Prefs.scopedPageNames ? (scopeName + '/') : ''}${name}`;
|
13
|
-
};
|
14
|
-
|
15
|
-
export const allocPage = ({ scope, pages }, name) => {
|
16
|
-
const reason = nameToReason(scope, name);
|
17
|
-
|
18
|
-
if (pages.has(reason)) {
|
19
|
-
return pagePtr(pages.get(reason));
|
20
|
-
}
|
21
|
-
|
22
|
-
const ind = pages.size;
|
23
|
-
pages.set(reason, ind);
|
24
|
-
|
25
|
-
scope.pages ??= new Map();
|
26
|
-
scope.pages.set(reason, ind);
|
27
|
-
|
28
|
-
return pagePtr(ind);
|
29
|
-
};
|
30
|
-
|
31
|
-
export const allocBytes = ({ scope, pages }, reason, bytes) => {
|
32
|
-
bytes += 2; // overallocate by 2 bytes to ensure null termination
|
33
|
-
|
34
|
-
const allocs = pages.allocs ??= new Map();
|
35
|
-
const bins = pages.bins ??= [];
|
36
|
-
|
37
|
-
if (allocs.has(reason)) {
|
38
|
-
return allocs.get(reason);
|
39
|
-
}
|
40
|
-
|
41
|
-
let bin = bins.find(x => (pageSize - x.used) >= bytes);
|
42
|
-
if (!bin) {
|
43
|
-
// new bin
|
44
|
-
const page = pages.size;
|
45
|
-
bin = {
|
46
|
-
used: 0,
|
47
|
-
page
|
48
|
-
};
|
49
|
-
|
50
|
-
const id = bins.push(bin);
|
51
|
-
pages.set(`#bin: ${id}`, page);
|
52
|
-
}
|
53
|
-
|
54
|
-
const ptr = pagePtr(bin.page) + bin.used;
|
55
|
-
bin.used += bytes;
|
56
|
-
|
57
|
-
allocs.set(reason, ptr);
|
58
|
-
return ptr;
|
59
|
-
};
|
60
|
-
|
61
|
-
export const allocStr = ({ scope, pages }, str, bytestring) => {
|
62
|
-
// basic string interning for ~free
|
63
|
-
const bytes = 4 + str.length * (bytestring ? 1 : 2);
|
64
|
-
return allocBytes({ scope, pages }, str, bytes);
|
65
|
-
};
|