Top Description Fields Constructors Methods
org.apache.derby.impl.services.bytecode

pack-priv Class Conditional

extends Object
Class Inheritance
Imports
org.apache.derby.iapi.services.classfile.VMOpcode, org.apache.derby.shared.common.sanity.SanityManager

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

Modifier and TypeField 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.

Constructor Summary

AccessConstructor 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.

Method Summary

Modifier and TypeMethod and Description
pack-priv Conditional

Returns:

The conditional this conditional was nested in, if any.
end
(BCMethod mb, CodeChunk
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
fillIn(BCMethod
Method this conditional is for
mb
,
CodeChunk
Our code chunk
chunk
,
int
pc of the branch or goto opcode in the code stream
branch_pc
,
int
pc where we want to jump to.
target_pc
)

Fill in the offsets for a conditional or goto instruction that were dummied up as zero during code generation.

pack-priv Type[]

Returns:

the type stack on entering the then block
startElse
(BCMethod mb, CodeChunk
CodeChunk this conditional lives in
chunk
,
Type[]
Type stack on completing the conditional then block.
thenStack
)

Complete the 'then' block and start the 'else' block for this conditional

Inherited from java.lang.Object:
cloneequalsfinalizegetClasshashCodenotifynotifyAlltoStringwaitwaitwait

Field Detail

BRANCH16LIMITback 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_pcback to summary
private final int if_pc

pc of the 'if' opcode.

parentback to summary
private final Conditional parent
stackback to summary
private Type[] stack
thenGoto_pcback 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.

Constructor Detail

Conditionalback to summary
pack-priv Conditional(Conditional parent, CodeChunk chunk, short ifOpcode, Type[] entryStack)

Start a conditional block.

Parameters
parent:Conditional

Current conditional block, null if no nesting is going on.

chunk:CodeChunk

CodeChunk this conditional lives in

ifOpcode:short

Opcode for the if check.

entryStack:Type[]

Type stack on entering the conditional then block.

Method Detail

endback to summary
pack-priv Conditional end(BCMethod mb, CodeChunk chunk, Type[] elseStack, int stackNumber)

Complete the conditional and patch up any jump instructions.

Parameters
chunk:CodeChunk

CodeChunk this conditional lives in

elseStack:Type[]

Current stack, which is the stack at the end of the else

stackNumber:int

Current number of valid elements in elseStack

Returns:Conditional

The conditional this conditional was nested in, if any.

fillInback 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.

Parameters
mb:BCMethod

Method this conditional is for

chunk:CodeChunk

Our code chunk

branch_pc:int

pc of the branch or goto opcode in the code stream

target_pc:int

pc where we want to jump to.

startElseback to summary
pack-priv Type[] startElse(BCMethod mb, CodeChunk chunk, Type[] thenStack)

Complete the 'then' block and start the 'else' block for this conditional

Parameters
chunk:CodeChunk

CodeChunk this conditional lives in

thenStack:Type[]

Type stack on completing the conditional then block.

Returns:Type[]

the type stack on entering the then block