public final class Instruction extends Object
operator
and
(optionally) some operands
.
In addition, an instruction may (or may not) have
valid bcIndex
andposition
fields that
together encode a description of the bytecode that it came from.
Although we use a single class, Instruction
,
to implement all IR instructions, there are logically a number
of different kinds of instructions.
For example, binary operators, array loads, calls,
and null_checks all have different number of operands with differing
semantics. To manage this in an abstract, somewhat object-oriented,
but still highly efficient fashion we have the notion of an
Instruction Format. An Instruction Format is a class
external to Instruction (defined in the instructionFormat package)
that provides static methods to create instructions and symbolically
access their operands. Every instance of Operator
is assigned to exactly one Instruction Format. Thus, the instruction's
operator implies which Instruction Format class can be used to
access the instruction's operands.
There are some common logical operands (eg Result, Location) that appear in a large number of Instruction Formats. In addition to the basic Instruction Format classes, we provided additional classes (eg ResultCarrier, LocationCarrier) that allow manipulation of all instructions that contain a common operands.
A configuration (OptOptVIFcopyingGC) is defined in which all methods of all Instruction Format classes verify that the operator of the instruction being manipulated actually belongs to the appropriate Instruction Format. This configuration is quite slow, but is an important sanity check to make sure that Instruction Formats are being used in a consistent fashion.
The instruction's operator also has a number of traits. Methods on
Instruction
are provided to query these operator traits.
In general, clients should use the methods of Instruction to query
traits, since a particular instruction may override the operator-provided
default in some cases. For example, isMove()
, isBranch()
,
isPEI()
, and isCall()
are some of the trait queries.
Unfortunately, the combination of operators, operator traits, and Instruction Formats often leads to a tricky decision of which of three roughly equivalent idioms one should use when writing code that needs to manipulate instructions and their operands. For example,
if (Call.conforms(instr)) { return Call.getResult(instr); }and
if (instr.operator() == CALL) { return Call.getResult(instr); }and
if (instr.isCall()) { return ResultCarrier.getResult(instr); }are more or less the same. In some cases, picking an idiom is simply a matter of taste, but in others making the wrong choice can lead to code that is less robust or maintainable as operators and/or instruction formats are added and removed from the IR. One should always think carefully about which idiom is the most concise, maintainable, robust and efficient means of accomplishing a given task. Some general rules of thumb (or at least one person's opinion):
Operator
,
Operand
,
BasicBlock
Modifier and Type | Class and Description |
---|---|
private static class |
Instruction.BASE_OE
Shared functionality for operand enumerations
|
private static class |
Instruction.MOE
Enumerate the memory operands of an instruction
|
private static class |
Instruction.OE
enumerate leaf operands in the given ranges
|
private static class |
Instruction.OEDefsOnly
Enumerate the def operands of an instruction (ignores memory
operands, since the contained operands of a MO are uses).
|
private static class |
Instruction.ROE
Enumerate the root operands of an instruction
|
Modifier and Type | Field and Description |
---|---|
int |
bcIndex
The index of the bytecode that this instruction came from.
|
private Instruction |
next
The next instruction in the intra-basic-block list of instructions,
will be
null if no such instruction exists. |
private static byte |
OI_GC
BITFIELD used to encode
operatorInfo . |
private static byte |
OI_GC_VALID
BITFIELD used to encode
operatorInfo . |
private static byte |
OI_INVALID
BITFIELD used to encode
operatorInfo . |
private static byte |
OI_PEI
BITFIELD used to encode
operatorInfo . |
private static byte |
OI_PEI_VALID
BITFIELD used to encode
operatorInfo . |
private Operator |
operator
The operator for this instruction.
|
private byte |
operatorInfo
Override and refine the operator-based trait (characteristic)
information.
|
private Operand[] |
ops
The operands of this instruction.
|
InlineSequence |
position
A description of the tree of inlined methods that contains the bytecode
that this instruction came from.
|
private Instruction |
prev
The previous instruction in the intra-basic-block list of instructions,
will be
null if no such instruction exists. |
Modifier | Constructor and Description |
---|---|
private |
Instruction(Operator op,
int size) |
Modifier and Type | Method and Description |
---|---|
void |
BURS_backdoor_linkWithNext(Instruction other)
Allow BURS a back door into linkWithNext.
|
void |
changeOperatorTo(Operator newlySetOperator) |
(package private) void |
clearLinks()
For IR internal use only; general clients should always use higer level
mutation functions.
|
void |
copyPosition(Instruction source)
|
Instruction |
copyWithoutLinks()
Create a copy of this instruction.
|
static Instruction |
create(Operator op,
int size)
INTERNAL IR USE ONLY: create a new instruction with the specified number
of operands.
|
void |
flipBranchProbability()
Invert the probabilty of this branch being taken.
|
BasicBlock |
getBasicBlock()
Gets the basic block that contains this instruction.
|
float |
getBranchProbability()
Return the probability (in the range 0.0 - 1.0) that this two-way
branch instruction is taken (as opposed to falling through).
|
BasicBlock |
getBranchTarget()
Returns the basic block jumped to by this BRANCH instruction.
|
Enumeration<BasicBlock> |
getBranchTargets()
Return an enumeration of the basic blocks that are targets of this
branch instruction.
|
int |
getBytecodeIndex()
Get the
bytecode index of the instruction. |
Operand |
getClearOperand(int i)
NOTE: It is incorrect to use getClearOperand with a constant argument
outside of the automatically generated code in Operators.
|
Enumeration<Operand> |
getDefs()
Enumerate all defs (both pure defs and def/uses) of an instruction.
|
Enumeration<Operand> |
getDefUses()
Enumerate all the def/uses of an instruction.
|
Enumeration<Operand> |
getMemoryOperands()
Enumerate all memory operands of an instruction
|
private char |
getMIR_START_opcode() |
(package private) Instruction |
getNext()
For IR internal use only; general clients should use
nextInstructionInCodeOrder() . |
int |
getNumberOfDefs()
Returns the number of operands that are defs
(either pure defs or combined def/uses).
|
int |
getNumberOfOperands()
Get the number of operands in this instruction.
|
private int |
getNumberOfOperandsVarUsesOrDefs() |
int |
getNumberOfPureDefs()
Returns the number of operands that are pure defs.
|
int |
getNumberOfPureUses()
Returns the number of operands that are pure uses.
|
int |
getNumberOfUses()
Returns the number of operands that are uses
(either combined def/uses or pure uses).
|
char |
getOpcode()
Return the opcode of the instruction's operator
(a unique id suitable for use in switches); see
Operator.opcode . |
Operand |
getOperand(int i)
NOTE: It is incorrect to use getOperand with a constant argument
outside of the automatically generated code in Operators.
|
Enumeration<Operand> |
getOperands()
Enumerate all "leaf" operands of an instruction.
|
(package private) Instruction |
getPrev()
For IR internal use only; General clients should use
prevInstructionInCodeOrder() . |
Enumeration<Operand> |
getPureDefs()
Enumerate all the pure defs (ie not including def/uses) of an instruction.
|
Enumeration<Operand> |
getPureUses()
Enumerate all the pure uses (ie not including def/uses) of an instruction.
|
Enumeration<Operand> |
getRootOperands()
Enumerate all the root operands of an instruction
(DOES NOT ENUMERATE CONTAINED OPERANDS OF MEMORY OPERANDS).
|
Enumeration<Operand> |
getRootUses()
Enumerate all root uses of an instruction.
|
Enumeration<Operand> |
getUses()
Enumerate all uses of an instruction (includes def/use).
|
boolean |
hasMemoryOperand() |
boolean |
hasPrev() |
void |
insertAfter(Instruction newInstr)
Insertion: Insert newInstr immediately after this in the
instruction stream.
|
void |
insertBefore(Instruction newInstr)
Insertion: Insert newInstr immediately before this in the
instruction stream.
|
boolean |
isAcquire()
Is the instruction an acquire (monitorenter/lock)?
|
boolean |
isAllocation()
Is the instruction an actual memory allocation instruction
(NEW, NEWARRAY, etc)?
|
private void |
isBackwardLinked() |
boolean |
isBbFirst()
Return
true if this instruction is the first instruction in a
basic block. |
boolean |
isBbInside()
Mainly intended for assertion checking; returns true if the instruction
is expected to appear on the "inside" of a basic block, false otherwise.
|
boolean |
isBbLast()
Return
true if this instruction is the last instruction in a
basic block. |
boolean |
isBranch()
Is the instruction an intraprocedural branch?
|
boolean |
isCall()
Is the instruction a call (one kind of interprocedural branch)?
|
boolean |
isCompare()
Is the instruction a compare (val,val) => condition?
|
boolean |
isConditionalBranch()
Is the instruction a conditional intraprocedural branch?
|
boolean |
isConditionalCall()
Is the instruction a conditional call?
|
boolean |
isDirectBranch()
Is the instruction a direct intraprocedural branch?
|
boolean |
isDirectCalll()
Is the instruction a direct call?
|
boolean |
isDynamicLinkingPoint()
Could the instruction either directly or indirectly
cause dynamic class loading?
|
boolean |
isExplicitLoad()
Is the instruction an explicit load of a finite set of values from
a finite set of memory locations (load, load multiple, _not_ call)?
|
boolean |
isExplicitStore()
Is the instruction an explicit store of a finite set of values to
a finite set of memory locations (store, store multiple, _not_ call)?
|
private void |
isForwardLinked() |
boolean |
isGCPoint()
Is the instruction a potential GC point?
|
boolean |
isImplicitLoad()
Should the instruction be treated as a load from some unknown location(s)
for the purposes of scheduling and/or modeling the memory subsystem?
|
boolean |
isImplicitStore()
Should the instruction be treated as a store to some unknown location(s)
for the purposes of scheduling and/or modeling the memory subsystem?
|
boolean |
isIndirectBranch()
Is the instruction an indirect intraprocedural branch?
|
boolean |
isIndirectCall()
Is the instruction an indirect call?
|
private void |
isLinked() |
boolean |
isMarkedAsPEI()
Has the instruction been explictly marked as a a PEI (Potentially Excepting Instruction)?
|
boolean |
isMove()
Does the instruction represent a simple move (the value is unchanged)
from one "register" location to another "register" location?
|
boolean |
isNonPureCall()
Is the instruction a call but not a pure call (one kind of interprocedural branch)?
|
private void |
isNotLinked() |
boolean |
isPEI()
Is the instruction a PEI (Potentially Excepting Instruction)?
|
boolean |
isPureCall()
Is the instruction a pure call (one kind of interprocedural branch)?
|
boolean |
isRelease()
Is the instruction a release (monitorexit/unlock)?
|
boolean |
isReturn()
Is the instruction a return (interprocedural branch)?
|
boolean |
isThrow()
Is the instruction a throw of a Java exception?
|
boolean |
isTSPoint()
Is the instruction a potential thread switch point?
|
boolean |
isTwoWayBranch()
Is this instruction a branch that has that has only two possible
successors?
|
boolean |
isUnconditionalBranch()
Is the instruction an unconditional intraprocedural branch?
|
boolean |
isUnconditionalCall()
Is the instruction an unconditional call?
|
boolean |
isYieldPoint()
Is the instruction a yield point?
|
(package private) void |
linkWithNext(Instruction other)
For IR internal use only; general clients should always use higer level
mutation functions.
|
void |
markAsGCPoint()
NOTE: ONLY FOR USE ON MIR INSTRUCTIONS!!!!
|
void |
markAsNonGCPoint()
NOTE: ONLY FOR USE ON MIR INSTRUCTIONS!!!!
|
void |
markAsNonPEI()
Record that this instruction is not a PEI.
|
void |
markAsNonPEINonGCPoint()
NOTE: ONLY FOR USE ON MIR INSTRUCTIONS!!!!
|
void |
markAsPEI()
NOTE: ONLY FOR USE ON MIR INSTRUCTIONS!!!!
|
boolean |
mayBeVolatileFieldLoad()
Might this instruction be a load from a field that is declared
to be volatile?
|
Instruction |
nextInstructionInCodeOrder()
Return the next instruction with respect to the current
code linearization order.
|
Operator |
operator()
Return the instruction's operator.
|
private Operand |
outOfLineCopy(Operand op) |
Instruction |
prevInstructionInCodeOrder()
Return the previous instruction with respect to the current
code linearization order.
|
void |
putOperand(int i,
Operand op)
NOTE: It is incorrect to use putOperand with a constant argument
outside of the automatically generated code in Operators.
|
Instruction |
remove()
Removal: Remove this from the instruction stream.
|
void |
replace(Instruction newInstr)
Replacement: Replace this with newInstr.
|
void |
replaceOperand(Operand oldOp,
Operand newOp)
Replace all occurances of the first operand with the second.
|
void |
replaceRegister(Register r,
Register n)
Replace all occurances of register r with register n
|
void |
replaceSimilarOperands(Operand oldOp,
Operand newOp)
Replace any operands that are similar to the first operand
with a copy of the second operand.
|
void |
resizeNumberOfOperands(int newSize)
Enlarge the number of operands in this instruction, if necessary.
|
void |
setBranchProbability(float takenProbability)
Record the probability (in the range 0.0 - 1.0) that this two-way
branch instruction is taken (as opposed to falling through).
|
void |
setBytecodeIndex(int bci)
Set the
bytecode index of the instruction. |
(package private) void |
setNext(Instruction n)
For IR internal use only; general clients should always use higer level
mutation functions.
|
(package private) void |
setPrev(Instruction p)
For IR internal use only; general clients should always use higer level
mutation functions.
|
boolean |
similar(Instruction similarInstr)
Are two instructions similar, i.e. having the same operator and
the same number of similar operands?
|
String |
toString()
Returns the string representation of this instruction
(mainly intended for use when printing the IR).
|
private static final byte OI_INVALID
operatorInfo
.
NB: OI_INVALID must be default value!private static final byte OI_PEI_VALID
operatorInfo
.private static final byte OI_PEI
operatorInfo
.private static final byte OI_GC_VALID
operatorInfo
.private static final byte OI_GC
operatorInfo
.public int bcIndex
position
, the bcIndex field
uniquely identifies the source position of the bytecode that
this instruction came from.public InlineSequence position
In combination with the bcIndex
, the position field
uniquely identifies the source position of the bytecode that
this instruction came from.
A single position operator can be shared by many instruction objects.
InlineSequence
,
OptEncodedCallSiteTree
private Operator operator
The same operator object can be shared by many instruction objects.
private Instruction next
null
if no such instruction exists.private Instruction prev
null
if no such instruction exists.private byte operatorInfo
Operator
private Instruction(Operator op, int size)
public static Instruction create(Operator op, int size)
For internal use only -- general clients MUST use the appropriate InstructionFormat class's create and mutate methods to create instruction objects!!!
op
- operatorsize
- number of operandspublic Instruction copyWithoutLinks()
public String toString()
public Instruction nextInstructionInCodeOrder()
null
if no such instruction existspublic Instruction prevInstructionInCodeOrder()
null
if no such instruction existspublic boolean hasPrev()
public BasicBlock getBasicBlock()
Note: this instruction takes O(1) time for LABEL and BBEND instructions, but will take O(# of instrs in the block) for all other instructions. Therefore, although it can be used on any instruction, care must be taken when using it to avoid doing silly O(N^2) work for what could be done in O(N) work.
public void copyPosition(Instruction source)
bcIndex
,
position
) for this instruction to be the same as the
source instruction's source position description.source
- the instruction to copy the source position frompublic int getBytecodeIndex()
bytecode index
of the instruction.public void setBytecodeIndex(int bci)
bytecode index
of the instruction.bci
- the new bytecode indexpublic void changeOperatorTo(Operator newlySetOperator)
public char getOpcode()
Operator.opcode
.public int getNumberOfOperands()
private int getNumberOfOperandsVarUsesOrDefs()
public int getNumberOfDefs()
By convention, operands are ordered in instructions such that all defs are first, followed by all combined defs/uses, followed by all pure uses. Note that this may change in the future.
public int getNumberOfPureDefs()
By convention, operands are ordered in instructions such that all defs are first, followed by all combined defs/uses, followed by all pure uses. Note that this may change in the future.
public int getNumberOfPureUses()
By convention, operands are ordered in instructions such that all defs are first, followed by all combined defs/uses, followed by all pure uses. Note that this may change in the future.
public int getNumberOfUses()
By convention, operands are ordered in instructions such that all defs are first, followed by all combined defs/uses, followed by all pure uses. Note that this may change in the future.
public void replaceOperand(Operand oldOp, Operand newOp)
oldOp
- The operand to replacenewOp
- The new one to replace it withpublic void replaceSimilarOperands(Operand oldOp, Operand newOp)
oldOp
- The operand whose similar operands should be replacednewOp
- The new one to replace it withpublic void replaceRegister(Register r, Register n)
r
- the old registern
- the new registerpublic boolean hasMemoryOperand()
true
if this instruction holds any memory or
stack location operandspublic Enumeration<Operand> getOperands()
NOTE: DOES NOT RETURN MEMORY OPERANDS, ONLY THEIR CONTAINED OPERANDS!!!!!
public Enumeration<Operand> getMemoryOperands()
public Enumeration<Operand> getRootOperands()
public Enumeration<Operand> getDefs()
public Enumeration<Operand> getPureDefs()
public Enumeration<Operand> getPureUses()
public Enumeration<Operand> getDefUses()
public Enumeration<Operand> getUses()
public Enumeration<Operand> getRootUses()
public boolean isMove()
true
if the instruction is a simple move
or false
if it is not.public boolean isBranch()
true
if the instruction is am
intraprocedural branch or false
if it is not.public boolean isConditionalBranch()
true
if the instruction is a conditional
intraprocedural branch or false
if it is not.public boolean isTwoWayBranch()
true
if the instruction is an
interprocedural conditional branch with only two possible
outcomes (taken or not taken).public boolean isUnconditionalBranch()
true
if the instruction is an unconditional
intraprocedural branch or false
if it is not.public boolean isDirectBranch()
true
if the instruction is a direct
intraprocedural branch or false
if it is not.public boolean isIndirectBranch()
true
if the instruction is an indirect
interprocedural branch or false
if it is not.public boolean isCall()
true
if the instruction is a call
or false
if it is not.public boolean isPureCall()
true
if the instruction is a pure call
or false
if it is not.public boolean isNonPureCall()
true
if the instruction is a nonpure call
or false
if it is not.public boolean isConditionalCall()
true
if the instruction is a
conditional call or false
if it is not.public boolean isUnconditionalCall()
true
if the instruction is an unconditional
call or false
if it is not.public boolean isDirectCalll()
true
if the instruction is a direct call
or false
if it is not.public boolean isIndirectCall()
true
if the instruction is an indirect call
or false
if it is not.public boolean isExplicitLoad()
true
if the instruction is an explicit load
or false
if it is not.public boolean isImplicitLoad()
true
if the instruction is an implicit load
or false
if it is not.public boolean isExplicitStore()
true
if the instruction is an explicit store
or false
if it is not.public boolean isImplicitStore()
true
if the instruction is an implicit store
or false
if it is not.public boolean isThrow()
true
if the instruction is a throw
or false
if it is not.public boolean isPEI()
true
if the instruction is a PEI
or false
if it is not.public boolean isMarkedAsPEI()
true
if the instruction is explicitly marked as a PEI
or false
if it is not.public boolean isGCPoint()
true
if the instruction is a potential
GC point or false
if it is not.public boolean isTSPoint()
true
if the instruction is a potential
thread switch point or false
if it is not.public boolean isCompare()
true
if the instruction is a compare
or false
if it is not.public boolean isAllocation()
true
if the instruction is an allocation
or false
if it is not.public boolean isReturn()
true
if the instruction is a return
or false
if it is not.public boolean isAcquire()
true
if the instruction is an acquire
or false
if it is not.public boolean isRelease()
true
if the instruction is a release
or false
if it is not.public boolean isDynamicLinkingPoint()
true
if the instruction is a dynamic linking point
or false
if it is not.public boolean isYieldPoint()
true
if the instruction is a yield point
or false
if it is not.public void markAsNonPEI()
private char getMIR_START_opcode()
public void markAsPEI()
public void markAsNonGCPoint()
public void markAsGCPoint()
public void markAsNonPEINonGCPoint()
public float getBranchProbability()
public void setBranchProbability(float takenProbability)
takenProbability
- The probability that the branch is taken.public void flipBranchProbability()
public BasicBlock getBranchTarget()
public Enumeration<BasicBlock> getBranchTargets()
public boolean isBbFirst()
true
if this instruction is the first instruction in a
basic block. By convention (construction) every basic block starts
with a label instruction and a label instruction only appears at
the start of a basic blocktrue
if the instruction is the first instruction
in its basic block or false
if it is not.public boolean isBbLast()
true
if this instruction is the last instruction in a
basic block. By convention (construction) every basic block ends
with a BBEND instruction and a BBEND instruction only appears at the
end of a basic blocktrue
if the instruction is the last instruction
in its basic block or false
if it is not.public boolean isBbInside()
true
if the instruction is expected to appear
on the inside (not first or last) of its basic block
or false
if it is expected to be a first/last
instruction.public void insertAfter(Instruction newInstr)
newInstr
- the instruction to insert, must not be in an
instruction list already.public void insertBefore(Instruction newInstr)
newInstr
- the instruction to insert, must not be in
an instruction list already.public void replace(Instruction newInstr)
newInstr
- the replacement instruction must not be in an
instruction list already and must not be a
LABEL or BBEND instruction.public Instruction remove()
NOTE: We allow the removal of branch instructions, but don't update the CFG data structure.....right now we just assume the caller knows what they are doing and takes care of it.
NB: execution of this method nulls out the prev & next fields of this
private void isLinked()
private void isBackwardLinked()
private void isForwardLinked()
private void isNotLinked()
public Operand getOperand(int i)
i
- which operand to returnpublic Operand getClearOperand(int i)
i
- which operand to returnpublic void putOperand(int i, Operand op)
i
- which operand to setop
- the operand to set it toprivate Operand outOfLineCopy(Operand op)
public void resizeNumberOfOperands(int newSize)
newSize
- the new minimum number of operands.Instruction getNext()
nextInstructionInCodeOrder()
.next
void setNext(Instruction n)
next
field of the instruction.n
- the new value for nextInstruction getPrev()
prevInstructionInCodeOrder()
.prev
void setPrev(Instruction p)
prev
field of the instruction.p
- the new value for prevvoid clearLinks()
public boolean similar(Instruction similarInstr)
similarInstr
- instruction to compare againstvoid linkWithNext(Instruction other)
next
field to
point to other and other's prev
field to point to this.other
- the instruction to link with.public void BURS_backdoor_linkWithNext(Instruction other)
other
- the next instructionpublic boolean mayBeVolatileFieldLoad()
true
if the instruction might be a load
from a volatile field or false
if it
cannot be a load from a volatile field