use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class EscapeAnalysis method scalarReplacement.
/**
* Performs scalar replacement on all eligible arrays.
*/
private void scalarReplacement() {
// Iterate through lattice, looking for non-escaping replaceable arrays
for (EscapeSet escSet : latticeValues) {
if (!escSet.replaceableArray || escSet.escape != EscapeState.NONE) {
continue;
}
// Get the instructions for the definition and move of the array
int e = escSet.regSet.nextSetBit(0);
SsaInsn def = ssaMeth.getDefinitionForRegister(e);
SsaInsn prev = getInsnForMove(def);
// Create a map for the new registers that will be created
TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
int length = ((CstLiteralBits) lengthReg).getIntBits();
ArrayList<RegisterSpec> newRegs = new ArrayList<RegisterSpec>(length);
HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>();
// Replace the definition of the array with registers
replaceDef(def, prev, length, newRegs);
// Mark definition instructions for deletion
deletedInsns.add(prev);
deletedInsns.add(def);
// Go through all uses of the array
List<SsaInsn> useList = ssaMeth.getUseListForRegister(e);
for (SsaInsn use : useList) {
// Replace the use with scalars and then mark it for deletion
replaceUse(use, prev, newRegs, deletedInsns);
deletedInsns.add(use);
}
// Delete all marked instructions
ssaMeth.deleteInsns(deletedInsns);
ssaMeth.onInsnsChanged();
// Convert the method back to SSA form
SsaConverter.updateSsaMethod(ssaMeth, regCount);
// Propagate and remove extra moves added by scalar replacement
movePropagate();
}
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class EscapeAnalysis method insertExceptionThrow.
/**
* Replaces instructions that trigger an ArrayIndexOutofBounds exception
* with an actual throw of the exception.
*
* @param insn {@code non-null;} instruction causing the exception
* @param index {@code non-null;} index value that is out of bounds
* @param deletedInsns {@code non-null;} set of instructions marked for
* deletion
*/
private void insertExceptionThrow(SsaInsn insn, RegisterSpec index, HashSet<SsaInsn> deletedInsns) {
// Create a new ArrayIndexOutOfBoundsException
CstType exception = new CstType(Exceptions.TYPE_ArrayIndexOutOfBoundsException);
insertThrowingInsnBefore(insn, RegisterSpecList.EMPTY, null, RegOps.NEW_INSTANCE, exception);
// Add a successor block with a move result pseudo for the exception
SsaBasicBlock currBlock = insn.getBlock();
SsaBasicBlock newBlock = currBlock.insertNewSuccessor(currBlock.getPrimarySuccessor());
SsaInsn newInsn = newBlock.getInsns().get(0);
RegisterSpec newReg = RegisterSpec.make(ssaMeth.makeNewSsaReg(), exception);
insertPlainInsnBefore(newInsn, RegisterSpecList.EMPTY, newReg, RegOps.MOVE_RESULT_PSEUDO, null);
// Add another successor block to initialize the exception
SsaBasicBlock newBlock2 = newBlock.insertNewSuccessor(newBlock.getPrimarySuccessor());
SsaInsn newInsn2 = newBlock2.getInsns().get(0);
CstNat newNat = new CstNat(new CstString("<init>"), new CstString("(I)V"));
CstMethodRef newRef = new CstMethodRef(exception, newNat);
insertThrowingInsnBefore(newInsn2, RegisterSpecList.make(newReg, index), null, RegOps.INVOKE_DIRECT, newRef);
deletedInsns.add(newInsn2);
// Add another successor block to throw the new exception
SsaBasicBlock newBlock3 = newBlock2.insertNewSuccessor(newBlock2.getPrimarySuccessor());
SsaInsn newInsn3 = newBlock3.getInsns().get(0);
insertThrowingInsnBefore(newInsn3, RegisterSpecList.make(newReg), null, RegOps.THROW, null);
newBlock3.replaceSuccessor(newBlock3.getPrimarySuccessorIndex(), ssaMeth.getExitBlock().getIndex());
deletedInsns.add(newInsn3);
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class LocalVariableExtractor method processBlock.
/**
* Processes a single block.
*
* @param blockIndex {@code >= 0;} block index of the block to process
*/
private void processBlock(int blockIndex) {
RegisterSpecSet primaryState = resultInfo.mutableCopyOfStarts(blockIndex);
SsaBasicBlock block = blocks.get(blockIndex);
List<SsaInsn> insns = block.getInsns();
int insnSz = insns.size();
// The exit block has no insns and no successors
if (blockIndex == method.getExitBlockIndex()) {
return;
}
/*
* We may have to treat the last instruction specially: If it
* can (but doesn't always) throw, and the exception can be
* caught within the same method, then we need to use the
* state *before* executing it to be what is merged into
* exception targets.
*/
SsaInsn lastInsn = insns.get(insnSz - 1);
boolean hasExceptionHandlers = lastInsn.getOriginalRopInsn().getCatches().size() != 0;
boolean canThrowDuringLastInsn = hasExceptionHandlers && (lastInsn.getResult() != null);
int freezeSecondaryStateAt = insnSz - 1;
RegisterSpecSet secondaryState = primaryState;
for (int i = 0; i < insnSz; i++) {
if (canThrowDuringLastInsn && (i == freezeSecondaryStateAt)) {
// Until this point, primaryState == secondaryState.
primaryState.setImmutable();
primaryState = primaryState.mutableCopy();
}
SsaInsn insn = insns.get(i);
RegisterSpec result;
result = insn.getLocalAssignment();
if (result == null) {
// We may be nuking an existing local
result = insn.getResult();
if (result != null && primaryState.get(result.getReg()) != null) {
primaryState.remove(primaryState.get(result.getReg()));
}
continue;
}
result = result.withSimpleType();
RegisterSpec already = primaryState.get(result);
/*
* The equals() check ensures we only add new info if
* the instruction causes a change to the set of
* active variables.
*/
if (!result.equals(already)) {
/*
* If this insn represents a local moving from one register
* to another, remove the association between the old register
* and the local.
*/
RegisterSpec previous = primaryState.localItemToSpec(result.getLocalItem());
if (previous != null && (previous.getReg() != result.getReg())) {
primaryState.remove(previous);
}
resultInfo.addAssignment(insn, result);
primaryState.put(result);
}
}
primaryState.setImmutable();
/*
* Merge this state into the start state for each successor,
* and update the work set where required (that is, in cases
* where the start state for a block changes).
*/
IntList successors = block.getSuccessorList();
int succSz = successors.size();
int primarySuccessor = block.getPrimarySuccessorIndex();
for (int i = 0; i < succSz; i++) {
int succ = successors.get(i);
RegisterSpecSet state = (succ == primarySuccessor) ? primaryState : secondaryState;
if (resultInfo.mergeStarts(succ, state)) {
workSet.set(succ);
}
}
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class RegisterMapper method map.
/**
*
* @param sources old register set
* @return new mapped register set, or old if nothing has changed.
*/
public final RegisterSpecSet map(RegisterSpecSet sources) {
int sz = sources.getMaxSize();
RegisterSpecSet newSources = new RegisterSpecSet(getNewRegisterCount());
for (int i = 0; i < sz; i++) {
RegisterSpec registerSpec = sources.get(i);
if (registerSpec != null) {
newSources.put(map(registerSpec));
}
}
newSources.setImmutable();
// Return the old sources if nothing has changed.
return newSources.equals(sources) ? sources : newSources;
}
use of com.android.dx.rop.code.RegisterSpec in project buck by facebook.
the class SCCP method replaceConstants.
/**
* Replaces TypeBearers in source register specs with constant type
* bearers if possible. These are then referenced in later optimization
* steps.
*/
private void replaceConstants() {
for (int reg = 0; reg < regCount; reg++) {
if (latticeValues[reg] != CONSTANT) {
continue;
}
if (!(latticeConstants[reg] instanceof TypedConstant)) {
// We can't do much with these
continue;
}
SsaInsn defn = ssaMeth.getDefinitionForRegister(reg);
TypeBearer typeBearer = defn.getResult().getTypeBearer();
if (typeBearer.isConstant()) {
/*
* The definition was a constant already.
* The uses should be as well.
*/
continue;
}
// Update the destination RegisterSpec with the constant value
RegisterSpec dest = defn.getResult();
RegisterSpec newDest = dest.withType((TypedConstant) latticeConstants[reg]);
defn.setResult(newDest);
/*
* Update the sources RegisterSpec's of all non-move uses.
* These will be used in later steps.
*/
for (SsaInsn insn : ssaMeth.getUseListForRegister(reg)) {
if (insn.isPhiOrMove()) {
continue;
}
NormalSsaInsn nInsn = (NormalSsaInsn) insn;
RegisterSpecList sources = insn.getSources();
int index = sources.indexOfRegister(reg);
RegisterSpec spec = sources.get(index);
RegisterSpec newSpec = spec.withType((TypedConstant) latticeConstants[reg]);
nInsn.changeOneSource(index, newSpec);
}
}
}
Aggregations