use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class EscapeAnalysis method replaceUse.
/**
* Replaces the use for a scalar replaceable array. Gets and puts become
* move instructions, and array lengths and fills are handled. Can also
* identify ArrayIndexOutOfBounds exceptions and throw them if detected.
*
* @param use {@code non-null;} move result instruction for array
* @param prev {@code non-null;} instruction for instantiating new array
* @param newRegs {@code non-null;} mapping of array indices to new
* registers
* @param deletedInsns {@code non-null;} set of instructions marked for
* deletion
*/
private void replaceUse(SsaInsn use, SsaInsn prev, ArrayList<RegisterSpec> newRegs, HashSet<SsaInsn> deletedInsns) {
int index;
int length = newRegs.size();
SsaInsn next;
RegisterSpecList sources;
RegisterSpec source, result;
CstLiteralBits indexReg;
switch(use.getOpcode().getOpcode()) {
case RegOps.AGET:
// Replace array gets with moves
next = getMoveForInsn(use);
sources = use.getSources();
indexReg = ((CstLiteralBits) sources.get(1).getTypeBearer());
index = indexReg.getIntBits();
if (index < length) {
source = newRegs.get(index);
result = source.withReg(next.getResult().getReg());
insertPlainInsnBefore(next, RegisterSpecList.make(source), result, RegOps.MOVE, null);
} else {
// Throw an exception if the index is out of bounds
insertExceptionThrow(next, sources.get(1), deletedInsns);
deletedInsns.add(next.getBlock().getInsns().get(2));
}
deletedInsns.add(next);
break;
case RegOps.APUT:
// Replace array puts with moves
sources = use.getSources();
indexReg = ((CstLiteralBits) sources.get(2).getTypeBearer());
index = indexReg.getIntBits();
if (index < length) {
source = sources.get(0);
result = source.withReg(newRegs.get(index).getReg());
insertPlainInsnBefore(use, RegisterSpecList.make(source), result, RegOps.MOVE, null);
// Update the newReg entry to mark value as unknown now
newRegs.set(index, result.withSimpleType());
} else {
// Throw an exception if the index is out of bounds
insertExceptionThrow(use, sources.get(2), deletedInsns);
}
break;
case RegOps.ARRAY_LENGTH:
// Replace array lengths with const instructions
TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
//CstInteger lengthReg = CstInteger.make(length);
next = getMoveForInsn(use);
insertPlainInsnBefore(next, RegisterSpecList.EMPTY, next.getResult(), RegOps.CONST, (Constant) lengthReg);
deletedInsns.add(next);
break;
case RegOps.MARK_LOCAL:
// Remove mark local instructions
break;
case RegOps.FILL_ARRAY_DATA:
// Create const instructions for each fill value
Insn ropUse = use.getOriginalRopInsn();
FillArrayDataInsn fill = (FillArrayDataInsn) ropUse;
ArrayList<Constant> constList = fill.getInitValues();
for (int i = 0; i < length; i++) {
RegisterSpec newFill = RegisterSpec.make(newRegs.get(i).getReg(), (TypeBearer) constList.get(i));
insertPlainInsnBefore(use, RegisterSpecList.EMPTY, newFill, RegOps.CONST, constList.get(i));
// Update the newRegs to hold the new const value
newRegs.set(i, newFill);
}
break;
default:
}
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class PhiTypeResolver method resolveResultType.
/**
* Resolves the result of a phi insn based on its operands. The "void"
* type, which is a nonsensical type for a register, is used for
* registers defined by as-of-yet-unresolved phi operations.
*
* @return true if the result type changed, false if no change
*/
boolean resolveResultType(PhiInsn insn) {
insn.updateSourcesToDefinitions(ssaMeth);
RegisterSpecList sources = insn.getSources();
// Start by finding the first non-void operand
RegisterSpec first = null;
int firstIndex = -1;
int szSources = sources.size();
for (int i = 0; i < szSources; i++) {
RegisterSpec rs = sources.get(i);
if (rs.getBasicType() != Type.BT_VOID) {
first = rs;
firstIndex = i;
}
}
if (first == null) {
// All operands are void -- we're not ready to resolve yet
return false;
}
LocalItem firstLocal = first.getLocalItem();
Type mergedType = first.getType();
boolean sameLocals = true;
for (int i = 0; i < szSources; i++) {
if (i == firstIndex) {
continue;
}
RegisterSpec rs = sources.get(i);
// Just skip void (unresolved phi results) for now
if (rs.getBasicType() == Type.BT_VOID) {
continue;
}
sameLocals = sameLocals && equalsHandlesNulls(firstLocal, rs.getLocalItem());
mergedType = (Type) Merger.mergeType(mergedType, rs.getType());
}
Type newResultType;
if (mergedType != null) {
newResultType = mergedType;
} else {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < szSources; i++) {
sb.append(sources.get(i).toString());
sb.append(' ');
}
throw new RuntimeException("Couldn't map types in phi insn:" + sb);
}
LocalItem newLocal = sameLocals ? firstLocal : null;
RegisterSpec result = insn.getResult();
if ((result.getTypeBearer() == newResultType) && equalsHandlesNulls(newLocal, result.getLocalItem())) {
return false;
}
insn.changeResultType(newResultType, newLocal);
return true;
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class PhiTypeResolver method run.
/**
* Runs the phi-type resolver.
*/
private void run() {
int regCount = ssaMeth.getRegCount();
for (int reg = 0; reg < regCount; reg++) {
SsaInsn definsn = ssaMeth.getDefinitionForRegister(reg);
if (definsn != null && (definsn.getResult().getBasicType() == Type.BT_VOID)) {
worklist.set(reg);
}
}
int reg;
while (0 <= (reg = worklist.nextSetBit(0))) {
worklist.clear(reg);
/*
* definitions on the worklist have a type of BT_VOID, which
* must have originated from a PhiInsn.
*/
PhiInsn definsn = (PhiInsn) ssaMeth.getDefinitionForRegister(reg);
if (resolveResultType(definsn)) {
/*
* If the result type has changed, re-resolve all phis
* that use this.
*/
List<SsaInsn> useList = ssaMeth.getUseListForRegister(reg);
int sz = useList.size();
for (int i = 0; i < sz; i++) {
SsaInsn useInsn = useList.get(i);
RegisterSpec resultReg = useInsn.getResult();
if (resultReg != null && useInsn instanceof PhiInsn) {
worklist.set(resultReg.getReg());
}
}
}
}
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class SCCP method simulateStmt.
/**
* Simulates a statement and set the result lattice value.
* @param insn instruction to simulate
*/
private void simulateStmt(SsaInsn insn) {
Insn ropInsn = insn.getOriginalRopInsn();
if (ropInsn.getOpcode().getBranchingness() != Rop.BRANCH_NONE || ropInsn.getOpcode().isCallLike()) {
simulateBranch(insn);
}
int opcode = insn.getOpcode().getOpcode();
RegisterSpec result = insn.getResult();
if (result == null) {
// Find move-result-pseudo result for int div and int rem
if (opcode == RegOps.DIV || opcode == RegOps.REM) {
SsaBasicBlock succ = insn.getBlock().getPrimarySuccessor();
result = succ.getInsns().get(0).getResult();
} else {
return;
}
}
int resultReg = result.getReg();
int resultValue = VARYING;
Constant resultConstant = null;
switch(opcode) {
case RegOps.CONST:
{
CstInsn cstInsn = (CstInsn) ropInsn;
resultValue = CONSTANT;
resultConstant = cstInsn.getConstant();
break;
}
case RegOps.MOVE:
{
if (insn.getSources().size() == 1) {
int sourceReg = insn.getSources().get(0).getReg();
resultValue = latticeValues[sourceReg];
resultConstant = latticeConstants[sourceReg];
}
break;
}
case RegOps.ADD:
case RegOps.SUB:
case RegOps.MUL:
case RegOps.DIV:
case RegOps.AND:
case RegOps.OR:
case RegOps.XOR:
case RegOps.SHL:
case RegOps.SHR:
case RegOps.USHR:
case RegOps.REM:
{
resultConstant = simulateMath(insn, result.getBasicType());
if (resultConstant != null) {
resultValue = CONSTANT;
}
break;
}
case RegOps.MOVE_RESULT_PSEUDO:
{
if (latticeValues[resultReg] == CONSTANT) {
resultValue = latticeValues[resultReg];
resultConstant = latticeConstants[resultReg];
}
break;
}
// TODO: Eliminate check casts that we can prove the type of.
default:
{
}
}
if (setLatticeValueTo(resultReg, resultValue, resultConstant)) {
addUsersToWorklist(resultReg, resultValue);
}
}
use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class SCCP method simulateBranch.
/**
* Simulates branch insns, if possible. Adds reachable successor blocks
* to the CFG worklists.
* @param insn branch to simulate
*/
private void simulateBranch(SsaInsn insn) {
Rop opcode = insn.getOpcode();
RegisterSpecList sources = insn.getSources();
boolean constantBranch = false;
boolean constantSuccessor = false;
// Check if the insn is a branch with a constant condition
if (opcode.getBranchingness() == Rop.BRANCH_IF) {
Constant cA = null;
Constant cB = null;
RegisterSpec specA = sources.get(0);
int regA = specA.getReg();
if (!ssaMeth.isRegALocal(specA) && latticeValues[regA] == CONSTANT) {
cA = latticeConstants[regA];
}
if (sources.size() == 2) {
RegisterSpec specB = sources.get(1);
int regB = specB.getReg();
if (!ssaMeth.isRegALocal(specB) && latticeValues[regB] == CONSTANT) {
cB = latticeConstants[regB];
}
}
// Calculate the result of the condition
if (cA != null && sources.size() == 1) {
switch(((TypedConstant) cA).getBasicType()) {
case Type.BT_INT:
constantBranch = true;
int vA = ((CstInteger) cA).getValue();
switch(opcode.getOpcode()) {
case RegOps.IF_EQ:
constantSuccessor = (vA == 0);
break;
case RegOps.IF_NE:
constantSuccessor = (vA != 0);
break;
case RegOps.IF_LT:
constantSuccessor = (vA < 0);
break;
case RegOps.IF_GE:
constantSuccessor = (vA >= 0);
break;
case RegOps.IF_LE:
constantSuccessor = (vA <= 0);
break;
case RegOps.IF_GT:
constantSuccessor = (vA > 0);
break;
default:
throw new RuntimeException("Unexpected op");
}
break;
default:
}
} else if (cA != null && cB != null) {
switch(((TypedConstant) cA).getBasicType()) {
case Type.BT_INT:
constantBranch = true;
int vA = ((CstInteger) cA).getValue();
int vB = ((CstInteger) cB).getValue();
switch(opcode.getOpcode()) {
case RegOps.IF_EQ:
constantSuccessor = (vA == vB);
break;
case RegOps.IF_NE:
constantSuccessor = (vA != vB);
break;
case RegOps.IF_LT:
constantSuccessor = (vA < vB);
break;
case RegOps.IF_GE:
constantSuccessor = (vA >= vB);
break;
case RegOps.IF_LE:
constantSuccessor = (vA <= vB);
break;
case RegOps.IF_GT:
constantSuccessor = (vA > vB);
break;
default:
throw new RuntimeException("Unexpected op");
}
break;
default:
}
}
}
/*
* If condition is constant, add only the target block to the
* worklist. Otherwise, add all successors to the worklist.
*/
SsaBasicBlock block = insn.getBlock();
if (constantBranch) {
int successorBlock;
if (constantSuccessor) {
successorBlock = block.getSuccessorList().get(1);
} else {
successorBlock = block.getSuccessorList().get(0);
}
addBlockToWorklist(ssaMeth.getBlocks().get(successorBlock));
branchWorklist.add(insn);
} else {
for (int i = 0; i < block.getSuccessorList().size(); i++) {
int successorBlock = block.getSuccessorList().get(i);
addBlockToWorklist(ssaMeth.getBlocks().get(successorBlock));
}
}
}
Aggregations