use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class DeadCodeRemover method pruneDeadInstructions.
/**
* Removes all instructions from every unreachable block.
*/
private void pruneDeadInstructions() {
HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>();
ssaMeth.computeReachability();
for (SsaBasicBlock block : ssaMeth.getBlocks()) {
if (block.isReachable())
continue;
// Prune instructions from unreachable blocks
for (int i = 0; i < block.getInsns().size(); i++) {
SsaInsn insn = block.getInsns().get(i);
RegisterSpecList sources = insn.getSources();
int sourcesSize = sources.size();
// Delete this instruction completely if it has sources
if (sourcesSize != 0) {
deletedInsns.add(insn);
}
// Delete this instruction from all usage lists.
for (int j = 0; j < sourcesSize; j++) {
RegisterSpec source = sources.get(j);
useList[source.getReg()].remove(insn);
}
// Remove this instruction result from the sources of any phis
RegisterSpec result = insn.getResult();
if (result == null)
continue;
for (SsaInsn use : useList[result.getReg()]) {
if (use instanceof PhiInsn) {
PhiInsn phiUse = (PhiInsn) use;
phiUse.removePhiRegister(result);
}
}
}
}
ssaMeth.deleteInsns(deletedInsns);
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class EscapeAnalysis method processMoveResultPseudoInsn.
/**
* Determine the origin of a move result pseudo instruction that generates
* an object. Creates a new EscapeSet for the new object accordingly.
*
* @param insn {@code non-null;} move result pseudo instruction to process
* @return {@code non-null;} an EscapeSet for the object referred to by the
* move result pseudo instruction
*/
private EscapeSet processMoveResultPseudoInsn(SsaInsn insn) {
RegisterSpec result = insn.getResult();
SsaInsn prevSsaInsn = getInsnForMove(insn);
int prevOpcode = prevSsaInsn.getOpcode().getOpcode();
EscapeSet escSet;
RegisterSpec prevSource;
switch(prevOpcode) {
// New instance / Constant
case RegOps.NEW_INSTANCE:
case RegOps.CONST:
escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
break;
// New array
case RegOps.NEW_ARRAY:
case RegOps.FILLED_NEW_ARRAY:
prevSource = prevSsaInsn.getSources().get(0);
if (prevSource.getTypeBearer().isConstant()) {
// New fixed array
escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
escSet.replaceableArray = true;
} else {
// New variable array
escSet = new EscapeSet(result.getReg(), regCount, EscapeState.GLOBAL);
}
break;
// Loading a static object
case RegOps.GET_STATIC:
escSet = new EscapeSet(result.getReg(), regCount, EscapeState.GLOBAL);
break;
// Type cast / load an object from a field or array
case RegOps.CHECK_CAST:
case RegOps.GET_FIELD:
case RegOps.AGET:
prevSource = prevSsaInsn.getSources().get(0);
int setIndex = findSetIndex(prevSource);
// Set should already exist, try to find it
if (setIndex != latticeValues.size()) {
escSet = latticeValues.get(setIndex);
escSet.regSet.set(result.getReg());
return escSet;
}
// Set not found, must be either null or unknown
if (prevSource.getType() == Type.KNOWN_NULL) {
escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
} else {
escSet = new EscapeSet(result.getReg(), regCount, EscapeState.GLOBAL);
}
break;
default:
return null;
}
// Add the newly created escSet to the lattice and return it
latticeValues.add(escSet);
return escSet;
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class EscapeAnalysis method processInsn.
/**
* Process a single instruction, looking for new objects resulting from
* move result or move param.
*
* @param insn {@code non-null;} instruction to process
*/
private void processInsn(SsaInsn insn) {
int op = insn.getOpcode().getOpcode();
RegisterSpec result = insn.getResult();
EscapeSet escSet;
// Identify new objects
if (op == RegOps.MOVE_RESULT_PSEUDO && result.getTypeBearer().getBasicType() == Type.BT_OBJECT) {
// Handle objects generated through move_result_pseudo
escSet = processMoveResultPseudoInsn(insn);
processRegister(result, escSet);
} else if (op == RegOps.MOVE_PARAM && result.getTypeBearer().getBasicType() == Type.BT_OBJECT) {
// Track method arguments that are objects
escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
latticeValues.add(escSet);
processRegister(result, escSet);
} else if (op == RegOps.MOVE_RESULT && result.getTypeBearer().getBasicType() == Type.BT_OBJECT) {
// Track method return values that are objects
escSet = new EscapeSet(result.getReg(), regCount, EscapeState.NONE);
latticeValues.add(escSet);
processRegister(result, escSet);
}
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
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.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class ConstCollector method updateConstUses.
/**
* Updates all uses of various consts to use the values in the newly
* assigned registers.
*
* @param newRegs {@code non-null;} mapping between constant and new reg
* @param origRegCount {@code >=0;} original SSA reg count, not including
* newly added constant regs
*/
private void updateConstUses(HashMap<TypedConstant, RegisterSpec> newRegs, int origRegCount) {
/*
* set of constants associated with a local variable; used
* only if COLLECT_ONE_LOCAL is true.
*/
final HashSet<TypedConstant> usedByLocal = new HashSet<TypedConstant>();
final ArrayList<SsaInsn>[] useList = ssaMeth.getUseListCopy();
for (int i = 0; i < origRegCount; i++) {
SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
if (insn == null) {
continue;
}
final RegisterSpec origReg = insn.getResult();
TypeBearer typeBearer = insn.getResult().getTypeBearer();
if (!typeBearer.isConstant())
continue;
TypedConstant cst = (TypedConstant) typeBearer;
final RegisterSpec newReg = newRegs.get(cst);
if (newReg == null) {
continue;
}
if (ssaMeth.isRegALocal(origReg)) {
if (!COLLECT_ONE_LOCAL) {
continue;
} else {
/*
* TODO: If the same local gets the same cst
* multiple times, it would be nice to reuse the
* register.
*/
if (usedByLocal.contains(cst)) {
continue;
} else {
usedByLocal.add(cst);
fixLocalAssignment(origReg, newRegs.get(cst));
}
}
}
// maps an original const register to the new collected register
RegisterMapper mapper = new RegisterMapper() {
@Override
public int getNewRegisterCount() {
return ssaMeth.getRegCount();
}
@Override
public RegisterSpec map(RegisterSpec registerSpec) {
if (registerSpec.getReg() == origReg.getReg()) {
return newReg.withLocalItem(registerSpec.getLocalItem());
}
return registerSpec;
}
};
for (SsaInsn use : useList[origReg.getReg()]) {
if (use.canThrow() && use.getBlock().getSuccessors().cardinality() > 1) {
continue;
}
use.mapSourceRegisters(mapper);
}
}
}
Aggregations