Search in sources :

Example 1 with RegisterSpecSet

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

the class OutputFinisher method hasLocalInfo.

/**
     * Helper for {@link #add} which scrutinizes a single
     * instruction for local variable information.
     *
     * @param insn {@code non-null;} instruction to scrutinize
     * @return {@code true} iff the instruction refers to any
     * named locals
     */
private static boolean hasLocalInfo(DalvInsn insn) {
    if (insn instanceof LocalSnapshot) {
        RegisterSpecSet specs = ((LocalSnapshot) insn).getLocals();
        int size = specs.size();
        for (int i = 0; i < size; i++) {
            if (hasLocalInfo(specs.get(i))) {
                return true;
            }
        }
    } else if (insn instanceof LocalStart) {
        RegisterSpec spec = ((LocalStart) insn).getLocal();
        if (hasLocalInfo(spec)) {
            return true;
        }
    }
    return false;
}
Also used : RegisterSpecSet(com.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 2 with RegisterSpecSet

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

the class LocalVariableExtractor method processBlock.

/**
     * Processes a single block.
     *
     * @param blockIndex {@code >= 0;} block index of the block to process
     */
private void processBlock(int blockIndex) {
    RegisterSpecSet primaryState = resultInfo.mutableCopyOfStarts(blockIndex);
    SsaBasicBlock block = blocks.get(blockIndex);
    List<SsaInsn> insns = block.getInsns();
    int insnSz = insns.size();
    // The exit block has no insns and no successors
    if (blockIndex == method.getExitBlockIndex()) {
        return;
    }
    /*
         * We may have to treat the last instruction specially: If it
         * can (but doesn't always) throw, and the exception can be
         * caught within the same method, then we need to use the
         * state *before* executing it to be what is merged into
         * exception targets.
         */
    SsaInsn lastInsn = insns.get(insnSz - 1);
    boolean hasExceptionHandlers = lastInsn.getOriginalRopInsn().getCatches().size() != 0;
    boolean canThrowDuringLastInsn = hasExceptionHandlers && (lastInsn.getResult() != null);
    int freezeSecondaryStateAt = insnSz - 1;
    RegisterSpecSet secondaryState = primaryState;
    for (int i = 0; i < insnSz; i++) {
        if (canThrowDuringLastInsn && (i == freezeSecondaryStateAt)) {
            // Until this point, primaryState == secondaryState.
            primaryState.setImmutable();
            primaryState = primaryState.mutableCopy();
        }
        SsaInsn insn = insns.get(i);
        RegisterSpec result;
        result = insn.getLocalAssignment();
        if (result == null) {
            // We may be nuking an existing local
            result = insn.getResult();
            if (result != null && primaryState.get(result.getReg()) != null) {
                primaryState.remove(primaryState.get(result.getReg()));
            }
            continue;
        }
        result = result.withSimpleType();
        RegisterSpec already = primaryState.get(result);
        /*
             * The equals() check ensures we only add new info if
             * the instruction causes a change to the set of
             * active variables.
             */
        if (!result.equals(already)) {
            /*
                 * If this insn represents a local moving from one register
                 * to another, remove the association between the old register
                 * and the local.
                 */
            RegisterSpec previous = primaryState.localItemToSpec(result.getLocalItem());
            if (previous != null && (previous.getReg() != result.getReg())) {
                primaryState.remove(previous);
            }
            resultInfo.addAssignment(insn, result);
            primaryState.put(result);
        }
    }
    primaryState.setImmutable();
    /*
         * Merge this state into the start state for each successor,
         * and update the work set where required (that is, in cases
         * where the start state for a block changes).
         */
    IntList successors = block.getSuccessorList();
    int succSz = successors.size();
    int primarySuccessor = block.getPrimarySuccessorIndex();
    for (int i = 0; i < succSz; i++) {
        int succ = successors.get(i);
        RegisterSpecSet state = (succ == primarySuccessor) ? primaryState : secondaryState;
        if (resultInfo.mergeStarts(succ, state)) {
            workSet.set(succ);
        }
    }
}
Also used : RegisterSpecSet(com.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.android.dx.rop.code.RegisterSpec) IntList(com.android.dx.util.IntList)

Example 3 with RegisterSpecSet

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

the class RegisterMapper method map.

/**
     *
     * @param sources old register set
     * @return new mapped register set, or old if nothing has changed.
     */
public final RegisterSpecSet map(RegisterSpecSet sources) {
    int sz = sources.getMaxSize();
    RegisterSpecSet newSources = new RegisterSpecSet(getNewRegisterCount());
    for (int i = 0; i < sz; i++) {
        RegisterSpec registerSpec = sources.get(i);
        if (registerSpec != null) {
            newSources.put(map(registerSpec));
        }
    }
    newSources.setImmutable();
    // Return the old sources if nothing has changed.
    return newSources.equals(sources) ? sources : newSources;
}
Also used : RegisterSpecSet(com.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 4 with RegisterSpecSet

use of com.android.dx.rop.code.RegisterSpecSet 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 5 with RegisterSpecSet

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

the class LocalVariableExtractor method processBlock.

/**
 * Processes a single block.
 *
 * @param blockIndex {@code >= 0;} block index of the block to process
 */
private void processBlock(int blockIndex) {
    RegisterSpecSet primaryState = resultInfo.mutableCopyOfStarts(blockIndex);
    SsaBasicBlock block = blocks.get(blockIndex);
    List<SsaInsn> insns = block.getInsns();
    int insnSz = insns.size();
    // The exit block has no insns and no successors
    if (blockIndex == method.getExitBlockIndex()) {
        return;
    }
    /*
         * We may have to treat the last instruction specially: If it
         * can (but doesn't always) throw, and the exception can be
         * caught within the same method, then we need to use the
         * state *before* executing it to be what is merged into
         * exception targets.
         */
    SsaInsn lastInsn = insns.get(insnSz - 1);
    boolean hasExceptionHandlers = lastInsn.getOriginalRopInsn().getCatches().size() != 0;
    boolean canThrowDuringLastInsn = hasExceptionHandlers && (lastInsn.getResult() != null);
    int freezeSecondaryStateAt = insnSz - 1;
    RegisterSpecSet secondaryState = primaryState;
    for (int i = 0; i < insnSz; i++) {
        if (canThrowDuringLastInsn && (i == freezeSecondaryStateAt)) {
            // Until this point, primaryState == secondaryState.
            primaryState.setImmutable();
            primaryState = primaryState.mutableCopy();
        }
        SsaInsn insn = insns.get(i);
        RegisterSpec result;
        result = insn.getLocalAssignment();
        if (result == null) {
            // We may be nuking an existing local
            result = insn.getResult();
            if (result != null && primaryState.get(result.getReg()) != null) {
                primaryState.remove(primaryState.get(result.getReg()));
            }
            continue;
        }
        result = result.withSimpleType();
        RegisterSpec already = primaryState.get(result);
        /*
             * The equals() check ensures we only add new info if
             * the instruction causes a change to the set of
             * active variables.
             */
        if (!result.equals(already)) {
            /*
                 * If this insn represents a local moving from one register
                 * to another, remove the association between the old register
                 * and the local.
                 */
            RegisterSpec previous = primaryState.localItemToSpec(result.getLocalItem());
            if (previous != null && (previous.getReg() != result.getReg())) {
                primaryState.remove(previous);
            }
            resultInfo.addAssignment(insn, result);
            primaryState.put(result);
        }
    }
    primaryState.setImmutable();
    /*
         * Merge this state into the start state for each successor,
         * and update the work set where required (that is, in cases
         * where the start state for a block changes).
         */
    IntList successors = block.getSuccessorList();
    int succSz = successors.size();
    int primarySuccessor = block.getPrimarySuccessorIndex();
    for (int i = 0; i < succSz; i++) {
        int succ = successors.get(i);
        RegisterSpecSet state = (succ == primarySuccessor) ? primaryState : secondaryState;
        if (resultInfo.mergeStarts(succ, state)) {
            workSet.set(succ);
        }
    }
}
Also used : RegisterSpecSet(com.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.android.dx.rop.code.RegisterSpec) IntList(com.android.dx.util.IntList)

Aggregations

RegisterSpecSet (com.android.dx.rop.code.RegisterSpecSet)14 RegisterSpec (com.android.dx.rop.code.RegisterSpec)10 FillArrayDataInsn (com.android.dx.rop.code.FillArrayDataInsn)2 Insn (com.android.dx.rop.code.Insn)2 PlainCstInsn (com.android.dx.rop.code.PlainCstInsn)2 PlainInsn (com.android.dx.rop.code.PlainInsn)2 Rop (com.android.dx.rop.code.Rop)2 SwitchInsn (com.android.dx.rop.code.SwitchInsn)2 ThrowingCstInsn (com.android.dx.rop.code.ThrowingCstInsn)2 ThrowingInsn (com.android.dx.rop.code.ThrowingInsn)2 Constant (com.android.dx.rop.cst.Constant)2 IntList (com.android.dx.util.IntList)2 InvokePolymorphicInsn (com.android.dx.rop.code.InvokePolymorphicInsn)1