public abstract class GenericStackManager extends IRTools
Modifier and Type | Class and Description |
---|---|
protected static class |
GenericStackManager.ScratchRegister
Class to represent a physical register currently allocated as a
scratch register.
|
Modifier and Type | Field and Description |
---|---|
private ActiveSet |
activeSet
We may rely on information from linear scan to choose scratch registers.
|
protected boolean |
allocFrame |
private int |
caughtExceptionOffset
Memory location (4 bytes) to be used for caughtExceptions
|
static byte |
CONDITION_VALUE |
private int |
conversionOffset
Memory location (8 bytes) to be used for type conversions
|
protected static boolean |
DEBUG |
static byte |
DOUBLE_VALUE |
static byte |
FLOAT_VALUE |
private boolean |
frameRequired
Have we decided that a stack frame is required for this method?
|
protected int |
frameSize |
static byte |
INT_VALUE |
protected IR |
ir |
protected int[] |
nonVolatileFPRLocation |
protected int[] |
nonVolatileGPRLocation
An array which holds the spill location number used to stash nonvolatile
registers.
|
protected GenericRegisterPreferences |
pref
Object holding register preferences
|
private boolean |
prologueYieldpoint
Is there a prologue yieldpoint in this method?
|
protected RegisterAllocatorState |
regAllocState |
protected GenericRegisterRestrictions |
restrict
Object holding register restrictions
|
protected int[] |
saveVolatileFPRLocation |
protected int[] |
saveVolatileGPRLocation
An array which holds the spill location number used to stash volatile
registers in the SaveVolatile protocol.
|
protected ArrayList<GenericStackManager.ScratchRegister> |
scratchInUse
For each physical register, holds a ScratchRegister which records
the current scratch assignment for the physical register.
|
protected ScratchMap |
scratchMap
An object used to track adjustments to the GC maps induced by scratch
registers
|
protected int |
spillPointer
Spill pointer (in bytes) relative to the beginning of the
stack frame (starts after the header).
|
private int |
sysCallOffset
We will have to save and restore all non-volatile registers around
system calls, to protect ourselve from malicious native code that may
bash these registers.
|
private static boolean |
USE_LINEAR_SCAN
Should we use information from linear scan in choosing scratch
registers?
|
protected static boolean |
VERBOSE |
protected static boolean |
VERBOSE_DEBUG |
protected static int |
WORDSIZE
Size of a word, in bytes
|
Constructor and Description |
---|
GenericStackManager() |
Modifier and Type | Method and Description |
---|---|
protected static int |
align(int number,
int alignment) |
abstract int |
allocateNewSpillLocation(int type)
Allocates a new spill location and grows the
frame size to reflect the new layout.
|
Register |
allocateNonVolatileRegister(Register symbReg)
Find a nonvolatile register to allocate starting at the reg corresponding
to the symbolic register passed.
|
int |
allocateOnStackFrame(int size)
Allocates the specified number of bytes in the stackframe,
returning the offset to the start of the allocated space.
|
void |
allocateParameterSpace(int s)
Ensure that there's enough space for passing parameters.
|
int |
allocateSpaceForCaughtException()
We encountered a catch block that actually uses its caught
exception object; allocate a stack slot for the exception delivery
code to use to pass the exception object to us.
|
int |
allocateSpaceForConversion()
We encountered a float/int conversion that uses
the stack as temporary storage.
|
int |
allocateSpaceForSysCall(int n)
We will have to save and restore all non-volatile registers around
system calls, to protect ourselves from malicious native code that may
bash these registers.
|
Register |
allocateVolatileRegister(Register symbReg)
Find an volatile register to allocate starting at the reg corresponding
to the symbolic register passed
|
private boolean |
appearsIn(Register r,
Instruction s) |
abstract void |
cleanUpAndInsertEpilogue()
Cleans up some junk that's left in the IR after register allocation,
and adds epilogue code.
|
abstract void |
computeNonVolatileArea()
Computes the number of stack words needed to hold nonvolatile
registers.
|
void |
computeRestrictions(IR ir)
Sets up register restrictions.
|
private GenericStackManager.ScratchRegister |
createScratchBefore(RegisterAllocatorState regAllocState,
Instruction s,
Register r,
Register symb)
Make physicals register r available to be used as a scratch register
before instruction s.
|
private boolean |
definesSpillLocation(int loc,
Instruction s) |
private boolean |
definesSpillLocation(Register r,
Instruction s) |
void |
forceFrameAllocation()
We encountered a magic (get/set framepointer) that is going to force
us to actually create the stack frame.
|
protected boolean |
frameIsRequired() |
private GenericStackManager.ScratchRegister |
getCurrentScratchRegister(Register r,
Instruction s)
If there is a scratch register available which currently holds the
value of symbolic register r, then return that scratch register.
|
private GenericStackManager.ScratchRegister |
getFirstAvailableScratchRegister(Register r,
Instruction s)
Finds the first available register which can serve as a scratch
register for symbolic register r in instruction s.
|
private Register |
getFirstDeadFPRNotUsedIn(Register r,
Instruction s,
ArrayList<Register> reserved)
Return a FPR that does not appear in instruction s, and is dead
before instruction s, to hold symbolic register r.
|
private Register |
getFirstDeadGPRNotUsedIn(Register r,
Instruction s,
ArrayList<Register> reserved)
Return a GPR that does not appear in instruction s, and is dead
before instruction s, to hold symbolic register r.
|
private Register |
getFirstFPRNotUsedIn(Register r,
Instruction s,
ArrayList<Register> reserved)
Returns a FPR that does not appear in instruction s, to be used as a
scratch register to hold register r.
|
private Register |
getFirstGPRNotUsedIn(Register r,
Instruction s,
ArrayList<Register> reserved)
Return a GPR that does not appear in instruction s, to hold symbolic
register r.
|
abstract int |
getFrameFixedSize()
Returns the size of the fixed portion of the stack.
|
protected int |
getNonvolatileFPROffset(int n) |
protected int |
getNonvolatileGPROffset(int n) |
int |
getOffsetForSysCall()
We will have to save and restore all non-volatile registers around
system calls, to protect ourselves from malicious native code that may
bash these registers.
|
private GenericStackManager.ScratchRegister |
getPhysicalScratchRegister(Register r) |
(package private) GenericRegisterPreferences |
getPreferences() |
private ArrayList<Register> |
getReservedScratchRegisters(Instruction s) |
(package private) GenericRegisterRestrictions |
getRestrictions() |
(package private) ScratchMap |
getScratchMap() |
private GenericStackManager.ScratchRegister |
getScratchRegister(Register symb,
Instruction s,
boolean beCheap)
Gets a scratch register to hold symbolic register symb in instruction
s.
|
private GenericStackManager.ScratchRegister |
getScratchRegisterUsingIntervals(Register r,
Instruction s)
Finds a register which can serve as a scratch
register for symbolic register r in instruction s.
|
byte |
getValueType(Register r)
Given a symbolic register, return a code that indicates the type
of the value stored in the register.
|
protected boolean |
hasPrologueYieldpoint() |
private GenericStackManager.ScratchRegister |
holdInScratchAfter(Instruction s,
Register symb,
boolean beCheap)
Inserts code as needed so that after instruction s, the value of
a symbolic register will be held in a particular scratch physical
register.
|
abstract void |
initForArch(IR ir)
Perform some architecture-specific initialization.
|
abstract void |
insertNormalPrologue()
Inserts the prologue for a normal method.
|
private void |
insertPrologue() |
void |
insertPrologueAndEpilogue()
PROLOGUE/EPILOGUE.
|
void |
insertSpillAfter(Instruction s,
Register r,
byte type,
int location)
Insert a spill of a physical register after instruction s.
|
abstract void |
insertSpillBefore(Instruction s,
Register r,
byte type,
int location)
Insert a spill of a physical register before instruction s.
|
void |
insertSpillCode()
After register allocation, go back through the IR and insert
compensating code to deal with spills.
|
void |
insertSpillCode(ActiveSet set)
After register allocation, go back through the IR and insert
compensating code to deal with spills.
|
void |
insertUnspillAfter(Instruction s,
Register r,
byte type,
int location)
Insert a load of a physical register from a spill location before
instruction s.
|
abstract void |
insertUnspillBefore(Instruction s,
Register r,
byte type,
int location)
Insert a load of a physical register from a spill location before
instruction s.
|
boolean |
isDeadBefore(Register r,
Instruction s) |
protected boolean |
isLegal(Register symb,
Register phys,
Instruction s) |
private boolean |
isPEIWithCatch(Instruction s,
BasicBlock instructionsBB) |
abstract boolean |
isSysCall(Instruction s) |
private void |
markDirtyScratchRegisters(Instruction s)
Walk over the currently available scratch registers.
|
private GenericStackManager.ScratchRegister |
moveToScratchBefore(Instruction s,
Register symb,
boolean beCheap)
Assigns symbolic register symb to a physical register, and inserts code
before instruction s to load the register from the appropriate stack
location.
|
abstract boolean |
needScratch(Register r,
Instruction s)
Given symbolic register r in instruction s, do we need to ensure that
r is in a scratch register is s (as opposed to a memory operand)
|
void |
prepare(IR ir)
Called as part of the register allocator startup.
|
protected void |
reloadScratchRegisterBefore(Instruction s,
GenericStackManager.ScratchRegister scratch)
Restores the contents of a scratch register before instruction s if
necessary.
|
abstract void |
replaceOperandWithSpillLocation(Instruction s,
RegisterOperand symb)
In instruction s, replace all appearances of a symbolic register
operand with uses of the appropriate spill location, as cached by the
register allocator.
|
private void |
replaceRegisterWithScratch(Instruction s,
Register r1,
Register r2)
Replaces all occurrences of register r1 in an instruction with register
r2.
|
private void |
restoreAllScratchRegistersBefore(Instruction s)
Walk over the currently available scratch registers, and spill their
contents to memory before instruction s.
|
abstract void |
restoreScratchRegistersBefore(Instruction s)
Walk over the currently available scratch registers.
|
protected void |
setFrameRequired()
Records that we need a stack frame for this method.
|
private Register |
spillLocationUse(int loc,
Instruction s)
Assuming instruction s uses the spill location loc,
return the symbolic register that embodies that use.
|
private Register |
spillLocationUse(Register r,
Instruction s) |
protected void |
unloadScratchRegisterBefore(Instruction s,
GenericStackManager.ScratchRegister scratch)
Spills the contents of a scratch register to memory before
instruction s.
|
private boolean |
usesSpillLocation(int loc,
Instruction s) |
private boolean |
usesSpillLocation(Register r,
Instruction s) |
A, AC, AC, CPOS, CR, D, DC, defDoublesAsUse, definedIn, F, FC, getCondMoveOp, getDefaultOperand, getLoadOp, getLoadOp, getMoveOp, getStoreOp, getStoreOp, I, IC, insertInstructionsAfter, L, LC, makeBlockOnEdge, mayBeVolatileFieldLoad, moveInstruction, moveIntoRegister, moveIntoRegister, nonPEIGC, offsetOperand, TG, usedIn, useDoublesAsDef
public static final byte INT_VALUE
public static final byte DOUBLE_VALUE
public static final byte FLOAT_VALUE
public static final byte CONDITION_VALUE
protected static final boolean DEBUG
protected static final boolean VERBOSE
protected static final boolean VERBOSE_DEBUG
protected static final int WORDSIZE
protected RegisterAllocatorState regAllocState
protected int frameSize
protected boolean allocFrame
protected final GenericRegisterPreferences pref
protected GenericRegisterRestrictions restrict
protected int spillPointer
private boolean frameRequired
private int conversionOffset
private int caughtExceptionOffset
private boolean prologueYieldpoint
private int sysCallOffset
protected final ArrayList<GenericStackManager.ScratchRegister> scratchInUse
protected final int[] nonVolatileGPRLocation
protected final int[] nonVolatileFPRLocation
protected final int[] saveVolatileGPRLocation
protected final int[] saveVolatileFPRLocation
protected ScratchMap scratchMap
private static boolean USE_LINEAR_SCAN
public GenericStackManager()
GenericRegisterPreferences getPreferences()
GenericRegisterRestrictions getRestrictions()
ScratchMap getScratchMap()
public abstract void initForArch(IR ir)
ir
- the IRpublic abstract boolean isSysCall(Instruction s)
s
- the instruction to checkpublic abstract boolean needScratch(Register r, Instruction s)
r
- the symbolic registers
- the instruction that has an occurrence of the registertrue
if the symbolic register needs to be a scratch
registerpublic abstract int allocateNewSpillLocation(int type)
type
- the type to spillpublic abstract void cleanUpAndInsertEpilogue()
public abstract int getFrameFixedSize()
public abstract void computeNonVolatileArea()
frameSize
field of this object
frameRequired
field of this object
public abstract void insertNormalPrologue()
public abstract void restoreScratchRegistersBefore(Instruction s)
For any scratch register r which is def'ed by instruction s, spill r before s and remove r from the pool of available scratch registers.
For any scratch register r which is used by instruction s, restore r before s and remove r from the pool of available scratch registers.
For any scratch register r which has current contents symb, and symb is spilled to location M, and s defs M: the old value of symb is dead. Mark this.
Invalidate any scratch register assignments that are illegal in s.
s
- the instruction to processpublic abstract void replaceOperandWithSpillLocation(Instruction s, RegisterOperand symb)
s
- the instruction to mutate.symb
- the symbolic register operand to replaceprivate void replaceRegisterWithScratch(Instruction s, Register r1, Register r2)
s
- instruction to processr1
- register to replacer2
- the replacement registerpublic int allocateSpaceForSysCall(int n)
n
- the number of GPR registers to save and restore.public int getOffsetForSysCall()
protected void unloadScratchRegisterBefore(Instruction s, GenericStackManager.ScratchRegister scratch)
scratch
- the scratch register to spills
- the instruction before which the spill needs to occurprotected void reloadScratchRegisterBefore(Instruction s, GenericStackManager.ScratchRegister scratch)
scratch
- the scratch register whose contents may need to be restoreds
- the instruction before which the restores needs to occurprivate ArrayList<Register> getReservedScratchRegisters(Instruction s)
s
- the instruction whose reserved scratch registers are of interestnull
)private GenericStackManager.ScratchRegister getCurrentScratchRegister(Register r, Instruction s)
Additionally, if there is a scratch register available which is mapped to the same stack location as r, then return that scratch register.
Else return null
.
r
- the symbolic register to holds
- the instruction for which we need r in a registernull
private GenericStackManager.ScratchRegister getPhysicalScratchRegister(Register r)
r
- the register to checknull
otherwiseprivate void markDirtyScratchRegisters(Instruction s)
For any register which is dirty, note this in the scratch map for instruction s.
s
- the instruction which needs an update in the scratch mapprivate void restoreAllScratchRegistersBefore(Instruction s)
SPECIAL CASE: If s is a return instruction, only restore the scratch registers that are used by s. The others are dead.
s
- the instruction before which the scratch registers need to be
restoredpublic boolean isDeadBefore(Register r, Instruction s)
r
- the registers
- the instructiontrue
if the register is dead immediately before
the instructionprivate GenericStackManager.ScratchRegister holdInScratchAfter(Instruction s, Register symb, boolean beCheap)
s
- the instruction after which the value will be held in scratchsymb
- the register whose value needs to be held in scratchbeCheap
- don't expend much effort optimizing scratch
assignmentsprotected boolean isLegal(Register symb, Register phys, Instruction s)
symb
- the symbolic register that we want to assignphys
- the scratch registers
- the instruction where the assignment would take placeprivate GenericStackManager.ScratchRegister getScratchRegister(Register symb, Instruction s, boolean beCheap)
symb
- the symbolic register to holds
- the instruction where the scratch register is neededbeCheap
- don't expend too much effortnull
private GenericStackManager.ScratchRegister getScratchRegisterUsingIntervals(Register r, Instruction s)
Inserts spills if necessary to ensure that the returned scratch register is free for use.
r
- the symbolic register that needs a scratchs
- the instruction where the scratch register is needednull
private GenericStackManager.ScratchRegister getFirstAvailableScratchRegister(Register r, Instruction s)
Inserts spills if necessary to ensure that the returned scratch register is free for use.
r
- the symbolic register that needs a scratchs
- the instruction where the scratch register is needednull
private GenericStackManager.ScratchRegister moveToScratchBefore(Instruction s, Register symb, boolean beCheap)
s
- the instruction before which the register needs to be loadedsymb
- the symbolic register to be assigned to a scratchbeCheap
- don't expend to much effort to optimize scratch
assignmentsprivate GenericStackManager.ScratchRegister createScratchBefore(RegisterAllocatorState regAllocState, Instruction s, Register r, Register symb)
regAllocState
- TODOs
- the instruction before which the scratch register will be createdr
- the physical register to be used as scratchsymb
- the symbolic register which needs a scratch registerprivate boolean usesSpillLocation(Register r, Instruction s)
private Register spillLocationUse(Register r, Instruction s)
private boolean definesSpillLocation(Register r, Instruction s)
private boolean definesSpillLocation(int loc, Instruction s)
private boolean usesSpillLocation(int loc, Instruction s)
private Register spillLocationUse(int loc, Instruction s)
Note that at most one such register can be used, since at most one live register can use a given spill location.
s
- instruction to checkloc
- spill locationprivate Register getFirstFPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved)
r
- the register that needs a scratch registers
- the instruction for which the scratch register is neededreserved
- the registers that must not be usedOptimizingCompilerException
- if no free FPR was foundprivate Register getFirstDeadFPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved)
r
- the register that needs a scratch registers
- the instruction for which the scratch register is neededreserved
- the registers that must not be usednull
if no register found, a dead and unused FPR otherwiseprivate Register getFirstGPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved)
r
- the register that needs a scratch registers
- the instruction for which the scratch register is neededreserved
- the registers that must not be usedprivate Register getFirstDeadGPRNotUsedIn(Register r, Instruction s, ArrayList<Register> reserved)
r
- the register that needs a scratch registers
- the instruction for which the scratch register is neededreserved
- the registers that must not be usednull
if no register found, a dead and unused GPR otherwiseprivate boolean appearsIn(Register r, Instruction s)
private boolean isPEIWithCatch(Instruction s, BasicBlock instructionsBB)
s
- the instruction to checkinstructionsBB
- the block that contains the instructionprotected int getNonvolatileGPROffset(int n)
n
- number of the non-volatile GPRprotected int getNonvolatileFPROffset(int n)
n
- number of the non-volatile FPRpublic final void insertPrologueAndEpilogue()
private void insertPrologue()
public void insertSpillCode()
public void insertSpillCode(ActiveSet set)
set
- information from linear scan analysis (may be null
)public abstract void insertSpillBefore(Instruction s, Register r, byte type, int location)
s
- the instruction before which the spill should occurr
- the register (should be physical) to spilltype
- one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
CONDITION_VALUElocation
- the spill locationpublic final void insertSpillAfter(Instruction s, Register r, byte type, int location)
s
- the instruction after which the spill should occurr
- the register (should be physical) to spilltype
- one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
CONDITION_VALUElocation
- the spill locationpublic abstract void insertUnspillBefore(Instruction s, Register r, byte type, int location)
s
- the instruction before which the spill should occurr
- the register (should be physical) to spilltype
- one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
CONDITION_VALUElocation
- the spill locationpublic final void insertUnspillAfter(Instruction s, Register r, byte type, int location)
s
- the instruction before which the spill should occurr
- the register (should be physical) to spilltype
- one of INT_VALUE, FLOAT_VALUE, DOUBLE_VALUE, or
CONDITION_VALUElocation
- the spill locationprotected boolean frameIsRequired()
true
if and only if a stack frame
must be allocated for this method
lprotected void setFrameRequired()
protected boolean hasPrologueYieldpoint()
true
if and only if this IR has a prologue yieldpointpublic void allocateParameterSpace(int s)
size - STACKFRAME_HEADER_SIZE
bytes.s
- space needed for parameterspublic int allocateOnStackFrame(int size)
size
- the number of bytes to allocatepublic void forceFrameAllocation()
public int allocateSpaceForConversion()
public int allocateSpaceForCaughtException()
public void prepare(IR ir)
ir
- the IRpublic final void computeRestrictions(IR ir)
ir
- the IR which will get the restrictionspublic final Register allocateVolatileRegister(Register symbReg)
symbReg
- the place to start the searchpublic final byte getValueType(Register r)
r
- a symbolic registerprotected static int align(int number, int alignment)
public final Register allocateNonVolatileRegister(Register symbReg)
TODO: Clean up this interface.
symbReg
- the place to start the search