porffor 0.55.23 → 0.55.25
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 +2 -2
- package/compiler/allocator.js +2 -3
- package/compiler/builtins/_internal_object.ts +24 -22
- package/compiler/builtins/console.ts +1 -1
- package/compiler/builtins/object.ts +15 -11
- package/compiler/builtins/object_prototypeWithHidden.js +1 -1
- package/compiler/builtins.js +6 -6
- package/compiler/builtins_objects.js +1 -1
- package/compiler/builtins_precompiled.js +23 -21
- package/compiler/codegen.js +20 -74
- package/compiler/index.js +2 -1
- package/package.json +1 -1
- package/r.cjs +5 -4
- package/runner/flamegraph.js +13 -13
- package/runner/index.js +1 -1
- package/runner/repl.js +1 -2
package/compiler/2c.js
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
import { read_ieee754_binary64, read_signedLEB128, read_unsignedLEB128 } from './encoding.js';
|
2
|
-
import { Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
2
|
+
import { Blocktype, Opcodes, Valtype, PageSize } from './wasmSpec.js';
|
3
3
|
import { operatorOpcode } from './expression.js';
|
4
4
|
import { log } from './log.js';
|
5
5
|
import './prefs.js';
|
@@ -218,7 +218,7 @@ export default ({ funcs, globals, tags, data, exceptions, pages }) => {
|
|
218
218
|
if (pages.size > 0) {
|
219
219
|
includes.set('stdlib.h', true);
|
220
220
|
prepend.set('_memory', `char* _memory; u32 _memoryPages = ${pages.size};\n`);
|
221
|
-
prependMain.set('_initMemory', `_memory = malloc(_memoryPages * ${
|
221
|
+
prependMain.set('_initMemory', `_memory = malloc(_memoryPages * ${PageSize});\n`);
|
222
222
|
if (Prefs['2cMemcpy']) includes.set('string.h', true);
|
223
223
|
}
|
224
224
|
|
package/compiler/allocator.js
CHANGED
@@ -1,9 +1,8 @@
|
|
1
|
-
import { PageSize } from './wasmSpec.js';
|
2
1
|
import './prefs.js';
|
3
2
|
|
4
3
|
const pagePtr = ind => {
|
5
4
|
if (ind === 0) return 16;
|
6
|
-
return ind *
|
5
|
+
return ind * pageSize;
|
7
6
|
};
|
8
7
|
|
9
8
|
export const nameToReason = (scope, name) => {
|
@@ -37,7 +36,7 @@ export const allocBytes = ({ scope, pages }, reason, bytes) => {
|
|
37
36
|
return allocs.get(reason);
|
38
37
|
}
|
39
38
|
|
40
|
-
let bin = bins.find(x => (
|
39
|
+
let bin = bins.find(x => (pageSize - x.used) >= bytes);
|
41
40
|
if (!bin) {
|
42
41
|
// new bin
|
43
42
|
const page = pages.size;
|
@@ -182,8 +182,8 @@ export const __Porffor_object_accessorSet = (entryPtr: i32): Function|undefined
|
|
182
182
|
|
183
183
|
export const __Porffor_object_hash = (key: any): i32 => {
|
184
184
|
if (Porffor.wasm`local.get ${key+1}` == Porffor.TYPES.symbol) {
|
185
|
-
// symbol, hash is just
|
186
|
-
return
|
185
|
+
// symbol, hash is unused so just return 0
|
186
|
+
return 0;
|
187
187
|
}
|
188
188
|
|
189
189
|
// bytestring or string, fnv-1a hash (custom variant)
|
@@ -386,26 +386,28 @@ export const __Porffor_object_lookup = (obj: any, target: any, targetHash: i32):
|
|
386
386
|
}
|
387
387
|
}
|
388
388
|
} else {
|
389
|
-
if (targetHash == 0) targetHash = __Porffor_object_hash(target);
|
390
389
|
for (; ptr < endPtr; ptr += 18) {
|
391
|
-
|
392
|
-
|
393
|
-
// todo: is below needed anymore?
|
394
|
-
if (hash == 0) {
|
395
|
-
if (out) break; // ran out of keys
|
396
|
-
out = true;
|
397
|
-
}
|
398
|
-
|
399
|
-
if (hash == targetHash) {
|
390
|
+
if (Porffor.wasm.i32.load(ptr, 0, 0) == targetHash) {
|
400
391
|
const key: i32 = Porffor.wasm.i32.load(ptr, 0, 4);
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
392
|
+
Porffor.wasm`
|
393
|
+
local.get ${key}
|
394
|
+
i32.const 2147483647
|
395
|
+
i32.and
|
396
|
+
|
397
|
+
i32.const 67 ;; bytestring
|
398
|
+
i32.const 195 ;; string
|
399
|
+
local.get ${key}
|
400
|
+
i32.const 30
|
401
|
+
i32.shr_u
|
402
|
+
select
|
403
|
+
|
404
|
+
local.get ${target}
|
405
|
+
local.get ${target+1}
|
406
|
+
call __Porffor_strcmp
|
407
|
+
if 64
|
408
|
+
local.get ${ptr}
|
409
|
+
return
|
410
|
+
end`;
|
409
411
|
}
|
410
412
|
}
|
411
413
|
}
|
@@ -801,7 +803,7 @@ export const __Porffor_object_delete = (obj: any, key: any): boolean => {
|
|
801
803
|
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return true;
|
802
804
|
}
|
803
805
|
|
804
|
-
const entryPtr: i32 = __Porffor_object_lookup(obj, key);
|
806
|
+
const entryPtr: i32 = __Porffor_object_lookup(obj, key, __Porffor_object_hash(key));
|
805
807
|
if (entryPtr == -1) {
|
806
808
|
// not found, stop
|
807
809
|
return true;
|
@@ -851,7 +853,7 @@ export const __Porffor_object_deleteStrict = (obj: any, key: any): boolean => {
|
|
851
853
|
if (Porffor.wasm`local.get ${obj+1}` != Porffor.TYPES.object) return true;
|
852
854
|
}
|
853
855
|
|
854
|
-
const entryPtr: i32 = __Porffor_object_lookup(obj, key);
|
856
|
+
const entryPtr: i32 = __Porffor_object_lookup(obj, key, __Porffor_object_hash(key));
|
855
857
|
if (entryPtr == -1) {
|
856
858
|
// not found, stop
|
857
859
|
return true;
|
@@ -181,7 +181,7 @@ export const __Porffor_print = (arg: any, colors: boolean = true, depth: number
|
|
181
181
|
|
182
182
|
case Porffor.TYPES.function:
|
183
183
|
Porffor.printStatic('[Function ');
|
184
|
-
__Porffor_printString(__Porffor_funcLut_name(arg));
|
184
|
+
__Porffor_printString(__Porffor_funcLut_name(arg) || '(anonymous)');
|
185
185
|
Porffor.printStatic(']');
|
186
186
|
return;
|
187
187
|
|
@@ -143,16 +143,17 @@ export const __Object_fromEntries = (iterable: any): object => {
|
|
143
143
|
|
144
144
|
|
145
145
|
export const __Object_prototype_hasOwnProperty = (_this: any, prop: any) => {
|
146
|
+
if (_this == null) throw new TypeError('Argument is nullish, expected object');
|
146
147
|
const p: any = ecma262.ToPropertyKey(prop);
|
147
148
|
|
148
149
|
const t: i32 = Porffor.rawType(_this);
|
149
150
|
if (t == Porffor.TYPES.object) {
|
150
|
-
return Porffor.object.lookup(_this, p) != -1;
|
151
|
+
return Porffor.object.lookup(_this, p, __Porffor_object_hash(p)) != -1;
|
151
152
|
}
|
152
153
|
|
153
154
|
const obj: any = __Porffor_object_underlying(_this);
|
154
155
|
if (Porffor.rawType(obj) == Porffor.TYPES.object) {
|
155
|
-
if (Porffor.object.lookup(obj, p) != -1) return true;
|
156
|
+
if (Porffor.object.lookup(obj, p, __Porffor_object_hash(p)) != -1) return true;
|
156
157
|
}
|
157
158
|
|
158
159
|
const keys: any[] = __Object_keys(_this);
|
@@ -172,7 +173,7 @@ export const __Porffor_object_in = (obj: any, prop: any): boolean => {
|
|
172
173
|
|
173
174
|
let lastProto = obj;
|
174
175
|
while (true) {
|
175
|
-
obj = Porffor.object.getPrototypeWithHidden(obj);
|
176
|
+
obj = Porffor.object.getPrototypeWithHidden(obj, Porffor.rawType(obj));
|
176
177
|
if (Porffor.fastOr(obj == null, Porffor.wasm`local.get ${obj}` == Porffor.wasm`local.get ${lastProto}`)) break;
|
177
178
|
|
178
179
|
if (__Object_prototype_hasOwnProperty(obj, prop)) return true;
|
@@ -193,7 +194,7 @@ export const __Porffor_object_instanceof = (obj: any, constr: any, checkProto: a
|
|
193
194
|
|
194
195
|
let lastProto = obj;
|
195
196
|
while (true) {
|
196
|
-
obj = Porffor.object.getPrototypeWithHidden(obj);
|
197
|
+
obj = Porffor.object.getPrototypeWithHidden(obj, Porffor.rawType(obj));
|
197
198
|
if (Porffor.fastOr(obj == null, Porffor.wasm`local.get ${obj}` == Porffor.wasm`local.get ${lastProto}`)) break;
|
198
199
|
|
199
200
|
if (obj === checkProto) return true;
|
@@ -235,10 +236,12 @@ export const __Porffor_object_assignAll = (target: any, source: any): any => {
|
|
235
236
|
|
236
237
|
|
237
238
|
export const __Object_prototype_propertyIsEnumerable = (_this: any, prop: any) => {
|
239
|
+
if (_this == null) throw new TypeError('Argument is nullish, expected object');
|
240
|
+
|
238
241
|
const p: any = ecma262.ToPropertyKey(prop);
|
239
242
|
|
240
243
|
if (Porffor.rawType(_this) == Porffor.TYPES.object) {
|
241
|
-
const entryPtr: i32 = Porffor.object.lookup(_this, p);
|
244
|
+
const entryPtr: i32 = Porffor.object.lookup(_this, p, __Porffor_object_hash(p));
|
242
245
|
if (entryPtr == -1) return false;
|
243
246
|
|
244
247
|
return Porffor.object.isEnumerable(entryPtr);
|
@@ -246,7 +249,7 @@ export const __Object_prototype_propertyIsEnumerable = (_this: any, prop: any) =
|
|
246
249
|
|
247
250
|
const obj: any = __Porffor_object_underlying(_this);
|
248
251
|
if (Porffor.rawType(obj) == Porffor.TYPES.object) {
|
249
|
-
const entryPtr: i32 = Porffor.object.lookup(obj, p);
|
252
|
+
const entryPtr: i32 = Porffor.object.lookup(obj, p, __Porffor_object_hash(p));
|
250
253
|
if (entryPtr != -1) return Porffor.object.isEnumerable(entryPtr);
|
251
254
|
}
|
252
255
|
|
@@ -339,9 +342,10 @@ export const __Object_isSealed = (obj: any): boolean => {
|
|
339
342
|
|
340
343
|
|
341
344
|
export const __Object_getOwnPropertyDescriptor = (obj: any, prop: any): object|undefined => {
|
345
|
+
if (obj == null) throw new TypeError('Argument is nullish, expected object');
|
342
346
|
const p: any = ecma262.ToPropertyKey(prop);
|
343
347
|
|
344
|
-
const entryPtr: i32 = Porffor.object.lookup(obj, p);
|
348
|
+
const entryPtr: i32 = Porffor.object.lookup(obj, p, __Porffor_object_hash(p));
|
345
349
|
if (entryPtr == -1) {
|
346
350
|
if (Porffor.rawType(obj) == Porffor.TYPES.function) {
|
347
351
|
// hack: function .name and .length
|
@@ -636,7 +640,7 @@ export const __Object_groupBy = (items: any, callbackFn: any): object => {
|
|
636
640
|
|
637
641
|
export const __Object_getPrototypeOf = (obj: any): any => {
|
638
642
|
if (obj == null) throw new TypeError('Object is nullish, expected object');
|
639
|
-
return Porffor.object.getPrototypeWithHidden(obj);
|
643
|
+
return Porffor.object.getPrototypeWithHidden(obj, Porffor.rawType(obj));
|
640
644
|
};
|
641
645
|
|
642
646
|
export const __Object_setPrototypeOf = (obj: any, proto: any): any => {
|
@@ -653,7 +657,7 @@ export const __Object_prototype_isPrototypeOf = (_this: any, obj: any) => {
|
|
653
657
|
if (_this == null) throw new TypeError('This is nullish, expected object');
|
654
658
|
|
655
659
|
if (!Porffor.object.isObject(obj)) return false;
|
656
|
-
return _this == Porffor.object.getPrototypeWithHidden(obj);
|
660
|
+
return _this == Porffor.object.getPrototypeWithHidden(obj, Porffor.rawType(obj));
|
657
661
|
};
|
658
662
|
|
659
663
|
|
@@ -665,7 +669,7 @@ export const __Object_prototype_toString = (_this: any) => {
|
|
665
669
|
let ovr: any = obj.toString;
|
666
670
|
if (Porffor.rawType(ovr) == Porffor.TYPES.function && ovr != __Object_prototype_toString) return ovr.call(_this);
|
667
671
|
|
668
|
-
const entryPtr: i32 = Porffor.object.lookup(obj, 'toString');
|
672
|
+
const entryPtr: i32 = Porffor.object.lookup(obj, 'toString', __Porffor_object_hash('toString')); // todo: comptime
|
669
673
|
if (entryPtr != -1) {
|
670
674
|
ovr = Porffor.object.readValue(entryPtr);
|
671
675
|
if (Porffor.rawType(ovr) == Porffor.TYPES.function) return ovr.call(_this);
|
@@ -712,7 +716,7 @@ export const __Object_prototype_valueOf = (_this: any) => {
|
|
712
716
|
let ovr: any = obj.valueOf;
|
713
717
|
if (Porffor.rawType(ovr) == Porffor.TYPES.function && ovr != __Object_prototype_valueOf) return ovr.call(_this);
|
714
718
|
|
715
|
-
const entryPtr: i32 = Porffor.object.lookup(obj, 'valueOf');
|
719
|
+
const entryPtr: i32 = Porffor.object.lookup(obj, 'valueOf', __Porffor_object_hash('valueOf')); // todo: comptime
|
716
720
|
if (entryPtr != -1) {
|
717
721
|
ovr = Porffor.object.readValue(entryPtr);
|
718
722
|
if (Porffor.rawType(ovr) == Porffor.TYPES.function) return ovr.call(_this);
|
@@ -1,6 +1,6 @@
|
|
1
1
|
export default ({ TYPES, TYPE_NAMES }) => {
|
2
2
|
let out = `// @porf --valtype=i32
|
3
|
-
export const __Porffor_object_getPrototypeWithHidden = (obj: any, trueType: i32
|
3
|
+
export const __Porffor_object_getPrototypeWithHidden = (obj: any, trueType: i32): any => {
|
4
4
|
const objectProto: any = __Porffor_object_getPrototype(obj);
|
5
5
|
if (Porffor.rawType(objectProto) == Porffor.TYPES.empty) {
|
6
6
|
if (Porffor.comptime.flag\`hasFunc.#get___String_prototype\`) {
|
package/compiler/builtins.js
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
import * as PrecompiledBuiltins from './builtins_precompiled.js';
|
2
2
|
import ObjectBuiltins from './builtins_objects.js';
|
3
|
-
import { Blocktype, Opcodes, Valtype
|
3
|
+
import { PageSize, Blocktype, Opcodes, Valtype } from './wasmSpec.js';
|
4
4
|
import { TYPES, TYPE_NAMES } from './types.js';
|
5
5
|
import { number, unsignedLEB128 } from './encoding.js';
|
6
6
|
import './prefs.js';
|
@@ -778,7 +778,7 @@ export const BuiltinFuncs = function() {
|
|
778
778
|
wasm: [
|
779
779
|
number(1, Valtype.i32),
|
780
780
|
[ Opcodes.memory_grow, 0 ],
|
781
|
-
number(
|
781
|
+
number(PageSize, Valtype.i32),
|
782
782
|
[ Opcodes.i32_mul ]
|
783
783
|
]
|
784
784
|
},
|
@@ -787,23 +787,23 @@ export const BuiltinFuncs = function() {
|
|
787
787
|
locals: [],
|
788
788
|
globals: [ Valtype.i32, Valtype.i32 ],
|
789
789
|
globalNames: [ 'chunkPtr', 'chunkOffset' ],
|
790
|
-
globalInits: [ 0, 100 *
|
790
|
+
globalInits: [ 0, 100 * PageSize ],
|
791
791
|
returns: [ Valtype.i32 ],
|
792
792
|
returnType: TYPES.number,
|
793
793
|
wasm: [
|
794
794
|
// if chunkOffset >= chunks:
|
795
795
|
[ Opcodes.global_get, 1 ],
|
796
|
-
number(
|
796
|
+
number(PageSize * (Prefs.allocatorChunks ?? 16), Valtype.i32),
|
797
797
|
[ Opcodes.i32_ge_s ],
|
798
798
|
[ Opcodes.if, Valtype.i32 ],
|
799
799
|
// chunkOffset = 1 page
|
800
|
-
number(
|
800
|
+
number(pageSize, Valtype.i32),
|
801
801
|
[ Opcodes.global_set, 1 ],
|
802
802
|
|
803
803
|
// return chunkPtr = allocated
|
804
804
|
number(Prefs.allocatorChunks ?? 16, Valtype.i32),
|
805
805
|
[ Opcodes.memory_grow, 0 ],
|
806
|
-
number(
|
806
|
+
number(PageSize, Valtype.i32),
|
807
807
|
[ Opcodes.i32_mul ],
|
808
808
|
[ Opcodes.global_set, 0 ],
|
809
809
|
[ Opcodes.global_get, 0 ],
|