if condition
then code
else code
what actually gets built is
if !condition branch to eb:
then code
goto end: // skip else
eb:
else code
end:
If no else condition was provided then the code is:
if !condition branch to end:
then code
end:
Note all branches here are using relative offsets, not absolute program counters.
If the then code leads to the conditional branch offset being too big (>32k)
because the then code is larger than 32767 bytes then this is built:
// when else code is present
if condition branch to tb: (relative offset +8)
goto_w eb: // indirect for else block (5 bytes)
tb:
then code (> 32767 bytes)
goto end:
eb:
else code
end:
// when only then code is present
if condition branch to tb: (relative offset +8)
goto_w end: // indirect for else block (5 bytes)
tb:
then code (> 32767 bytes)
end:
If there is an else branch and only it is larger than 32767 bytes then
the code is:
if !condition branch to eb: (offset increased by two over previous value)
then code
goto_w end: // skip else
eb:
else code (> 32767 bytes)
end:
This has one special case where the size of conditional branch to eb:
now must change from a 16bit value to a 32 bit value. The generated code
for this is the same as when both the then code and the else code require
32bit offsets for the branches. This code is:
if condition branch to tb: (relative offset +8)
goto_w eb: // indirect for else block (5 bytes)
tb:
then code (> 32767 bytes)
goto_w end:
eb:
else code (> 32767 bytes)
end:
In theory, at the moment this should not happen as this would mean a total
code size that exceeds the limit on the code size for a method (64k). This
code handles this case as it does occur if the limit for a branch is lowered
for testing purposes, to ensure the complete set of branch re-write code works.
This lowering of the limit can be done by changing the constant BRANCH16LIMIT.
Modifier and Type | Field and Description |
---|---|
private static final int | BRANCH16LIMIT
Limit of a 16 bit branch. |
private final int | if_pc
pc of the 'if' opcode. |
private final Conditional | |
private Type[] | |
private int | thenGoto_pc
pc of the GOTO added at the end of the then block to transfer control to the end of this conditional. |
Access | Constructor and Description |
---|---|
pack-priv | Conditional(Conditional
Current conditional block, null if no nesting is going on. parent, CodeChunk CodeChunk this conditional lives in chunk, short Opcode for the if check. ifOpcode, Type[] Type stack on entering the conditional then block. entryStack)Start a conditional block. |
Modifier and Type | Method and Description |
---|---|
pack-priv Conditional | Returns: The conditional this conditional was nested in, if any.CodeChunk this conditional lives in chunk, Type[] Current stack, which is the stack at the end of the else elseStack, int Current number of valid elements in elseStack stackNumber)Complete the conditional and patch up any jump instructions. |
private void | |
pack-priv Type[] |
BRANCH16LIMIT | back to summary |
---|---|
private static final int BRANCH16LIMIT Limit of a 16 bit branch. If broad testing of the switch from 16bit to 32bit offsets is required then this constant can be reduced to a lower value, say 50 and run complete tests. This will cover all the combinations. This works because the GOTO_W instruction works with any offset value. |
if_pc | back to summary |
---|---|
private final int if_pc pc of the 'if' opcode. |
parent | back to summary |
---|---|
private final Conditional parent |
stack | back to summary |
---|---|
private Type[] stack |
thenGoto_pc | back to summary |
---|---|
private int thenGoto_pc pc of the GOTO added at the end of the then block to transfer control to the end of this conditional. That is at the end of the else block. |
Conditional | back to summary |
---|---|
pack-priv Conditional(Conditional parent, CodeChunk chunk, short ifOpcode, Type[] entryStack) Start a conditional block.
|
end | back to summary |
---|---|
pack-priv Conditional end(BCMethod mb, CodeChunk chunk, Type[] elseStack, int stackNumber) Complete the conditional and patch up any jump instructions.
|
fillIn | back to summary |
---|---|
private void fillIn(BCMethod mb, CodeChunk chunk, int branch_pc, int target_pc) Fill in the offsets for a conditional or goto instruction that were dummied up as zero during code generation. Handles modifying branch logic when the offset for the branch is greater than can fit in 16 bits. In this case a GOTO_W with a 32 bit offset will be used, see details within the method for how this is acheived in all situations. This method might insert instructions in the already generated byte code, thus increasing the program counter. |
startElse | back to summary |
---|---|
pack-priv Type[] startElse(BCMethod mb, CodeChunk chunk, Type[] thenStack) Complete the 'then' block and start the 'else' block for this conditional |