Skip to content

Commit 0358137

Browse files
committed
Fix(parser): handle bipush operand and wide prefix producing *_w instructions
1 parent 74dfbd3 commit 0358137

3 files changed

Lines changed: 564 additions & 19 deletions

File tree

dissasembleClass.js

Lines changed: 41 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,15 @@ function disassemble(ast, constantPool) {
303303
line += ` ${operands.index}`;
304304
} else if ("value" in operands) {
305305
line += ` ${operands.value}`;
306+
} else if ("byte" in operands) { // bipush immediate byte
307+
line += ` ${operands.byte}`;
308+
}
309+
310+
// For widened iinc (iinc_w) include constant
311+
if (opcodeName === 'iinc_w' && 'const' in operands) {
312+
line += ` ${operands.const}`;
313+
} else if (opcodeName === 'iinc' && 'const' in operands) {
314+
line += ` ${operands.index} ${operands.const}`; // existing narrow iinc already has index and const but index printed earlier
306315
}
307316

308317
output.push(line);
@@ -467,15 +476,36 @@ function parseClassFile(jsonObject, opcodeNames) {
467476
for (const inst of codeInfo.code.instructions) {
468477
const opcode = inst.instruction.opcode;
469478
const opcodeInfo = inst.instruction.info || {};
470-
const opcodeLength = opcodeInfo.length || 1;
471-
472-
const instruction = {
473-
pc,
474-
opcode,
475-
opcodeName: opcodeNames[opcode], // To be resolved later
476-
operands: opcodeInfo,
477-
comment: null
478-
};
479+
const opcodeLength = opcodeInfo.length || 1; // includes wide combined length from parser
480+
481+
// Handle wide specially: we want a synthetic widened opcode name like istore_w
482+
let instruction;
483+
if (opcode === 0xc4) { // wide
484+
const modified = opcodeInfo.modifiedOpcode;
485+
const widenedNameBase = opcodeNames[modified];
486+
// Map base mnemonic to widened form suffix, javap uses <mnemonic>_w (except iinc which becomes iinc_w)
487+
const widenedName = widenedNameBase + "_w";
488+
// Build operand structure
489+
const wideOperands = { index: opcodeInfo.index };
490+
if (modified === 0x84) { // iinc
491+
wideOperands.const = opcodeInfo.info.const; // 16-bit const already parsed
492+
}
493+
instruction = {
494+
pc,
495+
opcode: modified,
496+
opcodeName: widenedName,
497+
operands: wideOperands,
498+
comment: null
499+
};
500+
} else {
501+
instruction = {
502+
pc,
503+
opcode,
504+
opcodeName: opcodeNames[opcode], // To be resolved later
505+
operands: opcodeInfo,
506+
comment: null
507+
};
508+
}
479509

480510
// Resolve operands for specific opcodes
481511
if ("index" in opcodeInfo) {
@@ -533,8 +563,8 @@ function parseClassFile(jsonObject, opcodeNames) {
533563
}
534564
}
535565

536-
instructions.push(instruction);
537-
pc += opcodeLength; // Simplification; in reality, instruction lengths vary
566+
instructions.push(instruction);
567+
pc += opcodeLength; // length already accounts for wide expanded length
538568
}
539569

540570
methodInfo.code = {

parsers.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -434,8 +434,9 @@ const WideInstructionParser = Parser.start()
434434
.buffer("length", {
435435
length: () => 0,
436436
formatter: function () {
437-
// Length of what WideInstructionParser parses: 1 (modifiedOpcode) + 2 (index) + optional 2 (const for iinc)
438-
return 1 + 2 + (this.modifiedOpcode === 0x84 ? 2 : 0);
437+
// Total length INCLUDING the wide opcode itself:
438+
// 1 (wide) + 1 (modifiedOpcode) + 2 (index) + optional 2 (const for iinc)
439+
return 1 + 1 + 2 + (this.modifiedOpcode === 0x84 ? 2 : 0);
439440
},
440441
});
441442

0 commit comments

Comments
 (0)