Search in sources :

Example 46 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.

the class InsnFormat method isRegListSequential.

/**
 * Helper method to determine if a list of registers are sequential,
 * including degenerate cases for empty or single-element lists.
 *
 * @param list {@code non-null;} the list of registers
 * @return {@code true} iff the list is sequentially ordered
 */
protected static boolean isRegListSequential(RegisterSpecList list) {
    int sz = list.size();
    if (sz < 2) {
        return true;
    }
    int first = list.get(0).getReg();
    int next = first;
    for (int i = 0; i < sz; i++) {
        RegisterSpec one = list.get(i);
        if (one.getReg() != next) {
            return false;
        }
        next += one.getCategory();
    }
    return true;
}
Also used : RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 47 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.

the class LocalList method make.

/**
 * Constructs an instance for the given method, based on the given
 * block order and intermediate local information.
 *
 * @param insns {@code non-null;} instructions to convert
 * @return {@code non-null;} the constructed list
 */
public static LocalList make(DalvInsnList insns) {
    int sz = insns.size();
    /*
         * Go through the insn list, looking for all the local
         * variable pseudoinstructions, splitting out LocalSnapshots
         * into separate per-variable starts, adding explicit ends
         * wherever a variable is replaced or moved, and collecting
         * these and all the other local variable "activity"
         * together into an output list (without the other insns).
         *
         * Note: As of this writing, this method won't be handed any
         * insn lists that contain local ends, but I (danfuzz) expect
         * that to change at some point, when we start feeding that
         * info explicitly into the rop layer rather than only trying
         * to infer it. So, given that expectation, this code is
         * written to deal with them.
         */
    MakeState state = new MakeState(sz);
    for (int i = 0; i < sz; i++) {
        DalvInsn insn = insns.get(i);
        if (insn instanceof LocalSnapshot) {
            RegisterSpecSet snapshot = ((LocalSnapshot) insn).getLocals();
            state.snapshot(insn.getAddress(), snapshot);
        } else if (insn instanceof LocalStart) {
            RegisterSpec local = ((LocalStart) insn).getLocal();
            state.startLocal(insn.getAddress(), local);
        }
    }
    LocalList result = state.finish();
    if (DEBUG) {
        debugVerify(result);
    }
    return result;
}
Also used : RegisterSpecSet(com.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 48 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.

the class EscapeAnalysis method processUse.

/**
 * Handles non-phi uses of new objects. Checks to see how instruction is
 * used and updates the escape state accordingly.
 *
 * @param def {@code non-null;} register holding definition of new object
 * @param use {@code non-null;} use of object being processed
 * @param escSet {@code non-null;} EscapeSet for the object
 * @param regWorklist {@code non-null;} worklist of instructions left to
 * process for this object
 */
private void processUse(RegisterSpec def, SsaInsn use, EscapeSet escSet, ArrayList<RegisterSpec> regWorklist) {
    int useOpcode = use.getOpcode().getOpcode();
    switch(useOpcode) {
        case RegOps.MOVE:
            // Follow uses of the move by adding it to the worklist
            escSet.regSet.set(use.getResult().getReg());
            regWorklist.add(use.getResult());
            break;
        case RegOps.IF_EQ:
        case RegOps.IF_NE:
        case RegOps.CHECK_CAST:
            // Compared objects can't be replaced, so promote if necessary
            if (escSet.escape.compareTo(EscapeState.METHOD) < 0) {
                escSet.escape = EscapeState.METHOD;
            }
            break;
        case RegOps.APUT:
            // For array puts, check for a constant array index
            RegisterSpec putIndex = use.getSources().get(2);
            if (!putIndex.getTypeBearer().isConstant()) {
                // If not constant, array can't be replaced
                escSet.replaceableArray = false;
            }
        // Intentional fallthrough
        case RegOps.PUT_FIELD:
            // Skip non-object puts
            RegisterSpec putValue = use.getSources().get(0);
            if (putValue.getTypeBearer().getBasicType() != Type.BT_OBJECT) {
                break;
            }
            escSet.replaceableArray = false;
            // Raise 1st object's escape state to 2nd if 2nd is higher
            RegisterSpecList sources = use.getSources();
            if (sources.get(0).getReg() == def.getReg()) {
                int setIndex = findSetIndex(sources.get(1));
                if (setIndex != latticeValues.size()) {
                    EscapeSet parentSet = latticeValues.get(setIndex);
                    addEdge(parentSet, escSet);
                    if (escSet.escape.compareTo(parentSet.escape) < 0) {
                        escSet.escape = parentSet.escape;
                    }
                }
            } else {
                int setIndex = findSetIndex(sources.get(0));
                if (setIndex != latticeValues.size()) {
                    EscapeSet childSet = latticeValues.get(setIndex);
                    addEdge(escSet, childSet);
                    if (childSet.escape.compareTo(escSet.escape) < 0) {
                        childSet.escape = escSet.escape;
                    }
                }
            }
            break;
        case RegOps.AGET:
            // For array gets, check for a constant array index
            RegisterSpec getIndex = use.getSources().get(1);
            if (!getIndex.getTypeBearer().isConstant()) {
                // If not constant, array can't be replaced
                escSet.replaceableArray = false;
            }
            break;
        case RegOps.PUT_STATIC:
            // Static puts cause an object to escape globally
            escSet.escape = EscapeState.GLOBAL;
            break;
        case RegOps.INVOKE_STATIC:
        case RegOps.INVOKE_VIRTUAL:
        case RegOps.INVOKE_SUPER:
        case RegOps.INVOKE_DIRECT:
        case RegOps.INVOKE_INTERFACE:
        case RegOps.RETURN:
        case RegOps.THROW:
            // These operations cause an object to escape interprocedurally
            escSet.escape = EscapeState.INTER;
            break;
        default:
            break;
    }
}
Also used : RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 49 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.

the class EscapeAnalysis method movePropagate.

/**
 * Identifies extra moves added by scalar replacement and propagates the
 * source of the move to any users of the result.
 */
private void movePropagate() {
    for (int i = 0; i < ssaMeth.getRegCount(); i++) {
        SsaInsn insn = ssaMeth.getDefinitionForRegister(i);
        // Look for move instructions only
        if (insn == null || insn.getOpcode() == null || insn.getOpcode().getOpcode() != RegOps.MOVE) {
            continue;
        }
        final ArrayList<SsaInsn>[] useList = ssaMeth.getUseListCopy();
        final RegisterSpec source = insn.getSources().get(0);
        final RegisterSpec result = insn.getResult();
        // Ignore moves that weren't added due to scalar replacement
        if (source.getReg() < regCount && result.getReg() < regCount) {
            continue;
        }
        // Create a mapping from source to result
        RegisterMapper mapper = new RegisterMapper() {

            @Override
            public int getNewRegisterCount() {
                return ssaMeth.getRegCount();
            }

            @Override
            public RegisterSpec map(RegisterSpec registerSpec) {
                if (registerSpec.getReg() == result.getReg()) {
                    return source;
                }
                return registerSpec;
            }
        };
        // Modify all uses of the move to use the source of the move instead
        for (SsaInsn use : useList[result.getReg()]) {
            use.mapSourceRegisters(mapper);
        }
    }
}
Also used : ArrayList(java.util.ArrayList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 50 with RegisterSpec

use of com.android.dx.rop.code.RegisterSpec in project J2ME-Loader by nikita36078.

the class EscapeAnalysis method scalarReplacement.

/**
 * Performs scalar replacement on all eligible arrays.
 */
private void scalarReplacement() {
    // Iterate through lattice, looking for non-escaping replaceable arrays
    for (EscapeSet escSet : latticeValues) {
        if (!escSet.replaceableArray || escSet.escape != EscapeState.NONE) {
            continue;
        }
        // Get the instructions for the definition and move of the array
        int e = escSet.regSet.nextSetBit(0);
        SsaInsn def = ssaMeth.getDefinitionForRegister(e);
        SsaInsn prev = getInsnForMove(def);
        // Create a map for the new registers that will be created
        TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
        int length = ((CstLiteralBits) lengthReg).getIntBits();
        ArrayList<RegisterSpec> newRegs = new ArrayList<RegisterSpec>(length);
        HashSet<SsaInsn> deletedInsns = new HashSet<SsaInsn>();
        // Replace the definition of the array with registers
        replaceDef(def, prev, length, newRegs);
        // Mark definition instructions for deletion
        deletedInsns.add(prev);
        deletedInsns.add(def);
        // Go through all uses of the array
        List<SsaInsn> useList = ssaMeth.getUseListForRegister(e);
        for (SsaInsn use : useList) {
            // Replace the use with scalars and then mark it for deletion
            replaceUse(use, prev, newRegs, deletedInsns);
            deletedInsns.add(use);
        }
        // Delete all marked instructions
        ssaMeth.deleteInsns(deletedInsns);
        ssaMeth.onInsnsChanged();
        // Convert the method back to SSA form
        SsaConverter.updateSsaMethod(ssaMeth, regCount);
        // Propagate and remove extra moves added by scalar replacement
        movePropagate();
    }
}
Also used : CstLiteralBits(com.android.dx.rop.cst.CstLiteralBits) ArrayList(java.util.ArrayList) TypeBearer(com.android.dx.rop.type.TypeBearer) RegisterSpec(com.android.dx.rop.code.RegisterSpec) HashSet(java.util.HashSet)

Aggregations

RegisterSpec (com.android.dx.rop.code.RegisterSpec)135 RegisterSpecList (com.android.dx.rop.code.RegisterSpecList)50 PlainInsn (com.android.dx.rop.code.PlainInsn)24 Constant (com.android.dx.rop.cst.Constant)20 TypedConstant (com.android.dx.rop.cst.TypedConstant)16 TypeBearer (com.android.dx.rop.type.TypeBearer)16 ArrayList (java.util.ArrayList)16 Insn (com.android.dx.rop.code.Insn)14 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)14 Rop (com.android.dx.rop.code.Rop)14 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)14 CstType (com.android.dx.rop.cst.CstType)14 BitSet (java.util.BitSet)11 LocalItem (com.android.dx.rop.code.LocalItem)10 RegisterSpecSet (com.android.dx.rop.code.RegisterSpecSet)10 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)10 CstString (com.android.dx.rop.cst.CstString)10 HashSet (java.util.HashSet)10 SourcePosition (com.android.dx.rop.code.SourcePosition)8 CstFieldRef (com.android.dx.rop.cst.CstFieldRef)8