public final class BC2IR extends Object
The only public entry point is BC2IR.generateHIR. generateHIR is passed an argument GenerationContext. The context is assumed to be "empty" but "initialized." Invoking generateHIR on a context results in it being "filled in" with the HIR for the method (and for any inlined methods) as specified by the state of the context.
The basic idea is to abstractly interpret the bytecode stream, translating it into a register-based IR along the way. At each program point BC2IR has an abstract stack and an abstract local variable array. Based on this, and on the bytecode, it can generate instructions. It also does a number of forward flow-sensitive dataflow analyses and optimistic optimizations in the process. There's lots of details in John Whaley's master thesis from MIT. However, one needs to be careful because this code has substantial diverged from the system described in his thesis. Some optimizations/features described in Johns's thesis are not implemented here. Some optimizations/features implemented here are not described in John's thesis. In particular this code takes a different approach to JSRs (inlining them), and has more advanced and effective implementation of the inlining transformation.
IRGenOptions
,
GenerationContext
,
ConvertBCtoHIR
Modifier and Type | Class and Description |
---|---|
private static class |
BC2IR.DummyStackSlot
Dummy stack slot
|
Modifier and Type | Field and Description |
---|---|
private Operand[] |
_localState
Current state of local variables.
|
private int |
bciAdjustment
OSR field: TODO rework this mechanism!
|
private BytecodeStream |
bcodes
Bytecodes for the method being generated.
|
private BBSet |
blocks
The set of BasicBlockLEs we are generating
|
private BasicBlockLE |
currentBBLE
Current BBLE.
|
private Operand |
currentGuard |
(package private) static boolean |
DBG_SELECTED |
private static boolean |
DBG_SELECTIVE
Debugging with method_to_print.
|
static BC2IR.DummyStackSlot |
DUMMY
Dummy slot.
|
private boolean |
endOfBasicBlock
Does basic block end here?
|
private boolean |
fallThrough
Do we fall through to the next basic block?
|
private GenerationContext |
gc
The generation context.
|
private boolean |
inlinedSomething
Was something inlined?
|
private int |
instrIndex
Bytecode index of current instruction.
|
private Instruction |
lastInstr
Last instruction generated (for ELIM_COPY_LOCALS)
|
private Instruction |
lastOsrBarrier
osr barrier needs type information of locals and stacks,
it has to be created before a _callHelper.
|
private boolean |
osrGuardedInline |
private int |
param1
OSR: used for PSEUDO_InvokeStatic to recover the type info
|
private int |
param2
OSR: used for PSEUDO_InvokeStatic to recover the type info
|
private int |
runoff
Index of next basic block.
|
private OperandStack |
stack
Current simulated stack state.
|
Modifier | Constructor and Description |
---|---|
private |
BC2IR(GenerationContext context)
Construct the BC2IR object for the generation context.
|
Modifier and Type | Method and Description |
---|---|
Instruction |
_aloadHelper(Operator operator,
Operand ref,
Operand index,
TypeReference type) |
private Instruction |
_binaryDualHelper(Operator operator,
Operand op1,
Operand op2,
TypeReference type) |
Instruction |
_binaryHelper(Operator operator,
Operand op1,
Operand op2,
TypeReference type) |
private Instruction |
_callHelper(MethodReference meth,
MethodOperand methOp)
Pop method parameters off the expression stack.
|
private Instruction |
_createOsrBarrier() |
private Instruction |
_gotoHelper(int offset) |
private Instruction |
_guardedBinaryDualHelper(Operator operator,
Operand op1,
Operand op2,
Operand guard,
TypeReference type) |
private Instruction |
_guardedBinaryHelper(Operator operator,
Operand op1,
Operand op2,
Operand guard,
TypeReference type) |
private Instruction |
_intIfCmpHelper(ConditionOperand cond) |
private Instruction |
_intIfHelper(ConditionOperand cond) |
private Instruction |
_jsrHelper(int offset) |
private Operand |
_loadLocalForOSR(Operand op)
make a temporary register, and create a move instruction
|
private Instruction |
_moveDualHelper(Operator operator,
Operand val,
TypeReference type) |
(package private) Instruction |
_moveHelper(Operator operator,
Operand val,
TypeReference type) |
static Instruction |
_osrHelper(Instruction barrier,
GenerationContext gc)
Creates an OSR point instruction with its dependent OsrBarrier
which provides type and variable information.
|
private Operand |
_prepareDoubleConstant(Operand op)
special process for long/double constants
|
private Operand |
_prepareLongConstant(Operand op)
special process for long/double constants
|
private Instruction |
_refIfCmpHelper(ConditionOperand cond) |
private Instruction |
_refIfNullHelper(ConditionOperand cond) |
private Instruction |
_retHelper(int var) |
private void |
_returnHelper(Operator operator,
Operand val) |
(package private) Instruction |
_unaryDualHelper(Operator operator,
Operand val,
TypeReference type) |
(package private) Instruction |
_unaryHelper(Operator operator,
Operand val,
TypeReference type) |
void |
appendInstruction(Instruction s)
Append an instruction to the current basic block.
|
private void |
assertIsAssignable(TypeReference parentType,
TypeReference childType)
Assert that the given child type is a subclass of the given parent type.
|
void |
assertIsType(Operand op,
TypeReference type)
Assert that the given operand is of the given type, or of
a subclass of the given type.
|
void |
clearCurrentGuard() |
static Operand |
copyGuardFromOperand(Operand op) |
private boolean |
couldCauseClassLoading(TypeReference typeRef) |
private void |
db(String val)
Print a debug string to the sysWrite stream
|
private Instruction |
do_aload(int index)
Simulates a load from a given local variable of a reference.
|
private Instruction |
do_astore(int index)
Simulates a store into a given local variable of an object ref.
|
boolean |
do_BoundsCheck(Operand ref,
Operand index)
Generates a boundscheck instruction for the given operand and index.
|
private boolean |
do_CheckStore(Operand ref,
Operand elem,
TypeReference elemType)
Generate a storecheck for the given array and elem
|
private Instruction |
do_dload(int index)
Simulates a load from a given local variable of a double.
|
private Instruction |
do_fload(int index)
Simulates a load from a given local variable of a float.
|
private Instruction |
do_iinc(int index,
int amount)
Simulates the incrementing of a given int local variable.
|
private Instruction |
do_iload(int index)
Simulates a load from a given local variable of an int.
|
private boolean |
do_IntZeroCheck(Operand div)
Generates a check for 0 for the given operand
|
private Instruction |
do_lload(int index)
Simulates a load from a given local variable of a long.
|
private boolean |
do_LongZeroCheck(Operand div)
Generates a checks for 0 for the given operand
|
boolean |
do_NullCheck(Operand ref)
Generates a null-check instruction for the given operand.
|
private Instruction |
do_store(int index,
Operand op1)
Simulates a store into a given local variable of an int/long/double/float
|
private void |
finish(GenerationContext context) |
Instruction |
generateAnewarray(TypeReference arrayTypeRef,
TypeReference elementTypeRef) |
private void |
generateFrom(int fromIndex)
Generate instructions for a basic block.
|
private void |
generateHIR()
Main generation loop.
|
static void |
generateHIR(GenerationContext context)
Generate HIR as specified by the argument GenerationContext.
|
private BranchOperand |
generateTarget(int offset) |
TypeReference |
getArrayTypeOf(Operand op)
Returns the data type of the given operand, assuming that the operand is
an array reference.
|
Operand |
getConstantOperand(int index)
Fetch the value of the next operand, a constant, from the bytecode
stream.
|
Operand |
getCurrentGuard() |
private Operand |
getLocal(int i)
Gets the specified local variable.
|
private Operand |
getLocalDual(int i)
Gets the specified local variable (long, double).
|
private BasicBlockLE |
getOrCreateBlock(int target)
Gets or creates a block at the specified target.
|
private BasicBlockLE |
getOrCreateBlock(int target,
BasicBlockLE from,
OperandStack simStack,
Operand[] simLocals)
Get or create a block at the specified target.
|
private TypeReference |
getRefTypeOf(Operand op)
Returns the data type of the given operand, assuming that the operand is
a reference.
|
static boolean |
hasGuard(RegisterOperand rop) |
static boolean |
hasLessConservativeGuard(RegisterOperand rop1,
RegisterOperand rop2) |
static boolean |
isNonNull(Operand op) |
private LocationOperand |
makeInstanceFieldRef(FieldReference f) |
private LocationOperand |
makeStaticFieldRef(FieldReference f)
Make a field reference operand referring to the given field with the
given type.
|
private TypeOperand |
makeTypeOperand(RVMType type)
Make a type operand that refers to the given type.
|
private TypeOperand |
makeTypeOperand(TypeReference type)
Make a type operand that refers to the given type.
|
void |
markGuardlessNonNull(RegisterOperand rop) |
private boolean |
maybeInlineMethod(InlineDecision inlDec,
Instruction callSite)
Attempt to inline a method.
|
(package private) Operand |
pop()
Pops an operand from the stack.
|
(package private) Operand |
pop(TypeReference type)
Pops an operand of the given type from the stack.
|
Operand |
popAddress()
Pops an address operand from the stack.
|
(package private) Operand |
popDouble()
Pops a double operand from the stack.
|
(package private) void |
popDummy()
Pops a dummy operand from the stack.
|
(package private) Operand |
popFloat()
Pops a float operand from the stack.
|
Operand |
popInt()
Pops an int operand from the stack.
|
(package private) Operand |
popLong()
Pops a long operand from the stack.
|
Operand |
popRef()
Pops a ref operand from the stack.
|
private Operand |
popShiftInt(boolean longShift)
Pop an int from the stack to be used in a shift.
|
private String |
printBlocks() |
void |
push(Operand r)
Push a single width operand (int, float, ref, ...) on the simulated stack.
|
(package private) void |
push(Operand r,
TypeReference type)
Push an operand of the specified type on the simulated stack.
|
private Instruction |
pushCopy(Operand op1)
Pushes a copy of the given operand onto simulated stack.
|
(package private) void |
pushDual(Operand r)
Push a double width operand (long, double) on the simulated stack.
|
private BasicBlock |
rectifyStateWithArithmeticExceptionHandler() |
private BasicBlock |
rectifyStateWithArithmeticExceptionHandler(boolean linkToExitIfUncaught) |
private BasicBlock |
rectifyStateWithArrayBoundsExceptionHandler() |
private BasicBlock |
rectifyStateWithArrayBoundsExceptionHandler(boolean linkToExitIfUncaught) |
private BasicBlock |
rectifyStateWithArrayStoreExceptionHandler() |
private BasicBlock |
rectifyStateWithArrayStoreExceptionHandler(boolean linkToExitIfUncaught) |
private BasicBlock |
rectifyStateWithErrorHandler() |
private BasicBlock |
rectifyStateWithErrorHandler(boolean linkToExitIfUncaught) |
BasicBlock |
rectifyStateWithExceptionHandler(TypeReference exceptionType) |
private BasicBlock |
rectifyStateWithExceptionHandler(TypeReference exceptionType,
boolean linkToExitIfUncaught) |
void |
rectifyStateWithExceptionHandlers() |
private void |
rectifyStateWithExceptionHandlers(boolean linkToExitIfUncaught) |
private BasicBlock |
rectifyStateWithNullPtrExceptionHandler() |
private BasicBlock |
rectifyStateWithNullPtrExceptionHandler(boolean linkToExitIfUncaught) |
private void |
replaceLocalsOnStack(int index,
TypeReference type)
Replaces copies of local
<#index,type> with
newly-generated temporaries, and generates the necessary move instructions. |
private void |
setCurrentGuard(Operand guard) |
static void |
setGuardForRegOp(RegisterOperand rop,
Operand guard) |
private void |
setLocal(int i,
Operand op)
Set the specified local variable
|
private void |
setLocalDual(int i,
Operand op)
Set the specified local variable
|
private InlineDecision |
shouldInline(Instruction call,
boolean isExtant,
int realBCI)
Should we inline a call site?
|
private void |
start(GenerationContext context) |
public static final BC2IR.DummyStackSlot DUMMY
private GenerationContext gc
private BytecodeStream bcodes
private int instrIndex
private boolean osrGuardedInline
private int bciAdjustment
private Instruction lastInstr
private boolean endOfBasicBlock
private boolean fallThrough
private BasicBlockLE currentBBLE
private OperandStack stack
private Operand[] _localState
private int runoff
private Operand currentGuard
private boolean inlinedSomething
private int param1
private int param2
private Instruction lastOsrBarrier
private static final boolean DBG_SELECTIVE
DBG_SELECTIVE
to true.
DBG_SELECTED
will then be true
when the method matches.
You must also uncomment the assignment to DBG_SELECTIVE in
start(GenerationContext)
.static final boolean DBG_SELECTED
private BC2IR(GenerationContext context)
context
- the context to generate HIR intopublic static void generateHIR(GenerationContext context)
This is the only external entry point to BC2IR.
Note: most clients should be calling methods in ConvertBCtoHIR or in Inliner rather than invoking BC2IR.generateHIR directly.
context
- the generation contextprivate void start(GenerationContext context)
private void finish(GenerationContext context)
private void generateHIR()
public Instruction generateAnewarray(TypeReference arrayTypeRef, TypeReference elementTypeRef)
private void generateFrom(int fromIndex)
fromIndex
- bytecode index to start fromInstruction _unaryHelper(Operator operator, Operand val, TypeReference type)
Instruction _unaryDualHelper(Operator operator, Operand val, TypeReference type)
public Instruction _binaryHelper(Operator operator, Operand op1, Operand op2, TypeReference type)
private Instruction _guardedBinaryHelper(Operator operator, Operand op1, Operand op2, Operand guard, TypeReference type)
private Instruction _binaryDualHelper(Operator operator, Operand op1, Operand op2, TypeReference type)
private Instruction _guardedBinaryDualHelper(Operator operator, Operand op1, Operand op2, Operand guard, TypeReference type)
Instruction _moveHelper(Operator operator, Operand val, TypeReference type)
private Instruction _moveDualHelper(Operator operator, Operand val, TypeReference type)
public Instruction _aloadHelper(Operator operator, Operand ref, Operand index, TypeReference type)
private Instruction _callHelper(MethodReference meth, MethodOperand methOp)
meth
- the method to callmethOp
- data about the methodprivate void _returnHelper(Operator operator, Operand val)
public void appendInstruction(Instruction s)
s
- instruction to appendprivate LocationOperand makeStaticFieldRef(FieldReference f)
f
- desired fieldprivate LocationOperand makeInstanceFieldRef(FieldReference f)
private TypeOperand makeTypeOperand(TypeReference type)
type
- desired typeprivate TypeOperand makeTypeOperand(RVMType type)
type
- desired typeprivate boolean couldCauseClassLoading(TypeReference typeRef)
public Operand getConstantOperand(int index)
index
- constant pool indexprivate Instruction do_iload(int index)
index
- local variable numbernull
if no instruction is necessary, a move instruction
otherwiseprivate Instruction do_fload(int index)
index
- local variable numbernull
if no instruction is necessary, a move instruction
otherwiseprivate Instruction do_aload(int index)
index
- local variable numbernull
if no instruction is necessary, a move instruction
otherwiseprivate Instruction do_lload(int index)
index
- local variable numbernull
if no instruction is necessary, a move instruction
otherwiseprivate Instruction do_dload(int index)
index
- local variable numbernull
if no instruction is necessary, a move instruction
otherwiseprivate Instruction do_iinc(int index, int amount)
index
- local variable numberamount
- amount to increment bynull
private Instruction do_store(int index, Operand op1)
index
- local variable numberop1
- the value to storenull
if no instruction is necessary, the generated
instruction otherwiseprivate Instruction do_astore(int index)
index
- local variable numbernull
if no instruction is necessary, the generated
instruction otherwisepublic void push(Operand r)
r
- operand to pushvoid pushDual(Operand r)
r
- operand to pushvoid push(Operand r, TypeReference type)
r
- operand to pushtype
- data type of operandprivate Instruction pushCopy(Operand op1)
op1
- operand to pushnull
Operand pop()
public Operand popAddress()
void popDummy()
Operand pop(TypeReference type)
type
- the expected type of the operandprivate Operand popShiftInt(boolean longShift)
(x << 16) << 16 == x << 32
, which isn't true in the bytecodelongShift
- is this a shift of a longprivate Instruction _jsrHelper(int offset)
private Instruction _retHelper(int var)
public TypeReference getArrayTypeOf(Operand op)
null
constant.)op
- operand to get type ofprivate TypeReference getRefTypeOf(Operand op)
null
constant.)op
- operand to get type ofpublic void assertIsType(Operand op, TypeReference type)
op
- operand to checktype
- expected type of operandprivate void assertIsAssignable(TypeReference parentType, TypeReference childType)
parentType
- parent typechildType
- child typeprivate void db(String val)
val
- string to printprivate String printBlocks()
public static boolean hasGuard(RegisterOperand rop)
public static boolean hasLessConservativeGuard(RegisterOperand rop1, RegisterOperand rop2)
public void markGuardlessNonNull(RegisterOperand rop)
public static Operand copyGuardFromOperand(Operand op)
public static void setGuardForRegOp(RegisterOperand rop, Operand guard)
private void setCurrentGuard(Operand guard)
public void clearCurrentGuard()
public Operand getCurrentGuard()
public boolean do_NullCheck(Operand ref)
ref
- the reference to check for nulltrue
if an unconditional throw is generated, false
otherwisepublic boolean do_BoundsCheck(Operand ref, Operand index)
ref
- the array referenceindex
- the array indextrue
if an unconditional throw is generated, false
otherwiseprivate boolean do_IntZeroCheck(Operand div)
div
- the value to checktrue
if an unconditional trap is generated, false
otherwiseprivate boolean do_LongZeroCheck(Operand div)
div
- the value to checktrue
if an unconditional trap is generated, false
otherwiseprivate boolean do_CheckStore(Operand ref, Operand elem, TypeReference elemType)
ref
- the array referenceelem
- the element to be written to the arrayelemType
- the type of the array references elementstrue
if an unconditional throw is generated, false
otherwiseprivate BasicBlockLE getOrCreateBlock(int target)
target
- target indexnull
private BasicBlockLE 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.
If the target is between bcodes.index() and runoff, runoff is
updated to be target.target
- target indexfrom
- the block from which control is being transfered
and to which stack rectification instructions are added.simStack
- stack state to rectify, or null
simLocals
- local state to rectify, or null
null
private BranchOperand generateTarget(int offset)
private Instruction _gotoHelper(int offset)
private Instruction _intIfHelper(ConditionOperand cond)
private Instruction _intIfCmpHelper(ConditionOperand cond)
private Instruction _refIfNullHelper(ConditionOperand cond)
private Instruction _refIfCmpHelper(ConditionOperand cond)
private void replaceLocalsOnStack(int index, TypeReference type)
<#index,type>
with
newly-generated temporaries, and generates the necessary move instructions.index
- the local's indextype
- the local's typeprivate BasicBlock rectifyStateWithNullPtrExceptionHandler()
private BasicBlock rectifyStateWithArrayBoundsExceptionHandler()
private BasicBlock rectifyStateWithArithmeticExceptionHandler()
private BasicBlock rectifyStateWithArrayStoreExceptionHandler()
private BasicBlock rectifyStateWithErrorHandler()
public void rectifyStateWithExceptionHandlers()
public BasicBlock rectifyStateWithExceptionHandler(TypeReference exceptionType)
private BasicBlock rectifyStateWithNullPtrExceptionHandler(boolean linkToExitIfUncaught)
private BasicBlock rectifyStateWithArrayBoundsExceptionHandler(boolean linkToExitIfUncaught)
private BasicBlock rectifyStateWithArithmeticExceptionHandler(boolean linkToExitIfUncaught)
private BasicBlock rectifyStateWithArrayStoreExceptionHandler(boolean linkToExitIfUncaught)
private BasicBlock rectifyStateWithErrorHandler(boolean linkToExitIfUncaught)
private BasicBlock rectifyStateWithExceptionHandler(TypeReference exceptionType, boolean linkToExitIfUncaught)
private void rectifyStateWithExceptionHandlers(boolean linkToExitIfUncaught)
private InlineDecision shouldInline(Instruction call, boolean isExtant, int realBCI)
call
- the call instruction being considered for inliningisExtant
- is the receiver of a virtual method an extant object?realBCI
- the real bytecode index of the call instruction, not adjusted because of OSRnull
)private boolean maybeInlineMethod(InlineDecision inlDec, Instruction callSite)
inlDec
- the inline decision for this call sitecallSite
- the call instruction we are attempting to inlinetrue
if inlining succeeded, false
otherwiseprivate Instruction _createOsrBarrier()
private Operand _prepareLongConstant(Operand op)
op
- a long constantprivate Operand _prepareDoubleConstant(Operand op)
op
- a double constantprivate Operand _loadLocalForOSR(Operand op)
op
- the local variable.public static Instruction _osrHelper(Instruction barrier, GenerationContext gc)
barrier
- the OSR barrier instructiongc
- context that has information about OSRprivate Operand getLocal(int i)
i
- local variable numberprivate Operand getLocalDual(int i)
i
- local variable numberprivate void setLocal(int i, Operand op)
i
- local variable numberop
- Operand to store in the localprivate void setLocalDual(int i, Operand op)
i
- local variable numberop
- Operand to store in the local