use of com.android.dx.rop.cst.CstString 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.cst.CstString in project buck by facebook.
the class DebugInfoEncoder method entryAnnotationString.
/**
* Returns a string representation of this LocalList entry that is
* appropriate for emitting as an annotation.
*
* @param e {@code non-null;} entry
* @return {@code non-null;} annotation string
*/
private String entryAnnotationString(LocalList.Entry e) {
StringBuilder sb = new StringBuilder();
sb.append(RegisterSpec.PREFIX);
sb.append(e.getRegister());
sb.append(' ');
CstString name = e.getName();
if (name == null) {
sb.append("null");
} else {
sb.append(name.toHuman());
}
sb.append(' ');
CstType type = e.getType();
if (type == null) {
sb.append("null");
} else {
sb.append(type.toHuman());
}
CstString signature = e.getSignature();
if (signature != null) {
sb.append(' ');
sb.append(signature.toHuman());
}
return sb.toString();
}
use of com.android.dx.rop.cst.CstString in project buck by facebook.
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;
}
use of com.android.dx.rop.cst.CstString in project buck by facebook.
the class HeaderItem method writeTo.
/** {@inheritDoc} */
@Override
public void writeTo(DexFile file, AnnotatedOutput out) {
int mapOff = file.getMap().getFileOffset();
Section firstDataSection = file.getFirstDataSection();
Section lastDataSection = file.getLastDataSection();
int dataOff = firstDataSection.getFileOffset();
int dataSize = lastDataSection.getFileOffset() + lastDataSection.writeSize() - dataOff;
String magic = file.getDexOptions().getMagic();
if (out.annotates()) {
out.annotate(8, "magic: " + new CstString(magic).toQuoted());
out.annotate(4, "checksum");
out.annotate(20, "signature");
out.annotate(4, "file_size: " + Hex.u4(file.getFileSize()));
out.annotate(4, "header_size: " + Hex.u4(SizeOf.HEADER_ITEM));
out.annotate(4, "endian_tag: " + Hex.u4(DexFormat.ENDIAN_TAG));
out.annotate(4, "link_size: 0");
out.annotate(4, "link_off: 0");
out.annotate(4, "map_off: " + Hex.u4(mapOff));
}
// Write the magic number.
for (int i = 0; i < 8; i++) {
out.writeByte(magic.charAt(i));
}
// Leave space for the checksum and signature.
out.writeZeroes(24);
out.writeInt(file.getFileSize());
out.writeInt(SizeOf.HEADER_ITEM);
out.writeInt(DexFormat.ENDIAN_TAG);
/*
* Write zeroes for the link size and data, as the output
* isn't a staticly linked file.
*/
out.writeZeroes(8);
out.writeInt(mapOff);
// Write out each section's respective header part.
file.getStringIds().writeHeaderPart(out);
file.getTypeIds().writeHeaderPart(out);
file.getProtoIds().writeHeaderPart(out);
file.getFieldIds().writeHeaderPart(out);
file.getMethodIds().writeHeaderPart(out);
file.getClassDefs().writeHeaderPart(out);
if (out.annotates()) {
out.annotate(4, "data_size: " + Hex.u4(dataSize));
out.annotate(4, "data_off: " + Hex.u4(dataOff));
}
out.writeInt(dataSize);
out.writeInt(dataOff);
}
use of com.android.dx.rop.cst.CstString in project buck by facebook.
the class ProtoIdItem method makeShortForm.
/**
* Creates the short-form of the given prototype.
*
* @param prototype {@code non-null;} the prototype
* @return {@code non-null;} the short form
*/
private static CstString makeShortForm(Prototype prototype) {
StdTypeList parameters = prototype.getParameterTypes();
int size = parameters.size();
StringBuilder sb = new StringBuilder(size + 1);
sb.append(shortFormCharFor(prototype.getReturnType()));
for (int i = 0; i < size; i++) {
sb.append(shortFormCharFor(parameters.getType(i)));
}
return new CstString(sb.toString());
}
Aggregations