Search in sources :

Example 61 with RegisterSpec

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

the class FirstFitLocalCombiningAllocator method processPhiInsn.

/**
 * Attempts to map the sources and result of a phi to a common register.
 * Will try existing mappings first, from most to least common. If none
 * of the registers have mappings yet, a new mapping is created.
 */
private void processPhiInsn(PhiInsn insn) {
    RegisterSpec result = insn.getResult();
    int resultReg = result.getReg();
    int category = result.getCategory();
    RegisterSpecList sources = insn.getSources();
    int sourcesSize = sources.size();
    // List of phi sources / result that need mapping
    ArrayList<RegisterSpec> ssaRegs = new ArrayList<RegisterSpec>();
    // Track how many times a particular mapping is found
    Multiset mapSet = new Multiset(sourcesSize + 1);
    /*
         * If the result of the phi has an existing mapping, get it.
         * Otherwise, add it to the list of regs that need mapping.
         */
    if (ssaRegsMapped.get(resultReg)) {
        mapSet.add(mapper.oldToNew(resultReg));
    } else {
        ssaRegs.add(result);
    }
    for (int i = 0; i < sourcesSize; i++) {
        RegisterSpec source = sources.get(i);
        SsaInsn def = ssaMeth.getDefinitionForRegister(source.getReg());
        RegisterSpec sourceDef = def.getResult();
        int sourceReg = sourceDef.getReg();
        /*
             * If a source of the phi has an existing mapping, get it.
             * Otherwise, add it to the list of regs that need mapping.
             */
        if (ssaRegsMapped.get(sourceReg)) {
            mapSet.add(mapper.oldToNew(sourceReg));
        } else {
            ssaRegs.add(sourceDef);
        }
    }
    // Try all existing mappings, with the most common ones first
    for (int i = 0; i < mapSet.getSize(); i++) {
        int maxReg = mapSet.getAndRemoveHighestCount();
        tryMapRegs(ssaRegs, maxReg, category, false);
    }
    // Map any remaining unmapped regs with whatever fits
    int mapReg = findNextUnreservedRopReg(paramRangeEnd, category);
    while (!tryMapRegs(ssaRegs, mapReg, category, false)) {
        mapReg = findNextUnreservedRopReg(mapReg + 1, category);
    }
}
Also used : ArrayList(java.util.ArrayList) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaInsn(com.android.dx.ssa.SsaInsn) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 62 with RegisterSpec

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

the class FirstFitLocalCombiningAllocator method tryMapRegs.

/**
 * Tries to map a list of SSA registers into the a rop reg, marking
 * used rop space as reserved. SSA registers that don't fit are left
 * unmapped.
 *
 * @param specs {@code non-null;} SSA registers to attempt to map
 * @param ropReg {@code >=0;} rop register to map to
 * @param maxAllowedCategory {@code 1..2;} maximum category
 * allowed in mapping.
 * @param markReserved do so if {@code true}
 * @return {@code true} if all registers were mapped, {@code false}
 * if some remain unmapped
 */
private boolean tryMapRegs(ArrayList<RegisterSpec> specs, int ropReg, int maxAllowedCategory, boolean markReserved) {
    boolean remaining = false;
    for (RegisterSpec spec : specs) {
        if (ssaRegsMapped.get(spec.getReg())) {
            continue;
        }
        boolean succeeded;
        succeeded = tryMapReg(spec, ropReg, maxAllowedCategory);
        remaining = !succeeded || remaining;
        if (succeeded && markReserved) {
            // This only needs to be called once really with
            // the widest category used, but <shrug>
            markReserved(ropReg, spec.getCategory());
        }
    }
    return !remaining;
}
Also used : RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 63 with RegisterSpec

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

the class FirstFitLocalCombiningAllocator method handleCheckCastResults.

/**
 * Handles check cast results to reuse the same source register.
 * Inserts a move if it can't map the same register to both and the
 * check cast is not caught.
 */
private void handleCheckCastResults() {
    for (NormalSsaInsn insn : moveResultPseudoInsns) {
        RegisterSpec moveRegSpec = insn.getResult();
        int moveReg = moveRegSpec.getReg();
        BitSet predBlocks = insn.getBlock().getPredecessors();
        // Expect one predecessor block only
        if (predBlocks.cardinality() != 1) {
            continue;
        }
        SsaBasicBlock predBlock = ssaMeth.getBlocks().get(predBlocks.nextSetBit(0));
        ArrayList<SsaInsn> insnList = predBlock.getInsns();
        /**
         * If the predecessor block has a check-cast, it will be the last
         * instruction
         */
        SsaInsn checkCastInsn = insnList.get(insnList.size() - 1);
        if (checkCastInsn.getOpcode().getOpcode() != RegOps.CHECK_CAST) {
            continue;
        }
        RegisterSpec checkRegSpec = checkCastInsn.getSources().get(0);
        int checkReg = checkRegSpec.getReg();
        /**
         * See if either register is already mapped. Most likely the move
         * result will be mapped already since the cast result is stored
         * in a local variable.
         */
        int category = checkRegSpec.getCategory();
        boolean moveMapped = ssaRegsMapped.get(moveReg);
        boolean checkMapped = ssaRegsMapped.get(checkReg);
        if (moveMapped & !checkMapped) {
            int moveRopReg = mapper.oldToNew(moveReg);
            checkMapped = tryMapReg(checkRegSpec, moveRopReg, category);
        }
        if (checkMapped & !moveMapped) {
            int checkRopReg = mapper.oldToNew(checkReg);
            moveMapped = tryMapReg(moveRegSpec, checkRopReg, category);
        }
        // Map any unmapped registers to anything available
        if (!moveMapped || !checkMapped) {
            int ropReg = findNextUnreservedRopReg(paramRangeEnd, category);
            ArrayList<RegisterSpec> ssaRegs = new ArrayList<RegisterSpec>(2);
            ssaRegs.add(moveRegSpec);
            ssaRegs.add(checkRegSpec);
            while (!tryMapRegs(ssaRegs, ropReg, category, false)) {
                ropReg = findNextUnreservedRopReg(ropReg + 1, category);
            }
        }
        /*
             * If source and result have a different mapping, insert a move so
             * they can have the same mapping. Don't do this if the check cast
             * is caught, since it will overwrite a potentially live value.
             */
        boolean hasExceptionHandlers = checkCastInsn.getOriginalRopInsn().getCatches().size() != 0;
        int moveRopReg = mapper.oldToNew(moveReg);
        int checkRopReg = mapper.oldToNew(checkReg);
        if (moveRopReg != checkRopReg && !hasExceptionHandlers) {
            ((NormalSsaInsn) checkCastInsn).changeOneSource(0, insertMoveBefore(checkCastInsn, checkRegSpec));
            addMapping(checkCastInsn.getSources().get(0), moveRopReg);
        }
    }
}
Also used : NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaBasicBlock(com.android.dx.ssa.SsaBasicBlock) BitSet(java.util.BitSet) ArrayList(java.util.ArrayList) NormalSsaInsn(com.android.dx.ssa.NormalSsaInsn) SsaInsn(com.android.dx.ssa.SsaInsn) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 64 with RegisterSpec

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

the class FirstFitLocalCombiningAllocator method handleLocalAssociatedParams.

/**
 * Maps all local-associated parameters to rop registers.
 */
private void handleLocalAssociatedParams() {
    for (ArrayList<RegisterSpec> ssaRegs : localVariables.values()) {
        int sz = ssaRegs.size();
        int paramIndex = -1;
        int paramCategory = 0;
        // First, find out if this local variable is a parameter.
        for (int i = 0; i < sz; i++) {
            RegisterSpec ssaSpec = ssaRegs.get(i);
            int ssaReg = ssaSpec.getReg();
            paramIndex = getParameterIndexForReg(ssaReg);
            if (paramIndex >= 0) {
                paramCategory = ssaSpec.getCategory();
                addMapping(ssaSpec, paramIndex);
                break;
            }
        }
        if (paramIndex < 0) {
            // This local wasn't a parameter.
            continue;
        }
        // Any remaining local-associated registers will be mapped later.
        tryMapRegs(ssaRegs, paramIndex, paramCategory, true);
    }
}
Also used : RegisterSpec(com.android.dx.rop.code.RegisterSpec)

Example 65 with RegisterSpec

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

the class FirstFitLocalCombiningAllocator method fitPlanForRange.

/**
 * Attempts to build a plan for fitting a range of sources into rop
 * registers.
 *
 * @param ropReg {@code >= 0;} rop reg that begins range
 * @param insn {@code non-null;} insn to plan range for
 * @param categoriesForIndex {@code non-null;} indexed by source index;
 * the category for each source
 * @param outMovesRequired {@code non-null;} an output parameter indexed by
 * source index that will contain the set of sources which need
 * moves inserted
 * @return the width of the fit that that does not involve added moves or
 * {@code -1} if "no fit possible"
 */
private int fitPlanForRange(int ropReg, NormalSsaInsn insn, int[] categoriesForIndex, BitSet outMovesRequired) {
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();
    int fitWidth = 0;
    IntSet liveOut = insn.getBlock().getLiveOutRegs();
    RegisterSpecList liveOutSpecs = ssaSetToSpecs(liveOut);
    // An SSA reg may only be mapped into a range once.
    BitSet seen = new BitSet(ssaMeth.getRegCount());
    for (int i = 0; i < szSources; i++) {
        RegisterSpec ssaSpec = sources.get(i);
        int ssaReg = ssaSpec.getReg();
        int category = categoriesForIndex[i];
        if (i != 0) {
            ropReg += categoriesForIndex[i - 1];
        }
        if (ssaRegsMapped.get(ssaReg) && mapper.oldToNew(ssaReg) == ropReg) {
            // This is a register that is already mapped appropriately.
            fitWidth += category;
        } else if (rangeContainsReserved(ropReg, category)) {
            fitWidth = -1;
            break;
        } else if (!ssaRegsMapped.get(ssaReg) && canMapReg(ssaSpec, ropReg) && !seen.get(ssaReg)) {
            // This is a register that can be mapped appropriately.
            fitWidth += category;
        } else if (!mapper.areAnyPinned(liveOutSpecs, ropReg, category) && !mapper.areAnyPinned(sources, ropReg, category)) {
            /*
                 * This is a source that can be moved. We can insert a
                 * move as long as:
                 *
                 *   * no SSA register pinned to the desired rop reg
                 *     is live out on the block
                 *
                 *   * no SSA register pinned to desired rop reg is
                 *     a source of this insn (since this may require
                 *     overlapping moves, which we can't presently handle)
                 */
            outMovesRequired.set(i);
        } else {
            fitWidth = -1;
            break;
        }
        seen.set(ssaReg);
    }
    return fitWidth;
}
Also used : IntSet(com.android.dx.util.IntSet) BitSet(java.util.BitSet) RegisterSpecList(com.android.dx.rop.code.RegisterSpecList) RegisterSpec(com.android.dx.rop.code.RegisterSpec)

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