Search in sources :

Example 56 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

the class Ropper method addReturnBlock.

/**
     * Constructs and adds the return block, if necessary. The return
     * block merely contains an appropriate {@code return}
     * instruction.
     */
private void addReturnBlock() {
    Rop returnOp = machine.getReturnOp();
    if (returnOp == null) {
        /*
             * The method being converted never returns normally, so there's
             * no need for a return block.
             */
        return;
    }
    SourcePosition returnPos = machine.getReturnPosition();
    int label = getSpecialLabel(RETURN);
    if (isSynchronized()) {
        InsnList insns = new InsnList(1);
        Insn insn = new ThrowingInsn(Rops.MONITOR_EXIT, returnPos, RegisterSpecList.make(getSynchReg()), StdTypeList.EMPTY);
        insns.set(0, insn);
        insns.setImmutable();
        int nextLabel = getSpecialLabel(SYNCH_RETURN);
        BasicBlock bb = new BasicBlock(label, insns, IntList.makeImmutable(nextLabel), nextLabel);
        addBlock(bb, IntList.EMPTY);
        label = nextLabel;
    }
    InsnList insns = new InsnList(1);
    TypeList sourceTypes = returnOp.getSources();
    RegisterSpecList sources;
    if (sourceTypes.size() == 0) {
        sources = RegisterSpecList.EMPTY;
    } else {
        RegisterSpec source = RegisterSpec.make(0, sourceTypes.getType(0));
        sources = RegisterSpecList.make(source);
    }
    Insn insn = new PlainInsn(returnOp, returnPos, null, sources);
    insns.set(0, insn);
    insns.setImmutable();
    BasicBlock bb = new BasicBlock(label, insns, IntList.EMPTY, -1);
    addBlock(bb, IntList.EMPTY);
}
Also used : PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) Rop(com.taobao.android.dx.rop.code.Rop) Insn(com.taobao.android.dx.rop.code.Insn) PlainCstInsn(com.taobao.android.dx.rop.code.PlainCstInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) ThrowingInsn(com.taobao.android.dx.rop.code.ThrowingInsn) ThrowingCstInsn(com.taobao.android.dx.rop.code.ThrowingCstInsn) SourcePosition(com.taobao.android.dx.rop.code.SourcePosition) BasicBlock(com.taobao.android.dx.rop.code.BasicBlock) InsnList(com.taobao.android.dx.rop.code.InsnList) ThrowingInsn(com.taobao.android.dx.rop.code.ThrowingInsn) RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) StdTypeList(com.taobao.android.dx.rop.type.StdTypeList) TypeList(com.taobao.android.dx.rop.type.TypeList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 57 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

the class RopperMachine method getSources.

/**
     * Helper for {@link #run}, which gets the list of sources for the.
     * instruction.
     *
     * @param opcode the opcode being translated
     * @param stackPointer {@code >= 0;} the stack pointer after the
     * instruction's arguments have been popped
     * @return {@code non-null;} the sources
     */
private RegisterSpecList getSources(int opcode, int stackPointer) {
    int count = argCount();
    if (count == 0) {
        // We get an easy out if there aren't any sources.
        return RegisterSpecList.EMPTY;
    }
    int localIndex = getLocalIndex();
    RegisterSpecList sources;
    if (localIndex >= 0) {
        // The instruction is operating on a local variable.
        sources = new RegisterSpecList(1);
        sources.set(0, RegisterSpec.make(localIndex, arg(0)));
    } else {
        sources = new RegisterSpecList(count);
        int regAt = stackPointer;
        for (int i = 0; i < count; i++) {
            RegisterSpec spec = RegisterSpec.make(regAt, arg(i));
            sources.set(i, spec);
            regAt += spec.getCategory();
        }
        switch(opcode) {
            case ByteOps.IASTORE:
                {
                    /*
                     * The Java argument order for array stores is
                     * (array, index, value), but the rop argument
                     * order is (value, array, index). The following
                     * code gets the right arguments in the right
                     * places.
                     */
                    if (count != 3) {
                        throw new RuntimeException("shouldn't happen");
                    }
                    RegisterSpec array = sources.get(0);
                    RegisterSpec index = sources.get(1);
                    RegisterSpec value = sources.get(2);
                    sources.set(0, value);
                    sources.set(1, array);
                    sources.set(2, index);
                    break;
                }
            case ByteOps.PUTFIELD:
                {
                    /*
                     * Similar to above: The Java argument order for
                     * putfield is (object, value), but the rop
                     * argument order is (value, object).
                     */
                    if (count != 2) {
                        throw new RuntimeException("shouldn't happen");
                    }
                    RegisterSpec obj = sources.get(0);
                    RegisterSpec value = sources.get(1);
                    sources.set(0, value);
                    sources.set(1, obj);
                    break;
                }
        }
    }
    sources.setImmutable();
    return sources;
}
Also used : RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 58 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

the class OutputFinisher method addConstants.

/**
     * Helper for {@link #getAllConstants} which adds all the info for
     * a single instruction.
     *
     * @param result {@code non-null;} result set to add to
     * @param insn {@code non-null;} instruction to scrutinize
     */
private static void addConstants(HashSet<Constant> result, DalvInsn insn) {
    if (insn instanceof CstInsn) {
        Constant cst = ((CstInsn) insn).getConstant();
        result.add(cst);
    } else if (insn instanceof LocalSnapshot) {
        RegisterSpecSet specs = ((LocalSnapshot) insn).getLocals();
        int size = specs.size();
        for (int i = 0; i < size; i++) {
            addConstants(result, specs.get(i));
        }
    } else if (insn instanceof LocalStart) {
        RegisterSpec spec = ((LocalStart) insn).getLocal();
        addConstants(result, spec);
    }
}
Also used : RegisterSpecSet(com.taobao.android.dx.rop.code.RegisterSpecSet) Constant(com.taobao.android.dx.rop.cst.Constant) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 59 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

the class OutputFinisher method align64bits.

private void align64bits(Dop[] opcodes) {
    while (true) {
        int notAligned64bitRegAccess = 0;
        int aligned64bitRegAccess = 0;
        int notAligned64bitParamAccess = 0;
        int aligned64bitParamAccess = 0;
        int lastParameter = unreservedRegCount + reservedCount + reservedParameterCount;
        int firstParameter = lastParameter - paramSize;
        // Collects the number of time that 64-bit registers are accessed aligned or not.
        for (DalvInsn insn : insns) {
            RegisterSpecList regs = insn.getRegisters();
            for (int usedRegIdx = 0; usedRegIdx < regs.size(); usedRegIdx++) {
                RegisterSpec reg = regs.get(usedRegIdx);
                if (reg.isCategory2()) {
                    boolean isParameter = reg.getReg() >= firstParameter;
                    if (reg.isEvenRegister()) {
                        if (isParameter) {
                            aligned64bitParamAccess++;
                        } else {
                            aligned64bitRegAccess++;
                        }
                    } else {
                        if (isParameter) {
                            notAligned64bitParamAccess++;
                        } else {
                            notAligned64bitRegAccess++;
                        }
                    }
                }
            }
        }
        if (notAligned64bitParamAccess > aligned64bitParamAccess && notAligned64bitRegAccess > aligned64bitRegAccess) {
            addReservedRegisters(1);
        } else if (notAligned64bitParamAccess > aligned64bitParamAccess) {
            addReservedParameters(1);
        } else if (notAligned64bitRegAccess > aligned64bitRegAccess) {
            addReservedRegisters(1);
            // so the number of aligned become the number of unaligned.
            if (paramSize != 0 && aligned64bitParamAccess > notAligned64bitParamAccess) {
                addReservedParameters(1);
            }
        } else {
            break;
        }
        if (!reserveRegisters(opcodes)) {
            break;
        }
    }
}
Also used : RegisterSpecList(com.taobao.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 60 with RegisterSpec

use of com.taobao.android.dx.rop.code.RegisterSpec in project atlas by alibaba.

the class RopToDop method dopFor.

/**
     * Returns the dalvik opcode appropriate for the given register-based
     * instruction.
     *
     * @param insn {@code non-null;} the original instruction
     * @return the corresponding dalvik opcode; one of the constants in
     * {@link Dops}
     */
public static Dop dopFor(Insn insn) {
    Rop rop = insn.getOpcode();
    /*
         * First, just try looking up the rop in the MAP of easy
         * cases.
         */
    Dop result = MAP.get(rop);
    if (result != null) {
        return result;
    }
    switch(rop.getOpcode()) {
        case RegOps.MOVE_EXCEPTION:
            return Dops.MOVE_EXCEPTION;
        case RegOps.INVOKE_STATIC:
            return Dops.INVOKE_STATIC;
        case RegOps.INVOKE_VIRTUAL:
            return Dops.INVOKE_VIRTUAL;
        case RegOps.INVOKE_SUPER:
            return Dops.INVOKE_SUPER;
        case RegOps.INVOKE_DIRECT:
            return Dops.INVOKE_DIRECT;
        case RegOps.INVOKE_INTERFACE:
            return Dops.INVOKE_INTERFACE;
        case RegOps.NEW_ARRAY:
            return Dops.NEW_ARRAY;
        case RegOps.FILLED_NEW_ARRAY:
            return Dops.FILLED_NEW_ARRAY;
        case RegOps.FILL_ARRAY_DATA:
            return Dops.FILL_ARRAY_DATA;
        case RegOps.MOVE_RESULT:
            {
                RegisterSpec resultReg = insn.getResult();
                if (resultReg == null) {
                    return Dops.NOP;
                } else {
                    switch(resultReg.getBasicType()) {
                        case Type.BT_INT:
                        case Type.BT_FLOAT:
                        case Type.BT_BOOLEAN:
                        case Type.BT_BYTE:
                        case Type.BT_CHAR:
                        case Type.BT_SHORT:
                            return Dops.MOVE_RESULT;
                        case Type.BT_LONG:
                        case Type.BT_DOUBLE:
                            return Dops.MOVE_RESULT_WIDE;
                        case Type.BT_OBJECT:
                            return Dops.MOVE_RESULT_OBJECT;
                        default:
                            {
                                throw new RuntimeException("Unexpected basic type");
                            }
                    }
                }
            }
        case RegOps.GET_FIELD:
            {
                CstFieldRef ref = (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
                int basicType = ref.getBasicType();
                switch(basicType) {
                    case Type.BT_BOOLEAN:
                        return Dops.IGET_BOOLEAN;
                    case Type.BT_BYTE:
                        return Dops.IGET_BYTE;
                    case Type.BT_CHAR:
                        return Dops.IGET_CHAR;
                    case Type.BT_SHORT:
                        return Dops.IGET_SHORT;
                    case Type.BT_INT:
                        return Dops.IGET;
                }
                break;
            }
        case RegOps.PUT_FIELD:
            {
                CstFieldRef ref = (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
                int basicType = ref.getBasicType();
                switch(basicType) {
                    case Type.BT_BOOLEAN:
                        return Dops.IPUT_BOOLEAN;
                    case Type.BT_BYTE:
                        return Dops.IPUT_BYTE;
                    case Type.BT_CHAR:
                        return Dops.IPUT_CHAR;
                    case Type.BT_SHORT:
                        return Dops.IPUT_SHORT;
                    case Type.BT_INT:
                        return Dops.IPUT;
                }
                break;
            }
        case RegOps.GET_STATIC:
            {
                CstFieldRef ref = (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
                int basicType = ref.getBasicType();
                switch(basicType) {
                    case Type.BT_BOOLEAN:
                        return Dops.SGET_BOOLEAN;
                    case Type.BT_BYTE:
                        return Dops.SGET_BYTE;
                    case Type.BT_CHAR:
                        return Dops.SGET_CHAR;
                    case Type.BT_SHORT:
                        return Dops.SGET_SHORT;
                    case Type.BT_INT:
                        return Dops.SGET;
                }
                break;
            }
        case RegOps.PUT_STATIC:
            {
                CstFieldRef ref = (CstFieldRef) ((ThrowingCstInsn) insn).getConstant();
                int basicType = ref.getBasicType();
                switch(basicType) {
                    case Type.BT_BOOLEAN:
                        return Dops.SPUT_BOOLEAN;
                    case Type.BT_BYTE:
                        return Dops.SPUT_BYTE;
                    case Type.BT_CHAR:
                        return Dops.SPUT_CHAR;
                    case Type.BT_SHORT:
                        return Dops.SPUT_SHORT;
                    case Type.BT_INT:
                        return Dops.SPUT;
                }
                break;
            }
        case RegOps.CONST:
            {
                Constant cst = ((ThrowingCstInsn) insn).getConstant();
                if (cst instanceof CstType) {
                    return Dops.CONST_CLASS;
                } else if (cst instanceof CstString) {
                    return Dops.CONST_STRING;
                }
                break;
            }
    }
    throw new RuntimeException("unknown rop: " + rop);
}
Also used : Rop(com.taobao.android.dx.rop.code.Rop) ThrowingCstInsn(com.taobao.android.dx.rop.code.ThrowingCstInsn) Constant(com.taobao.android.dx.rop.cst.Constant) CstType(com.taobao.android.dx.rop.cst.CstType) CstFieldRef(com.taobao.android.dx.rop.cst.CstFieldRef) CstString(com.taobao.android.dx.rop.cst.CstString) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Aggregations

RegisterSpec (com.taobao.android.dx.rop.code.RegisterSpec)66 RegisterSpecList (com.taobao.android.dx.rop.code.RegisterSpecList)24 PlainInsn (com.taobao.android.dx.rop.code.PlainInsn)12 Constant (com.taobao.android.dx.rop.cst.Constant)10 TypedConstant (com.taobao.android.dx.rop.cst.TypedConstant)8 ArrayList (java.util.ArrayList)8 Insn (com.taobao.android.dx.rop.code.Insn)7 PlainCstInsn (com.taobao.android.dx.rop.code.PlainCstInsn)7 Rop (com.taobao.android.dx.rop.code.Rop)7 ThrowingCstInsn (com.taobao.android.dx.rop.code.ThrowingCstInsn)7 CstType (com.taobao.android.dx.rop.cst.CstType)7 TypeBearer (com.taobao.android.dx.rop.type.TypeBearer)7 LocalItem (com.taobao.android.dx.rop.code.LocalItem)5 RegisterSpecSet (com.taobao.android.dx.rop.code.RegisterSpecSet)5 ThrowingInsn (com.taobao.android.dx.rop.code.ThrowingInsn)5 CstString (com.taobao.android.dx.rop.cst.CstString)5 BitSet (java.util.BitSet)5 HashSet (java.util.HashSet)5 SourcePosition (com.taobao.android.dx.rop.code.SourcePosition)4 CstFieldRef (com.taobao.android.dx.rop.cst.CstFieldRef)4