watr 4.3.1 → 4.3.4
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/dist/watr.js +118 -72
- package/dist/watr.min.js +6 -6
- package/dist/watr.wat +128517 -0
- package/package.json +2 -2
- package/src/encode.js +20 -25
- package/src/optimize.js +109 -61
- package/types/src/encode.d.ts +1 -0
- package/types/src/encode.d.ts.map +1 -1
- package/types/src/optimize.d.ts +4 -5
- package/types/src/optimize.d.ts.map +1 -1
- package/watr.js +2 -2
package/dist/watr.js
CHANGED
|
@@ -14,7 +14,8 @@ __export(encode_exports, {
|
|
|
14
14
|
i64: () => i64,
|
|
15
15
|
i8: () => i8,
|
|
16
16
|
uleb: () => uleb,
|
|
17
|
-
uleb5: () => uleb5
|
|
17
|
+
uleb5: () => uleb5,
|
|
18
|
+
v128: () => v128
|
|
18
19
|
});
|
|
19
20
|
|
|
20
21
|
// src/util.js
|
|
@@ -116,7 +117,8 @@ i32.parse = (n) => {
|
|
|
116
117
|
};
|
|
117
118
|
function i64(n, buffer = []) {
|
|
118
119
|
if (typeof n === "string") n = i64.parse(n);
|
|
119
|
-
else if (typeof n === "
|
|
120
|
+
else if (typeof n === "number") n = BigInt(n);
|
|
121
|
+
if (typeof n === "bigint" && n > 0x7fffffffffffffffn) {
|
|
120
122
|
n = n - 0x10000000000000000n;
|
|
121
123
|
}
|
|
122
124
|
while (true) {
|
|
@@ -130,14 +132,19 @@ function i64(n, buffer = []) {
|
|
|
130
132
|
}
|
|
131
133
|
return buffer;
|
|
132
134
|
}
|
|
135
|
+
var _buf = new ArrayBuffer(8);
|
|
136
|
+
var _u8 = new Uint8Array(_buf);
|
|
137
|
+
var _i32 = new Int32Array(_buf);
|
|
138
|
+
var _f32 = new Float32Array(_buf);
|
|
139
|
+
var _f64 = new Float64Array(_buf);
|
|
140
|
+
var _i64 = new BigInt64Array(_buf);
|
|
133
141
|
i64.parse = (n) => {
|
|
134
142
|
n = cleanInt(n);
|
|
135
143
|
n = n[0] === "-" ? -BigInt(n.slice(1)) : BigInt(n);
|
|
136
144
|
if (n < -0x8000000000000000n || n > 0xffffffffffffffffn) err(`i64 constant out of range`);
|
|
137
|
-
|
|
138
|
-
return
|
|
145
|
+
_i64[0] = n;
|
|
146
|
+
return _i64[0];
|
|
139
147
|
};
|
|
140
|
-
var byteView = new DataView(new Float64Array(1).buffer);
|
|
141
148
|
var F32_SIGN = 2147483648;
|
|
142
149
|
var F32_NAN = 2139095040;
|
|
143
150
|
function f32(input, value, idx) {
|
|
@@ -145,17 +152,12 @@ function f32(input, value, idx) {
|
|
|
145
152
|
value = i32.parse(input.slice(idx + 4));
|
|
146
153
|
value |= F32_NAN;
|
|
147
154
|
if (input[0] === "-") value |= F32_SIGN;
|
|
148
|
-
|
|
155
|
+
_i32[0] = value;
|
|
149
156
|
} else {
|
|
150
157
|
value = typeof input === "string" ? f32.parse(input) : input;
|
|
151
|
-
|
|
158
|
+
_f32[0] = value;
|
|
152
159
|
}
|
|
153
|
-
return [
|
|
154
|
-
byteView.getUint8(3),
|
|
155
|
-
byteView.getUint8(2),
|
|
156
|
-
byteView.getUint8(1),
|
|
157
|
-
byteView.getUint8(0)
|
|
158
|
-
];
|
|
160
|
+
return [_u8[0], _u8[1], _u8[2], _u8[3]];
|
|
159
161
|
}
|
|
160
162
|
var F64_SIGN = 0x8000000000000000n;
|
|
161
163
|
var F64_NAN = 0x7ff0000000000000n;
|
|
@@ -164,21 +166,12 @@ function f64(input, value, idx) {
|
|
|
164
166
|
value = i64.parse(input.slice(idx + 4));
|
|
165
167
|
value |= F64_NAN;
|
|
166
168
|
if (input[0] === "-") value |= F64_SIGN;
|
|
167
|
-
|
|
169
|
+
_i64[0] = value;
|
|
168
170
|
} else {
|
|
169
171
|
value = typeof input === "string" ? f64.parse(input) : input;
|
|
170
|
-
|
|
172
|
+
_f64[0] = value;
|
|
171
173
|
}
|
|
172
|
-
return [
|
|
173
|
-
byteView.getUint8(7),
|
|
174
|
-
byteView.getUint8(6),
|
|
175
|
-
byteView.getUint8(5),
|
|
176
|
-
byteView.getUint8(4),
|
|
177
|
-
byteView.getUint8(3),
|
|
178
|
-
byteView.getUint8(2),
|
|
179
|
-
byteView.getUint8(1),
|
|
180
|
-
byteView.getUint8(0)
|
|
181
|
-
];
|
|
174
|
+
return [_u8[0], _u8[1], _u8[2], _u8[3], _u8[4], _u8[5], _u8[6], _u8[7]];
|
|
182
175
|
}
|
|
183
176
|
f64.parse = (input, max = Number.MAX_VALUE) => {
|
|
184
177
|
input = input.replaceAll("_", "");
|
|
@@ -202,6 +195,12 @@ f64.parse = (input, max = Number.MAX_VALUE) => {
|
|
|
202
195
|
return sign * parseFloat(input);
|
|
203
196
|
};
|
|
204
197
|
f32.parse = (input) => f64.parse(input, 34028234663852886e22);
|
|
198
|
+
var v128 = (input) => {
|
|
199
|
+
let n = typeof input === "string" ? BigInt(input.replaceAll("_", "")) : BigInt(input);
|
|
200
|
+
let arr = new Uint8Array(16);
|
|
201
|
+
for (let i = 0; i < 16; i++) arr[i] = Number(n & 0xffn), n >>= 8n;
|
|
202
|
+
return [...arr];
|
|
203
|
+
};
|
|
205
204
|
|
|
206
205
|
// src/const.js
|
|
207
206
|
var INSTR = [
|
|
@@ -1765,7 +1764,7 @@ var IMM = {
|
|
|
1765
1764
|
i64: (n) => i64(n.shift()),
|
|
1766
1765
|
f32: (n) => f32(n.shift()),
|
|
1767
1766
|
f64: (n) => f64(n.shift()),
|
|
1768
|
-
v128: (n) => (
|
|
1767
|
+
v128: (n) => v128(n.shift()),
|
|
1769
1768
|
// Combinations
|
|
1770
1769
|
typeidx_field: (n, c) => {
|
|
1771
1770
|
let typeId = id(n.shift(), c.type);
|
|
@@ -3085,6 +3084,7 @@ var treeshake = (ast) => {
|
|
|
3085
3084
|
}
|
|
3086
3085
|
return result;
|
|
3087
3086
|
};
|
|
3087
|
+
var roundEven = (x) => x - Math.floor(x) !== 0.5 ? Math.round(x) : 2 * Math.round(x / 2);
|
|
3088
3088
|
var FOLDABLE = {
|
|
3089
3089
|
// i32
|
|
3090
3090
|
"i32.add": (a, b) => a + b | 0,
|
|
@@ -3168,7 +3168,7 @@ var FOLDABLE = {
|
|
|
3168
3168
|
"f32.ceil": (a) => Math.fround(Math.ceil(a)),
|
|
3169
3169
|
"f32.floor": (a) => Math.fround(Math.floor(a)),
|
|
3170
3170
|
"f32.trunc": (a) => Math.fround(Math.trunc(a)),
|
|
3171
|
-
"f32.nearest": (a) => Math.fround(
|
|
3171
|
+
"f32.nearest": (a) => Math.fround(roundEven(a)),
|
|
3172
3172
|
"f64.add": (a, b) => a + b,
|
|
3173
3173
|
"f64.sub": (a, b) => a - b,
|
|
3174
3174
|
"f64.mul": (a, b) => a * b,
|
|
@@ -3179,7 +3179,7 @@ var FOLDABLE = {
|
|
|
3179
3179
|
"f64.ceil": (a) => Math.ceil(a),
|
|
3180
3180
|
"f64.floor": (a) => Math.floor(a),
|
|
3181
3181
|
"f64.trunc": (a) => Math.trunc(a),
|
|
3182
|
-
"f64.nearest":
|
|
3182
|
+
"f64.nearest": roundEven
|
|
3183
3183
|
};
|
|
3184
3184
|
var getConst = (node) => {
|
|
3185
3185
|
if (!Array.isArray(node) || node.length !== 2) return null;
|
|
@@ -3489,7 +3489,7 @@ var localReuse = (ast) => {
|
|
|
3489
3489
|
const sub = node[i];
|
|
3490
3490
|
if (!Array.isArray(sub)) continue;
|
|
3491
3491
|
if (sub[0] === "local") {
|
|
3492
|
-
localDecls.push({
|
|
3492
|
+
localDecls.push({ node: sub, idx: i });
|
|
3493
3493
|
if (typeof sub[1] === "string" && sub[1][0] === "$") {
|
|
3494
3494
|
localTypes.set(sub[1], sub[2]);
|
|
3495
3495
|
}
|
|
@@ -3519,55 +3519,101 @@ var localReuse = (ast) => {
|
|
|
3519
3519
|
});
|
|
3520
3520
|
return result;
|
|
3521
3521
|
};
|
|
3522
|
+
var isPure = (node) => {
|
|
3523
|
+
if (!Array.isArray(node)) return true;
|
|
3524
|
+
const op = node[0];
|
|
3525
|
+
if (typeof op !== "string") return false;
|
|
3526
|
+
if (op === "call" || op === "call_indirect" || op === "return_call" || op === "return_call_indirect") return false;
|
|
3527
|
+
if (op.includes(".store") || op.includes(".load") || op.includes("memory.")) return false;
|
|
3528
|
+
if (op === "global.set") return false;
|
|
3529
|
+
for (let i = 1; i < node.length; i++) if (Array.isArray(node[i]) && !isPure(node[i])) return false;
|
|
3530
|
+
return true;
|
|
3531
|
+
};
|
|
3532
|
+
var countLocalUses = (node) => {
|
|
3533
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3534
|
+
const ensure = (name2) => {
|
|
3535
|
+
if (!counts.has(name2)) counts.set(name2, { gets: 0, sets: 0, tees: 0 });
|
|
3536
|
+
return counts.get(name2);
|
|
3537
|
+
};
|
|
3538
|
+
walk2(node, (n) => {
|
|
3539
|
+
if (!Array.isArray(n) || n.length < 2 || typeof n[1] !== "string") return;
|
|
3540
|
+
if (n[0] === "local.get") ensure(n[1]).gets++;
|
|
3541
|
+
else if (n[0] === "local.set") ensure(n[1]).sets++;
|
|
3542
|
+
else if (n[0] === "local.tee") ensure(n[1]).tees++;
|
|
3543
|
+
});
|
|
3544
|
+
return counts;
|
|
3545
|
+
};
|
|
3546
|
+
var canSubst = (k) => getConst(k.val) || k.pure && k.singleUse;
|
|
3547
|
+
var substGets = (node, known) => walkPost2(node, (n) => {
|
|
3548
|
+
if (!Array.isArray(n) || n[0] !== "local.get" || n.length !== 2) return;
|
|
3549
|
+
const k = typeof n[1] === "string" && known.get(n[1]);
|
|
3550
|
+
if (k && canSubst(k)) return clone2(k.val);
|
|
3551
|
+
});
|
|
3522
3552
|
var propagate = (ast) => {
|
|
3523
3553
|
const result = clone2(ast);
|
|
3524
|
-
walk2(result, (
|
|
3525
|
-
if (!Array.isArray(
|
|
3526
|
-
const
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3554
|
+
walk2(result, (funcNode) => {
|
|
3555
|
+
if (!Array.isArray(funcNode) || funcNode[0] !== "func") return;
|
|
3556
|
+
const params = /* @__PURE__ */ new Set();
|
|
3557
|
+
for (const sub of funcNode)
|
|
3558
|
+
if (Array.isArray(sub) && sub[0] === "param" && typeof sub[1] === "string") params.add(sub[1]);
|
|
3559
|
+
for (let pass = 0; pass < 4; pass++) {
|
|
3560
|
+
let changed = false;
|
|
3561
|
+
const uses = countLocalUses(funcNode);
|
|
3562
|
+
const getUses = (name2) => uses.get(name2) || { gets: 0, sets: 0, tees: 0 };
|
|
3563
|
+
const known = /* @__PURE__ */ new Map();
|
|
3564
|
+
for (let i = 1; i < funcNode.length; i++) {
|
|
3565
|
+
const instr2 = funcNode[i];
|
|
3530
3566
|
if (!Array.isArray(instr2)) continue;
|
|
3531
3567
|
const op = instr2[0];
|
|
3532
|
-
if (op === "local
|
|
3533
|
-
|
|
3534
|
-
|
|
3535
|
-
const
|
|
3536
|
-
|
|
3537
|
-
|
|
3538
|
-
|
|
3539
|
-
|
|
3540
|
-
}
|
|
3541
|
-
|
|
3542
|
-
|
|
3543
|
-
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
const local = instr2[1];
|
|
3552
|
-
if (typeof local === "string" && constLocals.has(local)) {
|
|
3553
|
-
const constVal = constLocals.get(local);
|
|
3568
|
+
if (op === "param" || op === "result" || op === "local" || op === "type" || op === "export") continue;
|
|
3569
|
+
if (op === "local.set" && instr2.length === 3 && typeof instr2[1] === "string") {
|
|
3570
|
+
substGets(instr2[2], known);
|
|
3571
|
+
const u = getUses(instr2[1]);
|
|
3572
|
+
known.set(instr2[1], {
|
|
3573
|
+
val: instr2[2],
|
|
3574
|
+
pure: isPure(instr2[2]),
|
|
3575
|
+
singleUse: u.gets <= 1 && u.sets <= 1 && u.tees === 0
|
|
3576
|
+
});
|
|
3577
|
+
continue;
|
|
3578
|
+
}
|
|
3579
|
+
if (op === "block" || op === "loop" || op === "if") known.clear();
|
|
3580
|
+
if (op === "call" || op === "call_indirect" || op === "return_call" || op === "return_call_indirect") {
|
|
3581
|
+
for (const [k, v] of known) if (!getConst(v.val)) known.delete(k);
|
|
3582
|
+
}
|
|
3583
|
+
if (op === "local.get" && instr2.length === 2 && typeof instr2[1] === "string") {
|
|
3584
|
+
const k = known.get(instr2[1]);
|
|
3585
|
+
if (k && canSubst(k)) {
|
|
3586
|
+
const r = clone2(k.val);
|
|
3554
3587
|
instr2.length = 0;
|
|
3555
|
-
instr2.push(...
|
|
3588
|
+
instr2.push(...Array.isArray(r) ? r : [r]);
|
|
3589
|
+
changed = true;
|
|
3590
|
+
continue;
|
|
3556
3591
|
}
|
|
3557
|
-
} else if (op === "block" || op === "loop" || op === "if" || op === "call" || op === "call_indirect") {
|
|
3558
|
-
constLocals.clear();
|
|
3559
3592
|
}
|
|
3560
|
-
|
|
3561
|
-
|
|
3562
|
-
|
|
3563
|
-
if (
|
|
3564
|
-
|
|
3565
|
-
return clone2(constVal);
|
|
3566
|
-
}
|
|
3567
|
-
});
|
|
3593
|
+
if (op !== "block" && op !== "loop" && op !== "if") {
|
|
3594
|
+
const prev = JSON.stringify(instr2);
|
|
3595
|
+
substGets(instr2, known);
|
|
3596
|
+
if (JSON.stringify(instr2) !== prev) changed = true;
|
|
3597
|
+
}
|
|
3568
3598
|
}
|
|
3569
|
-
|
|
3570
|
-
|
|
3599
|
+
const postUses = countLocalUses(funcNode);
|
|
3600
|
+
const pu = (name2) => postUses.get(name2) || { gets: 0, sets: 0, tees: 0 };
|
|
3601
|
+
for (let i = funcNode.length - 1; i >= 1; i--) {
|
|
3602
|
+
const sub = funcNode[i];
|
|
3603
|
+
if (!Array.isArray(sub)) continue;
|
|
3604
|
+
const name2 = typeof sub[1] === "string" ? sub[1] : null;
|
|
3605
|
+
if (!name2 || params.has(name2)) continue;
|
|
3606
|
+
const u = pu(name2);
|
|
3607
|
+
if (sub[0] === "local.set" && u.gets === 0 && u.tees === 0 && isPure(sub[2])) {
|
|
3608
|
+
funcNode.splice(i, 1);
|
|
3609
|
+
changed = true;
|
|
3610
|
+
} else if (sub[0] === "local" && name2[0] === "$" && u.gets === 0 && u.sets === 0 && u.tees === 0) {
|
|
3611
|
+
funcNode.splice(i, 1);
|
|
3612
|
+
changed = true;
|
|
3613
|
+
}
|
|
3614
|
+
}
|
|
3615
|
+
if (!changed) break;
|
|
3616
|
+
}
|
|
3571
3617
|
});
|
|
3572
3618
|
return result;
|
|
3573
3619
|
};
|
|
@@ -3718,7 +3764,7 @@ function genImports(imports) {
|
|
|
3718
3764
|
}
|
|
3719
3765
|
function compile2(source, ...values) {
|
|
3720
3766
|
let opts = {};
|
|
3721
|
-
if (!Array.isArray(source) && values.length && typeof values[values.length - 1] === "object" && values[values.length - 1] !== null && !
|
|
3767
|
+
if (!Array.isArray(source) && values.length && typeof values[values.length - 1] === "object" && values[values.length - 1] !== null && !values[values.length - 1].byteLength) {
|
|
3722
3768
|
opts = values.pop();
|
|
3723
3769
|
}
|
|
3724
3770
|
if (Array.isArray(source) && source.raw) {
|
|
@@ -3743,7 +3789,7 @@ function compile2(source, ...values) {
|
|
|
3743
3789
|
}
|
|
3744
3790
|
return parsed;
|
|
3745
3791
|
}
|
|
3746
|
-
if (value
|
|
3792
|
+
if (value.byteLength !== void 0) return [...value];
|
|
3747
3793
|
return value;
|
|
3748
3794
|
}
|
|
3749
3795
|
return node;
|