Search in sources :

Example 1 with RegisterSpecSet

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

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.taobao.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 2 with RegisterSpecSet

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

the class RopTranslator method outputBlock.

/**
     * Helper for {@link #outputInstructions}, which does the processing
     * and output of one block.
     *
     * @param block {@code non-null;} the block to process and output
     * @param nextLabel {@code >= -1;} the next block that will be processed, or
     * {@code -1} if there is no next block
     */
private void outputBlock(BasicBlock block, int nextLabel) {
    // Append the code address for this block.
    CodeAddress startAddress = addresses.getStart(block);
    output.add(startAddress);
    // Append the local variable state for the block.
    if (locals != null) {
        RegisterSpecSet starts = locals.getStarts(block);
        output.add(new LocalSnapshot(startAddress.getPosition(), starts));
    }
    /*
         * Choose and append an output instruction for each original
         * instruction.
         */
    translationVisitor.setBlock(block, addresses.getLast(block));
    block.getInsns().forEach(translationVisitor);
    // Insert the block end code address.
    output.add(addresses.getEnd(block));
    // Set up for end-of-block activities.
    int succ = block.getPrimarySuccessor();
    Insn lastInsn = block.getLastInsn();
    if ((succ >= 0) && (succ != nextLabel)) {
        /*
             * The block has a "primary successor" and that primary
             * successor isn't the next block to be output.
             */
        Rop lastRop = lastInsn.getOpcode();
        if ((lastRop.getBranchingness() == Rop.BRANCH_IF) && (block.getSecondarySuccessor() == nextLabel)) {
            /*
                 * The block ends with an "if" of some sort, and its
                 * secondary successor (the "then") is in fact the
                 * next block to output. So, reverse the sense of
                 * the test, so that we can just emit the next block
                 * without an interstitial goto.
                 */
            output.reverseBranch(1, addresses.getStart(succ));
        } else {
            /*
                 * Our only recourse is to add a goto here to get the
                 * flow to be correct.
                 */
            TargetInsn insn = new TargetInsn(Dops.GOTO, lastInsn.getPosition(), RegisterSpecList.EMPTY, addresses.getStart(succ));
            output.add(insn);
        }
    }
}
Also used : Insn(com.taobao.android.dx.rop.code.Insn) ThrowingInsn(com.taobao.android.dx.rop.code.ThrowingInsn) PlainCstInsn(com.taobao.android.dx.rop.code.PlainCstInsn) ThrowingCstInsn(com.taobao.android.dx.rop.code.ThrowingCstInsn) SwitchInsn(com.taobao.android.dx.rop.code.SwitchInsn) FillArrayDataInsn(com.taobao.android.dx.rop.code.FillArrayDataInsn) PlainInsn(com.taobao.android.dx.rop.code.PlainInsn) Rop(com.taobao.android.dx.rop.code.Rop) RegisterSpecSet(com.taobao.android.dx.rop.code.RegisterSpecSet)

Example 3 with RegisterSpecSet

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

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.taobao.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec)

Example 4 with RegisterSpecSet

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

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.taobao.android.dx.rop.code.RegisterSpecSet) RegisterSpec(com.taobao.android.dx.rop.code.RegisterSpec) IntList(com.taobao.android.dx.util.IntList)

Example 5 with RegisterSpecSet

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

the class LocalVariableInfo method mergeStarts.

/**
     * Merges the given register set into the set for the block with the
     * given index. If there was not already an associated set, then this
     * is the same as calling {@link #setStarts}. Otherwise, this will
     * merge the two sets and call {@link #setStarts} on the result of the
     * merge.
     *
     * @param index {@code >= 0;} the block index
     * @param specs {@code non-null;} the register set to merge into the start set
     * for the block
     * @return {@code true} if the merge resulted in an actual change
     * to the associated set (including storing one for the first time) or
     * {@code false} if there was no change
     */
public boolean mergeStarts(int index, RegisterSpecSet specs) {
    RegisterSpecSet start = getStarts0(index);
    boolean changed = false;
    if (start == null) {
        setStarts(index, specs);
        return true;
    }
    RegisterSpecSet newStart = start.mutableCopy();
    newStart.intersect(specs, true);
    if (start.equals(newStart)) {
        return false;
    }
    newStart.setImmutable();
    setStarts(index, newStart);
    return true;
}
Also used : RegisterSpecSet(com.taobao.android.dx.rop.code.RegisterSpecSet)

Aggregations

RegisterSpecSet (com.taobao.android.dx.rop.code.RegisterSpecSet)7 RegisterSpec (com.taobao.android.dx.rop.code.RegisterSpec)5 FillArrayDataInsn (com.taobao.android.dx.rop.code.FillArrayDataInsn)1 Insn (com.taobao.android.dx.rop.code.Insn)1 PlainCstInsn (com.taobao.android.dx.rop.code.PlainCstInsn)1 PlainInsn (com.taobao.android.dx.rop.code.PlainInsn)1 Rop (com.taobao.android.dx.rop.code.Rop)1 SwitchInsn (com.taobao.android.dx.rop.code.SwitchInsn)1 ThrowingCstInsn (com.taobao.android.dx.rop.code.ThrowingCstInsn)1 ThrowingInsn (com.taobao.android.dx.rop.code.ThrowingInsn)1 Constant (com.taobao.android.dx.rop.cst.Constant)1 IntList (com.taobao.android.dx.util.IntList)1