class Conditional
extends java.lang.Object
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 | Description |
---|---|---|
private static int |
BRANCH16LIMIT |
Limit of a 16 bit branch.
|
private int |
if_pc |
pc of the 'if' opcode.
|
private Conditional |
parent |
|
private Type[] |
stack |
|
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.
|
Constructor | Description |
---|---|
Conditional(Conditional parent,
CodeChunk chunk,
short ifOpcode,
Type[] entryStack) |
Start a conditional block.
|
Modifier and Type | Method | Description |
---|---|---|
(package private) Conditional |
end(BCMethod mb,
CodeChunk chunk,
Type[] elseStack,
int stackNumber) |
Complete the conditional and patch up any jump instructions.
|
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.
|
(package private) Type[] |
startElse(BCMethod mb,
CodeChunk chunk,
Type[] thenStack) |
Complete the 'then' block and start the 'else' block for this conditional
|
private static final int BRANCH16LIMIT
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.
private final Conditional parent
private final int if_pc
private Type[] stack
private int thenGoto_pc
Conditional(Conditional parent, CodeChunk chunk, short ifOpcode, Type[] entryStack)
parent
- Current conditional block, null if no nesting is going on.chunk
- CodeChunk this conditional lives inifOpcode
- Opcode for the if check.entryStack
- Type stack on entering the conditional then block.Type[] startElse(BCMethod mb, CodeChunk chunk, Type[] thenStack)
chunk
- CodeChunk this conditional lives inthenStack
- Type stack on completing the conditional then block.Conditional end(BCMethod mb, CodeChunk chunk, Type[] elseStack, int stackNumber)
chunk
- CodeChunk this conditional lives inelseStack
- Current stack, which is the stack at the end of the elsestackNumber
- Current number of valid elements in elseStackprivate void fillIn(BCMethod mb, CodeChunk chunk, int branch_pc, int target_pc)
mb
- Method this conditional is forchunk
- Our code chunkbranch_pc
- pc of the branch or goto opcode in the code streamtarget_pc
- pc where we want to jump to.Apache Derby V10.14 Internals - Copyright © 2004,2018 The Apache Software Foundation. All Rights Reserved.