porffor 0.34.4 → 0.34.6
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 +12 -12
- package/compiler/builtins/__internal_string.ts +48 -0
- package/compiler/builtins/_internal_object.ts +2 -3
- package/compiler/builtins/_internal_string.ts +38 -0
- package/compiler/builtins/object.ts +6 -0
- package/compiler/builtins.js +5 -5
- package/compiler/builtins_precompiled.js +246 -231
- package/compiler/codegen.js +30 -182
- package/compiler/wrap.js +2 -2
- package/package.json +1 -1
- package/r.js +113 -0
- package/runner/index.js +1 -1
- package/runner/repl.js +1 -1
package/compiler/codegen.js
CHANGED
@@ -615,148 +615,22 @@ const concatStrings = (scope, left, right, leftType, rightType, allBytestrings =
|
|
615
615
|
];
|
616
616
|
};
|
617
617
|
|
618
|
-
const compareStrings = (scope, left, right, leftType, rightType
|
619
|
-
// todo:
|
620
|
-
// todo: convert left and right to strings if not
|
621
|
-
// todo: optimize by looking up names in arrays and using that if exists?
|
622
|
-
// todo: optimize this if using literals/known lengths?
|
623
|
-
|
624
|
-
const leftPointer = localTmp(scope, 'compare_left_pointer', Valtype.i32);
|
625
|
-
const leftLength = localTmp(scope, 'compare_left_length', Valtype.i32);
|
626
|
-
const rightPointer = localTmp(scope, 'compare_right_pointer', Valtype.i32);
|
627
|
-
|
628
|
-
const index = localTmp(scope, 'compare_index', Valtype.i32);
|
629
|
-
const indexEnd = localTmp(scope, 'compare_index_end', Valtype.i32);
|
630
|
-
|
631
|
-
if (!skipTypeCheck && !allBytestrings) includeBuiltin(scope, '__Porffor_bytestringToString');
|
618
|
+
const compareStrings = (scope, left, right, leftType, rightType) => {
|
619
|
+
// todo/perf: add mode to use strcmp instead
|
632
620
|
return [
|
633
|
-
|
634
|
-
...(
|
635
|
-
|
636
|
-
[ Opcodes.local_set, rightPointer ],
|
637
|
-
|
638
|
-
Opcodes.i32_to_u,
|
639
|
-
[ Opcodes.local_set, leftPointer ],
|
640
|
-
|
641
|
-
[ Opcodes.local_get, leftPointer ],
|
642
|
-
[ Opcodes.local_get, rightPointer ],
|
643
|
-
] : [
|
644
|
-
...left,
|
645
|
-
Opcodes.i32_to_u,
|
646
|
-
[ Opcodes.local_tee, leftPointer ],
|
647
|
-
|
648
|
-
...right,
|
649
|
-
Opcodes.i32_to_u,
|
650
|
-
[ Opcodes.local_tee, rightPointer ],
|
651
|
-
]),
|
652
|
-
|
653
|
-
// fast path: check leftPointer == rightPointer
|
654
|
-
// use if (block) for everything after to "return" a value early
|
655
|
-
[ Opcodes.i32_ne ],
|
656
|
-
[ Opcodes.if, Valtype.i32 ],
|
657
|
-
|
658
|
-
// get lengths
|
659
|
-
[ Opcodes.local_get, leftPointer ],
|
660
|
-
[ Opcodes.i32_load, 0, 0 ],
|
661
|
-
[ Opcodes.local_tee, leftLength ],
|
662
|
-
|
663
|
-
[ Opcodes.local_get, rightPointer ],
|
664
|
-
[ Opcodes.i32_load, 0, 0 ],
|
665
|
-
|
666
|
-
...(skipTypeCheck || allBytestrings ? [] : [
|
667
|
-
...leftType,
|
668
|
-
...number(TYPES.bytestring, Valtype.i32),
|
669
|
-
[ Opcodes.i32_eq ],
|
670
|
-
[ Opcodes.if, Blocktype.void ],
|
671
|
-
[ Opcodes.local_get, leftPointer ],
|
672
|
-
[ Opcodes.local_get, leftLength ],
|
673
|
-
[ Opcodes.call, funcIndex.__Porffor_bytestringToString ],
|
674
|
-
[ Opcodes.local_set, leftPointer ],
|
675
|
-
[ Opcodes.end ],
|
676
|
-
|
677
|
-
...rightType,
|
678
|
-
...number(TYPES.bytestring, Valtype.i32),
|
679
|
-
[ Opcodes.i32_eq ],
|
680
|
-
[ Opcodes.if, Blocktype.void ],
|
681
|
-
[ Opcodes.local_get, rightPointer ],
|
682
|
-
[ Opcodes.local_get, rightPointer ],
|
683
|
-
[ Opcodes.i32_load, 0, 0 ],
|
684
|
-
[ Opcodes.call, funcIndex.__Porffor_bytestringToString ],
|
685
|
-
[ Opcodes.local_set, rightPointer ],
|
686
|
-
[ Opcodes.end ]
|
687
|
-
]),
|
688
|
-
|
689
|
-
// fast path: check leftLength != rightLength
|
690
|
-
[ Opcodes.i32_ne ],
|
691
|
-
[ Opcodes.if, Blocktype.void ],
|
692
|
-
...number(0, Valtype.i32),
|
693
|
-
[ Opcodes.br, 1 ],
|
694
|
-
[ Opcodes.end ],
|
695
|
-
|
696
|
-
// no fast path for length = 0 as it would probably be slower for most of the time?
|
697
|
-
|
698
|
-
// tmp could have already been used
|
699
|
-
...number(0, Valtype.i32),
|
700
|
-
[ Opcodes.local_set, index ],
|
701
|
-
|
702
|
-
// setup index end as length * sizeof valtype (1 for bytestring, 2 for string)
|
703
|
-
// we do this instead of having to do mul/div each iter for perf™
|
704
|
-
[ Opcodes.local_get, leftLength ],
|
705
|
-
...(allBytestrings ? [] : [
|
706
|
-
...number(ValtypeSize.i16, Valtype.i32),
|
707
|
-
[ Opcodes.i32_mul ],
|
708
|
-
]),
|
709
|
-
[ Opcodes.local_set, indexEnd ],
|
710
|
-
|
711
|
-
// iterate over each char and check if eq
|
712
|
-
[ Opcodes.loop, Blocktype.void ],
|
713
|
-
|
714
|
-
// fetch left
|
715
|
-
[ Opcodes.local_get, index ],
|
716
|
-
[ Opcodes.local_get, leftPointer ],
|
717
|
-
[ Opcodes.i32_add ],
|
718
|
-
allBytestrings ?
|
719
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ] :
|
720
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
721
|
-
|
722
|
-
// fetch right
|
723
|
-
[ Opcodes.local_get, index ],
|
724
|
-
[ Opcodes.local_get, rightPointer ],
|
725
|
-
[ Opcodes.i32_add ],
|
726
|
-
allBytestrings ?
|
727
|
-
[ Opcodes.i32_load8_u, 0, ValtypeSize.i32 ] :
|
728
|
-
[ Opcodes.i32_load16_u, Math.log2(ValtypeSize.i16) - 1, ValtypeSize.i32 ],
|
729
|
-
|
730
|
-
// not equal, "return" false
|
731
|
-
[ Opcodes.i32_ne ],
|
732
|
-
[ Opcodes.if, Blocktype.void ],
|
733
|
-
...number(0, Valtype.i32),
|
734
|
-
[ Opcodes.br, 2 ],
|
735
|
-
[ Opcodes.end ],
|
736
|
-
|
737
|
-
// index += sizeof valtype (1 for bytestring, 2 for string)
|
738
|
-
[ Opcodes.local_get, index ],
|
739
|
-
...number(allBytestrings ? ValtypeSize.i8 : ValtypeSize.i16, Valtype.i32),
|
740
|
-
[ Opcodes.i32_add ],
|
741
|
-
[ Opcodes.local_tee, index ],
|
621
|
+
...left,
|
622
|
+
...(valtypeBinary === Valtype.i32 ? [ [ Opcodes.f64_convert_i32_s ] ] : []),
|
623
|
+
...leftType,
|
742
624
|
|
743
|
-
|
744
|
-
[ Opcodes.
|
745
|
-
|
746
|
-
[ Opcodes.br_if, 0 ],
|
747
|
-
[ Opcodes.end ],
|
625
|
+
...right,
|
626
|
+
...(valtypeBinary === Valtype.i32 ? [ [ Opcodes.f64_convert_i32_s ] ] : []),
|
627
|
+
...rightType,
|
748
628
|
|
749
|
-
|
750
|
-
|
629
|
+
[ Opcodes.call, includeBuiltin(scope, '__Porffor_compareStrings').index ],
|
630
|
+
[ Opcodes.drop ],
|
751
631
|
|
752
|
-
//
|
753
|
-
|
754
|
-
...number(1, Valtype.i32),
|
755
|
-
[ Opcodes.end ],
|
756
|
-
|
757
|
-
// convert i32 result to valtype
|
758
|
-
// do not do as automatically added by binary exp gen for equality ops
|
759
|
-
// Opcodes.i32_from_u
|
632
|
+
// convert valtype result to i32 as i32 output expected
|
633
|
+
Opcodes.i32_trunc_sat_f64_u
|
760
634
|
];
|
761
635
|
};
|
762
636
|
|
@@ -999,9 +873,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
999
873
|
// string comparison
|
1000
874
|
if (op === '===' || op === '==' || op === '!==' || op === '!=') {
|
1001
875
|
return [
|
1002
|
-
...left,
|
1003
|
-
...right,
|
1004
|
-
...compareStrings(scope, [], [], leftType, rightType, false, knownLeft === TYPES.string && knownRight === TYPES.string),
|
876
|
+
...compareStrings(scope, left, right, leftType, rightType),
|
1005
877
|
...(op === '!==' || op === '!=' ? [ [ Opcodes.i32_eqz ] ] : [])
|
1006
878
|
];
|
1007
879
|
}
|
@@ -1027,9 +899,7 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
1027
899
|
// string comparison
|
1028
900
|
if (op === '===' || op === '==' || op === '!==' || op === '!=') {
|
1029
901
|
return [
|
1030
|
-
...left,
|
1031
|
-
...right,
|
1032
|
-
...compareStrings(scope, [], [], leftType, rightType, knownLeft === TYPES.bytestring && knownRight === TYPES.bytestring),
|
902
|
+
...compareStrings(scope, left, right, leftType, rightType),
|
1033
903
|
...(op === '!==' || op === '!=' ? [ [ Opcodes.i32_eqz ] ] : [])
|
1034
904
|
];
|
1035
905
|
}
|
@@ -1118,43 +988,19 @@ const performOp = (scope, op, left, right, leftType, rightType, _global = false,
|
|
1118
988
|
tmpRight = localTmp(scope, '__tmpop_right');
|
1119
989
|
|
1120
990
|
ops.unshift(...stringOnly([
|
1121
|
-
// if left
|
991
|
+
// if left or right are string or bytestring
|
1122
992
|
...leftType,
|
993
|
+
...number(TYPE_FLAGS.parity, Valtype.i32),
|
994
|
+
[ Opcodes.i32_or ],
|
1123
995
|
...number(TYPES.bytestring, Valtype.i32),
|
1124
996
|
[ Opcodes.i32_eq ],
|
1125
997
|
|
1126
|
-
// if right is bytestring
|
1127
998
|
...rightType,
|
1128
|
-
...number(
|
1129
|
-
[ Opcodes.i32_eq ],
|
1130
|
-
|
1131
|
-
// if both are true
|
1132
|
-
[ Opcodes.i32_and ],
|
1133
|
-
[ Opcodes.if, Blocktype.void ],
|
1134
|
-
...compareStrings(scope, [ [ Opcodes.local_get, tmpLeft ] ], [ [ Opcodes.local_get, tmpRight ] ], leftType, rightType, true),
|
1135
|
-
...(op === '!==' || op === '!=' ? [ [ Opcodes.i32_eqz ] ] : []),
|
1136
|
-
[ Opcodes.br, 1 ],
|
1137
|
-
[ Opcodes.end ],
|
1138
|
-
|
1139
|
-
// if left is string or bytestring
|
1140
|
-
...leftType,
|
1141
|
-
...number(TYPES.string, Valtype.i32),
|
1142
|
-
[ Opcodes.i32_eq ],
|
1143
|
-
...leftType,
|
1144
|
-
...number(TYPES.bytestring, Valtype.i32),
|
1145
|
-
[ Opcodes.i32_eq ],
|
999
|
+
...number(TYPE_FLAGS.parity, Valtype.i32),
|
1146
1000
|
[ Opcodes.i32_or ],
|
1147
|
-
|
1148
|
-
// if right is string or bytestring
|
1149
|
-
...rightType,
|
1150
|
-
...number(TYPES.string, Valtype.i32),
|
1151
|
-
[ Opcodes.i32_eq ],
|
1152
|
-
...rightType,
|
1153
1001
|
...number(TYPES.bytestring, Valtype.i32),
|
1154
1002
|
[ Opcodes.i32_eq ],
|
1155
|
-
[ Opcodes.i32_or ],
|
1156
1003
|
|
1157
|
-
// if either
|
1158
1004
|
[ Opcodes.i32_or ],
|
1159
1005
|
[ Opcodes.if, Blocktype.void ],
|
1160
1006
|
...compareStrings(scope, [ [ Opcodes.local_get, tmpLeft ] ], [ [ Opcodes.local_get, tmpRight ] ], leftType, rightType),
|
@@ -2589,7 +2435,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2589
2435
|
|
2590
2436
|
// get if func we are calling is a constructor or not
|
2591
2437
|
[ Opcodes.local_get, funcLocal ],
|
2592
|
-
...number(
|
2438
|
+
...number(64, Valtype.i32),
|
2593
2439
|
[ Opcodes.i32_mul ],
|
2594
2440
|
...number(4, Valtype.i32),
|
2595
2441
|
[ Opcodes.i32_add ],
|
@@ -2615,7 +2461,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2615
2461
|
// [ Opcodes.call, 1 ],
|
2616
2462
|
|
2617
2463
|
// [ Opcodes.local_get, funcLocal ],
|
2618
|
-
// ...number(
|
2464
|
+
// ...number(64, Valtype.i32),
|
2619
2465
|
// [ Opcodes.i32_mul ],
|
2620
2466
|
// [ Opcodes.i32_load16_u, 0, ...unsignedLEB128(allocPage(scope, 'func lut') * pageSize), 'read func lut' ],
|
2621
2467
|
// Opcodes.i32_from_u,
|
@@ -2627,7 +2473,7 @@ const generateCall = (scope, decl, _global, _name, unusedValue = false) => {
|
|
2627
2473
|
...brTable([
|
2628
2474
|
// get argc of func we are calling
|
2629
2475
|
[ Opcodes.local_get, funcLocal ],
|
2630
|
-
...number(
|
2476
|
+
...number(64, Valtype.i32),
|
2631
2477
|
[ Opcodes.i32_mul ],
|
2632
2478
|
[ Opcodes.i32_load16_u, 0, ...unsignedLEB128(allocPage(scope, 'func lut') * pageSize), 'read func lut' ]
|
2633
2479
|
], tableBc, valtypeBinary)
|
@@ -5812,14 +5658,16 @@ const generateClass = (scope, decl) => {
|
|
5812
5658
|
optional: false
|
5813
5659
|
};
|
5814
5660
|
|
5815
|
-
const constr =
|
5816
|
-
|
5661
|
+
const constr = {
|
5662
|
+
...(body.find(x => x.kind === 'constructor')?.value ?? {
|
5663
|
+
type: 'FunctionExpression',
|
5664
|
+
params: [],
|
5665
|
+
body: {
|
5666
|
+
type: 'BlockStatement',
|
5667
|
+
body: []
|
5668
|
+
}
|
5669
|
+
}),
|
5817
5670
|
id: root,
|
5818
|
-
params: [],
|
5819
|
-
body: {
|
5820
|
-
type: 'BlockStatement',
|
5821
|
-
body: []
|
5822
|
-
}
|
5823
5671
|
};
|
5824
5672
|
|
5825
5673
|
const [ func, out ] = generateFunc(scope, {
|
package/compiler/wrap.js
CHANGED
@@ -318,7 +318,7 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
318
318
|
const printDecomp = (middleIndex, func, funcs, globals, exceptions) => {
|
319
319
|
console.log(`\x1B[35m\x1B[1mporffor backtrace\u001b[0m`);
|
320
320
|
|
321
|
-
const surrounding = Prefs.backtraceSurrounding ??
|
321
|
+
const surrounding = Prefs.backtraceSurrounding ?? 10;
|
322
322
|
let min = middleIndex - surrounding;
|
323
323
|
let max = middleIndex + surrounding + 1;
|
324
324
|
if (Prefs.backtraceFunc || middleIndex == -1) {
|
@@ -350,7 +350,7 @@ export default (source, flags = [ 'module' ], customImports = {}, print = str =>
|
|
350
350
|
Number.isNaN(funcInd) || Number.isNaN(blobOffset)) return false;
|
351
351
|
|
352
352
|
// convert blob offset -> function wasm offset
|
353
|
-
const func = funcs.find(x => x.
|
353
|
+
const func = funcs.find(x => x.asmIndex === funcInd);
|
354
354
|
if (!func) return false;
|
355
355
|
|
356
356
|
const { wasm: assembledWasmFlat, wasmNonFlat: assembledWasmOps, localDecl } = func.assembled;
|
package/package.json
CHANGED
package/r.js
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
function $DONE(error) {
|
2
|
+
if (error) {
|
3
|
+
Porffor.printStatic('Test262:AsyncTestFailure:Error: unknown');
|
4
|
+
} else {
|
5
|
+
Porffor.printStatic('Test262:AsyncTestComplete');
|
6
|
+
}
|
7
|
+
}
|
8
|
+
function assert(mustBeTrue) {
|
9
|
+
if (mustBeTrue === true) {
|
10
|
+
return;
|
11
|
+
}
|
12
|
+
|
13
|
+
throw new Test262Error('assert failed');
|
14
|
+
}
|
15
|
+
|
16
|
+
assert.throws = function (expectedErrorConstructor, func) {
|
17
|
+
if (typeof func !== 'function') {
|
18
|
+
throw new Test262Error('assert.throws invoked with a non-function value');
|
19
|
+
}
|
20
|
+
|
21
|
+
try {
|
22
|
+
func();
|
23
|
+
} catch {
|
24
|
+
return;
|
25
|
+
}
|
26
|
+
|
27
|
+
throw new Test262Error('assert.throws failed');
|
28
|
+
};
|
29
|
+
|
30
|
+
assert._isSameValue = function (a, b) {
|
31
|
+
if (a === b) {
|
32
|
+
// Handle +/-0 vs. -/+0
|
33
|
+
return a !== 0 || 1 / a === 1 / b;
|
34
|
+
}
|
35
|
+
|
36
|
+
// Handle NaN vs. NaN
|
37
|
+
return a !== a && b !== b;
|
38
|
+
};
|
39
|
+
|
40
|
+
assert.sameValue = function (actual, expected) {
|
41
|
+
if (assert._isSameValue(actual, expected)) {
|
42
|
+
return;
|
43
|
+
}
|
44
|
+
|
45
|
+
throw new Test262Error('assert.sameValue failed');
|
46
|
+
};
|
47
|
+
|
48
|
+
assert.notSameValue = function (actual, unexpected) {
|
49
|
+
if (!assert._isSameValue(actual, unexpected)) {
|
50
|
+
return;
|
51
|
+
}
|
52
|
+
|
53
|
+
throw new Test262Error('assert.notSameValue failed');
|
54
|
+
};
|
55
|
+
// define our $262 here too
|
56
|
+
var $262 = {
|
57
|
+
global: globalThis,
|
58
|
+
gc() { /* noop */ },
|
59
|
+
detachArrayBuffer(buffer) {
|
60
|
+
return Porffor.arraybuffer.detach(buffer);
|
61
|
+
},
|
62
|
+
getGlobal(name) {
|
63
|
+
return globalThis[name];
|
64
|
+
},
|
65
|
+
// todo: setGlobal
|
66
|
+
destroy() { /* noop */ },
|
67
|
+
agent: {}
|
68
|
+
};
|
69
|
+
|
70
|
+
function Test262Error() {}
|
71
|
+
|
72
|
+
Test262Error.thrower = function (message) {
|
73
|
+
throw new Test262Error(message);
|
74
|
+
};
|
75
|
+
|
76
|
+
function $DONOTEVALUATE() {
|
77
|
+
throw 'Test262: This statement should not be evaluated.';
|
78
|
+
}
|
79
|
+
// Copyright (C) 2015 the V8 project authors. All rights reserved.
|
80
|
+
// This code is governed by the BSD license found in the LICENSE file.
|
81
|
+
/*---
|
82
|
+
es6id: 25.4.5.3
|
83
|
+
description: PerformPromiseThen on a rejected promise
|
84
|
+
info: |
|
85
|
+
7. Return PerformPromiseThen(promise, onFulfilled, onRejected,
|
86
|
+
resultCapability).
|
87
|
+
|
88
|
+
25.4.5.3.1 PerformPromiseThen
|
89
|
+
|
90
|
+
[...]
|
91
|
+
9. Else if the value of promise's [[PromiseState]] internal slot is
|
92
|
+
"rejected",
|
93
|
+
a. Let reason be the value of promise's [[PromiseResult]] internal slot.
|
94
|
+
b. Perform EnqueueJob("PromiseJobs", PromiseReactionJob,
|
95
|
+
«rejectReaction, reason»).
|
96
|
+
[...]
|
97
|
+
flags: [async]
|
98
|
+
---*/
|
99
|
+
|
100
|
+
var value = {};
|
101
|
+
var p = new Promise(function(_, reject) {
|
102
|
+
reject(value);
|
103
|
+
});
|
104
|
+
|
105
|
+
p.then(function() {
|
106
|
+
$DONE('The `onFulfilled` handler should not be invoked.');
|
107
|
+
}, function(x) {
|
108
|
+
if (x !== value) {
|
109
|
+
$DONE('The `onRejected` handler should be invoked with the promise result.');
|
110
|
+
return;
|
111
|
+
}
|
112
|
+
$DONE();
|
113
|
+
});
|
package/runner/index.js
CHANGED
package/runner/repl.js
CHANGED
@@ -42,7 +42,7 @@ const memoryToString = mem => {
|
|
42
42
|
|
43
43
|
const buf = new Uint8Array(mem.buffer);
|
44
44
|
|
45
|
-
let longestType =
|
45
|
+
let longestType = 4, longestName = 4;
|
46
46
|
for (const x of lastPages) {
|
47
47
|
const [ type, name ] = x.split(': ');
|
48
48
|
if (type.length > longestType) longestType = type.length;
|