Search in sources :

Example 1 with RopMethod

use of com.android.dx.rop.code.RopMethod in project buck by facebook.

the class CfTranslator method processMethods.

/**
     * Processes the methods of the given class.
     *
     * @param context
     * @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);
                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);
        }
    }
}
Also used : DalvCode(com.android.dx.dex.code.DalvCode) RopMethod(com.android.dx.rop.code.RopMethod) AnnotationsList(com.android.dx.rop.annotation.AnnotationsList) MethodList(com.android.dx.cf.iface.MethodList) DexTranslationAdvice(com.android.dx.rop.code.DexTranslationAdvice) TranslationAdvice(com.android.dx.rop.code.TranslationAdvice) EncodedMethod(com.android.dx.dex.file.EncodedMethod) ConcreteMethod(com.android.dx.cf.code.ConcreteMethod) RopMethod(com.android.dx.rop.code.RopMethod) Method(com.android.dx.cf.iface.Method) CstString(com.android.dx.rop.cst.CstString) CstMethodRef(com.android.dx.rop.cst.CstMethodRef) LocalVariableInfo(com.android.dx.rop.code.LocalVariableInfo) Annotations(com.android.dx.rop.annotation.Annotations) EncodedMethod(com.android.dx.dex.file.EncodedMethod) CstType(com.android.dx.rop.cst.CstType) ConcreteMethod(com.android.dx.cf.code.ConcreteMethod) TypeList(com.android.dx.rop.type.TypeList)

Example 2 with RopMethod

use of com.android.dx.rop.code.RopMethod in project buck by facebook.

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));
}
Also used : RopMethod(com.android.dx.rop.code.RopMethod)

Example 3 with RopMethod

use of com.android.dx.rop.code.RopMethod in project buck by facebook.

the class Optimizer method optimize.

/**
     * Runs optimization algorthims over this method, and returns a new
     * instance of RopMethod with the changes.
     *
     * @param rmeth method to process
     * @param paramWidth the total width, in register-units, of this method's
     * parameters
     * @param isStatic true if this method has no 'this' pointer argument.
     * @param inPreserveLocals true if local variable info should be preserved,
     * at the cost of some registers and insns
     * @param inAdvice {@code non-null;} translation advice
     * @param steps set of optional optimization steps to run
     * @return optimized method
     */
public static RopMethod optimize(RopMethod rmeth, int paramWidth, boolean isStatic, boolean inPreserveLocals, TranslationAdvice inAdvice, EnumSet<OptionalStep> steps) {
    SsaMethod ssaMeth = null;
    preserveLocals = inPreserveLocals;
    advice = inAdvice;
    ssaMeth = SsaConverter.convertToSsaMethod(rmeth, paramWidth, isStatic);
    runSsaFormSteps(ssaMeth, steps);
    RopMethod resultMeth = SsaToRop.convertToRopMethod(ssaMeth, false);
    if (resultMeth.getBlocks().getRegCount() > advice.getMaxOptimalRegisterCount()) {
        // Try to see if we can squeeze it under the register count bar
        resultMeth = optimizeMinimizeRegisters(rmeth, paramWidth, isStatic, steps);
    }
    return resultMeth;
}
Also used : RopMethod(com.android.dx.rop.code.RopMethod)

Example 4 with RopMethod

use of com.android.dx.rop.code.RopMethod in project buck by facebook.

the class Optimizer method optimizeMinimizeRegisters.

/**
     * Runs the optimizer with a strategy to minimize the number of rop-form
     * registers used by the end result. Dex bytecode does not have instruction
     * forms that take register numbers larger than 15 for all instructions.
     * If we've produced a method that uses more than 16 registers, try again
     * with a different strategy to see if we can get under the bar. The end
     * result will be much more efficient.
     *
     * @param rmeth method to process
     * @param paramWidth the total width, in register-units, of this method's
     * parameters
     * @param isStatic true if this method has no 'this' pointer argument.
     * @param steps set of optional optimization steps to run
     * @return optimized method
     */
private static RopMethod optimizeMinimizeRegisters(RopMethod rmeth, int paramWidth, boolean isStatic, EnumSet<OptionalStep> steps) {
    SsaMethod ssaMeth;
    RopMethod resultMeth;
    ssaMeth = SsaConverter.convertToSsaMethod(rmeth, paramWidth, isStatic);
    EnumSet<OptionalStep> newSteps = steps.clone();
    /*
         * CONST_COLLECTOR trades insns for registers, which is not an
         * appropriate strategy here.
         */
    newSteps.remove(OptionalStep.CONST_COLLECTOR);
    runSsaFormSteps(ssaMeth, newSteps);
    resultMeth = SsaToRop.convertToRopMethod(ssaMeth, true);
    return resultMeth;
}
Also used : RopMethod(com.android.dx.rop.code.RopMethod)

Example 5 with RopMethod

use of com.android.dx.rop.code.RopMethod in project buck by facebook.

the class DotDumper method endParsingMember.

public void endParsingMember(ByteArray bytes, int offset, String name, String descriptor, Member member) {
    if (!(member instanceof Method)) {
        return;
    }
    if (!shouldDumpMethod(name)) {
        return;
    }
    ConcreteMethod meth = new ConcreteMethod((Method) member, classFile, true, true);
    TranslationAdvice advice = DexTranslationAdvice.THE_ONE;
    RopMethod rmeth = Ropper.convert(meth, advice, classFile.getMethods());
    if (optimize) {
        boolean isStatic = AccessFlags.isStatic(meth.getAccessFlags());
        rmeth = Optimizer.optimize(rmeth, BaseDumper.computeParamWidth(meth, isStatic), isStatic, true, advice);
    }
    System.out.println("digraph " + name + "{");
    System.out.println("\tfirst -> n" + Hex.u2(rmeth.getFirstLabel()) + ";");
    BasicBlockList blocks = rmeth.getBlocks();
    int sz = blocks.size();
    for (int i = 0; i < sz; i++) {
        BasicBlock bb = blocks.get(i);
        int label = bb.getLabel();
        IntList successors = bb.getSuccessors();
        if (successors.size() == 0) {
            System.out.println("\tn" + Hex.u2(label) + " -> returns;");
        } else if (successors.size() == 1) {
            System.out.println("\tn" + Hex.u2(label) + " -> n" + Hex.u2(successors.get(0)) + ";");
        } else {
            System.out.print("\tn" + Hex.u2(label) + " -> {");
            for (int j = 0; j < successors.size(); j++) {
                int successor = successors.get(j);
                if (successor != bb.getPrimarySuccessor()) {
                    System.out.print(" n" + Hex.u2(successor) + " ");
                }
            }
            System.out.println("};");
            System.out.println("\tn" + Hex.u2(label) + " -> n" + Hex.u2(bb.getPrimarySuccessor()) + " [label=\"primary\"];");
        }
    }
    System.out.println("}");
}
Also used : RopMethod(com.android.dx.rop.code.RopMethod) ConcreteMethod(com.android.dx.cf.code.ConcreteMethod) BasicBlock(com.android.dx.rop.code.BasicBlock) DexTranslationAdvice(com.android.dx.rop.code.DexTranslationAdvice) TranslationAdvice(com.android.dx.rop.code.TranslationAdvice) ConcreteMethod(com.android.dx.cf.code.ConcreteMethod) RopMethod(com.android.dx.rop.code.RopMethod) Method(com.android.dx.cf.iface.Method) BasicBlockList(com.android.dx.rop.code.BasicBlockList) IntList(com.android.dx.util.IntList)

Aggregations

RopMethod (com.android.dx.rop.code.RopMethod)10 DexTranslationAdvice (com.android.dx.rop.code.DexTranslationAdvice)4 TranslationAdvice (com.android.dx.rop.code.TranslationAdvice)4 IntList (com.android.dx.util.IntList)4 ConcreteMethod (com.android.dx.cf.code.ConcreteMethod)3 Method (com.android.dx.cf.iface.Method)3 BasicBlock (com.android.dx.rop.code.BasicBlock)3 BasicBlockList (com.android.dx.rop.code.BasicBlockList)3 BitSet (java.util.BitSet)2 BytecodeArray (com.android.dx.cf.code.BytecodeArray)1 MethodList (com.android.dx.cf.iface.MethodList)1 DalvCode (com.android.dx.dex.code.DalvCode)1 EncodedMethod (com.android.dx.dex.file.EncodedMethod)1 Annotations (com.android.dx.rop.annotation.Annotations)1 AnnotationsList (com.android.dx.rop.annotation.AnnotationsList)1 Insn (com.android.dx.rop.code.Insn)1 InsnList (com.android.dx.rop.code.InsnList)1 LocalVariableInfo (com.android.dx.rop.code.LocalVariableInfo)1 CstMethodRef (com.android.dx.rop.cst.CstMethodRef)1 CstString (com.android.dx.rop.cst.CstString)1