porffor 0.47.6 → 0.47.8
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 +4 -4
- package/compiler/allocator.js +64 -0
- package/compiler/assemble.js +2 -2
- package/compiler/builtins/__internal_string.ts +117 -34
- package/compiler/builtins/boolean.ts +2 -5
- package/compiler/builtins/function.ts +12 -3
- package/compiler/builtins/object.ts +10 -12
- package/compiler/builtins/z_ecma262.ts +4 -6
- package/compiler/builtins.js +2 -2
- package/compiler/builtins_objects.js +2 -2
- package/compiler/builtins_precompiled.js +722 -787
- package/compiler/cache.js +44 -0
- package/compiler/codegen.js +193 -306
- package/compiler/index.js +7 -1
- package/compiler/opt.js +1 -1
- package/compiler/parse.js +1 -1
- package/compiler/pgo.js +1 -1
- package/compiler/precompile.js +15 -20
- package/compiler/prototype.js +135 -123
- package/compiler/types.js +1 -1
- package/compiler/wrap.js +5 -5
- package/package.json +1 -1
- package/rhemyn/compile.js +1 -1
- package/runner/index.js +1 -1
- package/runner/repl.js +3 -3
- package/compiler/allocators.js +0 -130
package/compiler/2c.js
CHANGED
@@ -2,7 +2,7 @@ import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from '.
|
|
2
2
|
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
4
|
import { log } from './log.js';
|
5
|
-
import
|
5
|
+
import './prefs.js';
|
6
6
|
|
7
7
|
const CValtype = {
|
8
8
|
i8: 'u8',
|
@@ -222,7 +222,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
222
222
|
|
223
223
|
const activeData = data.filter(x => x.page != null);
|
224
224
|
if (activeData.length > 0) {
|
225
|
-
const dataOffset = x => pages.get(x.page).
|
225
|
+
const dataOffset = x => pages.allocs.get(x.page) ?? (pages.get(x.page) * pageSize);
|
226
226
|
if (Prefs['2cMemcpy']) {
|
227
227
|
prependMain.set('_data', activeData.map(x => `memcpy(_memory + ${dataOffset(x)}, (unsigned char[]){${x.bytes.join(',')}}, ${x.bytes.length});`).join('\n '));
|
228
228
|
} else {
|
@@ -857,7 +857,7 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
857
857
|
const name = invOpcodes[i[0]];
|
858
858
|
const func = CMemFuncs[i[0]];
|
859
859
|
if (!prepend.has(name)) {
|
860
|
-
prepend.set(name,
|
860
|
+
prepend.set(name, `inline ${func.returns || 'void'} ${name}(i32 align, i32 offset, ${func.args.map((x, i) => `${func.argTypes[i]} ${x}`).join(', ')}) {\n ${func.c.replaceAll('\n', '\n ')}\n}\n`);
|
861
861
|
}
|
862
862
|
|
863
863
|
const immediates = [ i[1], read_unsignedLEB128(i.slice(2)) ];
|
@@ -915,5 +915,5 @@ _time_out = _time.tv_nsec / 1000000. + _time.tv_sec * 1000.;`);
|
|
915
915
|
const makeIncludes = includes => [...includes.keys()].map(x => `#include <${x}>\n`).join('');
|
916
916
|
out = platformSpecific(makeIncludes(winIncludes), makeIncludes(unixIncludes), false) + '\n' + makeIncludes(includes) + '\n' + alwaysPreface + [...prepend.values()].join('\n') + '\n\n' + out;
|
917
917
|
|
918
|
-
return `// generated by porffor ${globalThis.version
|
918
|
+
return `// generated by porffor ${globalThis.version}\n` + out.trim();
|
919
919
|
};
|
@@ -0,0 +1,64 @@
|
|
1
|
+
import { PageSize } from './wasmSpec.js';
|
2
|
+
import './prefs.js';
|
3
|
+
|
4
|
+
const pagePtr = ind => {
|
5
|
+
if (ind === 0) return 16;
|
6
|
+
return ind * PageSize;
|
7
|
+
};
|
8
|
+
|
9
|
+
export const nameToReason = (scope, name) => {
|
10
|
+
let scopeName = scope.name;
|
11
|
+
if (globalThis.precompile && scopeName === 'main') scopeName = globalThis.precompile;
|
12
|
+
|
13
|
+
return `${Prefs.scopedPageNames ? (scopeName + '/') : ''}${name}`;
|
14
|
+
};
|
15
|
+
|
16
|
+
export const allocPage = ({ scope, pages }, name) => {
|
17
|
+
const reason = nameToReason(scope, name);
|
18
|
+
|
19
|
+
if (pages.has(reason)) {
|
20
|
+
return pagePtr(pages.get(reason));
|
21
|
+
}
|
22
|
+
|
23
|
+
const ind = pages.size;
|
24
|
+
pages.set(reason, ind);
|
25
|
+
|
26
|
+
scope.pages ??= new Map();
|
27
|
+
scope.pages.set(reason, ind);
|
28
|
+
|
29
|
+
return pagePtr(ind);
|
30
|
+
};
|
31
|
+
|
32
|
+
export const allocBytes = ({ scope, pages }, reason, bytes) => {
|
33
|
+
const allocs = pages.allocs ??= new Map();
|
34
|
+
const bins = pages.bins ??= [];
|
35
|
+
|
36
|
+
if (allocs.has(reason)) {
|
37
|
+
return allocs.get(reason);
|
38
|
+
}
|
39
|
+
|
40
|
+
let bin = bins.find(x => (PageSize - x.used) >= bytes);
|
41
|
+
if (!bin) {
|
42
|
+
// new bin
|
43
|
+
const page = pages.size;
|
44
|
+
bin = {
|
45
|
+
used: 0,
|
46
|
+
page
|
47
|
+
};
|
48
|
+
|
49
|
+
const id = bins.push(bin);
|
50
|
+
pages.set(`#bin_${id}`, page);
|
51
|
+
}
|
52
|
+
|
53
|
+
const ptr = pagePtr(bin.page) + bin.used;
|
54
|
+
bin.used += bytes;
|
55
|
+
|
56
|
+
allocs.set(reason, ptr);
|
57
|
+
return ptr;
|
58
|
+
};
|
59
|
+
|
60
|
+
export const allocStr = ({ scope, pages }, str, bytestring) => {
|
61
|
+
// basic string interning for ~free
|
62
|
+
const bytes = 4 + str.length * (bytestring ? 1 : 2);
|
63
|
+
return allocBytes({ scope, pages }, str, bytes);
|
64
|
+
};
|
package/compiler/assemble.js
CHANGED
@@ -2,7 +2,7 @@ import { Valtype, FuncType, ExportDesc, Section, Magic, ModuleVersion, Opcodes,
|
|
2
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
|
-
import
|
5
|
+
import './prefs.js';
|
6
6
|
|
7
7
|
const createSection = (type, data) => [
|
8
8
|
type,
|
@@ -372,7 +372,7 @@ export default (funcs, globals, tags, pages, data, noTreeshake = false) => {
|
|
372
372
|
const bytes = unsignedLEB128(x.bytes.length).concat(x.bytes);
|
373
373
|
if (x.page != null) {
|
374
374
|
// type: active
|
375
|
-
let offset = pages.get(x.page).
|
375
|
+
let offset = pages.allocs.get(x.page) ?? (pages.get(x.page) * pageSize);
|
376
376
|
if (offset === 0) offset = 16;
|
377
377
|
bytes.unshift(0x00, Opcodes.i32_const, ...signedLEB128(offset), Opcodes.end);
|
378
378
|
} else {
|
@@ -158,44 +158,127 @@ end`;
|
|
158
158
|
return true;
|
159
159
|
} else {
|
160
160
|
// string, string
|
161
|
-
|
162
|
-
|
161
|
+
// change char lengths to byte lengths
|
162
|
+
al *= 2;
|
163
|
+
bl *= 2;
|
164
|
+
|
165
|
+
// copied from bytestring, bytestring
|
166
|
+
let ap32: i32 = a - 28;
|
167
|
+
let bp32: i32 = b - 28;
|
168
|
+
let ap8: i32 = a - 4;
|
169
|
+
let bp8: i32 = b - 4;
|
163
170
|
Porffor.wasm`
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
171
|
+
;; load in 2 i64x2 chunks while length >= 32
|
172
|
+
local.get ${al}
|
173
|
+
i32.const 32
|
174
|
+
i32.ge_s
|
175
|
+
if 64
|
176
|
+
loop 64
|
177
|
+
local.get ${ap32}
|
178
|
+
local.get ${al}
|
179
|
+
i32.add
|
180
|
+
v128.load 0 0
|
181
|
+
|
182
|
+
local.get ${bp32}
|
183
|
+
local.get ${al}
|
184
|
+
i32.add
|
185
|
+
v128.load 0 0
|
186
|
+
v128.xor
|
187
|
+
|
188
|
+
local.get ${ap32}
|
189
|
+
local.get ${al}
|
190
|
+
i32.add
|
191
|
+
v128.load 0 16
|
192
|
+
|
193
|
+
local.get ${bp32}
|
194
|
+
local.get ${al}
|
195
|
+
i32.add
|
196
|
+
v128.load 0 16
|
197
|
+
v128.xor
|
198
|
+
|
199
|
+
v128.or
|
200
|
+
v128.any_true
|
201
|
+
if 64
|
202
|
+
i32.const 0
|
203
|
+
i32.const 2
|
204
|
+
return
|
205
|
+
end
|
206
|
+
|
207
|
+
local.get ${al}
|
208
|
+
i32.const 32
|
209
|
+
i32.sub
|
210
|
+
local.tee ${al}
|
211
|
+
i32.const 32
|
212
|
+
i32.ge_s
|
213
|
+
br_if 0
|
184
214
|
end
|
215
|
+
end
|
185
216
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
217
|
+
;; load in i64 chunks while length >= 8
|
218
|
+
local.get ${al}
|
219
|
+
i32.const 8
|
220
|
+
i32.ge_s
|
221
|
+
if 64
|
222
|
+
loop 64
|
223
|
+
local.get ${ap8}
|
224
|
+
local.get ${al}
|
225
|
+
i32.add
|
226
|
+
i64.load 0 0
|
194
227
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
228
|
+
local.get ${bp8}
|
229
|
+
local.get ${al}
|
230
|
+
i32.add
|
231
|
+
i64.load 0 0
|
232
|
+
|
233
|
+
i64.ne
|
234
|
+
if 64
|
235
|
+
i32.const 0
|
236
|
+
i32.const 2
|
237
|
+
return
|
238
|
+
end
|
239
|
+
|
240
|
+
local.get ${al}
|
241
|
+
i32.const 8
|
242
|
+
i32.sub
|
243
|
+
local.tee ${al}
|
244
|
+
i32.const 8
|
245
|
+
i32.ge_s
|
246
|
+
br_if 0
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
;; load in u16 chunks while length >= 2
|
251
|
+
local.get ${al}
|
252
|
+
i32.const 2
|
253
|
+
i32.ge_s
|
254
|
+
if 64
|
255
|
+
loop 64
|
256
|
+
local.get ${a}
|
257
|
+
local.get ${al}
|
258
|
+
i32.add
|
259
|
+
i32.load16_u 0 2
|
260
|
+
|
261
|
+
local.get ${b}
|
262
|
+
local.get ${al}
|
263
|
+
i32.add
|
264
|
+
i32.load16_u 0 2
|
265
|
+
|
266
|
+
i32.ne
|
267
|
+
if 64
|
268
|
+
i32.const 0
|
269
|
+
i32.const 2
|
270
|
+
return
|
271
|
+
end
|
272
|
+
|
273
|
+
local.get ${al}
|
274
|
+
i32.const 2
|
275
|
+
i32.sub
|
276
|
+
local.tee ${al}
|
277
|
+
i32.const 2
|
278
|
+
i32.ge_s
|
279
|
+
br_if 0
|
280
|
+
end
|
281
|
+
end`;
|
199
282
|
return true;
|
200
283
|
}
|
201
284
|
}
|
@@ -18,11 +18,8 @@ export const Boolean = function (value: any): boolean|BooleanObject {
|
|
18
18
|
export const __Boolean_prototype_toString = (_this: boolean) => {
|
19
19
|
// 1. Let b be ? ThisBooleanValue(this value).
|
20
20
|
// 2. If b is true, return "true"; else return "false".
|
21
|
-
|
22
|
-
|
23
|
-
else out = 'false';
|
24
|
-
|
25
|
-
return out;
|
21
|
+
if (_this) return 'true';
|
22
|
+
return 'false';
|
26
23
|
};
|
27
24
|
|
28
25
|
// 20.3.3.3 Boolean.prototype.valueOf ()
|
@@ -1,7 +1,16 @@
|
|
1
1
|
import type {} from './porffor.d.ts';
|
2
2
|
|
3
3
|
export const __Function_prototype_toString = (_this: Function) => {
|
4
|
-
|
5
|
-
|
4
|
+
const out: bytestring = Porffor.allocate();
|
5
|
+
|
6
|
+
const prefix: bytestring = 'function ';
|
7
|
+
Porffor.bytestring.appendStr(out, prefix);
|
8
|
+
|
9
|
+
Porffor.bytestring.appendStr(out, _this.name);
|
10
|
+
|
11
|
+
const postfix: bytestring = '() { [native code] }';
|
12
|
+
Porffor.bytestring.appendStr(out, postfix);
|
6
13
|
return out;
|
7
|
-
};
|
14
|
+
};
|
15
|
+
|
16
|
+
export const __Function_prototype_toLocaleString = (_this: Function) => __Function_prototype_toString(_this);
|
@@ -698,33 +698,31 @@ export const __Object_prototype_toString = (_this: any) => {
|
|
698
698
|
}
|
699
699
|
}
|
700
700
|
|
701
|
-
let out: bytestring = Porffor.allocate();
|
702
|
-
|
703
701
|
// 1. If the this value is undefined, return "[object Undefined]".
|
704
|
-
if (_this === undefined) return
|
702
|
+
if (_this === undefined) return '[object Undefined]';
|
705
703
|
|
706
704
|
// 2. If the this value is null, return "[object Null]".
|
707
|
-
if (_this === null) return
|
705
|
+
if (_this === null) return '[object Null]';
|
708
706
|
|
709
707
|
// todo: toStringTag support
|
710
708
|
|
711
709
|
const t: i32 = Porffor.rawType(_this);
|
712
|
-
if (t == Porffor.TYPES.array) return
|
713
|
-
if (t == Porffor.TYPES.function) return
|
710
|
+
if (t == Porffor.TYPES.array) return '[object Array]';
|
711
|
+
if (t == Porffor.TYPES.function) return '[object Function]';
|
714
712
|
if (Porffor.fastOr(
|
715
713
|
t == Porffor.TYPES.boolean,
|
716
|
-
t == Porffor.TYPES.booleanobject)) return
|
714
|
+
t == Porffor.TYPES.booleanobject)) return '[object Boolean]';
|
717
715
|
if (Porffor.fastOr(
|
718
716
|
t == Porffor.TYPES.number,
|
719
|
-
t == Porffor.TYPES.numberobject)) return
|
717
|
+
t == Porffor.TYPES.numberobject)) return '[object Number]';
|
720
718
|
if (Porffor.fastOr(
|
721
719
|
t == Porffor.TYPES.string,
|
722
720
|
t == Porffor.TYPES.bytestring,
|
723
|
-
t == Porffor.TYPES.stringobject)) return
|
724
|
-
if (t == Porffor.TYPES.date) return
|
725
|
-
if (t == Porffor.TYPES.regexp) return
|
721
|
+
t == Porffor.TYPES.stringobject)) return '[object String]';
|
722
|
+
if (t == Porffor.TYPES.date) return '[object Date]';
|
723
|
+
if (t == Porffor.TYPES.regexp) return '[object RegExp]';
|
726
724
|
|
727
|
-
return
|
725
|
+
return '[object Object]';
|
728
726
|
};
|
729
727
|
|
730
728
|
export const __Object_prototype_toLocaleString = (_this: any) => __Object_prototype_toString(_this);
|
@@ -129,24 +129,22 @@ export const __ecma262_ToString = (argument: unknown): any => {
|
|
129
129
|
// 2. If argument is a Symbol, throw a TypeError exception.
|
130
130
|
if (type == Porffor.TYPES.symbol) throw new TypeError('Cannot convert a Symbol value to a string');
|
131
131
|
|
132
|
-
let out: bytestring = Porffor.allocate();
|
133
|
-
|
134
132
|
// 3. If argument is undefined, return "undefined".
|
135
133
|
if (Porffor.fastOr(
|
136
134
|
type == Porffor.TYPES.undefined,
|
137
|
-
type == Porffor.TYPES.empty)) return
|
135
|
+
type == Porffor.TYPES.empty)) return 'undefined';
|
138
136
|
|
139
137
|
// 4. If argument is null, return "null".
|
140
138
|
if (Porffor.fastAnd(
|
141
139
|
type == Porffor.TYPES.object,
|
142
|
-
argument == 0)) return
|
140
|
+
argument == 0)) return 'null';
|
143
141
|
|
144
142
|
if (type == Porffor.TYPES.boolean) {
|
145
143
|
// 5. If argument is true, return "true".
|
146
|
-
if (argument == true) return
|
144
|
+
if (argument == true) return 'true';
|
147
145
|
|
148
146
|
// 6. If argument is false, return "false".
|
149
|
-
return
|
147
|
+
return 'false';
|
150
148
|
}
|
151
149
|
|
152
150
|
// 7. If argument is a Number, return Number::toString(argument, 10).
|
package/compiler/builtins.js
CHANGED
@@ -3,7 +3,7 @@ import ObjectBuiltins from './builtins_objects.js';
|
|
3
3
|
import { Blocktype, Opcodes, Valtype, ValtypeSize } from './wasmSpec.js';
|
4
4
|
import { number } from './embedding.js';
|
5
5
|
import { TYPES, TYPE_NAMES } from './types.js';
|
6
|
-
import
|
6
|
+
import './prefs.js';
|
7
7
|
import { unsignedLEB128 } from './encoding.js';
|
8
8
|
|
9
9
|
export const importedFuncs = [
|
@@ -860,7 +860,7 @@ export const BuiltinFuncs = function() {
|
|
860
860
|
wasm: (scope, { typeSwitch, makeString }) => {
|
861
861
|
const bc = {};
|
862
862
|
for (const x in TYPE_NAMES) {
|
863
|
-
bc[x] = makeString(scope, TYPE_NAMES[x]
|
863
|
+
bc[x] = makeString(scope, TYPE_NAMES[x]);
|
864
864
|
}
|
865
865
|
|
866
866
|
return typeSwitch(scope, [ [ Opcodes.local_get, 1 ] ], bc);
|
@@ -64,7 +64,7 @@ export default function({ builtinFuncs }, Prefs) {
|
|
64
64
|
getPtr,
|
65
65
|
...number(existingFunc ? TYPES.function : TYPES.object, Valtype.i32),
|
66
66
|
|
67
|
-
...makeString(scope, x
|
67
|
+
...makeString(scope, x),
|
68
68
|
Opcodes.i32_to_u,
|
69
69
|
...number(TYPES.bytestring, Valtype.i32),
|
70
70
|
|
@@ -109,7 +109,7 @@ export default function({ builtinFuncs }, Prefs) {
|
|
109
109
|
}
|
110
110
|
|
111
111
|
if (typeof d.value === 'string') {
|
112
|
-
this[k] = (scope, { makeString }) => makeString(scope, d.value
|
112
|
+
this[k] = (scope, { makeString }) => makeString(scope, d.value);
|
113
113
|
this[k].type = TYPES.bytestring;
|
114
114
|
continue;
|
115
115
|
}
|