use of com.android.dx.rop.code.RopMethod in project buck by facebook.
the class BlockDumper method ropDump.
/**
* Does a registerizing dump.
*
* @param meth {@code non-null;} method data to dump
*/
private void ropDump(ConcreteMethod meth) {
TranslationAdvice advice = DexTranslationAdvice.THE_ONE;
BytecodeArray code = meth.getCode();
ByteArray bytes = code.getBytes();
RopMethod rmeth = Ropper.convert(meth, advice, classFile.getMethods());
StringBuffer sb = new StringBuffer(2000);
if (optimize) {
boolean isStatic = AccessFlags.isStatic(meth.getAccessFlags());
int paramWidth = computeParamWidth(meth, isStatic);
rmeth = Optimizer.optimize(rmeth, paramWidth, isStatic, true, advice);
}
BasicBlockList blocks = rmeth.getBlocks();
int[] order = blocks.getLabelsInOrder();
sb.append("first " + Hex.u2(rmeth.getFirstLabel()) + "\n");
for (int label : order) {
BasicBlock bb = blocks.get(blocks.indexOfLabel(label));
sb.append("block ");
sb.append(Hex.u2(label));
sb.append("\n");
IntList preds = rmeth.labelToPredecessors(label);
int psz = preds.size();
for (int i = 0; i < psz; i++) {
sb.append(" pred ");
sb.append(Hex.u2(preds.get(i)));
sb.append("\n");
}
InsnList il = bb.getInsns();
int ilsz = il.size();
for (int i = 0; i < ilsz; i++) {
Insn one = il.get(i);
sb.append(" ");
sb.append(il.get(i).toHuman());
sb.append("\n");
}
IntList successors = bb.getSuccessors();
int ssz = successors.size();
if (ssz == 0) {
sb.append(" returns\n");
} else {
int primary = bb.getPrimarySuccessor();
for (int i = 0; i < ssz; i++) {
int succ = successors.get(i);
sb.append(" next ");
sb.append(Hex.u2(succ));
if ((ssz != 1) && (succ == primary)) {
sb.append(" *");
}
sb.append("\n");
}
}
}
suppressDump = false;
setAt(bytes, 0);
parsed(bytes, 0, bytes.size(), sb.toString());
suppressDump = true;
}
use of com.android.dx.rop.code.RopMethod in project buck by facebook.
the class SsaDumper method endParsingMember.
/** {@inheritDoc} */
@Override
public void endParsingMember(ByteArray bytes, int offset, String name, String descriptor, Member member) {
if (!(member instanceof Method)) {
return;
}
if (!shouldDumpMethod(name)) {
return;
}
if ((member.getAccessFlags() & (AccessFlags.ACC_ABSTRACT | AccessFlags.ACC_NATIVE)) != 0) {
return;
}
ConcreteMethod meth = new ConcreteMethod((Method) member, classFile, true, true);
TranslationAdvice advice = DexTranslationAdvice.THE_ONE;
RopMethod rmeth = Ropper.convert(meth, advice, classFile.getMethods());
SsaMethod ssaMeth = null;
boolean isStatic = AccessFlags.isStatic(meth.getAccessFlags());
int paramWidth = computeParamWidth(meth, isStatic);
if (args.ssaStep == null) {
ssaMeth = Optimizer.debugNoRegisterAllocation(rmeth, paramWidth, isStatic, true, advice, EnumSet.allOf(Optimizer.OptionalStep.class));
} else if ("edge-split".equals(args.ssaStep)) {
ssaMeth = Optimizer.debugEdgeSplit(rmeth, paramWidth, isStatic, true, advice);
} else if ("phi-placement".equals(args.ssaStep)) {
ssaMeth = Optimizer.debugPhiPlacement(rmeth, paramWidth, isStatic, true, advice);
} else if ("renaming".equals(args.ssaStep)) {
ssaMeth = Optimizer.debugRenaming(rmeth, paramWidth, isStatic, true, advice);
} else if ("dead-code".equals(args.ssaStep)) {
ssaMeth = Optimizer.debugDeadCodeRemover(rmeth, paramWidth, isStatic, true, advice);
}
StringBuffer sb = new StringBuffer(2000);
sb.append("first ");
sb.append(Hex.u2(ssaMeth.blockIndexToRopLabel(ssaMeth.getEntryBlockIndex())));
sb.append('\n');
ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();
ArrayList<SsaBasicBlock> sortedBlocks = (ArrayList<SsaBasicBlock>) blocks.clone();
Collections.sort(sortedBlocks, SsaBasicBlock.LABEL_COMPARATOR);
for (SsaBasicBlock block : sortedBlocks) {
sb.append("block ").append(Hex.u2(block.getRopLabel())).append('\n');
BitSet preds = block.getPredecessors();
for (int i = preds.nextSetBit(0); i >= 0; i = preds.nextSetBit(i + 1)) {
sb.append(" pred ");
sb.append(Hex.u2(ssaMeth.blockIndexToRopLabel(i)));
sb.append('\n');
}
sb.append(" live in:" + block.getLiveInRegs());
sb.append("\n");
for (SsaInsn insn : block.getInsns()) {
sb.append(" ");
sb.append(insn.toHuman());
sb.append('\n');
}
if (block.getSuccessors().cardinality() == 0) {
sb.append(" returns\n");
} else {
int primary = block.getPrimarySuccessorRopLabel();
IntList succLabelList = block.getRopLabelSuccessorList();
int szSuccLabels = succLabelList.size();
for (int i = 0; i < szSuccLabels; i++) {
sb.append(" next ");
sb.append(Hex.u2(succLabelList.get(i)));
if (szSuccLabels != 1 && primary == succLabelList.get(i)) {
sb.append(" *");
}
sb.append('\n');
}
}
sb.append(" live out:" + block.getLiveOutRegs());
sb.append("\n");
}
suppressDump = false;
setAt(bytes, 0);
parsed(bytes, 0, bytes.size(), sb.toString());
suppressDump = true;
}
use of com.android.dx.rop.code.RopMethod in project J2ME-Loader by nikita36078.
the class CfTranslator method processMethods.
/**
* Processes the methods of the given class.
*
* @param context {@code non-null;} the state global to this invocation.
* @param cf {@code non-null;} class being translated
* @param cfOptions {@code non-null;} options for class translation
* @param dexOptions {@code non-null;} options for dex output
* @param out {@code non-null;} output class
* @param dexFile {@code non-null;} dex output
*/
private static void processMethods(DxContext context, DirectClassFile cf, CfOptions cfOptions, DexOptions dexOptions, ClassDefItem out, DexFile dexFile) {
CstType thisClass = cf.getThisClass();
MethodList methods = cf.getMethods();
int sz = methods.size();
for (int i = 0; i < sz; i++) {
Method one = methods.get(i);
try {
CstMethodRef meth = new CstMethodRef(thisClass, one.getNat());
int accessFlags = one.getAccessFlags();
boolean isStatic = AccessFlags.isStatic(accessFlags);
boolean isPrivate = AccessFlags.isPrivate(accessFlags);
boolean isNative = AccessFlags.isNative(accessFlags);
boolean isAbstract = AccessFlags.isAbstract(accessFlags);
boolean isConstructor = meth.isInstanceInit() || meth.isClassInit();
DalvCode code;
if (isNative || isAbstract) {
// There's no code for native or abstract methods.
code = null;
} else {
ConcreteMethod concrete = new ConcreteMethod(one, cf, (cfOptions.positionInfo != PositionList.NONE), cfOptions.localInfo);
TranslationAdvice advice;
advice = DexTranslationAdvice.THE_ONE;
RopMethod rmeth = Ropper.convert(concrete, advice, methods, dexOptions);
RopMethod nonOptRmeth = null;
int paramSize;
paramSize = meth.getParameterWordCount(isStatic);
String canonicalName = thisClass.getClassType().getDescriptor() + "." + one.getName().getString();
if (cfOptions.optimize && context.optimizerOptions.shouldOptimize(canonicalName)) {
if (DEBUG) {
System.err.println("Optimizing " + canonicalName);
}
nonOptRmeth = rmeth;
rmeth = Optimizer.optimize(rmeth, paramSize, isStatic, cfOptions.localInfo, advice);
if (DEBUG) {
context.optimizerOptions.compareOptimizerStep(nonOptRmeth, paramSize, isStatic, cfOptions, advice, rmeth);
}
if (cfOptions.statistics) {
context.codeStatistics.updateRopStatistics(nonOptRmeth, rmeth);
}
}
LocalVariableInfo locals = null;
if (cfOptions.localInfo) {
locals = LocalVariableExtractor.extract(rmeth);
}
code = RopTranslator.translate(rmeth, cfOptions.positionInfo, locals, paramSize, dexOptions);
if (cfOptions.statistics && nonOptRmeth != null) {
updateDexStatistics(context, cfOptions, dexOptions, rmeth, nonOptRmeth, locals, paramSize, concrete.getCode().size());
}
}
// Preserve the synchronized flag as its "declared" variant...
if (AccessFlags.isSynchronized(accessFlags)) {
accessFlags |= AccessFlags.ACC_DECLARED_SYNCHRONIZED;
/*
* ...but only native methods are actually allowed to be
* synchronized.
*/
if (!isNative) {
accessFlags &= ~AccessFlags.ACC_SYNCHRONIZED;
}
}
if (isConstructor) {
accessFlags |= AccessFlags.ACC_CONSTRUCTOR;
}
TypeList exceptions = AttributeTranslator.getExceptions(one);
EncodedMethod mi = new EncodedMethod(meth, accessFlags, code, exceptions);
if (meth.isInstanceInit() || meth.isClassInit() || isStatic || isPrivate) {
out.addDirectMethod(mi);
} else {
out.addVirtualMethod(mi);
}
Annotations annotations = AttributeTranslator.getMethodAnnotations(one);
if (annotations.size() != 0) {
out.addMethodAnnotations(meth, annotations, dexFile);
}
AnnotationsList list = AttributeTranslator.getParameterAnnotations(one);
if (list.size() != 0) {
out.addParameterAnnotations(meth, list, dexFile);
}
dexFile.getMethodIds().intern(meth);
} catch (RuntimeException ex) {
String msg = "...while processing " + one.getName().toHuman() + " " + one.getDescriptor().toHuman();
throw ExceptionWithContext.withContext(ex, msg);
}
}
}
use of com.android.dx.rop.code.RopMethod in project J2ME-Loader by nikita36078.
the class OptimizerOptions method compareOptimizerStep.
/**
* Compares the output of the optimizer run normally with a run skipping
* some optional steps. Results are printed to stderr.
*
* @param nonOptRmeth {@code non-null;} origional rop method
* @param paramSize {@code >= 0;} parameter size of method
* @param isStatic true if this method has no 'this' pointer argument.
* @param args {@code non-null;} translator arguments
* @param advice {@code non-null;} translation advice
* @param rmeth {@code non-null;} method with all optimization steps run.
*/
public void compareOptimizerStep(RopMethod nonOptRmeth, int paramSize, boolean isStatic, CfOptions args, TranslationAdvice advice, RopMethod rmeth) {
EnumSet<Optimizer.OptionalStep> steps;
steps = EnumSet.allOf(Optimizer.OptionalStep.class);
// This is the step to skip.
steps.remove(Optimizer.OptionalStep.CONST_COLLECTOR);
RopMethod skipRopMethod = Optimizer.optimize(nonOptRmeth, paramSize, isStatic, args.localInfo, advice, steps);
int normalInsns = rmeth.getBlocks().getEffectiveInstructionCount();
int skipInsns = skipRopMethod.getBlocks().getEffectiveInstructionCount();
System.err.printf("optimize step regs:(%d/%d/%.2f%%)" + " insns:(%d/%d/%.2f%%)\n", rmeth.getBlocks().getRegCount(), skipRopMethod.getBlocks().getRegCount(), 100.0 * ((skipRopMethod.getBlocks().getRegCount() - rmeth.getBlocks().getRegCount()) / (float) skipRopMethod.getBlocks().getRegCount()), normalInsns, skipInsns, 100.0 * ((skipInsns - normalInsns) / (float) skipInsns));
}
use of com.android.dx.rop.code.RopMethod in project J2ME-Loader by nikita36078.
the class Ropper method getRopMethod.
/**
* Extracts the resulting {@link RopMethod} from the instance.
*
* @return {@code non-null;} the method object
*/
private RopMethod getRopMethod() {
// Construct the final list of blocks.
int sz = result.size();
BasicBlockList bbl = new BasicBlockList(sz);
for (int i = 0; i < sz; i++) {
bbl.set(i, result.get(i));
}
bbl.setImmutable();
/*
* Note: The parameter assignment block is always the first
* that should be executed, hence the second argument to the
* constructor.
*/
return new RopMethod(bbl, getSpecialLabel(PARAM_ASSIGNMENT));
}
Aggregations