|
|||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |
java.lang.Objectorg.apache.derby.impl.services.bytecode.Conditional
class Conditional
A Conditional represents an if/then/else block.
When this is created the code will already have
the conditional check code. The code is optimized for branch
offsets that fit in 2 bytes, though will handle 4 byte offsets.
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.
Field Summary | |
---|---|
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 Summary | |
---|---|
Conditional(Conditional parent,
CodeChunk chunk,
short ifOpcode,
Type[] entryStack)
Start a conditional block. |
Method Summary | |
---|---|
(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 |
Methods inherited from class java.lang.Object |
---|
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Field Detail |
---|
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
Constructor Detail |
---|
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.Method Detail |
---|
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 elseStack
private 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.
|
Built on Thu 2012-03-29 21:53:33+0000, from revision ??? | ||||||||
PREV CLASS NEXT CLASS | FRAMES NO FRAMES | ||||||||
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD |