|
RPNXCortado
C++23 JVM class-file, bytecode, validation, and JAR toolkit
|
code_builder represents destinations with owned labels rather than numeric byte offsets. This lets finalization change instruction widths and switch padding without invalidating branches, exception ranges, or debug tables.
Create every label through the builder that will use it. A label may be referenced before it is bound, but it must be bound exactly once by the time the method is finalized. Labels from another builder lineage are rejected immediately.
The complete sumTo(int) method initializes two locals, loops while the index is at most the argument, and returns the accumulated sum:
The branch template accepts only the supported 16-bit symbolic branch opcodes. If a goto or jsr target is too distant, Cortado selects its wide form. If a conditional target is too distant, Cortado inverts the condition and inserts a goto_w. Client code continues to refer to the original label.
Compact local forms (iload_0 through iload_3), one-byte local operands, and wide local operands are similarly selected during construction. iinc selects the compact or wide immediate form from both its index and increment.
Use tableswitch when keys form a dense consecutive interval:
The low value is the key for the first target; subsequent targets increment the key by one. The target vector must not be empty.
Use lookupswitch for sparse keys. Pairs must be strictly increasing:
Cortado recalculates switch padding while branch widths stabilize. This matters because widening an earlier instruction can move the switch across a four-byte alignment boundary, which changes its own encoded size.
Exception regions also use labels. Their protected interval is [start, end), and the handler label must identify an instruction. Omit the catch type to make a catch-all handler.
The JVM enters a handler with the thrown reference as the only operand-stack value. The example stores it in local slot two before returning a fallback. Automatic analysis includes handler entry states when computing method limits and stack-map frames.
Finalization rejects, among other errors:
tableswitch targets or unsorted lookupswitch pairs;These checks cover structural assembly and stack height. JVM type-state merges and frame generation are described next in Verification, stack maps, and debug metadata.