@markw65/monkeyc-optimizer 1.1.21 → 1.1.22
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 +14 -1
- package/build/api.cjs +33 -33
- package/build/{chunk-ZDTW2QRS.cjs → chunk-563GVBVT.cjs} +1142 -757
- package/build/optimizer.cjs +17 -17
- package/build/sdk-util.cjs +14 -14
- package/build/src/api.d.ts +1 -1
- package/build/src/optimizer-types.d.ts +1 -0
- package/build/src/readprg/array-init.d.ts +2 -1
- package/build/src/readprg/bytecode.d.ts +2 -0
- package/build/src/readprg/cflow.d.ts +8 -1
- package/build/src/readprg/interp.d.ts +7 -6
- package/build/src/readprg/locals.d.ts +3 -2
- package/build/src/readprg.d.ts +4 -3
- package/build/src/type-flow/type-flow-util.d.ts +1 -1
- package/build/src/worker-task.d.ts +1 -0
- package/build/worker-thread.cjs +3 -3
- package/package.json +1 -1
|
@@ -26,8 +26,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
mod
|
|
27
27
|
));
|
|
28
28
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
-
var
|
|
30
|
-
__export(
|
|
29
|
+
var chunk_563GVBVT_exports = {};
|
|
30
|
+
__export(chunk_563GVBVT_exports, {
|
|
31
31
|
EnumTagsConst: () => EnumTagsConst,
|
|
32
32
|
LastTypeTag: () => LastTypeTag,
|
|
33
33
|
ObjectLikeTagsConst: () => ObjectLikeTagsConst,
|
|
@@ -125,7 +125,7 @@ __export(chunk_ZDTW2QRS_exports, {
|
|
|
125
125
|
visitorNode: () => visitorNode,
|
|
126
126
|
xml_util_exports: () => xml_util_exports
|
|
127
127
|
});
|
|
128
|
-
module.exports = __toCommonJS(
|
|
128
|
+
module.exports = __toCommonJS(chunk_563GVBVT_exports);
|
|
129
129
|
var import_chunk_HHQDDCTP = require("./chunk-HHQDDCTP.cjs");
|
|
130
130
|
var import_prettier_plugin_monkeyc = require("@markw65/prettier-plugin-monkeyc");
|
|
131
131
|
var import_node_assert = __toESM(require("node:assert"));
|
|
@@ -13663,6 +13663,23 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
|
|
|
13663
13663
|
);
|
|
13664
13664
|
const deadStores = /* @__PURE__ */ new Set();
|
|
13665
13665
|
const copyPropStores = /* @__PURE__ */ new Map();
|
|
13666
|
+
const copyPropRef = (curState, key, node) => {
|
|
13667
|
+
if (findCopyPropCandidates && declIsLocal(key)) {
|
|
13668
|
+
if (!curState.anticipated) {
|
|
13669
|
+
curState.anticipated = /* @__PURE__ */ new Map();
|
|
13670
|
+
}
|
|
13671
|
+
addAnt(curState.anticipated, key, node);
|
|
13672
|
+
if (!curState.partiallyAnticipated) {
|
|
13673
|
+
curState.partiallyAnticipated = /* @__PURE__ */ new Map();
|
|
13674
|
+
}
|
|
13675
|
+
addAnt(curState.partiallyAnticipated, key, node);
|
|
13676
|
+
if (logThisRun) {
|
|
13677
|
+
console.log(
|
|
13678
|
+
` antrefs: ${curState.partiallyAnticipated.get(key) !== false} ${curState.anticipated.get(key) !== false}`
|
|
13679
|
+
);
|
|
13680
|
+
}
|
|
13681
|
+
}
|
|
13682
|
+
};
|
|
13666
13683
|
order.forEach((block) => {
|
|
13667
13684
|
if (!block.succs) {
|
|
13668
13685
|
queue.enqueue(block);
|
|
@@ -13694,31 +13711,21 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
|
|
|
13694
13711
|
case "ref":
|
|
13695
13712
|
if (isTypeStateKey(event.decl)) {
|
|
13696
13713
|
if (logThisRun) {
|
|
13697
|
-
console.log(
|
|
13714
|
+
console.log(
|
|
13715
|
+
`${describeEvent(event)} (${sourceLocation(event.node.loc)})`
|
|
13716
|
+
);
|
|
13698
13717
|
console.log(` kill => ${tsKey(event.decl)}`);
|
|
13699
13718
|
}
|
|
13700
|
-
|
|
13701
|
-
if (!curState.anticipated) {
|
|
13702
|
-
curState.anticipated = /* @__PURE__ */ new Map();
|
|
13703
|
-
}
|
|
13704
|
-
addAnt(curState.anticipated, event.decl, event.node);
|
|
13705
|
-
if (!curState.partiallyAnticipated) {
|
|
13706
|
-
curState.partiallyAnticipated = /* @__PURE__ */ new Map();
|
|
13707
|
-
}
|
|
13708
|
-
addAnt(curState.partiallyAnticipated, event.decl, event.node);
|
|
13709
|
-
if (logThisRun) {
|
|
13710
|
-
console.log(
|
|
13711
|
-
` antrefs: ${curState.partiallyAnticipated.get(event.decl) !== false} ${curState.anticipated.get(event.decl) !== false}`
|
|
13712
|
-
);
|
|
13713
|
-
}
|
|
13714
|
-
}
|
|
13719
|
+
copyPropRef(curState, event.decl, event.node);
|
|
13715
13720
|
curState.dead.delete(event.decl);
|
|
13716
13721
|
}
|
|
13717
13722
|
break;
|
|
13718
13723
|
case "def":
|
|
13719
13724
|
if (isTypeStateKey(event.decl) && (event.node.type !== "VariableDeclarator" || event.node.init)) {
|
|
13720
13725
|
if (logThisRun) {
|
|
13721
|
-
console.log(
|
|
13726
|
+
console.log(
|
|
13727
|
+
`${describeEvent(event)} (${sourceLocation(event.node.loc)})`
|
|
13728
|
+
);
|
|
13722
13729
|
}
|
|
13723
13730
|
const assignNode = event.node.type === "AssignmentExpression" && event.node.operator === "=" && event.node.right || event.node.type === "VariableDeclarator" && event.node.init;
|
|
13724
13731
|
if (curState.dead.has(event.decl)) {
|
|
@@ -13764,6 +13771,8 @@ function findDeadStores(func, graph, nodeEquivs, findCopyPropCandidates, logThis
|
|
|
13764
13771
|
if (logThisRun) {
|
|
13765
13772
|
console.log(` anticipated => ${tsKey(event.decl)}`);
|
|
13766
13773
|
}
|
|
13774
|
+
} else if (event.node.type === "UpdateExpression") {
|
|
13775
|
+
copyPropRef(curState, event.decl, event.node.argument);
|
|
13767
13776
|
}
|
|
13768
13777
|
}
|
|
13769
13778
|
break;
|
|
@@ -21382,178 +21391,6 @@ var init_opcodes = (0, import_chunk_HHQDDCTP.__esm)({
|
|
|
21382
21391
|
})(Opcodes || {});
|
|
21383
21392
|
}
|
|
21384
21393
|
});
|
|
21385
|
-
function optimizeArrayInit(func, block, index, stackPreserving, context) {
|
|
21386
|
-
(0, import_node_assert6.default)(
|
|
21387
|
-
block.bytecodes[index].op === 20
|
|
21388
|
-
/* newa */
|
|
21389
|
-
);
|
|
21390
|
-
const putvStarts = [];
|
|
21391
|
-
let i;
|
|
21392
|
-
let initVal = null;
|
|
21393
|
-
for (i = index; ++i < block.bytecodes.length - 1; ) {
|
|
21394
|
-
const dup = block.bytecodes[i];
|
|
21395
|
-
if (dup.op !== 46 || dup.arg !== 0) {
|
|
21396
|
-
break;
|
|
21397
|
-
}
|
|
21398
|
-
const ipush = block.bytecodes[i + 1];
|
|
21399
|
-
if (ipush.op !== 37 || ipush.arg !== putvStarts.length) {
|
|
21400
|
-
break;
|
|
21401
|
-
}
|
|
21402
|
-
let found = i;
|
|
21403
|
-
for (let k = i + 1, depth = 0; ++k < block.bytecodes.length; ) {
|
|
21404
|
-
const bc = block.bytecodes[k];
|
|
21405
|
-
if (bc.op === 17 && depth === 1) {
|
|
21406
|
-
found = k;
|
|
21407
|
-
break;
|
|
21408
|
-
}
|
|
21409
|
-
const { pop, push } = getOpInfo(bc);
|
|
21410
|
-
depth += push - pop;
|
|
21411
|
-
if (depth < 0 || bc.op === 46 && bc.arg >= depth) {
|
|
21412
|
-
break;
|
|
21413
|
-
}
|
|
21414
|
-
}
|
|
21415
|
-
if (found === i)
|
|
21416
|
-
break;
|
|
21417
|
-
if (initVal !== false) {
|
|
21418
|
-
if (found === i + 3) {
|
|
21419
|
-
const bc = block.bytecodes[i + 2];
|
|
21420
|
-
if (initVal === null) {
|
|
21421
|
-
initVal = bc;
|
|
21422
|
-
} else if (initVal.op !== bc.op || initVal.arg !== bc.arg) {
|
|
21423
|
-
initVal = false;
|
|
21424
|
-
}
|
|
21425
|
-
} else {
|
|
21426
|
-
initVal = false;
|
|
21427
|
-
}
|
|
21428
|
-
}
|
|
21429
|
-
putvStarts.push(i);
|
|
21430
|
-
i = found;
|
|
21431
|
-
}
|
|
21432
|
-
if (block.bytecodes[i]?.op === 2) {
|
|
21433
|
-
const convertAputv = (i2) => {
|
|
21434
|
-
const bc = block.bytecodes[i2];
|
|
21435
|
-
const op = bc.op;
|
|
21436
|
-
bc.op = 2;
|
|
21437
|
-
bc.size = 1;
|
|
21438
|
-
delete bc.arg;
|
|
21439
|
-
(0, import_node_assert6.default)(
|
|
21440
|
-
op === 17
|
|
21441
|
-
/* aputv */
|
|
21442
|
-
);
|
|
21443
|
-
};
|
|
21444
|
-
convertAputv(i - 1);
|
|
21445
|
-
for (i = putvStarts.length; i--; ) {
|
|
21446
|
-
const offset = putvStarts[i];
|
|
21447
|
-
block.bytecodes.splice(offset, 2);
|
|
21448
|
-
if (i) {
|
|
21449
|
-
convertAputv(offset - 1);
|
|
21450
|
-
}
|
|
21451
|
-
}
|
|
21452
|
-
(0, import_chunk_HHQDDCTP.logger)(
|
|
21453
|
-
"array-init",
|
|
21454
|
-
1,
|
|
21455
|
-
`Optimizing unused ${putvStarts.length} element array init at block ${offsetToString(
|
|
21456
|
-
block.offset
|
|
21457
|
-
)}, starting at index ${index}, at offset ${offsetToString(
|
|
21458
|
-
block.bytecodes[index].offset
|
|
21459
|
-
)}`
|
|
21460
|
-
);
|
|
21461
|
-
if ((0, import_chunk_HHQDDCTP.wouldLog)("array-init", 5)) {
|
|
21462
|
-
(0, import_chunk_HHQDDCTP.log)(blockToString(block, context));
|
|
21463
|
-
}
|
|
21464
|
-
return true;
|
|
21465
|
-
}
|
|
21466
|
-
const bytecode = (op, arg) => {
|
|
21467
|
-
const bc = { op, arg, size: opcodeSize(op), offset: context.nextOffset++ };
|
|
21468
|
-
if (arg == null)
|
|
21469
|
-
delete bc.arg;
|
|
21470
|
-
return bc;
|
|
21471
|
-
};
|
|
21472
|
-
if (initVal) {
|
|
21473
|
-
if (putvStarts.length < 3)
|
|
21474
|
-
return false;
|
|
21475
|
-
(0, import_chunk_HHQDDCTP.logger)(
|
|
21476
|
-
"array-init",
|
|
21477
|
-
1,
|
|
21478
|
-
`Optimizing ${putvStarts.length} element array init with constant initializer ${bytecodeToString(
|
|
21479
|
-
initVal,
|
|
21480
|
-
null
|
|
21481
|
-
)} at block ${offsetToString(
|
|
21482
|
-
block.offset
|
|
21483
|
-
)}, starting at index ${index}, at offset ${offsetToString(
|
|
21484
|
-
block.bytecodes[index].offset
|
|
21485
|
-
)}`
|
|
21486
|
-
);
|
|
21487
|
-
block.bytecodes.splice(
|
|
21488
|
-
putvStarts[1],
|
|
21489
|
-
putvStarts[putvStarts.length - 1] - putvStarts[0]
|
|
21490
|
-
);
|
|
21491
|
-
block.bytecodes.splice(putvStarts[0], 1);
|
|
21492
|
-
block.bytecodes[putvStarts[0]].arg = putvStarts.length;
|
|
21493
|
-
const loopOffset2 = context.nextOffset;
|
|
21494
|
-
block.bytecodes.splice(
|
|
21495
|
-
index + 2,
|
|
21496
|
-
0,
|
|
21497
|
-
bytecode(37, 1),
|
|
21498
|
-
bytecode(4, void 0),
|
|
21499
|
-
bytecode(46, 1),
|
|
21500
|
-
bytecode(46, 1)
|
|
21501
|
-
);
|
|
21502
|
-
block.bytecodes.splice(
|
|
21503
|
-
index + 8,
|
|
21504
|
-
0,
|
|
21505
|
-
bytecode(46, 0),
|
|
21506
|
-
bytecode(40, loopOffset2),
|
|
21507
|
-
bytecode(2, void 0)
|
|
21508
|
-
);
|
|
21509
|
-
splitBlock(func, block, index + 10);
|
|
21510
|
-
splitBlock(func, block, index + 2);
|
|
21511
|
-
const loop2 = func.blocks.get(loopOffset2);
|
|
21512
|
-
loop2.preds.add(loopOffset2);
|
|
21513
|
-
loop2.taken = loopOffset2;
|
|
21514
|
-
return true;
|
|
21515
|
-
}
|
|
21516
|
-
if (stackPreserving || putvStarts.length < 4)
|
|
21517
|
-
return false;
|
|
21518
|
-
for (i = putvStarts.length; i-- > 1; ) {
|
|
21519
|
-
block.bytecodes.splice(putvStarts[i], 2);
|
|
21520
|
-
}
|
|
21521
|
-
(0, import_chunk_HHQDDCTP.logger)(
|
|
21522
|
-
"array-init",
|
|
21523
|
-
1,
|
|
21524
|
-
`Optimizing ${putvStarts.length} element array init at block ${offsetToString(
|
|
21525
|
-
block.offset
|
|
21526
|
-
)}, starting at index ${index}, at offset ${offsetToString(
|
|
21527
|
-
block.bytecodes[index].offset
|
|
21528
|
-
)}`
|
|
21529
|
-
);
|
|
21530
|
-
block.bytecodes[index + 2].arg = putvStarts.length - 1;
|
|
21531
|
-
const loopOffset = context.nextOffset;
|
|
21532
|
-
block.bytecodes.splice(
|
|
21533
|
-
index + 3,
|
|
21534
|
-
0,
|
|
21535
|
-
bytecode(46, 1),
|
|
21536
|
-
bytecode(46, 1),
|
|
21537
|
-
bytecode(37, 1),
|
|
21538
|
-
bytecode(4, void 0),
|
|
21539
|
-
bytecode(46, 0),
|
|
21540
|
-
bytecode(40, loopOffset)
|
|
21541
|
-
);
|
|
21542
|
-
splitBlock(func, block, index + 9);
|
|
21543
|
-
splitBlock(func, block, index + 3);
|
|
21544
|
-
const loop = func.blocks.get(loopOffset);
|
|
21545
|
-
loop.preds.add(loopOffset);
|
|
21546
|
-
loop.taken = loopOffset;
|
|
21547
|
-
return true;
|
|
21548
|
-
}
|
|
21549
|
-
var init_array_init = (0, import_chunk_HHQDDCTP.__esm)({
|
|
21550
|
-
"src/readprg/array-init.ts"() {
|
|
21551
|
-
"use strict";
|
|
21552
|
-
(0, import_chunk_HHQDDCTP.init_util)();
|
|
21553
|
-
init_bytecode();
|
|
21554
|
-
init_opcodes();
|
|
21555
|
-
}
|
|
21556
|
-
});
|
|
21557
21394
|
function postOrderTraverse2(func, visitor) {
|
|
21558
21395
|
const visited = /* @__PURE__ */ new Set();
|
|
21559
21396
|
const helper = (offset) => {
|
|
@@ -21621,7 +21458,7 @@ function postOrderPropagate(func, preBlock, processBc, postBlock, merge) {
|
|
|
21621
21458
|
top.preds?.forEach((pred) => {
|
|
21622
21459
|
const predBlock = func.blocks.get(pred);
|
|
21623
21460
|
const isExPred = predBlock.next !== top.offset && predBlock.taken !== top.offset;
|
|
21624
|
-
(0,
|
|
21461
|
+
(0, import_node_assert6.default)(!isExPred || predBlock.exsucc === top.offset);
|
|
21625
21462
|
merge(localState, predBlock, isExPred) && queue.enqueue(predBlock);
|
|
21626
21463
|
const jsrPreds = jsrMap.get(pred);
|
|
21627
21464
|
if (jsrPreds) {
|
|
@@ -21640,7 +21477,7 @@ function computeRetMap(func) {
|
|
|
21640
21477
|
const retMap = /* @__PURE__ */ new Map();
|
|
21641
21478
|
jsrMap.forEach((retBlocks, jsrBlock) => {
|
|
21642
21479
|
const jsrNext = func.blocks.get(jsrBlock).next;
|
|
21643
|
-
(0,
|
|
21480
|
+
(0, import_node_assert6.default)(jsrNext);
|
|
21644
21481
|
retBlocks.forEach((retBlock) => {
|
|
21645
21482
|
const retSuccs = retMap.get(retBlock);
|
|
21646
21483
|
if (retSuccs) {
|
|
@@ -21670,20 +21507,40 @@ function rpoPropagate(func, preBlock, processBc, postBlock, merge) {
|
|
|
21670
21507
|
const top = queue.dequeue();
|
|
21671
21508
|
const localState = preBlock(top);
|
|
21672
21509
|
const doMerge = (to, isExSucc) => {
|
|
21673
|
-
if (to == null)
|
|
21674
|
-
return;
|
|
21675
21510
|
const toBlock = func.blocks.get(to);
|
|
21676
21511
|
merge(top, localState, toBlock, isExSucc) && queue.enqueue(toBlock);
|
|
21677
21512
|
};
|
|
21678
|
-
|
|
21679
|
-
|
|
21513
|
+
let flags;
|
|
21514
|
+
for (let i = 0; i < top.bytecodes.length; i++) {
|
|
21515
|
+
const bc = top.bytecodes[i];
|
|
21516
|
+
flags = processBc(top, bc, localState);
|
|
21517
|
+
if (flags != null && flags & 16) {
|
|
21518
|
+
i = -1;
|
|
21519
|
+
continue;
|
|
21520
|
+
}
|
|
21680
21521
|
if (top.exsucc && (bc.op === 15 || bc.op === 51)) {
|
|
21681
21522
|
doMerge(top.exsucc, true);
|
|
21682
21523
|
}
|
|
21683
|
-
}
|
|
21524
|
+
}
|
|
21684
21525
|
postBlock(top, localState);
|
|
21685
|
-
|
|
21686
|
-
|
|
21526
|
+
if (flags == null)
|
|
21527
|
+
flags = 0;
|
|
21528
|
+
if (top.next != null) {
|
|
21529
|
+
if (!(flags & 8)) {
|
|
21530
|
+
doMerge(top.next, false);
|
|
21531
|
+
}
|
|
21532
|
+
if (flags & 2) {
|
|
21533
|
+
queue.enqueue(func.blocks.get(top.next));
|
|
21534
|
+
}
|
|
21535
|
+
}
|
|
21536
|
+
if (top.taken) {
|
|
21537
|
+
if (!(flags & 4)) {
|
|
21538
|
+
doMerge(top.taken, false);
|
|
21539
|
+
}
|
|
21540
|
+
if (flags & 1) {
|
|
21541
|
+
queue.enqueue(func.blocks.get(top.taken));
|
|
21542
|
+
}
|
|
21543
|
+
}
|
|
21687
21544
|
retMap.get(top.offset)?.forEach((retSucc) => doMerge(retSucc, false));
|
|
21688
21545
|
}
|
|
21689
21546
|
}
|
|
@@ -21694,257 +21551,10 @@ var init_cflow = (0, import_chunk_HHQDDCTP.__esm)({
|
|
|
21694
21551
|
init_opcodes();
|
|
21695
21552
|
}
|
|
21696
21553
|
});
|
|
21697
|
-
function
|
|
21698
|
-
|
|
21699
|
-
|
|
21700
|
-
|
|
21701
|
-
func,
|
|
21702
|
-
context,
|
|
21703
|
-
"local-dce-start",
|
|
21704
|
-
(block, footer) => footer ? `liveOutLocals: ${Array.from(
|
|
21705
|
-
liveOutLocals.get(block.offset) ?? []
|
|
21706
|
-
).join(" ")}
|
|
21707
|
-
` : ""
|
|
21708
|
-
)
|
|
21709
|
-
);
|
|
21710
|
-
}
|
|
21711
|
-
const { liveInLocals, liveOutLocals } = computeLiveLocals(func);
|
|
21712
|
-
let anyChanges = false;
|
|
21713
|
-
let changes = false;
|
|
21714
|
-
const makeNop = (bc) => {
|
|
21715
|
-
changes = true;
|
|
21716
|
-
makeArgless(
|
|
21717
|
-
bc,
|
|
21718
|
-
0
|
|
21719
|
-
/* nop */
|
|
21720
|
-
);
|
|
21721
|
-
};
|
|
21722
|
-
const makePopv = (bc) => {
|
|
21723
|
-
changes = true;
|
|
21724
|
-
makeArgless(
|
|
21725
|
-
bc,
|
|
21726
|
-
2
|
|
21727
|
-
/* popv */
|
|
21728
|
-
);
|
|
21729
|
-
};
|
|
21730
|
-
func.blocks.forEach((block) => {
|
|
21731
|
-
const reportPopv = (i, item, kill) => {
|
|
21732
|
-
(0, import_chunk_HHQDDCTP.logger)(
|
|
21733
|
-
"dce",
|
|
21734
|
-
2,
|
|
21735
|
-
`${func.name}: Convert ${i}:${bytecodeToString(
|
|
21736
|
-
block.bytecodes[i],
|
|
21737
|
-
context.symbolTable
|
|
21738
|
-
)} to popv for ${item.deps.map(
|
|
21739
|
-
(i2) => `${i2}:${bytecodeToString(
|
|
21740
|
-
block.bytecodes[i2],
|
|
21741
|
-
context.symbolTable
|
|
21742
|
-
)}${kill ? "=>nop" : ""}`
|
|
21743
|
-
).join(", ")} }`
|
|
21744
|
-
);
|
|
21745
|
-
};
|
|
21746
|
-
const reportNop = (item) => {
|
|
21747
|
-
(0, import_chunk_HHQDDCTP.logger)(
|
|
21748
|
-
"dce",
|
|
21749
|
-
2,
|
|
21750
|
-
`${func.name}: Kill ${item.deps.map((i) => bytecodeToString(block.bytecodes[i], context.symbolTable)).join(", ")}`
|
|
21751
|
-
);
|
|
21752
|
-
};
|
|
21753
|
-
changes = false;
|
|
21754
|
-
const dceInfo = {
|
|
21755
|
-
stack: [],
|
|
21756
|
-
locals: new Set(liveOutLocals.get(block.offset))
|
|
21757
|
-
};
|
|
21758
|
-
for (let i = block.bytecodes.length; i--; ) {
|
|
21759
|
-
const bytecode = block.bytecodes[i];
|
|
21760
|
-
switch (bytecode.op) {
|
|
21761
|
-
case 19: {
|
|
21762
|
-
const liveLocal = dceInfo.locals.has(bytecode.arg);
|
|
21763
|
-
if (!liveLocal) {
|
|
21764
|
-
(0, import_chunk_HHQDDCTP.logger)(
|
|
21765
|
-
"dce",
|
|
21766
|
-
2,
|
|
21767
|
-
`${func.name}: Killing store to unused local ${bytecode.arg} at ${offsetToString(block.offset)}:${i}`
|
|
21768
|
-
);
|
|
21769
|
-
makePopv(bytecode);
|
|
21770
|
-
dceInfo.stack.push({ dead: true, deps: [i] });
|
|
21771
|
-
} else {
|
|
21772
|
-
dceInfo.stack.push({ dead: false });
|
|
21773
|
-
}
|
|
21774
|
-
dceInfo.locals.delete(bytecode.arg);
|
|
21775
|
-
break;
|
|
21776
|
-
}
|
|
21777
|
-
case 2:
|
|
21778
|
-
dceInfo.stack.push({ dead: true, deps: [i] });
|
|
21779
|
-
break;
|
|
21780
|
-
case 46: {
|
|
21781
|
-
const item = dceInfo.stack.pop();
|
|
21782
|
-
if (item?.dead) {
|
|
21783
|
-
item.deps.push(i);
|
|
21784
|
-
reportNop(item);
|
|
21785
|
-
item.deps.forEach((index) => makeNop(block.bytecodes[index]));
|
|
21786
|
-
} else {
|
|
21787
|
-
if (dceInfo.stack.length > bytecode.arg) {
|
|
21788
|
-
dceInfo.stack[dceInfo.stack.length - 1 - bytecode.arg].dead = false;
|
|
21789
|
-
}
|
|
21790
|
-
}
|
|
21791
|
-
break;
|
|
21792
|
-
}
|
|
21793
|
-
case 18:
|
|
21794
|
-
case 44:
|
|
21795
|
-
case 43:
|
|
21796
|
-
case 24:
|
|
21797
|
-
case 37:
|
|
21798
|
-
case 38:
|
|
21799
|
-
case 39:
|
|
21800
|
-
case 52:
|
|
21801
|
-
case 49:
|
|
21802
|
-
case 50: {
|
|
21803
|
-
const item = dceInfo.stack.pop();
|
|
21804
|
-
if (item?.dead) {
|
|
21805
|
-
item.deps.push(i);
|
|
21806
|
-
reportNop(item);
|
|
21807
|
-
item.deps.forEach((index) => makeNop(block.bytecodes[index]));
|
|
21808
|
-
} else if (bytecode.op === 18) {
|
|
21809
|
-
dceInfo.locals.add(bytecode.arg);
|
|
21810
|
-
}
|
|
21811
|
-
break;
|
|
21812
|
-
}
|
|
21813
|
-
case 3:
|
|
21814
|
-
case 4:
|
|
21815
|
-
case 5:
|
|
21816
|
-
case 6:
|
|
21817
|
-
case 7:
|
|
21818
|
-
case 8:
|
|
21819
|
-
case 9:
|
|
21820
|
-
case 10:
|
|
21821
|
-
case 11:
|
|
21822
|
-
case 12:
|
|
21823
|
-
case 26:
|
|
21824
|
-
case 27:
|
|
21825
|
-
case 28:
|
|
21826
|
-
case 29:
|
|
21827
|
-
case 30:
|
|
21828
|
-
case 31:
|
|
21829
|
-
case 34:
|
|
21830
|
-
case 33:
|
|
21831
|
-
case 16:
|
|
21832
|
-
case 13: {
|
|
21833
|
-
const item = dceInfo.stack.pop();
|
|
21834
|
-
if (item?.dead) {
|
|
21835
|
-
reportPopv(i, item, false);
|
|
21836
|
-
makePopv(bytecode);
|
|
21837
|
-
dceInfo.stack.push({ dead: true, deps: item.deps.slice() });
|
|
21838
|
-
dceInfo.stack.push({ dead: true, deps: [i] });
|
|
21839
|
-
} else {
|
|
21840
|
-
dceInfo.stack.push({ dead: false });
|
|
21841
|
-
dceInfo.stack.push({ dead: false });
|
|
21842
|
-
}
|
|
21843
|
-
break;
|
|
21844
|
-
}
|
|
21845
|
-
case 21:
|
|
21846
|
-
case 32:
|
|
21847
|
-
case 45:
|
|
21848
|
-
case 48:
|
|
21849
|
-
case 20:
|
|
21850
|
-
case 54:
|
|
21851
|
-
case 47: {
|
|
21852
|
-
const item = dceInfo.stack.pop();
|
|
21853
|
-
if (item?.dead) {
|
|
21854
|
-
reportPopv(i, item, true);
|
|
21855
|
-
makePopv(bytecode);
|
|
21856
|
-
item.deps.forEach((index) => makeNop(block.bytecodes[index]));
|
|
21857
|
-
dceInfo.stack.push({ dead: true, deps: [i] });
|
|
21858
|
-
} else {
|
|
21859
|
-
dceInfo.stack.push({ dead: false });
|
|
21860
|
-
}
|
|
21861
|
-
break;
|
|
21862
|
-
}
|
|
21863
|
-
case 51:
|
|
21864
|
-
case 15:
|
|
21865
|
-
if (block.exsucc) {
|
|
21866
|
-
liveInLocals.get(block.exsucc)?.forEach((local) => dceInfo.locals.add(local));
|
|
21867
|
-
}
|
|
21868
|
-
default: {
|
|
21869
|
-
let { push, pop } = getOpInfo(bytecode);
|
|
21870
|
-
while (push-- > 0) {
|
|
21871
|
-
dceInfo.stack.pop();
|
|
21872
|
-
}
|
|
21873
|
-
while (pop-- > 0) {
|
|
21874
|
-
dceInfo.stack.push({ dead: false });
|
|
21875
|
-
}
|
|
21876
|
-
}
|
|
21877
|
-
}
|
|
21878
|
-
}
|
|
21879
|
-
if (changes) {
|
|
21880
|
-
anyChanges = true;
|
|
21881
|
-
block.bytecodes = block.bytecodes.filter(
|
|
21882
|
-
(bc) => bc.op !== 0
|
|
21883
|
-
/* nop */
|
|
21884
|
-
);
|
|
21885
|
-
if ((0, import_chunk_HHQDDCTP.wouldLog)("dce", 3)) {
|
|
21886
|
-
(0, import_chunk_HHQDDCTP.log)(functionBanner(func, context, "local-dce-end")());
|
|
21887
|
-
}
|
|
21888
|
-
}
|
|
21889
|
-
});
|
|
21890
|
-
(0, import_chunk_HHQDDCTP.setBanner)(null);
|
|
21891
|
-
return anyChanges;
|
|
21892
|
-
}
|
|
21893
|
-
function computeLiveLocals(func) {
|
|
21894
|
-
const liveOutLocals = /* @__PURE__ */ new Map();
|
|
21895
|
-
const liveInLocals = /* @__PURE__ */ new Map();
|
|
21896
|
-
postOrderPropagate(
|
|
21897
|
-
func,
|
|
21898
|
-
(block) => new Set(liveOutLocals.get(block.offset)),
|
|
21899
|
-
(block, bc, locals) => {
|
|
21900
|
-
switch (bc.op) {
|
|
21901
|
-
case 18:
|
|
21902
|
-
locals.add(bc.arg);
|
|
21903
|
-
break;
|
|
21904
|
-
case 19:
|
|
21905
|
-
locals.delete(bc.arg);
|
|
21906
|
-
break;
|
|
21907
|
-
case 51:
|
|
21908
|
-
case 15:
|
|
21909
|
-
if (block.exsucc) {
|
|
21910
|
-
liveInLocals.get(block.exsucc)?.forEach((local) => locals.add(local));
|
|
21911
|
-
}
|
|
21912
|
-
break;
|
|
21913
|
-
}
|
|
21914
|
-
},
|
|
21915
|
-
(block, locals) => {
|
|
21916
|
-
liveInLocals.set(block.offset, locals);
|
|
21917
|
-
},
|
|
21918
|
-
(locals, predBlock, isExPred) => {
|
|
21919
|
-
if (isExPred)
|
|
21920
|
-
return false;
|
|
21921
|
-
const predLocals = liveOutLocals.get(predBlock.offset);
|
|
21922
|
-
if (!predLocals) {
|
|
21923
|
-
liveOutLocals.set(predBlock.offset, new Set(locals));
|
|
21924
|
-
return true;
|
|
21925
|
-
}
|
|
21926
|
-
const size = predLocals.size;
|
|
21927
|
-
locals.forEach((local) => predLocals.add(local));
|
|
21928
|
-
return size !== predLocals.size;
|
|
21929
|
-
}
|
|
21930
|
-
);
|
|
21931
|
-
return { liveInLocals, liveOutLocals };
|
|
21932
|
-
}
|
|
21933
|
-
var init_dce = (0, import_chunk_HHQDDCTP.__esm)({
|
|
21934
|
-
"src/readprg/dce.ts"() {
|
|
21935
|
-
"use strict";
|
|
21936
|
-
(0, import_chunk_HHQDDCTP.init_util)();
|
|
21937
|
-
init_bytecode();
|
|
21938
|
-
init_cflow();
|
|
21939
|
-
init_opcodes();
|
|
21940
|
-
}
|
|
21941
|
-
});
|
|
21942
|
-
function interpItemToString(item) {
|
|
21943
|
-
let str = display(item.type);
|
|
21944
|
-
if (item.dup != null)
|
|
21945
|
-
str += ` dup<${item.dup}>`;
|
|
21946
|
-
if (item.equivs) {
|
|
21947
|
-
str += ` equivs: ${Array.from(item.equivs).join(", ")}`;
|
|
21554
|
+
function interpItemToString(item) {
|
|
21555
|
+
let str = display(item.type);
|
|
21556
|
+
if (item.equivs) {
|
|
21557
|
+
str += ` equivs: ${Array.from(item.equivs).join(", ")}`;
|
|
21948
21558
|
}
|
|
21949
21559
|
return str;
|
|
21950
21560
|
}
|
|
@@ -21961,7 +21571,7 @@ function checkState(state) {
|
|
|
21961
21571
|
const checkArray = (items) => items.forEach((item) => {
|
|
21962
21572
|
item.equivs?.forEach((e) => {
|
|
21963
21573
|
if (getEquivs(state, e) !== item.equivs) {
|
|
21964
|
-
(0,
|
|
21574
|
+
(0, import_node_assert7.default)(getEquivs(state, e) === item.equivs);
|
|
21965
21575
|
}
|
|
21966
21576
|
});
|
|
21967
21577
|
});
|
|
@@ -22055,10 +21665,6 @@ function mergeElems(fromElem, toElem) {
|
|
|
22055
21665
|
if (unionInto(toElem.type, fromElem.type)) {
|
|
22056
21666
|
changes = true;
|
|
22057
21667
|
}
|
|
22058
|
-
if (toElem.dup !== fromElem.dup) {
|
|
22059
|
-
changes = true;
|
|
22060
|
-
delete toElem.dup;
|
|
22061
|
-
}
|
|
22062
21668
|
return changes;
|
|
22063
21669
|
}
|
|
22064
21670
|
function mergeInto(from, to) {
|
|
@@ -22134,9 +21740,9 @@ function mergeInto(from, to) {
|
|
|
22134
21740
|
return changes;
|
|
22135
21741
|
}
|
|
22136
21742
|
function findEquivalent(localState, type, value2) {
|
|
22137
|
-
const find = (elems) => {
|
|
21743
|
+
const find = (elems, d) => {
|
|
22138
21744
|
let alternate = null;
|
|
22139
|
-
for (let i = elems.length; i--; ) {
|
|
21745
|
+
for (let i = elems.length - d; i--; ) {
|
|
22140
21746
|
const t = elems[i];
|
|
22141
21747
|
if (t && t.type.type === type) {
|
|
22142
21748
|
if (t.type.value === value2) {
|
|
@@ -22148,310 +21754,1044 @@ function findEquivalent(localState, type, value2) {
|
|
|
22148
21754
|
}
|
|
22149
21755
|
return alternate;
|
|
22150
21756
|
};
|
|
22151
|
-
const stackIndex = find(localState.stack);
|
|
21757
|
+
const stackIndex = find(localState.stack, 1);
|
|
22152
21758
|
if (stackIndex != null && stackIndex < localState.stack.length) {
|
|
22153
21759
|
return ~stackIndex;
|
|
22154
21760
|
}
|
|
22155
|
-
const localIndex = find(localState.locals);
|
|
21761
|
+
const localIndex = find(localState.locals, 0);
|
|
22156
21762
|
if (localIndex != null && localIndex < localState.locals.length) {
|
|
22157
21763
|
return localIndex;
|
|
22158
21764
|
}
|
|
22159
21765
|
return stackIndex != null ? ~stackIndex : localIndex;
|
|
22160
21766
|
}
|
|
22161
|
-
function
|
|
22162
|
-
const
|
|
22163
|
-
const equivSets = /* @__PURE__ */ new Map();
|
|
22164
|
-
const selfStores = /* @__PURE__ */ new Set();
|
|
22165
|
-
const liveInState = /* @__PURE__ */ new Map();
|
|
22166
|
-
const replacements = /* @__PURE__ */ new Map();
|
|
22167
|
-
const interpLogging = (0, import_chunk_HHQDDCTP.wouldLog)("interp", 1);
|
|
22168
|
-
if (interpLogging) {
|
|
22169
|
-
if ((0, import_chunk_HHQDDCTP.wouldLog)("interp", 7)) {
|
|
22170
|
-
(0, import_chunk_HHQDDCTP.setBanner)(functionBanner(func, context, "interp"));
|
|
22171
|
-
} else if ((0, import_chunk_HHQDDCTP.wouldLog)("interp", 3)) {
|
|
22172
|
-
(0, import_chunk_HHQDDCTP.setBanner)(
|
|
22173
|
-
() => `+++++++++++++ interp-prepare ${func.name} ++++++++++++++`
|
|
22174
|
-
);
|
|
22175
|
-
}
|
|
22176
|
-
}
|
|
22177
|
-
const xpush = (localState, block, bc, type, value2) => {
|
|
21767
|
+
function interpBytecode(bc, localState, context) {
|
|
21768
|
+
const xpush = (type, value2) => {
|
|
22178
21769
|
const tt = { type };
|
|
22179
21770
|
if (value2 != null) {
|
|
22180
21771
|
tt.value = value2;
|
|
22181
21772
|
}
|
|
22182
|
-
if (bc.size > 2) {
|
|
22183
|
-
const index = findEquivalent(localState, type, value2);
|
|
22184
|
-
let blockReps = replacements.get(block);
|
|
22185
|
-
if (index != null) {
|
|
22186
|
-
if (!blockReps) {
|
|
22187
|
-
blockReps = /* @__PURE__ */ new Map();
|
|
22188
|
-
replacements.set(block, blockReps);
|
|
22189
|
-
}
|
|
22190
|
-
if (index < 0) {
|
|
22191
|
-
const arg = localState.stack.length - ~index % localState.stack.length - 1;
|
|
22192
|
-
blockReps.set(bc, {
|
|
22193
|
-
op: 46,
|
|
22194
|
-
arg,
|
|
22195
|
-
offset: bc.offset,
|
|
22196
|
-
size: 2,
|
|
22197
|
-
invert: localState.stack.length <= ~index
|
|
22198
|
-
});
|
|
22199
|
-
} else {
|
|
22200
|
-
const arg = index % localState.locals.length;
|
|
22201
|
-
blockReps.set(bc, {
|
|
22202
|
-
op: 18,
|
|
22203
|
-
arg,
|
|
22204
|
-
offset: bc.offset,
|
|
22205
|
-
size: 2,
|
|
22206
|
-
invert: localState.locals.length <= index
|
|
22207
|
-
});
|
|
22208
|
-
}
|
|
22209
|
-
} else if (blockReps) {
|
|
22210
|
-
blockReps.delete(bc);
|
|
22211
|
-
if (!blockReps.size) {
|
|
22212
|
-
replacements.delete(block);
|
|
22213
|
-
}
|
|
22214
|
-
}
|
|
22215
|
-
}
|
|
22216
21773
|
localState.stack.push({
|
|
22217
21774
|
type: tt
|
|
22218
21775
|
});
|
|
22219
21776
|
};
|
|
22220
|
-
|
|
22221
|
-
|
|
22222
|
-
(
|
|
22223
|
-
|
|
22224
|
-
|
|
22225
|
-
|
|
22226
|
-
|
|
22227
|
-
|
|
22228
|
-
|
|
22229
|
-
|
|
22230
|
-
|
|
21777
|
+
const binary = (op) => {
|
|
21778
|
+
const args = localState.stack.slice(-2);
|
|
21779
|
+
if (args.length !== 2) {
|
|
21780
|
+
args.splice(
|
|
21781
|
+
0,
|
|
21782
|
+
2,
|
|
21783
|
+
{ type: {
|
|
21784
|
+
type: 524287
|
|
21785
|
+
/* Any */
|
|
21786
|
+
} },
|
|
21787
|
+
{ type: {
|
|
21788
|
+
type: 524287
|
|
21789
|
+
/* Any */
|
|
21790
|
+
} }
|
|
21791
|
+
);
|
|
21792
|
+
}
|
|
21793
|
+
const type = evaluateBinaryTypes(op, args[0].type, args[1].type);
|
|
21794
|
+
if (args[0].equivs) {
|
|
21795
|
+
removeEquiv2(localState, 1 - localState.stack.length);
|
|
21796
|
+
}
|
|
21797
|
+
if (args[1].equivs) {
|
|
21798
|
+
removeEquiv2(localState, 0 - localState.stack.length);
|
|
21799
|
+
}
|
|
21800
|
+
localState.stack.splice(-2, 2, { type });
|
|
21801
|
+
};
|
|
21802
|
+
switch (bc.op) {
|
|
21803
|
+
case 18: {
|
|
21804
|
+
let local = localState.locals[bc.arg];
|
|
21805
|
+
if (local) {
|
|
21806
|
+
local = { ...local };
|
|
21807
|
+
delete local.equivs;
|
|
21808
|
+
} else {
|
|
21809
|
+
local = { type: {
|
|
21810
|
+
type: 524287
|
|
21811
|
+
/* Any */
|
|
21812
|
+
} };
|
|
22231
21813
|
}
|
|
22232
|
-
|
|
22233
|
-
|
|
22234
|
-
|
|
22235
|
-
|
|
22236
|
-
|
|
22237
|
-
|
|
22238
|
-
|
|
22239
|
-
|
|
22240
|
-
|
|
21814
|
+
localState.stack.push(local);
|
|
21815
|
+
addEquiv2(localState, -localState.stack.length, bc.arg);
|
|
21816
|
+
break;
|
|
21817
|
+
}
|
|
21818
|
+
case 46: {
|
|
21819
|
+
const dup = localState.stack.length - bc.arg - 1;
|
|
21820
|
+
let other = localState.stack[dup];
|
|
21821
|
+
if (other) {
|
|
21822
|
+
other = { ...other };
|
|
21823
|
+
delete other.equivs;
|
|
21824
|
+
} else {
|
|
21825
|
+
other = { type: {
|
|
21826
|
+
type: 524287
|
|
21827
|
+
/* Any */
|
|
21828
|
+
} };
|
|
21829
|
+
}
|
|
21830
|
+
localState.stack.push(other);
|
|
21831
|
+
if (dup >= 0) {
|
|
21832
|
+
addEquiv2(localState, -localState.stack.length, ~dup);
|
|
21833
|
+
}
|
|
21834
|
+
break;
|
|
21835
|
+
}
|
|
21836
|
+
case 19: {
|
|
21837
|
+
let curItem = localState.locals[bc.arg];
|
|
21838
|
+
if (!curItem) {
|
|
21839
|
+
curItem = localState.locals[bc.arg] = {
|
|
21840
|
+
type: {
|
|
21841
|
+
type: 524287
|
|
21842
|
+
/* Any */
|
|
21843
|
+
}
|
|
21844
|
+
};
|
|
21845
|
+
}
|
|
21846
|
+
const value2 = localState.stack[localState.stack.length - 1];
|
|
21847
|
+
if (value2.equivs) {
|
|
21848
|
+
if (curItem.equivs?.has(-localState.stack.length)) {
|
|
21849
|
+
removeEquiv2(localState, -localState.stack.length);
|
|
21850
|
+
localState.stack.pop();
|
|
21851
|
+
break;
|
|
21852
|
+
}
|
|
21853
|
+
removeEquiv2(localState, bc.arg);
|
|
21854
|
+
addEquiv2(localState, bc.arg, -localState.stack.length);
|
|
21855
|
+
removeEquiv2(localState, -localState.stack.length);
|
|
21856
|
+
} else if (curItem.equivs) {
|
|
21857
|
+
removeEquiv2(localState, bc.arg);
|
|
21858
|
+
}
|
|
21859
|
+
localState.stack.pop();
|
|
21860
|
+
localState.locals[bc.arg].type = value2.type;
|
|
21861
|
+
break;
|
|
21862
|
+
}
|
|
21863
|
+
case 37:
|
|
21864
|
+
xpush(8, bc.arg);
|
|
21865
|
+
break;
|
|
21866
|
+
case 49:
|
|
21867
|
+
xpush(16, bc.arg);
|
|
21868
|
+
break;
|
|
21869
|
+
case 38:
|
|
21870
|
+
xpush(32, roundToFloat(bc.arg));
|
|
21871
|
+
break;
|
|
21872
|
+
case 50:
|
|
21873
|
+
xpush(64, bc.arg);
|
|
21874
|
+
break;
|
|
21875
|
+
case 52:
|
|
21876
|
+
xpush(128, String.fromCharCode(bc.arg));
|
|
21877
|
+
break;
|
|
21878
|
+
case 43:
|
|
21879
|
+
xpush(
|
|
21880
|
+
bc.arg ? 4 : 2
|
|
21881
|
+
/* False */
|
|
21882
|
+
);
|
|
21883
|
+
break;
|
|
21884
|
+
case 44:
|
|
21885
|
+
xpush(
|
|
21886
|
+
1
|
|
21887
|
+
/* Null */
|
|
21888
|
+
);
|
|
21889
|
+
break;
|
|
21890
|
+
case 39: {
|
|
21891
|
+
const argSym = context.symbolTable.symbolToLabelMap.get(bc.arg);
|
|
21892
|
+
const name = argSym && context.symbolTable.symbols.get(argSym)?.str;
|
|
21893
|
+
const value2 = `${name ?? "symbol"}<${bc.arg}>`;
|
|
21894
|
+
xpush(131072, value2);
|
|
21895
|
+
break;
|
|
21896
|
+
}
|
|
21897
|
+
case 24: {
|
|
21898
|
+
const symbol = context.symbolTable?.symbols.get(bc.arg);
|
|
21899
|
+
xpush(131072, symbol?.str);
|
|
21900
|
+
break;
|
|
21901
|
+
}
|
|
21902
|
+
case 3:
|
|
21903
|
+
binary("+");
|
|
21904
|
+
break;
|
|
21905
|
+
case 4:
|
|
21906
|
+
binary("-");
|
|
21907
|
+
break;
|
|
21908
|
+
case 5:
|
|
21909
|
+
binary("*");
|
|
21910
|
+
break;
|
|
21911
|
+
case 6:
|
|
21912
|
+
binary("/");
|
|
21913
|
+
break;
|
|
21914
|
+
case 9:
|
|
21915
|
+
binary("%");
|
|
21916
|
+
break;
|
|
21917
|
+
case 10:
|
|
21918
|
+
binary("<<");
|
|
21919
|
+
break;
|
|
21920
|
+
case 11:
|
|
21921
|
+
binary(">>");
|
|
21922
|
+
break;
|
|
21923
|
+
case 7:
|
|
21924
|
+
binary("&");
|
|
21925
|
+
break;
|
|
21926
|
+
case 8:
|
|
21927
|
+
binary("|");
|
|
21928
|
+
break;
|
|
21929
|
+
case 12:
|
|
21930
|
+
binary("^");
|
|
21931
|
+
break;
|
|
21932
|
+
case 26:
|
|
21933
|
+
binary("==");
|
|
21934
|
+
break;
|
|
21935
|
+
case 31:
|
|
21936
|
+
binary("!=");
|
|
21937
|
+
break;
|
|
21938
|
+
case 27:
|
|
21939
|
+
binary("<");
|
|
21940
|
+
break;
|
|
21941
|
+
case 28:
|
|
21942
|
+
binary("<=");
|
|
21943
|
+
break;
|
|
21944
|
+
case 29:
|
|
21945
|
+
binary(">");
|
|
21946
|
+
break;
|
|
21947
|
+
case 30:
|
|
21948
|
+
binary(">=");
|
|
21949
|
+
break;
|
|
21950
|
+
default: {
|
|
21951
|
+
const { pop, push } = getOpInfo(bc);
|
|
21952
|
+
for (let i = 0; i < pop; i++) {
|
|
21953
|
+
removeEquiv2(localState, -localState.stack.length);
|
|
21954
|
+
localState.stack.pop();
|
|
21955
|
+
}
|
|
21956
|
+
for (let i = 0; i < push; i++) {
|
|
21957
|
+
localState.stack.push({ type: {
|
|
21958
|
+
type: 524287
|
|
21959
|
+
/* Any */
|
|
21960
|
+
} });
|
|
21961
|
+
}
|
|
21962
|
+
break;
|
|
21963
|
+
}
|
|
21964
|
+
}
|
|
21965
|
+
}
|
|
21966
|
+
function interpFunc(func, context) {
|
|
21967
|
+
const { symbolTable } = context;
|
|
21968
|
+
const equivSets = /* @__PURE__ */ new Map();
|
|
21969
|
+
const selfStores = /* @__PURE__ */ new Set();
|
|
21970
|
+
const liveInState = /* @__PURE__ */ new Map();
|
|
21971
|
+
const replacements = /* @__PURE__ */ new Map();
|
|
21972
|
+
const interpLogging = (0, import_chunk_HHQDDCTP.wouldLog)("interp", 1);
|
|
21973
|
+
if (interpLogging) {
|
|
21974
|
+
if ((0, import_chunk_HHQDDCTP.wouldLog)("interp", 7)) {
|
|
21975
|
+
(0, import_chunk_HHQDDCTP.setBanner)(functionBanner(func, context, "interp"));
|
|
21976
|
+
} else if ((0, import_chunk_HHQDDCTP.wouldLog)("interp", 3)) {
|
|
21977
|
+
(0, import_chunk_HHQDDCTP.setBanner)(
|
|
21978
|
+
() => `+++++++++++++ interp-prepare ${func.name} ++++++++++++++`
|
|
21979
|
+
);
|
|
21980
|
+
}
|
|
21981
|
+
}
|
|
21982
|
+
rpoPropagate(
|
|
21983
|
+
func,
|
|
21984
|
+
(block) => {
|
|
21985
|
+
if (interpLogging) {
|
|
21986
|
+
(0, import_chunk_HHQDDCTP.logger)(
|
|
21987
|
+
"interp",
|
|
21988
|
+
3,
|
|
21989
|
+
`${offsetToString(block.offset)}: ${block.bytecodes[0]?.lineNum ? lineInfoToString(block.bytecodes[0]?.lineNum, context) : ""}
|
|
21990
|
+
${interpStateToString(liveInState.get(block.offset))}`
|
|
21991
|
+
);
|
|
21992
|
+
(0, import_chunk_HHQDDCTP.logger)("interp", 9, blockToString(block, context));
|
|
21993
|
+
}
|
|
21994
|
+
return cloneState2(liveInState.get(block.offset));
|
|
21995
|
+
},
|
|
21996
|
+
(block, bc, localState) => {
|
|
21997
|
+
switch (bc.op) {
|
|
21998
|
+
case 19: {
|
|
21999
|
+
selfStores.delete(bc);
|
|
22000
|
+
equivSets.delete(bc);
|
|
22001
|
+
const curItem = localState.locals[bc.arg];
|
|
22002
|
+
const curEquivs = curItem?.equivs;
|
|
22003
|
+
const selfStore = curEquivs?.has(bc.arg) && curEquivs.has(-localState.stack.length);
|
|
22004
|
+
interpBytecode(bc, localState, context);
|
|
22005
|
+
if (!localState.loopBlock) {
|
|
22006
|
+
if (selfStore) {
|
|
22007
|
+
selfStores.add(bc);
|
|
22008
|
+
break;
|
|
22009
|
+
}
|
|
22010
|
+
const postItem = curItem ?? localState.locals[bc.arg];
|
|
22011
|
+
if (postItem.equivs) {
|
|
22012
|
+
equivSets.set(
|
|
22013
|
+
bc,
|
|
22014
|
+
new Set(Array.from(postItem.equivs).filter((e) => e >= 0))
|
|
22015
|
+
);
|
|
22016
|
+
}
|
|
22017
|
+
}
|
|
22018
|
+
break;
|
|
22019
|
+
}
|
|
22020
|
+
case 37:
|
|
22021
|
+
case 49:
|
|
22022
|
+
case 38:
|
|
22023
|
+
case 50:
|
|
22024
|
+
case 52:
|
|
22025
|
+
case 39: {
|
|
22026
|
+
interpBytecode(bc, localState, context);
|
|
22027
|
+
const topType = localState.stack[localState.stack.length - 1].type;
|
|
22028
|
+
(0, import_node_assert7.default)(isExact(topType));
|
|
22029
|
+
const index = localState.loopBlock ? null : findEquivalent(localState, topType.type, topType.value);
|
|
22030
|
+
let blockReps = replacements.get(block);
|
|
22031
|
+
if (index != null) {
|
|
22032
|
+
if (!blockReps) {
|
|
22033
|
+
blockReps = /* @__PURE__ */ new Map();
|
|
22034
|
+
replacements.set(block, blockReps);
|
|
22035
|
+
}
|
|
22036
|
+
if (index < 0) {
|
|
22037
|
+
const arg = localState.stack.length - ~index % localState.stack.length - 2;
|
|
22038
|
+
blockReps.set(bc, {
|
|
22039
|
+
op: 46,
|
|
22040
|
+
arg,
|
|
22041
|
+
offset: bc.offset,
|
|
22042
|
+
size: 2,
|
|
22043
|
+
invert: localState.stack.length <= ~index
|
|
22044
|
+
});
|
|
22045
|
+
} else {
|
|
22046
|
+
const arg = index % localState.locals.length;
|
|
22047
|
+
blockReps.set(bc, {
|
|
22048
|
+
op: 18,
|
|
22049
|
+
arg,
|
|
22050
|
+
offset: bc.offset,
|
|
22051
|
+
size: 2,
|
|
22052
|
+
invert: localState.locals.length <= index
|
|
22053
|
+
});
|
|
22054
|
+
}
|
|
22055
|
+
} else if (blockReps) {
|
|
22056
|
+
blockReps.delete(bc);
|
|
22057
|
+
if (!blockReps.size) {
|
|
22058
|
+
replacements.delete(block);
|
|
22059
|
+
}
|
|
22060
|
+
}
|
|
22061
|
+
break;
|
|
22062
|
+
}
|
|
22063
|
+
case 40:
|
|
22064
|
+
case 41:
|
|
22065
|
+
if (block.taken === block.offset) {
|
|
22066
|
+
const inState = liveInState.get(block.offset);
|
|
22067
|
+
(0, import_node_assert7.default)(inState);
|
|
22068
|
+
if (inState.stack.length !== localState.stack.length - 1) {
|
|
22069
|
+
const condition = localState.stack[localState.stack.length - 1];
|
|
22070
|
+
const isTrue = mustBeTrue(condition.type);
|
|
22071
|
+
const isFalse = mustBeFalse(condition.type);
|
|
22072
|
+
(0, import_node_assert7.default)(isTrue || isFalse);
|
|
22073
|
+
interpBytecode(bc, localState, context);
|
|
22074
|
+
if (isTrue === (bc.op === 40)) {
|
|
22075
|
+
localState.loopBlock = true;
|
|
22076
|
+
inState.loopBlock = true;
|
|
22077
|
+
return 16;
|
|
22078
|
+
}
|
|
22079
|
+
return 4;
|
|
22080
|
+
}
|
|
22081
|
+
}
|
|
22082
|
+
interpBytecode(bc, localState, context);
|
|
22083
|
+
break;
|
|
22084
|
+
default:
|
|
22085
|
+
interpBytecode(bc, localState, context);
|
|
22086
|
+
}
|
|
22087
|
+
return null;
|
|
22088
|
+
},
|
|
22089
|
+
() => {
|
|
22090
|
+
},
|
|
22091
|
+
(from, localState, succBlock, isExSucc) => {
|
|
22092
|
+
if (isExSucc) {
|
|
22093
|
+
const tryEntry = from.try[from.try.length - 1].tryStart;
|
|
22094
|
+
const entryDepth = liveInState.get(tryEntry)?.stack.length ?? 0;
|
|
22095
|
+
localState = cloneState2(localState);
|
|
22096
|
+
while (entryDepth < localState.stack.length) {
|
|
22097
|
+
if (localState.stack[localState.stack.length - 1].equivs) {
|
|
22098
|
+
removeEquiv2(localState, -localState.stack.length);
|
|
22099
|
+
}
|
|
22100
|
+
localState.stack.pop();
|
|
22101
|
+
}
|
|
22102
|
+
localState.stack.push({ type: {
|
|
22103
|
+
type: 524287
|
|
22104
|
+
/* Any */
|
|
22105
|
+
} });
|
|
22106
|
+
}
|
|
22107
|
+
const succState = liveInState.get(succBlock.offset);
|
|
22108
|
+
if (!succState) {
|
|
22109
|
+
liveInState.set(succBlock.offset, cloneState2(localState));
|
|
22110
|
+
return true;
|
|
22111
|
+
}
|
|
22112
|
+
if (!mergeInto(localState, succState))
|
|
22113
|
+
return false;
|
|
22114
|
+
if (interpLogging) {
|
|
22115
|
+
(0, import_chunk_HHQDDCTP.logger)("interp", 3, `Re-Merge to ${offsetToString(succBlock.offset)}`);
|
|
22116
|
+
}
|
|
22117
|
+
return true;
|
|
22118
|
+
}
|
|
22119
|
+
);
|
|
22120
|
+
if (interpLogging) {
|
|
22121
|
+
if ((0, import_chunk_HHQDDCTP.wouldLog)("interp", 5)) {
|
|
22122
|
+
(0, import_chunk_HHQDDCTP.setBanner)(
|
|
22123
|
+
functionBanner(func, context, "interp", (block, footer) => {
|
|
22124
|
+
if (footer)
|
|
22125
|
+
return "";
|
|
22126
|
+
return interpStateToString(liveInState.get(block.offset));
|
|
22127
|
+
})
|
|
22128
|
+
);
|
|
22129
|
+
} else {
|
|
22130
|
+
(0, import_chunk_HHQDDCTP.setBanner)(() => `=============== interp ${func.name} ==============`);
|
|
22131
|
+
}
|
|
22132
|
+
if (equivSets.size) {
|
|
22133
|
+
(0, import_chunk_HHQDDCTP.log)(`====== equivSets =====`);
|
|
22134
|
+
equivSets.forEach(
|
|
22135
|
+
(value2, key) => (0, import_chunk_HHQDDCTP.log)(
|
|
22136
|
+
`L${key.arg} === ${Array.from(value2).sort().join(" ")} ${key.lineNum ? lineInfoToString(key.lineNum, context) : ""}`
|
|
22137
|
+
)
|
|
22138
|
+
);
|
|
22139
|
+
}
|
|
22140
|
+
if (selfStores.size) {
|
|
22141
|
+
(0, import_chunk_HHQDDCTP.log)(`====== selfStores =====`);
|
|
22142
|
+
selfStores.forEach(
|
|
22143
|
+
(value2) => (0, import_chunk_HHQDDCTP.log)(`${bytecodeToString(value2, symbolTable)}`)
|
|
22144
|
+
);
|
|
22145
|
+
}
|
|
22146
|
+
if (replacements.size) {
|
|
22147
|
+
(0, import_chunk_HHQDDCTP.log)(`====== replacements =====`);
|
|
22148
|
+
replacements.forEach(
|
|
22149
|
+
(blockRep) => blockRep.forEach(
|
|
22150
|
+
(rep, bc) => (0, import_chunk_HHQDDCTP.log)(
|
|
22151
|
+
`${bytecodeToString(bc, symbolTable)} => ${rep.invert ? "~" : ""}${bytecodeToString(rep, symbolTable)} ${bc.lineNum ? lineInfoToString(bc.lineNum, context) : ""}`
|
|
22152
|
+
)
|
|
22153
|
+
)
|
|
22154
|
+
);
|
|
22155
|
+
}
|
|
22156
|
+
}
|
|
22157
|
+
selfStores.forEach((bc) => makeArgless(
|
|
22158
|
+
bc,
|
|
22159
|
+
2
|
|
22160
|
+
/* popv */
|
|
22161
|
+
));
|
|
22162
|
+
replacements.forEach((blockRep, block) => {
|
|
22163
|
+
for (let i = block.bytecodes.length; i--; ) {
|
|
22164
|
+
const orig = block.bytecodes[i];
|
|
22165
|
+
const rep = blockRep.get(orig);
|
|
22166
|
+
if (!rep)
|
|
22167
|
+
continue;
|
|
22168
|
+
orig.op = rep.op;
|
|
22169
|
+
if (rep.arg != null) {
|
|
22170
|
+
orig.arg = rep.arg;
|
|
22171
|
+
} else {
|
|
22172
|
+
delete orig.arg;
|
|
22173
|
+
}
|
|
22174
|
+
orig.size = rep.size;
|
|
22175
|
+
if (rep.invert) {
|
|
22176
|
+
const invv = { ...orig };
|
|
22177
|
+
invv.op = 45;
|
|
22178
|
+
invv.size = 1;
|
|
22179
|
+
invv.offset++;
|
|
22180
|
+
delete invv.arg;
|
|
22181
|
+
block.bytecodes.splice(i + 1, 0, invv);
|
|
22182
|
+
}
|
|
22183
|
+
}
|
|
22184
|
+
});
|
|
22185
|
+
if (interpLogging)
|
|
22186
|
+
(0, import_chunk_HHQDDCTP.setBanner)(null);
|
|
22187
|
+
return { liveInState, equivSets };
|
|
22188
|
+
}
|
|
22189
|
+
function instForType(type, offset) {
|
|
22190
|
+
if (!hasValue(type))
|
|
22191
|
+
return null;
|
|
22192
|
+
switch (type.type) {
|
|
22193
|
+
case 1:
|
|
22194
|
+
return { op: 44, offset, size: 1 };
|
|
22195
|
+
case 2:
|
|
22196
|
+
case 4:
|
|
22197
|
+
return {
|
|
22198
|
+
op: 43,
|
|
22199
|
+
arg: type.type === 2 ? 0 : 1,
|
|
22200
|
+
offset,
|
|
22201
|
+
size: 1
|
|
22202
|
+
};
|
|
22203
|
+
case 8:
|
|
22204
|
+
return { op: 37, arg: type.value, offset, size: 1 };
|
|
22205
|
+
case 16:
|
|
22206
|
+
return { op: 49, arg: type.value, offset, size: 1 };
|
|
22207
|
+
case 32:
|
|
22208
|
+
return { op: 38, arg: type.value, offset, size: 1 };
|
|
22209
|
+
case 64:
|
|
22210
|
+
return { op: 50, arg: type.value, offset, size: 1 };
|
|
22211
|
+
case 128:
|
|
22212
|
+
return {
|
|
22213
|
+
op: 52,
|
|
22214
|
+
arg: type.value.charCodeAt(0),
|
|
22215
|
+
offset,
|
|
22216
|
+
size: 1
|
|
22217
|
+
};
|
|
22218
|
+
case 131072: {
|
|
22219
|
+
const match = type.value.match(/<(\d+)>$/);
|
|
22220
|
+
(0, import_node_assert7.default)(match);
|
|
22221
|
+
return {
|
|
22222
|
+
op: 37,
|
|
22223
|
+
arg: parseInt(match[1], 10),
|
|
22224
|
+
offset,
|
|
22225
|
+
size: 1
|
|
22226
|
+
};
|
|
22227
|
+
}
|
|
22228
|
+
}
|
|
22229
|
+
return null;
|
|
22230
|
+
}
|
|
22231
|
+
var init_interp2 = (0, import_chunk_HHQDDCTP.__esm)({
|
|
22232
|
+
"src/readprg/interp.ts"() {
|
|
22233
|
+
"use strict";
|
|
22234
|
+
init_interp_binary();
|
|
22235
|
+
(0, import_chunk_HHQDDCTP.init_logger)();
|
|
22236
|
+
init_interp();
|
|
22237
|
+
init_types();
|
|
22238
|
+
init_union_type();
|
|
22239
|
+
init_bytecode();
|
|
22240
|
+
init_cflow();
|
|
22241
|
+
init_opcodes();
|
|
22242
|
+
}
|
|
22243
|
+
});
|
|
22244
|
+
function optimizeArrayInit(func, block, index, context, interpState) {
|
|
22245
|
+
(0, import_node_assert8.default)(
|
|
22246
|
+
block.bytecodes[index].op === 20 || block.bytecodes[index].op === 54
|
|
22247
|
+
/* newba */
|
|
22248
|
+
);
|
|
22249
|
+
if (!interpState) {
|
|
22250
|
+
interpState = cloneState2(null);
|
|
22251
|
+
}
|
|
22252
|
+
const putvStarts = [];
|
|
22253
|
+
let i;
|
|
22254
|
+
let initInst = null;
|
|
22255
|
+
let initType = null;
|
|
22256
|
+
let initLocal = null;
|
|
22257
|
+
let usedLocals = 0n;
|
|
22258
|
+
let local = -1;
|
|
22259
|
+
const depth = interpState.stack.length;
|
|
22260
|
+
for (i = index; ++i < block.bytecodes.length - 1; ) {
|
|
22261
|
+
const dup = block.bytecodes[i];
|
|
22262
|
+
if (dup.op !== 46 || dup.arg !== 0) {
|
|
22263
|
+
break;
|
|
22264
|
+
}
|
|
22265
|
+
interpBytecode(dup, interpState, context);
|
|
22266
|
+
const ipush = block.bytecodes[i + 1];
|
|
22267
|
+
interpBytecode(ipush, interpState, context);
|
|
22268
|
+
if (interpState.stack.length !== depth + 2 || interpState.stack[depth + 1].type.type !== 8 || interpState.stack[depth + 1].type.value !== putvStarts.length) {
|
|
22269
|
+
break;
|
|
22270
|
+
}
|
|
22271
|
+
let found = i;
|
|
22272
|
+
let thisInit = null;
|
|
22273
|
+
let thisLocal = null;
|
|
22274
|
+
for (let k = i + 1; ++k < block.bytecodes.length; ) {
|
|
22275
|
+
const bc = block.bytecodes[k];
|
|
22276
|
+
interpBytecode(bc, interpState, context);
|
|
22277
|
+
if (bc.op === 17 && interpState.stack.length === depth) {
|
|
22278
|
+
found = k;
|
|
22279
|
+
break;
|
|
22280
|
+
}
|
|
22281
|
+
if (bc.op === 18) {
|
|
22282
|
+
usedLocals |= 1n << BigInt(bc.arg);
|
|
22283
|
+
}
|
|
22284
|
+
const delta = interpState.stack.length - depth;
|
|
22285
|
+
if (delta === 3) {
|
|
22286
|
+
const t = interpState.stack[interpState.stack.length - 1].type;
|
|
22287
|
+
if (bc.op === 18) {
|
|
22288
|
+
thisLocal = bc;
|
|
22289
|
+
} else {
|
|
22290
|
+
thisLocal = null;
|
|
22291
|
+
}
|
|
22292
|
+
if (hasValue(t) && t.type & (1 | 6 | 120 | 128 | 256 | 131072)) {
|
|
22293
|
+
thisInit = t;
|
|
22294
|
+
continue;
|
|
22295
|
+
}
|
|
22296
|
+
thisInit = null;
|
|
22297
|
+
}
|
|
22298
|
+
if (delta < 0 || bc.op === 46 && bc.arg >= delta - 1) {
|
|
22299
|
+
break;
|
|
22300
|
+
}
|
|
22301
|
+
}
|
|
22302
|
+
if (found === i)
|
|
22303
|
+
break;
|
|
22304
|
+
if (found - i !== 3) {
|
|
22305
|
+
initLocal = initType = false;
|
|
22306
|
+
} else {
|
|
22307
|
+
if (initLocal !== false) {
|
|
22308
|
+
if (thisLocal) {
|
|
22309
|
+
if (initLocal == null) {
|
|
22310
|
+
initLocal = thisLocal;
|
|
22311
|
+
} else if (initLocal.arg !== thisLocal.arg && !interpState.locals[initLocal.arg]?.equivs?.has(thisLocal.arg)) {
|
|
22312
|
+
initLocal = false;
|
|
22313
|
+
}
|
|
22314
|
+
} else {
|
|
22315
|
+
initLocal = false;
|
|
22316
|
+
}
|
|
22317
|
+
}
|
|
22318
|
+
if (initType !== false) {
|
|
22319
|
+
if (thisInit) {
|
|
22320
|
+
if (initType == null) {
|
|
22321
|
+
initType = thisInit;
|
|
22322
|
+
} else if (initType.type !== thisInit.type || initType.value !== thisInit.value) {
|
|
22323
|
+
initType = false;
|
|
22324
|
+
}
|
|
22325
|
+
if (initType) {
|
|
22326
|
+
const bc = block.bytecodes[found - 1];
|
|
22327
|
+
if (bc.op !== 46 && (!initInst || initInst.size > bc.size)) {
|
|
22328
|
+
const { push, pop } = getOpInfo(bc);
|
|
22329
|
+
if (push === 1 && pop === 0) {
|
|
22330
|
+
initInst = bc;
|
|
22331
|
+
}
|
|
22332
|
+
}
|
|
22333
|
+
}
|
|
22334
|
+
} else {
|
|
22335
|
+
initType = false;
|
|
22336
|
+
}
|
|
22337
|
+
}
|
|
22338
|
+
}
|
|
22339
|
+
putvStarts.push(i);
|
|
22340
|
+
i = found;
|
|
22341
|
+
}
|
|
22342
|
+
if (initType && (block.bytecodes[index].op === 20 ? initType.type === 1 : initType.type === 8 && initType.value === 0)) {
|
|
22343
|
+
(0, import_chunk_HHQDDCTP.logger)(
|
|
22344
|
+
"array-init",
|
|
22345
|
+
1,
|
|
22346
|
+
`${func.name}: Removing initialization of default initialized ${putvStarts.length} element array init at block ${offsetToString(
|
|
22347
|
+
block.offset
|
|
22348
|
+
)}, starting at index ${index}, at offset ${offsetToString(
|
|
22349
|
+
block.bytecodes[index].offset
|
|
22350
|
+
)}`
|
|
22351
|
+
);
|
|
22352
|
+
block.bytecodes.splice(index + 1, i - index - 1);
|
|
22353
|
+
return true;
|
|
22354
|
+
}
|
|
22355
|
+
const terminal = block.bytecodes[i];
|
|
22356
|
+
if (terminal?.op === 2) {
|
|
22357
|
+
const convertAputv = (i2) => {
|
|
22358
|
+
const bc = block.bytecodes[i2];
|
|
22359
|
+
const op = bc.op;
|
|
22360
|
+
bc.op = 2;
|
|
22361
|
+
bc.size = 1;
|
|
22362
|
+
delete bc.arg;
|
|
22363
|
+
(0, import_node_assert8.default)(
|
|
22364
|
+
op === 17
|
|
22365
|
+
/* aputv */
|
|
22366
|
+
);
|
|
22367
|
+
};
|
|
22368
|
+
convertAputv(i - 1);
|
|
22369
|
+
for (let i2 = putvStarts.length; i2--; ) {
|
|
22370
|
+
const offset = putvStarts[i2];
|
|
22371
|
+
block.bytecodes.splice(offset, 2);
|
|
22372
|
+
if (i2) {
|
|
22373
|
+
convertAputv(offset - 1);
|
|
22374
|
+
}
|
|
22375
|
+
}
|
|
22376
|
+
(0, import_chunk_HHQDDCTP.logger)(
|
|
22377
|
+
"array-init",
|
|
22378
|
+
1,
|
|
22379
|
+
`${func.name}: Optimizing unused ${putvStarts.length} element array init at block ${offsetToString(
|
|
22380
|
+
block.offset
|
|
22381
|
+
)}, starting at index ${index}, at offset ${offsetToString(
|
|
22382
|
+
block.bytecodes[index].offset
|
|
22383
|
+
)}`
|
|
22384
|
+
);
|
|
22385
|
+
if ((0, import_chunk_HHQDDCTP.wouldLog)("array-init", 5)) {
|
|
22386
|
+
(0, import_chunk_HHQDDCTP.log)(blockToString(block, context));
|
|
22387
|
+
}
|
|
22388
|
+
return true;
|
|
22389
|
+
}
|
|
22390
|
+
const bytecode = (op, arg) => {
|
|
22391
|
+
const bc = { op, arg, size: opcodeSize(op), offset: context.nextOffset++ };
|
|
22392
|
+
if (arg == null)
|
|
22393
|
+
delete bc.arg;
|
|
22394
|
+
return bc;
|
|
22395
|
+
};
|
|
22396
|
+
const tryLocal = (n) => {
|
|
22397
|
+
if (local === -1 && terminal?.op === 19 && !(usedLocals >> BigInt(terminal.arg) & 1n) && putvStarts.length >= n) {
|
|
22398
|
+
local = terminal.arg;
|
|
22399
|
+
block.bytecodes.splice(i++, 1);
|
|
22400
|
+
block.bytecodes.splice(++index, 0, terminal);
|
|
22401
|
+
for (let ix = putvStarts.length; ix--; ) {
|
|
22402
|
+
const dupIx = ++putvStarts[ix];
|
|
22403
|
+
const dup = block.bytecodes[dupIx];
|
|
22404
|
+
(0, import_node_assert8.default)(dup.op === 46 && dup.arg === 0);
|
|
22405
|
+
block.bytecodes[dupIx].op = 18;
|
|
22406
|
+
block.bytecodes[dupIx].arg = local;
|
|
22407
|
+
}
|
|
22408
|
+
return true;
|
|
22409
|
+
}
|
|
22410
|
+
return false;
|
|
22411
|
+
};
|
|
22412
|
+
if (initType) {
|
|
22413
|
+
if (!initInst) {
|
|
22414
|
+
initInst = instForType(initType, block.bytecodes[index + 3].offset);
|
|
22415
|
+
}
|
|
22416
|
+
} else {
|
|
22417
|
+
initInst = null;
|
|
22418
|
+
}
|
|
22419
|
+
if (initLocal && (!initInst || initInst.size > initLocal.size)) {
|
|
22420
|
+
initInst = initLocal;
|
|
22421
|
+
}
|
|
22422
|
+
if (initInst) {
|
|
22423
|
+
if (putvStarts.length < 3)
|
|
22424
|
+
return false;
|
|
22425
|
+
tryLocal(3);
|
|
22426
|
+
(0, import_chunk_HHQDDCTP.logger)(
|
|
22427
|
+
"array-init",
|
|
22428
|
+
1,
|
|
22429
|
+
`${func.name}: Optimizing ${putvStarts.length} element array init with constant initializer ${bytecodeToString(
|
|
22430
|
+
initInst,
|
|
22431
|
+
null
|
|
22432
|
+
)} at block ${offsetToString(
|
|
22433
|
+
block.offset
|
|
22434
|
+
)}, starting at index ${index}, at offset ${offsetToString(
|
|
22435
|
+
block.bytecodes[index].offset
|
|
22436
|
+
)}`
|
|
22437
|
+
);
|
|
22438
|
+
block.bytecodes.splice(index + 5, i - index - 5);
|
|
22439
|
+
block.bytecodes.splice(index + 1, 1);
|
|
22440
|
+
if (local < 0) {
|
|
22441
|
+
block.bytecodes[index + 1].op = 37;
|
|
22442
|
+
block.bytecodes[index + 1].arg = putvStarts.length;
|
|
22443
|
+
} else {
|
|
22444
|
+
if (index >= 2 && block.bytecodes[index - 2].op === 37 && block.bytecodes[index - 2].arg === putvStarts.length) {
|
|
22445
|
+
block.bytecodes.splice(index + 1, 1);
|
|
22446
|
+
block.bytecodes.splice(index - 1, 0, bytecode(46, 0));
|
|
22447
|
+
} else {
|
|
22448
|
+
block.bytecodes[index + 1].op = 37;
|
|
22449
|
+
block.bytecodes[index + 1].arg = putvStarts.length;
|
|
22450
|
+
}
|
|
22451
|
+
}
|
|
22452
|
+
(0, import_chunk_HHQDDCTP.logger)(
|
|
22453
|
+
"array-init",
|
|
22454
|
+
5,
|
|
22455
|
+
`index: ${index}, i: ${i}
|
|
22456
|
+
${blockToString(block, context)}`
|
|
22457
|
+
);
|
|
22458
|
+
const loopOffset2 = context.nextOffset;
|
|
22459
|
+
block.bytecodes.splice(
|
|
22460
|
+
index + 2,
|
|
22461
|
+
1,
|
|
22462
|
+
bytecode(37, 1),
|
|
22463
|
+
bytecode(4, void 0),
|
|
22464
|
+
local >= 0 ? bytecode(18, local) : bytecode(46, 1),
|
|
22465
|
+
bytecode(46, 1),
|
|
22466
|
+
initInst
|
|
22467
|
+
);
|
|
22468
|
+
block.bytecodes.splice(
|
|
22469
|
+
index + 8,
|
|
22470
|
+
0,
|
|
22471
|
+
bytecode(46, 0),
|
|
22472
|
+
bytecode(40, loopOffset2),
|
|
22473
|
+
bytecode(2, void 0)
|
|
22474
|
+
);
|
|
22475
|
+
splitBlock(func, block, index + 10);
|
|
22476
|
+
splitBlock(func, block, index + 2);
|
|
22477
|
+
const loop2 = func.blocks.get(loopOffset2);
|
|
22478
|
+
loop2.preds.add(loopOffset2);
|
|
22479
|
+
loop2.taken = loopOffset2;
|
|
22480
|
+
return true;
|
|
22481
|
+
}
|
|
22482
|
+
if (!tryLocal(3) && putvStarts.length < 4)
|
|
22483
|
+
return false;
|
|
22484
|
+
if (local >= 0) {
|
|
22485
|
+
block.bytecodes.splice(i, 0, bytecode(2, void 0));
|
|
22486
|
+
}
|
|
22487
|
+
for (let i2 = putvStarts.length; i2-- > 1; ) {
|
|
22488
|
+
block.bytecodes.splice(putvStarts[i2], 2);
|
|
22489
|
+
}
|
|
22490
|
+
(0, import_chunk_HHQDDCTP.logger)(
|
|
22491
|
+
"array-init",
|
|
22492
|
+
1,
|
|
22493
|
+
`${func.name}: Optimizing ${putvStarts.length} element array init at block ${offsetToString(
|
|
22494
|
+
block.offset
|
|
22495
|
+
)}, starting at index ${index}, at offset ${offsetToString(
|
|
22496
|
+
block.bytecodes[index].offset
|
|
22497
|
+
)}`
|
|
22498
|
+
);
|
|
22499
|
+
let loopOffset;
|
|
22500
|
+
if (local >= 0) {
|
|
22501
|
+
block.bytecodes.splice(index + 1, 2);
|
|
22502
|
+
if (index >= 2 && block.bytecodes[index - 2].op === 37 && block.bytecodes[index - 2].arg === putvStarts.length) {
|
|
22503
|
+
block.bytecodes.splice(index - 1, 0, bytecode(46, 0));
|
|
22504
|
+
} else {
|
|
22505
|
+
block.bytecodes.splice(
|
|
22506
|
+
index + 1,
|
|
22507
|
+
0,
|
|
22508
|
+
bytecode(37, putvStarts.length)
|
|
22509
|
+
);
|
|
22510
|
+
}
|
|
22511
|
+
index--;
|
|
22512
|
+
loopOffset = context.nextOffset;
|
|
22513
|
+
block.bytecodes.splice(
|
|
22514
|
+
index + 3,
|
|
22515
|
+
0,
|
|
22516
|
+
bytecode(18, local),
|
|
22517
|
+
bytecode(46, 1),
|
|
22518
|
+
bytecode(37, 1),
|
|
22519
|
+
bytecode(4, void 0),
|
|
22520
|
+
bytecode(46, 0),
|
|
22521
|
+
bytecode(40, loopOffset)
|
|
22522
|
+
);
|
|
22523
|
+
} else {
|
|
22524
|
+
block.bytecodes[index + 2].op = 37;
|
|
22525
|
+
block.bytecodes[index + 2].arg = putvStarts.length - 1;
|
|
22526
|
+
loopOffset = context.nextOffset;
|
|
22527
|
+
block.bytecodes.splice(
|
|
22528
|
+
index + 3,
|
|
22529
|
+
0,
|
|
22530
|
+
bytecode(46, 1),
|
|
22531
|
+
bytecode(46, 1),
|
|
22532
|
+
bytecode(37, 1),
|
|
22533
|
+
bytecode(4, void 0),
|
|
22534
|
+
bytecode(46, 0),
|
|
22535
|
+
bytecode(40, loopOffset)
|
|
22536
|
+
);
|
|
22537
|
+
}
|
|
22538
|
+
splitBlock(func, block, index + 9);
|
|
22539
|
+
splitBlock(func, block, index + 3);
|
|
22540
|
+
const loop = func.blocks.get(loopOffset);
|
|
22541
|
+
loop.preds.add(loopOffset);
|
|
22542
|
+
loop.taken = loopOffset;
|
|
22543
|
+
return true;
|
|
22544
|
+
}
|
|
22545
|
+
var init_array_init = (0, import_chunk_HHQDDCTP.__esm)({
|
|
22546
|
+
"src/readprg/array-init.ts"() {
|
|
22547
|
+
"use strict";
|
|
22548
|
+
init_types();
|
|
22549
|
+
(0, import_chunk_HHQDDCTP.init_util)();
|
|
22550
|
+
init_bytecode();
|
|
22551
|
+
init_interp2();
|
|
22552
|
+
init_opcodes();
|
|
22553
|
+
}
|
|
22554
|
+
});
|
|
22555
|
+
function localDCE(func, context) {
|
|
22556
|
+
if ((0, import_chunk_HHQDDCTP.wouldLog)("dce", 5)) {
|
|
22557
|
+
(0, import_chunk_HHQDDCTP.setBanner)(
|
|
22558
|
+
functionBanner(
|
|
22559
|
+
func,
|
|
22560
|
+
context,
|
|
22561
|
+
"local-dce-start",
|
|
22562
|
+
(block, footer) => footer ? `liveOutLocals: ${Array.from(
|
|
22563
|
+
liveOutLocals.get(block.offset) ?? []
|
|
22564
|
+
).join(" ")}
|
|
22565
|
+
` : ""
|
|
22566
|
+
)
|
|
22567
|
+
);
|
|
22568
|
+
}
|
|
22569
|
+
const { liveInLocals, liveOutLocals } = computeLiveLocals(func);
|
|
22570
|
+
let anyChanges = false;
|
|
22571
|
+
let changes = false;
|
|
22572
|
+
const makeNop = (bc) => {
|
|
22573
|
+
changes = true;
|
|
22574
|
+
makeArgless(
|
|
22575
|
+
bc,
|
|
22576
|
+
0
|
|
22577
|
+
/* nop */
|
|
22578
|
+
);
|
|
22579
|
+
};
|
|
22580
|
+
const makePopv = (bc) => {
|
|
22581
|
+
changes = true;
|
|
22582
|
+
makeArgless(
|
|
22583
|
+
bc,
|
|
22584
|
+
2
|
|
22585
|
+
/* popv */
|
|
22586
|
+
);
|
|
22587
|
+
};
|
|
22588
|
+
func.blocks.forEach((block) => {
|
|
22589
|
+
const reportPopv = (i, item, kill) => {
|
|
22590
|
+
(0, import_chunk_HHQDDCTP.logger)(
|
|
22591
|
+
"dce",
|
|
22592
|
+
2,
|
|
22593
|
+
`${func.name}: Convert ${i}:${bytecodeToString(
|
|
22594
|
+
block.bytecodes[i],
|
|
22595
|
+
context.symbolTable
|
|
22596
|
+
)} to popv for ${item.deps.map(
|
|
22597
|
+
(i2) => `${i2}:${bytecodeToString(
|
|
22598
|
+
block.bytecodes[i2],
|
|
22599
|
+
context.symbolTable
|
|
22600
|
+
)}${kill ? "=>nop" : ""}`
|
|
22601
|
+
).join(", ")} }`
|
|
22602
|
+
);
|
|
22603
|
+
};
|
|
22604
|
+
const reportNop = (item) => {
|
|
22605
|
+
(0, import_chunk_HHQDDCTP.logger)(
|
|
22606
|
+
"dce",
|
|
22607
|
+
2,
|
|
22608
|
+
`${func.name}: Kill ${item.deps.map((i) => bytecodeToString(block.bytecodes[i], context.symbolTable)).join(", ")}`
|
|
22609
|
+
);
|
|
22610
|
+
};
|
|
22611
|
+
changes = false;
|
|
22612
|
+
const dceInfo = {
|
|
22613
|
+
stack: [],
|
|
22614
|
+
locals: new Set(liveOutLocals.get(block.offset))
|
|
22615
|
+
};
|
|
22616
|
+
for (let i = block.bytecodes.length; i--; ) {
|
|
22617
|
+
const bytecode = block.bytecodes[i];
|
|
22618
|
+
switch (bytecode.op) {
|
|
22619
|
+
case 19: {
|
|
22620
|
+
const liveLocal = dceInfo.locals.has(bytecode.arg);
|
|
22621
|
+
if (!liveLocal) {
|
|
22622
|
+
(0, import_chunk_HHQDDCTP.logger)(
|
|
22623
|
+
"dce",
|
|
22624
|
+
2,
|
|
22625
|
+
`${func.name}: Killing store to unused local ${bytecode.arg} at ${offsetToString(block.offset)}:${i}`
|
|
22626
|
+
);
|
|
22627
|
+
makePopv(bytecode);
|
|
22628
|
+
dceInfo.stack.push({ dead: true, deps: [i] });
|
|
22629
|
+
} else {
|
|
22630
|
+
dceInfo.stack.push({ dead: false });
|
|
22631
|
+
}
|
|
22632
|
+
dceInfo.locals.delete(bytecode.arg);
|
|
22633
|
+
break;
|
|
22634
|
+
}
|
|
22635
|
+
case 2:
|
|
22636
|
+
dceInfo.stack.push({ dead: true, deps: [i] });
|
|
22637
|
+
break;
|
|
22638
|
+
case 46: {
|
|
22639
|
+
const item = dceInfo.stack.pop();
|
|
22640
|
+
if (item?.dead) {
|
|
22641
|
+
item.deps.push(i);
|
|
22642
|
+
reportNop(item);
|
|
22643
|
+
item.deps.forEach((index) => makeNop(block.bytecodes[index]));
|
|
22644
|
+
} else {
|
|
22645
|
+
if (dceInfo.stack.length > bytecode.arg) {
|
|
22646
|
+
dceInfo.stack[dceInfo.stack.length - 1 - bytecode.arg].dead = false;
|
|
22647
|
+
}
|
|
22648
|
+
}
|
|
22649
|
+
break;
|
|
22650
|
+
}
|
|
22651
|
+
case 18:
|
|
22652
|
+
case 44:
|
|
22653
|
+
case 43:
|
|
22654
|
+
case 24:
|
|
22655
|
+
case 37:
|
|
22656
|
+
case 38:
|
|
22657
|
+
case 39:
|
|
22658
|
+
case 52:
|
|
22659
|
+
case 49:
|
|
22660
|
+
case 50: {
|
|
22661
|
+
const item = dceInfo.stack.pop();
|
|
22662
|
+
if (item?.dead) {
|
|
22663
|
+
item.deps.push(i);
|
|
22664
|
+
reportNop(item);
|
|
22665
|
+
item.deps.forEach((index) => makeNop(block.bytecodes[index]));
|
|
22666
|
+
} else if (bytecode.op === 18) {
|
|
22667
|
+
dceInfo.locals.add(bytecode.arg);
|
|
22668
|
+
}
|
|
22669
|
+
break;
|
|
22670
|
+
}
|
|
22671
|
+
case 3:
|
|
22672
|
+
case 4:
|
|
22673
|
+
case 5:
|
|
22674
|
+
case 6:
|
|
22675
|
+
case 7:
|
|
22676
|
+
case 8:
|
|
22677
|
+
case 9:
|
|
22678
|
+
case 10:
|
|
22679
|
+
case 11:
|
|
22680
|
+
case 12:
|
|
22681
|
+
case 26:
|
|
22682
|
+
case 27:
|
|
22683
|
+
case 28:
|
|
22684
|
+
case 29:
|
|
22685
|
+
case 30:
|
|
22686
|
+
case 31:
|
|
22687
|
+
case 34:
|
|
22688
|
+
case 33:
|
|
22689
|
+
case 16:
|
|
22690
|
+
case 13: {
|
|
22691
|
+
const item = dceInfo.stack.pop();
|
|
22692
|
+
if (item?.dead) {
|
|
22693
|
+
reportPopv(i, item, false);
|
|
22694
|
+
makePopv(bytecode);
|
|
22695
|
+
dceInfo.stack.push({ dead: true, deps: item.deps.slice() });
|
|
22696
|
+
dceInfo.stack.push({ dead: true, deps: [i] });
|
|
22241
22697
|
} else {
|
|
22242
|
-
|
|
22243
|
-
|
|
22244
|
-
/* Any */
|
|
22245
|
-
} };
|
|
22698
|
+
dceInfo.stack.push({ dead: false });
|
|
22699
|
+
dceInfo.stack.push({ dead: false });
|
|
22246
22700
|
}
|
|
22247
|
-
localState.stack.push(local);
|
|
22248
|
-
addEquiv2(localState, -localState.stack.length, bc.arg);
|
|
22249
22701
|
break;
|
|
22250
22702
|
}
|
|
22251
|
-
case
|
|
22252
|
-
|
|
22253
|
-
|
|
22254
|
-
|
|
22255
|
-
|
|
22256
|
-
|
|
22257
|
-
|
|
22258
|
-
|
|
22259
|
-
|
|
22260
|
-
|
|
22261
|
-
|
|
22262
|
-
|
|
22263
|
-
|
|
22264
|
-
|
|
22265
|
-
|
|
22266
|
-
selfStores.add(bc);
|
|
22267
|
-
removeEquiv2(localState, -localState.stack.length);
|
|
22268
|
-
localState.stack.pop();
|
|
22269
|
-
break;
|
|
22270
|
-
}
|
|
22271
|
-
removeEquiv2(localState, bc.arg);
|
|
22272
|
-
addEquiv2(localState, bc.arg, -localState.stack.length);
|
|
22273
|
-
removeEquiv2(localState, -localState.stack.length);
|
|
22274
|
-
if (curItem.equivs) {
|
|
22275
|
-
equivSets.set(
|
|
22276
|
-
bc,
|
|
22277
|
-
new Set(Array.from(curItem.equivs).filter((e) => e >= 0))
|
|
22278
|
-
);
|
|
22279
|
-
}
|
|
22280
|
-
} else if (curItem.equivs) {
|
|
22281
|
-
removeEquiv2(localState, bc.arg);
|
|
22703
|
+
case 21:
|
|
22704
|
+
case 32:
|
|
22705
|
+
case 45:
|
|
22706
|
+
case 48:
|
|
22707
|
+
case 20:
|
|
22708
|
+
case 54:
|
|
22709
|
+
case 47: {
|
|
22710
|
+
const item = dceInfo.stack.pop();
|
|
22711
|
+
if (item?.dead) {
|
|
22712
|
+
reportPopv(i, item, true);
|
|
22713
|
+
makePopv(bytecode);
|
|
22714
|
+
item.deps.forEach((index) => makeNop(block.bytecodes[index]));
|
|
22715
|
+
dceInfo.stack.push({ dead: true, deps: [i] });
|
|
22716
|
+
} else {
|
|
22717
|
+
dceInfo.stack.push({ dead: false });
|
|
22282
22718
|
}
|
|
22283
|
-
localState.stack.pop();
|
|
22284
|
-
localState.locals[bc.arg].type = value2.type;
|
|
22285
|
-
break;
|
|
22286
|
-
}
|
|
22287
|
-
case 37:
|
|
22288
|
-
xpush(localState, block, bc, 8, bc.arg);
|
|
22289
|
-
break;
|
|
22290
|
-
case 49:
|
|
22291
|
-
xpush(localState, block, bc, 16, bc.arg);
|
|
22292
|
-
break;
|
|
22293
|
-
case 38:
|
|
22294
|
-
xpush(localState, block, bc, 32, roundToFloat(bc.arg));
|
|
22295
|
-
break;
|
|
22296
|
-
case 50:
|
|
22297
|
-
xpush(localState, block, bc, 64, bc.arg);
|
|
22298
|
-
break;
|
|
22299
|
-
case 52:
|
|
22300
|
-
xpush(
|
|
22301
|
-
localState,
|
|
22302
|
-
block,
|
|
22303
|
-
bc,
|
|
22304
|
-
128,
|
|
22305
|
-
String.fromCharCode(bc.arg)
|
|
22306
|
-
);
|
|
22307
|
-
break;
|
|
22308
|
-
case 43:
|
|
22309
|
-
xpush(
|
|
22310
|
-
localState,
|
|
22311
|
-
block,
|
|
22312
|
-
bc,
|
|
22313
|
-
bc.arg ? 4 : 2
|
|
22314
|
-
/* False */
|
|
22315
|
-
);
|
|
22316
|
-
break;
|
|
22317
|
-
case 44:
|
|
22318
|
-
xpush(
|
|
22319
|
-
localState,
|
|
22320
|
-
block,
|
|
22321
|
-
bc,
|
|
22322
|
-
1
|
|
22323
|
-
/* Null */
|
|
22324
|
-
);
|
|
22325
|
-
break;
|
|
22326
|
-
case 39: {
|
|
22327
|
-
const argSym = symbolTable?.symbolToLabelMap.get(bc.arg);
|
|
22328
|
-
const value2 = argSym && symbolTable?.symbols.get(argSym)?.str || `symbol<${bc.arg}>`;
|
|
22329
|
-
xpush(localState, block, bc, 131072, value2);
|
|
22330
22719
|
break;
|
|
22331
22720
|
}
|
|
22332
|
-
|
|
22333
|
-
|
|
22334
|
-
|
|
22335
|
-
|
|
22336
|
-
localState.stack.pop();
|
|
22721
|
+
case 51:
|
|
22722
|
+
case 15:
|
|
22723
|
+
if (block.exsucc) {
|
|
22724
|
+
liveInLocals.get(block.exsucc)?.forEach((local) => dceInfo.locals.add(local));
|
|
22337
22725
|
}
|
|
22338
|
-
|
|
22339
|
-
|
|
22340
|
-
|
|
22341
|
-
|
|
22342
|
-
} });
|
|
22726
|
+
default: {
|
|
22727
|
+
let { push, pop } = getOpInfo(bytecode);
|
|
22728
|
+
while (push-- > 0) {
|
|
22729
|
+
dceInfo.stack.pop();
|
|
22343
22730
|
}
|
|
22344
|
-
|
|
22345
|
-
|
|
22346
|
-
}
|
|
22347
|
-
},
|
|
22348
|
-
() => {
|
|
22349
|
-
},
|
|
22350
|
-
(from, localState, succBlock, isExSucc) => {
|
|
22351
|
-
if (isExSucc) {
|
|
22352
|
-
const tryEntry = from.try[from.try.length - 1].tryStart;
|
|
22353
|
-
const entryDepth = liveInState.get(tryEntry)?.stack.length ?? 0;
|
|
22354
|
-
localState = cloneState2(localState);
|
|
22355
|
-
while (entryDepth < localState.stack.length) {
|
|
22356
|
-
if (localState.stack[localState.stack.length - 1].equivs) {
|
|
22357
|
-
removeEquiv2(localState, -localState.stack.length);
|
|
22731
|
+
while (pop-- > 0) {
|
|
22732
|
+
dceInfo.stack.push({ dead: false });
|
|
22358
22733
|
}
|
|
22359
|
-
localState.stack.pop();
|
|
22360
22734
|
}
|
|
22361
|
-
localState.stack.push({ type: {
|
|
22362
|
-
type: 524287
|
|
22363
|
-
/* Any */
|
|
22364
|
-
} });
|
|
22365
|
-
}
|
|
22366
|
-
const succState = liveInState.get(succBlock.offset);
|
|
22367
|
-
if (!succState) {
|
|
22368
|
-
liveInState.set(succBlock.offset, cloneState2(localState));
|
|
22369
|
-
return true;
|
|
22370
|
-
}
|
|
22371
|
-
if (!mergeInto(localState, succState))
|
|
22372
|
-
return false;
|
|
22373
|
-
if (interpLogging) {
|
|
22374
|
-
(0, import_chunk_HHQDDCTP.logger)("interp", 3, `Re-Merge to ${offsetToString(succBlock.offset)}`);
|
|
22375
22735
|
}
|
|
22376
|
-
return true;
|
|
22377
|
-
}
|
|
22378
|
-
);
|
|
22379
|
-
if (interpLogging) {
|
|
22380
|
-
if ((0, import_chunk_HHQDDCTP.wouldLog)("interp", 5)) {
|
|
22381
|
-
(0, import_chunk_HHQDDCTP.setBanner)(
|
|
22382
|
-
functionBanner(func, context, "interp", (block, footer) => {
|
|
22383
|
-
if (footer)
|
|
22384
|
-
return "";
|
|
22385
|
-
return interpStateToString(liveInState.get(block.offset));
|
|
22386
|
-
})
|
|
22387
|
-
);
|
|
22388
|
-
} else {
|
|
22389
|
-
(0, import_chunk_HHQDDCTP.setBanner)(() => `=============== interp ${func.name} ==============`);
|
|
22390
|
-
}
|
|
22391
|
-
if (equivSets.size) {
|
|
22392
|
-
(0, import_chunk_HHQDDCTP.log)(`====== equivSets =====`);
|
|
22393
|
-
equivSets.forEach(
|
|
22394
|
-
(value2, key) => (0, import_chunk_HHQDDCTP.log)(
|
|
22395
|
-
`L${key.arg} === ${Array.from(value2).sort().join(" ")} ${key.lineNum ? lineInfoToString(key.lineNum, context) : ""}`
|
|
22396
|
-
)
|
|
22397
|
-
);
|
|
22398
|
-
}
|
|
22399
|
-
if (selfStores.size) {
|
|
22400
|
-
(0, import_chunk_HHQDDCTP.log)(`====== selfStores =====`);
|
|
22401
|
-
selfStores.forEach(
|
|
22402
|
-
(value2) => (0, import_chunk_HHQDDCTP.log)(`${bytecodeToString(value2, symbolTable)}`)
|
|
22403
|
-
);
|
|
22404
22736
|
}
|
|
22405
|
-
if (
|
|
22406
|
-
|
|
22407
|
-
|
|
22408
|
-
(
|
|
22409
|
-
|
|
22410
|
-
`${bytecodeToString(bc, symbolTable)} => ${rep.invert ? "~" : ""}${bytecodeToString(rep, symbolTable)} ${bc.lineNum ? lineInfoToString(bc.lineNum, context) : ""}`
|
|
22411
|
-
)
|
|
22412
|
-
)
|
|
22737
|
+
if (changes) {
|
|
22738
|
+
anyChanges = true;
|
|
22739
|
+
block.bytecodes = block.bytecodes.filter(
|
|
22740
|
+
(bc) => bc.op !== 0
|
|
22741
|
+
/* nop */
|
|
22413
22742
|
);
|
|
22743
|
+
if ((0, import_chunk_HHQDDCTP.wouldLog)("dce", 3)) {
|
|
22744
|
+
(0, import_chunk_HHQDDCTP.log)(functionBanner(func, context, "local-dce-end")());
|
|
22745
|
+
}
|
|
22414
22746
|
}
|
|
22415
|
-
}
|
|
22416
|
-
|
|
22417
|
-
|
|
22418
|
-
|
|
22419
|
-
|
|
22420
|
-
)
|
|
22421
|
-
|
|
22422
|
-
|
|
22423
|
-
|
|
22424
|
-
|
|
22425
|
-
|
|
22426
|
-
|
|
22427
|
-
|
|
22428
|
-
|
|
22429
|
-
|
|
22430
|
-
|
|
22431
|
-
|
|
22747
|
+
});
|
|
22748
|
+
(0, import_chunk_HHQDDCTP.setBanner)(null);
|
|
22749
|
+
return anyChanges;
|
|
22750
|
+
}
|
|
22751
|
+
function computeLiveLocals(func) {
|
|
22752
|
+
const liveOutLocals = /* @__PURE__ */ new Map();
|
|
22753
|
+
const liveInLocals = /* @__PURE__ */ new Map();
|
|
22754
|
+
postOrderPropagate(
|
|
22755
|
+
func,
|
|
22756
|
+
(block) => new Set(liveOutLocals.get(block.offset)),
|
|
22757
|
+
(block, bc, locals) => {
|
|
22758
|
+
switch (bc.op) {
|
|
22759
|
+
case 18:
|
|
22760
|
+
locals.add(bc.arg);
|
|
22761
|
+
break;
|
|
22762
|
+
case 19:
|
|
22763
|
+
locals.delete(bc.arg);
|
|
22764
|
+
break;
|
|
22765
|
+
case 51:
|
|
22766
|
+
case 15:
|
|
22767
|
+
if (block.exsucc) {
|
|
22768
|
+
liveInLocals.get(block.exsucc)?.forEach((local) => locals.add(local));
|
|
22769
|
+
}
|
|
22770
|
+
break;
|
|
22432
22771
|
}
|
|
22433
|
-
|
|
22434
|
-
|
|
22435
|
-
|
|
22436
|
-
|
|
22437
|
-
|
|
22438
|
-
|
|
22439
|
-
|
|
22440
|
-
|
|
22772
|
+
},
|
|
22773
|
+
(block, locals) => {
|
|
22774
|
+
liveInLocals.set(block.offset, locals);
|
|
22775
|
+
},
|
|
22776
|
+
(locals, predBlock, isExPred) => {
|
|
22777
|
+
if (isExPred)
|
|
22778
|
+
return false;
|
|
22779
|
+
const predLocals = liveOutLocals.get(predBlock.offset);
|
|
22780
|
+
if (!predLocals) {
|
|
22781
|
+
liveOutLocals.set(predBlock.offset, new Set(locals));
|
|
22782
|
+
return true;
|
|
22441
22783
|
}
|
|
22784
|
+
const size = predLocals.size;
|
|
22785
|
+
locals.forEach((local) => predLocals.add(local));
|
|
22786
|
+
return size !== predLocals.size;
|
|
22442
22787
|
}
|
|
22443
|
-
|
|
22444
|
-
|
|
22445
|
-
(0, import_chunk_HHQDDCTP.setBanner)(null);
|
|
22446
|
-
return { liveInState, equivSets };
|
|
22788
|
+
);
|
|
22789
|
+
return { liveInLocals, liveOutLocals };
|
|
22447
22790
|
}
|
|
22448
|
-
var
|
|
22449
|
-
"src/readprg/
|
|
22791
|
+
var init_dce = (0, import_chunk_HHQDDCTP.__esm)({
|
|
22792
|
+
"src/readprg/dce.ts"() {
|
|
22450
22793
|
"use strict";
|
|
22451
|
-
(0, import_chunk_HHQDDCTP.
|
|
22452
|
-
init_interp();
|
|
22453
|
-
init_types();
|
|
22454
|
-
init_union_type();
|
|
22794
|
+
(0, import_chunk_HHQDDCTP.init_util)();
|
|
22455
22795
|
init_bytecode();
|
|
22456
22796
|
init_cflow();
|
|
22457
22797
|
init_opcodes();
|
|
@@ -22664,21 +23004,44 @@ var init_sharing = (0, import_chunk_HHQDDCTP.__esm)({
|
|
|
22664
23004
|
});
|
|
22665
23005
|
function optimizeFunc(func, context) {
|
|
22666
23006
|
let changes;
|
|
23007
|
+
let liveInState;
|
|
22667
23008
|
do {
|
|
22668
23009
|
cleanCfg2(func, context);
|
|
22669
23010
|
changes = localDCE(func, context);
|
|
22670
23011
|
changes = blockSharing(func, context) || changes;
|
|
22671
23012
|
changes = simpleOpts(func, context) || changes;
|
|
22672
|
-
interpFunc(func, context);
|
|
23013
|
+
({ liveInState } = interpFunc(func, context));
|
|
23014
|
+
changes = doArrayInits(func, liveInState, context) || changes;
|
|
22673
23015
|
} while (changes);
|
|
23016
|
+
}
|
|
23017
|
+
function doArrayInits(func, liveInState, context) {
|
|
23018
|
+
const newAToProcess = /* @__PURE__ */ new Map();
|
|
22674
23019
|
func.blocks.forEach((block) => {
|
|
22675
|
-
|
|
22676
|
-
|
|
22677
|
-
|
|
22678
|
-
|
|
22679
|
-
|
|
23020
|
+
if (!block.bytecodes.some(
|
|
23021
|
+
(bc) => bc.op === 20 || bc.op === 54
|
|
23022
|
+
/* newba */
|
|
23023
|
+
)) {
|
|
23024
|
+
return;
|
|
22680
23025
|
}
|
|
23026
|
+
const blockState = cloneState2(liveInState.get(block.offset));
|
|
23027
|
+
const newAStates = /* @__PURE__ */ new Map();
|
|
23028
|
+
block.bytecodes.forEach((bc, index) => {
|
|
23029
|
+
interpBytecode(bc, blockState, context);
|
|
23030
|
+
if (bc.op === 20 || bc.op === 54) {
|
|
23031
|
+
newAStates.set(index, cloneState2(blockState));
|
|
23032
|
+
}
|
|
23033
|
+
});
|
|
23034
|
+
newAToProcess.set(block, newAStates);
|
|
22681
23035
|
});
|
|
23036
|
+
let changes = false;
|
|
23037
|
+
newAToProcess.forEach(
|
|
23038
|
+
(newAStates, block) => Array.from(newAStates.keys()).reverse().forEach((i) => {
|
|
23039
|
+
if (optimizeArrayInit(func, block, i, context, newAStates.get(i))) {
|
|
23040
|
+
changes = true;
|
|
23041
|
+
}
|
|
23042
|
+
})
|
|
23043
|
+
);
|
|
23044
|
+
return changes;
|
|
22682
23045
|
}
|
|
22683
23046
|
function simpleOpts(func, context) {
|
|
22684
23047
|
const equalsSym = 8388787;
|
|
@@ -22686,24 +23049,14 @@ function simpleOpts(func, context) {
|
|
|
22686
23049
|
return Array.from(func.blocks.values()).reduce((changes, block) => {
|
|
22687
23050
|
for (let i = block.bytecodes.length; i--; ) {
|
|
22688
23051
|
const cur = block.bytecodes[i];
|
|
22689
|
-
if (cur.op === 0) {
|
|
23052
|
+
if (cur.op === 0 || context.config.removeArgc && cur.op === 53) {
|
|
22690
23053
|
block.bytecodes.splice(i, 1);
|
|
22691
23054
|
changes = true;
|
|
22692
23055
|
if (logging3) {
|
|
22693
|
-
(0, import_chunk_HHQDDCTP.log)(`${func.name}: deleting
|
|
22694
|
-
if (i > 0) {
|
|
22695
|
-
(0, import_chunk_HHQDDCTP.log)(
|
|
22696
|
-
` - previous bytecode was ${bytecodeToString(
|
|
22697
|
-
block.bytecodes[i - 1],
|
|
22698
|
-
null
|
|
22699
|
-
)}`
|
|
22700
|
-
);
|
|
22701
|
-
}
|
|
23056
|
+
(0, import_chunk_HHQDDCTP.log)(`${func.name}: deleting ${bytecodeToString(cur, null)}`);
|
|
22702
23057
|
}
|
|
22703
23058
|
} else if (i && cur.op === 39 && cur.arg === equalsSym) {
|
|
22704
23059
|
changes = equalSymbolToEq(block, i) || changes;
|
|
22705
|
-
} else if (cur.op === 20) {
|
|
22706
|
-
changes = optimizeArrayInit(func, block, i, true, context) || changes;
|
|
22707
23060
|
} else if (i && cur.op === 10) {
|
|
22708
23061
|
const prev = block.bytecodes[i - 1];
|
|
22709
23062
|
if (prev.op === 37 || prev.op === 49) {
|
|
@@ -22840,7 +23193,7 @@ function cleanCfg2(func, context) {
|
|
|
22840
23193
|
}
|
|
22841
23194
|
const deadBlocks = /* @__PURE__ */ new Map();
|
|
22842
23195
|
func.blocks.forEach((block) => {
|
|
22843
|
-
if (isNopBlock(block)) {
|
|
23196
|
+
if (isNopBlock(block) && block.offset !== func.offset) {
|
|
22844
23197
|
deadBlocks.set(block.offset, block.next);
|
|
22845
23198
|
}
|
|
22846
23199
|
});
|
|
@@ -22878,8 +23231,9 @@ function cleanCfg2(func, context) {
|
|
|
22878
23231
|
removeBlock(func, offset);
|
|
22879
23232
|
});
|
|
22880
23233
|
}
|
|
23234
|
+
const deadCatches = /* @__PURE__ */ new Set();
|
|
22881
23235
|
func.blocks.forEach((block) => {
|
|
22882
|
-
if (block.next && !block.taken && block.next !== block.offset) {
|
|
23236
|
+
if (block.next && !block.taken && block.next !== block.offset && block.next !== func.offset) {
|
|
22883
23237
|
const next = func.blocks.get(block.next);
|
|
22884
23238
|
if (block.try === next.try) {
|
|
22885
23239
|
if (next.preds.size === 1) {
|
|
@@ -22962,6 +23316,7 @@ function cleanCfg2(func, context) {
|
|
|
22962
23316
|
)} with handler at ${handler}`
|
|
22963
23317
|
);
|
|
22964
23318
|
block.try.splice(i, 1);
|
|
23319
|
+
deadCatches.add(handler);
|
|
22965
23320
|
}
|
|
22966
23321
|
}
|
|
22967
23322
|
if (!block.try.length) {
|
|
@@ -22969,6 +23324,29 @@ function cleanCfg2(func, context) {
|
|
|
22969
23324
|
}
|
|
22970
23325
|
}
|
|
22971
23326
|
});
|
|
23327
|
+
deadCatches.forEach((cb) => {
|
|
23328
|
+
const todo = [cb];
|
|
23329
|
+
for (let i = 0; i < todo.length; i++) {
|
|
23330
|
+
const offset = todo[i];
|
|
23331
|
+
const block = func.blocks.get(offset);
|
|
23332
|
+
if (!block) {
|
|
23333
|
+
todo.splice(i--, 1);
|
|
23334
|
+
continue;
|
|
23335
|
+
}
|
|
23336
|
+
if (block.preds?.size) {
|
|
23337
|
+
continue;
|
|
23338
|
+
}
|
|
23339
|
+
if (block.next != null)
|
|
23340
|
+
todo.push(block.next);
|
|
23341
|
+
if (block.taken != null)
|
|
23342
|
+
todo.push(block.taken);
|
|
23343
|
+
if (block.exsucc != null)
|
|
23344
|
+
todo.push(block.exsucc);
|
|
23345
|
+
removeBlock(func, offset);
|
|
23346
|
+
todo.splice(i, 1);
|
|
23347
|
+
i = -1;
|
|
23348
|
+
}
|
|
23349
|
+
});
|
|
22972
23350
|
(0, import_chunk_HHQDDCTP.setBanner)(null);
|
|
22973
23351
|
}
|
|
22974
23352
|
var init_optimize2 = (0, import_chunk_HHQDDCTP.__esm)({
|
|
@@ -28536,7 +28914,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
|
|
|
28536
28914
|
const opt_time = await (0, import_chunk_HHQDDCTP.first_modified)(
|
|
28537
28915
|
Object.values(fnMap).map((v) => v.output)
|
|
28538
28916
|
);
|
|
28539
|
-
if (source_time < opt_time &&
|
|
28917
|
+
if (source_time < opt_time && 1680119325581 < opt_time) {
|
|
28540
28918
|
return { hasTests, diagnostics: prevDiagnostics };
|
|
28541
28919
|
}
|
|
28542
28920
|
}
|
|
@@ -28568,7 +28946,7 @@ async function generateOneConfig(buildConfig, manifestXML, dependencyFiles, conf
|
|
|
28568
28946
|
JSON.stringify({
|
|
28569
28947
|
hasTests: hasTests2,
|
|
28570
28948
|
diagnostics,
|
|
28571
|
-
optimizerVersion: "1.1.
|
|
28949
|
+
optimizerVersion: "1.1.22",
|
|
28572
28950
|
...Object.fromEntries(
|
|
28573
28951
|
configOptionsToCheck.map((option) => [option, config[option]])
|
|
28574
28952
|
)
|
|
@@ -28806,7 +29184,8 @@ var init_worker_task = (0, import_chunk_HHQDDCTP.__esm)({
|
|
|
28806
29184
|
data.xmlBuffer,
|
|
28807
29185
|
data.xmlOffset,
|
|
28808
29186
|
data.xmlLength,
|
|
28809
|
-
data.key
|
|
29187
|
+
data.key,
|
|
29188
|
+
data.config
|
|
28810
29189
|
);
|
|
28811
29190
|
}
|
|
28812
29191
|
};
|
|
@@ -28951,9 +29330,9 @@ function readPrgWithOffsets(view) {
|
|
|
28951
29330
|
}
|
|
28952
29331
|
return { view, sections };
|
|
28953
29332
|
}
|
|
28954
|
-
async function optimizeProgram(filepath, devKey, output) {
|
|
29333
|
+
async function optimizeProgram(filepath, devKey, output, config) {
|
|
28955
29334
|
if (/\.iq$/i.test(filepath)) {
|
|
28956
|
-
return optimizePackage(filepath, devKey, output);
|
|
29335
|
+
return optimizePackage(filepath, devKey, output, config);
|
|
28957
29336
|
}
|
|
28958
29337
|
const removeExt = (filepath2, ext) => path5.join(path5.dirname(filepath2), path5.basename(filepath2, ext));
|
|
28959
29338
|
if (!output) {
|
|
@@ -28967,7 +29346,8 @@ async function optimizeProgram(filepath, devKey, output) {
|
|
|
28967
29346
|
filepath,
|
|
28968
29347
|
view,
|
|
28969
29348
|
debugXml,
|
|
28970
|
-
key
|
|
29349
|
+
key,
|
|
29350
|
+
config
|
|
28971
29351
|
);
|
|
28972
29352
|
const promises = [];
|
|
28973
29353
|
promises.push(fs7.writeFile(output, buffer));
|
|
@@ -28986,7 +29366,7 @@ async function optimizeProgram(filepath, devKey, output) {
|
|
|
28986
29366
|
await Promise.all(promises);
|
|
28987
29367
|
return { signature, output };
|
|
28988
29368
|
}
|
|
28989
|
-
function optimizeProgramBuffer(filepath, view, debugXml, key) {
|
|
29369
|
+
function optimizeProgramBuffer(filepath, view, debugXml, key, config) {
|
|
28990
29370
|
const { sections } = readPrgWithOffsets(view);
|
|
28991
29371
|
(0, import_chunk_HHQDDCTP.logger)("readprg", 5, sections);
|
|
28992
29372
|
const symbolTable = new SymbolTable();
|
|
@@ -29017,7 +29397,10 @@ function optimizeProgramBuffer(filepath, view, debugXml, key) {
|
|
|
29017
29397
|
-1059145026
|
|
29018
29398
|
/* TEXT */
|
|
29019
29399
|
].view, lineTable);
|
|
29400
|
+
if (!config)
|
|
29401
|
+
config = {};
|
|
29020
29402
|
const context = {
|
|
29403
|
+
config,
|
|
29021
29404
|
filepath,
|
|
29022
29405
|
sections,
|
|
29023
29406
|
bytecodes,
|
|
@@ -29041,7 +29424,7 @@ function optimizeProgramBuffer(filepath, view, debugXml, key) {
|
|
|
29041
29424
|
buffers.push(Buffer.from(new ArrayBuffer(8)));
|
|
29042
29425
|
return { signature, buffer: Buffer.concat(buffers) };
|
|
29043
29426
|
}
|
|
29044
|
-
function optimizePackage(filepath, devKey, output) {
|
|
29427
|
+
function optimizePackage(filepath, devKey, output, config) {
|
|
29045
29428
|
if (!devKey) {
|
|
29046
29429
|
throw new Error(`Can't sign ${filepath} without a developer key`);
|
|
29047
29430
|
}
|
|
@@ -29081,7 +29464,8 @@ function optimizePackage(filepath, devKey, output) {
|
|
|
29081
29464
|
xmlBuffer: xmlBuffer.buffer,
|
|
29082
29465
|
xmlOffset: xmlBuffer.byteOffset,
|
|
29083
29466
|
xmlLength: xmlBuffer.byteLength,
|
|
29084
|
-
key
|
|
29467
|
+
key,
|
|
29468
|
+
config
|
|
29085
29469
|
}
|
|
29086
29470
|
}).then(
|
|
29087
29471
|
({
|
|
@@ -29232,7 +29616,7 @@ function optimizePackage(filepath, devKey, output) {
|
|
|
29232
29616
|
})
|
|
29233
29617
|
).finally(() => poolStarted && stopPool());
|
|
29234
29618
|
}
|
|
29235
|
-
function optimizePrgAndDebug(prgName, prgBuffer, prgOffset, prgLength, xmlName, xmlBuffer, xmlOffset, xmlLength, key) {
|
|
29619
|
+
function optimizePrgAndDebug(prgName, prgBuffer, prgOffset, prgLength, xmlName, xmlBuffer, xmlOffset, xmlLength, key, config) {
|
|
29236
29620
|
const xmlString = Buffer.from(xmlBuffer, xmlOffset, xmlLength).toString();
|
|
29237
29621
|
const debugXml = xml_util_exports.parseXml(xmlString, xmlName);
|
|
29238
29622
|
if (debugXml.body instanceof Error) {
|
|
@@ -29242,7 +29626,8 @@ function optimizePrgAndDebug(prgName, prgBuffer, prgOffset, prgLength, xmlName,
|
|
|
29242
29626
|
prgName,
|
|
29243
29627
|
new DataView(prgBuffer, prgOffset, prgLength),
|
|
29244
29628
|
debugXml,
|
|
29245
|
-
key
|
|
29629
|
+
key,
|
|
29630
|
+
config
|
|
29246
29631
|
);
|
|
29247
29632
|
return Promise.resolve({
|
|
29248
29633
|
sigBuffer: result.signature?.buffer,
|