final class BBSet extends Object
The backing data store is a red/black tree, but there are a number of very specialized operations that are performed during search/insertion so we roll our own instead of using one from the standard library.
Modifier and Type | Class and Description |
---|---|
private static class |
BBSet.TreeEnumerator |
Modifier and Type | Field and Description |
---|---|
private BytecodeStream |
bcodes
associated bytecodes
|
private int[] |
endPCs
End bytecode index for each exception handler range
|
private BasicBlockLE |
entry
entry block of the CFG
|
private TypeOperand[] |
exceptionTypes
Type of exception handled by each exception handler range.
|
private GenerationContext |
gc
associated generation context
|
private int[] |
handlerPCs
Start bytecode index of each the exception handler
|
private boolean |
noJSR
is it the case that we can ignore JSR processing because
BC2IR has not yet generated a JSR bytecode in this method?
|
private BasicBlockLE |
root
root of the backing red/black tree
|
private int[] |
startPCs
Start bytecode index for each exception handler ranges
|
Constructor and Description |
---|
BBSet(GenerationContext gc,
BytecodeStream bcodes,
Operand[] localState)
Initialize the BBSet to handle basic block generation for the argument
generation context and bytecode info.
|
Modifier and Type | Method and Description |
---|---|
private BasicBlockLE |
_createBBLE(int bcIndex,
Operand[] simLocals,
BasicBlockLE parent,
boolean left)
Allocate a new BBLE at the given bcIndex.
|
private BasicBlockLE |
condCreateAndInit(BasicBlockLE x,
boolean shouldCreate,
int target,
BasicBlockLE from,
OperandStack simStack,
Operand[] simLocals,
boolean left)
Conditionally create a block at the specified target as a child of x.
|
(package private) Enumeration<BasicBlockLE> |
contents() |
private int |
countBlack(BasicBlockLE node) |
private void |
db(String val)
Print a debug string to the sysWrite stream.
|
private int |
exceptionEndRange(int bcIndex)
Given a starting bytecode index, find the greatest bcIndex that
is still has the same inscope exception handlers.
|
(package private) void |
finalPass(boolean inlinedSomething)
Do a final pass over the generated basic blocks to create
the initial code ordering.
|
private void |
fixupBBSet(BasicBlockLE x)
Performs tree fixup (restore Red/Black invariants) after adding a
new node to the tree.
|
(package private) BasicBlockLE |
getEntry() |
(package private) int |
getNextBlockBytecodeIndex(BasicBlockLE x)
Gets the bytecode index of the block in the set which has the
next-higher bytecode index.
|
(package private) BasicBlockLE |
getNextEmptyBlock(BasicBlockLE start)
Finds the next ungenerated block, starting at the argument
block and searching forward, wrapping around to the beginning.
|
private BasicBlockLE |
getOrCreateBlock(BasicBlockLE x,
boolean shouldCreate,
int target,
BasicBlockLE from,
OperandStack simStack,
Operand[] simLocals)
Get or create a block at the specified target.
|
(package private) BasicBlockLE |
getOrCreateBlock(int target,
BasicBlockLE from,
OperandStack simStack,
Operand[] simLocals)
Get or create a block at the specified target.
|
private BasicBlockLE |
getSuccessor(BasicBlockLE x,
int value)
Returns the basic block's sucessor in bytecode sequence.
|
private void |
initializeExceptionHandlers(BasicBlockLE bble,
Operand[] simLocals)
Initialize bble's handlers array based on startPCs/endPCs.
|
private void |
injectMove(BasicBlock block,
RegisterOperand res,
Operand val) |
private void |
leftRotateBBSet(BasicBlockLE x) |
private void |
markBlockForRegeneration(BasicBlockLE p)
Mark a previously generated block for regeneration.
|
private boolean |
matchingJSRcontext(OperandStack simStack,
Operand[] simLocals,
BasicBlockLE candBBLE)
We specialize basic blocks with respect to the return addresses
they have on their expression stack and/or in their local variables
on entry to the block.
|
private BasicBlockLE |
minimumBB(BasicBlockLE x,
int value) |
private void |
parseExceptionTables()
Initializes the global exception handler arrays for the method.
|
(package private) void |
rectifyLocals(Operand[] localState,
BasicBlockLE p)
Rectify the given local variable state with the local variable state
stored in the given BBLE.
|
(package private) void |
rectifyStacks(BasicBlock block,
OperandStack stack,
BasicBlockLE p)
Rectify the given stack state with the state contained in the given
BBLE, adding the necessary move instructions to the end of the given
basic block to make register numbers agree and rectify mis-matched constants.
|
private void |
rightRotateBBSet(BasicBlockLE x) |
(package private) void |
seenJSR()
Notify the BBSet that BC2IR has encountered a JSR bytecode.
|
private void |
treeInsert(BasicBlockLE parent,
BasicBlockLE newBBLE,
boolean left)
Insert
newBBLE as a child of parent in our Red/Black tree. |
private void |
verifyTree() |
private void |
verifyTree(BasicBlockLE node,
int min,
int max) |
private BasicBlockLE root
private boolean noJSR
private final BasicBlockLE entry
private final GenerationContext gc
private final BytecodeStream bcodes
private int[] startPCs
private int[] endPCs
private int[] handlerPCs
private TypeOperand[] exceptionTypes
BBSet(GenerationContext gc, BytecodeStream bcodes, Operand[] localState)
gc
- the generation context to generate blocks forbcodes
- the bytecodes of said generation contextlocalState
- the state of the local variables for the block
beginning at bytecode 0.BasicBlockLE getEntry()
void seenJSR()
Enumeration<BasicBlockLE> contents()
int getNextBlockBytecodeIndex(BasicBlockLE x)
x
- basic block to start at.x
is currently the block with
the highest starting bytecode index, return bcodes.length()
.BasicBlockLE getNextEmptyBlock(BasicBlockLE start)
start
- the basic block at which to start looking.null
if all blocks are generated, the next
ungenerated block otherwiseBasicBlockLE getOrCreateBlock(int target, BasicBlockLE from, OperandStack simStack, Operand[] simLocals)
null
, rectifies stack state with target stack state.
If simLocals is non-null
, rectifies local state with target local state.
Any instructions needed to rectify stack/local state are appended to
from.target
- target indexfrom
- the block from which control is being transfered
and to which rectification instructions are added.simStack
- stack state to rectify, or null
simLocals
- local state to rectify, or null
null
private void markBlockForRegeneration(BasicBlockLE p)
p
- the block to mark for regenerationvoid rectifyStacks(BasicBlock block, OperandStack stack, BasicBlockLE p)
block
- basic block to append move instructions tostack
- stack to copyp
- BBLE to copy stack state intoprivate void injectMove(BasicBlock block, RegisterOperand res, Operand val)
void rectifyLocals(Operand[] localState, BasicBlockLE p)
localState
- local variable state to rectifyp
- target BBLE to rectify state tovoid finalPass(boolean inlinedSomething)
NOTE: Only some CFG edges are created here..... we're mainly just patching together a code linearization.
inlinedSomething
- was a normal method (i.e. non-magic) inlined?private void db(String val)
val
- string to printprivate void parseExceptionTables()
private void initializeExceptionHandlers(BasicBlockLE bble, Operand[] simLocals)
PRECONDITION: bble.low and bble.max have already been correctly set to reflect the invariant that a basic block is in exactly one "handler range."
Also initializes bble.block.exceptionHandlers.
bble
- the block whose handlers are to be initializedsimLocals
- local variablesprivate int exceptionEndRange(int bcIndex)
bcIndex
- the start bytecode indexprivate boolean matchingJSRcontext(OperandStack simStack, Operand[] simLocals, BasicBlockLE candBBLE)
The main motivation for inlining away all JSR's is that it eliminates the "JSR problem" for type accurate GC. It is also simpler to implement and arguably results in more efficient generated code (assuming that we don't get horrific code bloat). To deal with the code bloat, we detect excessive code duplication and stop IR generation (bail out to the baseline compiler).
simStack
- The expression stack to matchsimLocals
- The local variables to matchcandBBLE
- The candidate BaseicBlockLEtrue
if and only if a matching JSR context (see above)
was foundprivate BasicBlockLE getOrCreateBlock(BasicBlockLE x, boolean shouldCreate, int target, BasicBlockLE from, OperandStack simStack, Operand[] simLocals)
null
, rectifies stack state with target stack state.
If simLocals is non-null
, rectifies local state with target local state.
Any instructions needed to rectify stack/local state are appended to
from.
As blocks are created, they are added to the red/black tree below x.x
- starting node for search.shouldCreate
- should we create the block if we run off the tree?target
- target indexfrom
- the block from which control is being transfered
and to which rectification instructions are added.simStack
- stack state to rectify, or null
simLocals
- local state to rectify, or null
null
private BasicBlockLE condCreateAndInit(BasicBlockLE x, boolean shouldCreate, int target, BasicBlockLE from, OperandStack simStack, Operand[] simLocals, boolean left)
null
, rectifies stack state with target stack state.
If simLocals is non-null
, rectifies local state with target local state.
Any instructions needed to rectify stack/local state are appended to
from.x
- starting node for search.shouldCreate
- should we create the block if we run off the tree?target
- target indexfrom
- the block from which control is being transfered
and to which rectification instructions are added.simStack
- stack state to rectify, or null
simLocals
- local state to rectify, or null
left
- are we creating a left child of parent?null
if !shouldCreateprivate BasicBlockLE _createBBLE(int bcIndex, Operand[] simLocals, BasicBlockLE parent, boolean left)
bcIndex
- the bytecode index at which the block should be created.simLocals
- the localState to pass (via initializeExceptionHandler)to
to getOrCreateBlock if we need to create BBLEs for
exception handlers. This is only actually used if
!noJSR. We don't need the expression stack, since
the only thing on the expression stack on entry to
a handler block is the exception object (and thus
we can skip scanning the expression stack for
return addresses when creating a handler block).parent
- parent in Red/Black treeleft
- are we creating a left child of parent?private BasicBlockLE getSuccessor(BasicBlockLE x, int value)
x
- basic block at which to start the search for a higher blockvalue
- the contents of x.low (makes tail call elim work better
if we avoid the obvious 1 argument wrapper function)null
if x is the block with the highest bytecode index,
the block with the next-higher bytecode index otherwise.private BasicBlockLE minimumBB(BasicBlockLE x, int value)
private void treeInsert(BasicBlockLE parent, BasicBlockLE newBBLE, boolean left)
newBBLE
as a child of parent in our Red/Black tree.parent
- the parent nodenewBBLE
- the new child nodeleft
- is the child the left or right child of parent?private void fixupBBSet(BasicBlockLE x)
x
- node that was added.private void leftRotateBBSet(BasicBlockLE x)
private void rightRotateBBSet(BasicBlockLE x)
private void verifyTree()
private void verifyTree(BasicBlockLE node, int min, int max)
private int countBlack(BasicBlockLE node)