use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.
the class ConstCollector method getConstsSortedByCountUse.
/**
* Gets all of the collectable constant values used in this method,
* sorted by most used first. Skips non-collectable consts, such as
* non-string object constants
*
* @return {@code non-null;} list of constants in most-to-least used order
*/
private ArrayList<TypedConstant> getConstsSortedByCountUse() {
int regSz = ssaMeth.getRegCount();
final HashMap<TypedConstant, Integer> countUses = new HashMap<TypedConstant, Integer>();
/*
* Each collected constant can be used by just one local
* (used only if COLLECT_ONE_LOCAL is true).
*/
final HashSet<TypedConstant> usedByLocal = new HashSet<TypedConstant>();
// Count how many times each const value is used.
for (int i = 0; i < regSz; i++) {
SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
if (insn == null || insn.getOpcode() == null)
continue;
RegisterSpec result = insn.getResult();
TypeBearer typeBearer = result.getTypeBearer();
if (!typeBearer.isConstant())
continue;
TypedConstant cst = (TypedConstant) typeBearer;
// Find defining instruction for move-result-pseudo instructions
if (insn.getOpcode().getOpcode() == RegOps.MOVE_RESULT_PSEUDO) {
int pred = insn.getBlock().getPredecessors().nextSetBit(0);
ArrayList<SsaInsn> predInsns;
predInsns = ssaMeth.getBlocks().get(pred).getInsns();
insn = predInsns.get(predInsns.size() - 1);
}
if (insn.canThrow()) {
/*
* Don't move anything other than strings -- the risk
* of changing where an exception is thrown is too high.
*/
if (!(cst instanceof CstString) || !COLLECT_STRINGS) {
continue;
}
/*
* We can't move any throwable const whose throw will be
* caught, so don't count them.
*/
if (insn.getBlock().getSuccessors().cardinality() > 1) {
continue;
}
}
/*
* TODO: Might be nice to try and figure out which local
* wins most when collected.
*/
if (ssaMeth.isRegALocal(result)) {
if (!COLLECT_ONE_LOCAL) {
continue;
} else {
if (usedByLocal.contains(cst)) {
// Count one local usage only.
continue;
} else {
usedByLocal.add(cst);
}
}
}
Integer has = countUses.get(cst);
if (has == null) {
countUses.put(cst, 1);
} else {
countUses.put(cst, has + 1);
}
}
// Collect constants that have been reused.
ArrayList<TypedConstant> constantList = new ArrayList<TypedConstant>();
for (Map.Entry<TypedConstant, Integer> entry : countUses.entrySet()) {
if (entry.getValue() > 1) {
constantList.add(entry.getKey());
}
}
// Sort by use, with most used at the beginning of the list.
Collections.sort(constantList, new Comparator<Constant>() {
public int compare(Constant a, Constant b) {
int ret;
ret = countUses.get(b) - countUses.get(a);
if (ret == 0) {
/*
* Provide sorting determinisim for constants with same
* usage count.
*/
ret = a.compareTo(b);
}
return ret;
}
@Override
public boolean equals(Object obj) {
return obj == this;
}
});
return constantList;
}
Aggregations