Java Code Examples for com.android.dx.rop.code.RegisterSpec#make()

The following examples show how to use com.android.dx.rop.code.RegisterSpec#make() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: EscapeAnalysis.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Replaces the instructions that define an array with equivalent registers.
 * For each entry in the array, a register is created, initialized to zero.
 * A mapping between this register and the corresponding array index is
 * added.
 *
 * @param def {@code non-null;} move result instruction for array
 * @param prev {@code non-null;} instruction for instantiating new array
 * @param length size of the new array
 * @param newRegs {@code non-null;} mapping of array indices to new
 * registers to be populated
 */
private void replaceDef(SsaInsn def, SsaInsn prev, int length,
                            ArrayList<RegisterSpec> newRegs) {
    Type resultType = def.getResult().getType();

    // Create new zeroed out registers for each element in the array
    for (int i = 0; i < length; i++) {
        Constant newZero = Zeroes.zeroFor(resultType.getComponentType());
        TypedConstant typedZero = (TypedConstant) newZero;
        RegisterSpec newReg =
            RegisterSpec.make(ssaMeth.makeNewSsaReg(), typedZero);
        newRegs.add(newReg);
        insertPlainInsnBefore(def, RegisterSpecList.EMPTY, newReg,
                                  RegOps.CONST, newZero);
    }
}
 
Example 2
Source File: EscapeAnalysis.java    From J2ME-Loader with Apache License 2.0 6 votes vote down vote up
/**
 * Replaces the instructions that define an array with equivalent registers.
 * For each entry in the array, a register is created, initialized to zero.
 * A mapping between this register and the corresponding array index is
 * added.
 *
 * @param def {@code non-null;} move result instruction for array
 * @param prev {@code non-null;} instruction for instantiating new array
 * @param length size of the new array
 * @param newRegs {@code non-null;} mapping of array indices to new
 * registers to be populated
 */
private void replaceDef(SsaInsn def, SsaInsn prev, int length,
                            ArrayList<RegisterSpec> newRegs) {
    Type resultType = def.getResult().getType();

    // Create new zeroed out registers for each element in the array
    for (int i = 0; i < length; i++) {
        Constant newZero = Zeroes.zeroFor(resultType.getComponentType());
        TypedConstant typedZero = (TypedConstant) newZero;
        RegisterSpec newReg =
            RegisterSpec.make(ssaMeth.makeNewSsaReg(), typedZero);
        newRegs.add(newReg);
        insertPlainInsnBefore(def, RegisterSpecList.EMPTY, newReg,
                                  RegOps.CONST, newZero);
    }
}
 
Example 3
Source File: Ropper.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Gets the register spec to use to hold the object to synchronize on,
 * for a synchronized method.
 *
 * @return {@code non-null;} the register spec
 */
private RegisterSpec getSynchReg() {
    /*
     * We use the register that is just past the deepest possible
     * stack element, with a minimum of v1 since v0 is what's
     * always used to hold the caught exception when unwinding. We
     * don't need to do anything else special at this level, since
     * later passes will merely notice the highest register used
     * by explicit inspection.
     */
    int reg = getNormalRegCount();
    return RegisterSpec.make((reg < 1) ? 1 : reg, Type.OBJECT);
}
 
Example 4
Source File: Ropper.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Gets the register spec to use to hold the object to synchronize on,
 * for a synchronized method.
 *
 * @return {@code non-null;} the register spec
 */
private RegisterSpec getSynchReg() {
    /*
     * We use the register that is just past the deepest possible
     * stack element, with a minimum of v1 since v0 is what's
     * always used to hold the caught exception when unwinding. We
     * don't need to do anything else special at this level, since
     * later passes will merely notice the highest register used
     * by explicit inspection.
     */
    int reg = getNormalRegCount();
    return RegisterSpec.make((reg < 1) ? 1 : reg, Type.OBJECT);
}
 
Example 5
Source File: EscapeAnalysis.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * Replaces instructions that trigger an ArrayIndexOutofBounds exception
 * with an actual throw of the exception.
 *
 * @param insn {@code non-null;} instruction causing the exception
 * @param index {@code non-null;} index value that is out of bounds
 * @param deletedInsns {@code non-null;} set of instructions marked for
 * deletion
 */
private void insertExceptionThrow(SsaInsn insn, RegisterSpec index,
                                      HashSet<SsaInsn> deletedInsns) {
    // Create a new ArrayIndexOutOfBoundsException
    CstType exception =
        new CstType(Exceptions.TYPE_ArrayIndexOutOfBoundsException);
    insertThrowingInsnBefore(insn, RegisterSpecList.EMPTY, null,
                                 RegOps.NEW_INSTANCE, exception);

    // Add a successor block with a move result pseudo for the exception
    SsaBasicBlock currBlock = insn.getBlock();
    SsaBasicBlock newBlock =
        currBlock.insertNewSuccessor(currBlock.getPrimarySuccessor());
    SsaInsn newInsn = newBlock.getInsns().get(0);
    RegisterSpec newReg =
        RegisterSpec.make(ssaMeth.makeNewSsaReg(), exception);
    insertPlainInsnBefore(newInsn, RegisterSpecList.EMPTY, newReg,
                              RegOps.MOVE_RESULT_PSEUDO, null);

    // Add another successor block to initialize the exception
    SsaBasicBlock newBlock2 =
        newBlock.insertNewSuccessor(newBlock.getPrimarySuccessor());
    SsaInsn newInsn2 = newBlock2.getInsns().get(0);
    CstNat newNat = new CstNat(new CstString("<init>"), new CstString("(I)V"));
    CstMethodRef newRef = new CstMethodRef(exception, newNat);
    insertThrowingInsnBefore(newInsn2, RegisterSpecList.make(newReg, index),
                                 null, RegOps.INVOKE_DIRECT, newRef);
    deletedInsns.add(newInsn2);

    // Add another successor block to throw the new exception
    SsaBasicBlock newBlock3 =
        newBlock2.insertNewSuccessor(newBlock2.getPrimarySuccessor());
    SsaInsn newInsn3 = newBlock3.getInsns().get(0);
    insertThrowingInsnBefore(newInsn3, RegisterSpecList.make(newReg), null,
                                 RegOps.THROW, null);
    newBlock3.replaceSuccessor(newBlock3.getPrimarySuccessorIndex(),
                                   ssaMeth.getExitBlock().getIndex());
    deletedInsns.add(newInsn3);
}
 
Example 6
Source File: PhiInsn.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Makes a phi insn with a void result type.
 *
 * @param resultReg the result register for this phi insn.
 * @param block block containing this insn.
 */
public PhiInsn(final int resultReg, final SsaBasicBlock block) {
    /*
     * The result type here is bogus: The type depends on the
     * operand and will be derived later.
     */
    super(RegisterSpec.make(resultReg, Type.VOID), block);
    ropResultReg = resultReg;
}
 
Example 7
Source File: Ropper.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Gets the register spec to use to hold the object to synchronize on,
 * for a synchronized method.
 *
 * @return {@code non-null;} the register spec
 */
private RegisterSpec getSynchReg() {
    /*
     * We use the register that is just past the deepest possible
     * stack element, with a minimum of v1 since v0 is what's
     * always used to hold the caught exception when unwinding. We
     * don't need to do anything else special at this level, since
     * later passes will merely notice the highest register used
     * by explicit inspection.
     */
    int reg = getNormalRegCount();
    return RegisterSpec.make((reg < 1) ? 1 : reg, Type.OBJECT);
}
 
Example 8
Source File: PhiInsn.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Makes a phi insn with a void result type.
 *
 * @param resultReg the result register for this phi insn.
 * @param block block containing this insn.
 */
public PhiInsn(final int resultReg, final SsaBasicBlock block) {
    /*
     * The result type here is bogus: The type depends on the
     * operand and will be derived later.
     */
    super(RegisterSpec.make(resultReg, Type.VOID), block);
    ropResultReg = resultReg;
}
 
Example 9
Source File: EscapeAnalysis.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Replaces instructions that trigger an ArrayIndexOutofBounds exception
 * with an actual throw of the exception.
 *
 * @param insn {@code non-null;} instruction causing the exception
 * @param index {@code non-null;} index value that is out of bounds
 * @param deletedInsns {@code non-null;} set of instructions marked for
 * deletion
 */
private void insertExceptionThrow(SsaInsn insn, RegisterSpec index,
                                      HashSet<SsaInsn> deletedInsns) {
    // Create a new ArrayIndexOutOfBoundsException
    CstType exception =
        new CstType(Exceptions.TYPE_ArrayIndexOutOfBoundsException);
    insertThrowingInsnBefore(insn, RegisterSpecList.EMPTY, null,
                                 RegOps.NEW_INSTANCE, exception);

    // Add a successor block with a move result pseudo for the exception
    SsaBasicBlock currBlock = insn.getBlock();
    SsaBasicBlock newBlock =
        currBlock.insertNewSuccessor(currBlock.getPrimarySuccessor());
    SsaInsn newInsn = newBlock.getInsns().get(0);
    RegisterSpec newReg =
        RegisterSpec.make(ssaMeth.makeNewSsaReg(), exception);
    insertPlainInsnBefore(newInsn, RegisterSpecList.EMPTY, newReg,
                              RegOps.MOVE_RESULT_PSEUDO, null);

    // Add another successor block to initialize the exception
    SsaBasicBlock newBlock2 =
        newBlock.insertNewSuccessor(newBlock.getPrimarySuccessor());
    SsaInsn newInsn2 = newBlock2.getInsns().get(0);
    CstNat newNat = new CstNat(new CstString("<init>"), new CstString("(I)V"));
    CstMethodRef newRef = new CstMethodRef(exception, newNat);
    insertThrowingInsnBefore(newInsn2, RegisterSpecList.make(newReg, index),
                                 null, RegOps.INVOKE_DIRECT, newRef);
    deletedInsns.add(newInsn2);

    // Add another successor block to throw the new exception
    SsaBasicBlock newBlock3 =
        newBlock2.insertNewSuccessor(newBlock2.getPrimarySuccessor());
    SsaInsn newInsn3 = newBlock3.getInsns().get(0);
    insertThrowingInsnBefore(newInsn3, RegisterSpecList.make(newReg), null,
                                 RegOps.THROW, null);
    newBlock3.replaceSuccessor(newBlock3.getPrimarySuccessorIndex(),
                                   ssaMeth.getExitBlock().getIndex());
    deletedInsns.add(newInsn3);
}
 
Example 10
Source File: PhiInsn.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * Makes a phi insn with a void result type.
 *
 * @param resultReg the result register for this phi insn.
 * @param block block containing this insn.
 */
public PhiInsn(final int resultReg, final SsaBasicBlock block) {
    /*
     * The result type here is bogus: The type depends on the
     * operand and will be derived later.
     */
    super(RegisterSpec.make(resultReg, Type.VOID), block);
    ropResultReg = resultReg;
}
 
Example 11
Source File: PhiInsn.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Makes a phi insn with a void result type.
 *
 * @param resultReg the result register for this phi insn.
 * @param block block containing this insn.
 */
public PhiInsn(final int resultReg, final SsaBasicBlock block) {
    /*
     * The result type here is bogus: The type depends on the
     * operand and will be derived later.
     */
    super(RegisterSpec.make(resultReg, Type.VOID), block);
    ropResultReg = resultReg;
}
 
Example 12
Source File: RopTranslator.java    From Box with Apache License 2.0 5 votes vote down vote up
/** {@inheritDoc} */
@Override
public void visitPlainCstInsn(PlainCstInsn insn) {
    SourcePosition pos = insn.getPosition();
    Dop opcode = RopToDop.dopFor(insn);
    Rop rop = insn.getOpcode();
    int ropOpcode = rop.getOpcode();
    DalvInsn di;

    if (rop.getBranchingness() != Rop.BRANCH_NONE) {
        throw new RuntimeException("shouldn't happen");
    }

    if (ropOpcode == RegOps.MOVE_PARAM) {
        if (!paramsAreInOrder) {
            /*
             * Parameters are not in order at the top of the reg space.
             * We need to add moves.
             */

            RegisterSpec dest = insn.getResult();
            int param =
                ((CstInteger) insn.getConstant()).getValue();
            RegisterSpec source =
                RegisterSpec.make(regCount - paramSize + param,
                        dest.getType());
            di = new SimpleInsn(opcode, pos,
                                RegisterSpecList.make(dest, source));
            addOutput(di);
        }
    } else {
        // No moves required for the parameters
        RegisterSpecList regs = getRegs(insn);
        di = new CstInsn(opcode, pos, regs, insn.getConstant());
        addOutput(di);
    }
}
 
Example 13
Source File: RegisterAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Inserts a move instruction for a specified SSA register before a
 * specified instruction, creating a new SSA register and adjusting the
 * interference graph in the process. The insn currently must be the
 * last insn in a block.
 *
 * @param insn {@code non-null;} insn to insert move before, must
 * be last insn in block
 * @param reg {@code non-null;} SSA register to duplicate
 * @return {@code non-null;} spec of new SSA register created by move
 */
protected final RegisterSpec insertMoveBefore(SsaInsn insn,
        RegisterSpec reg) {
    SsaBasicBlock block = insn.getBlock();
    ArrayList<SsaInsn> insns = block.getInsns();
    int insnIndex = insns.indexOf(insn);

    if (insnIndex < 0) {
        throw new IllegalArgumentException (
                "specified insn is not in this block");
    }

    if (insnIndex != insns.size() - 1) {
        /*
         * Presently, the interference updater only works when
         * adding before the last insn, and the last insn must have no
         * result
         */
        throw new IllegalArgumentException(
                "Adding move here not supported:" + insn.toHuman());
    }

    /*
     * Get new register and make new move instruction.
     */

    // The new result must not have an associated local variable.
    RegisterSpec newRegSpec = RegisterSpec.make(ssaMeth.makeNewSsaReg(),
            reg.getTypeBearer());

    SsaInsn toAdd = SsaInsn.makeFromRop(
            new PlainInsn(Rops.opMove(newRegSpec.getType()),
                    SourcePosition.NO_INFO, newRegSpec,
                    RegisterSpecList.make(reg)), block);

    insns.add(insnIndex, toAdd);

    int newReg = newRegSpec.getReg();

    /*
     * Adjust interference graph based on what's live out of the current
     * block and what's used by the final instruction.
     */

    IntSet liveOut = block.getLiveOutRegs();
    IntIterator liveOutIter = liveOut.iterator();

    while (liveOutIter.hasNext()) {
        interference.add(newReg, liveOutIter.next());
    }

    // Everything that's a source in the last insn interferes.
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();

    for (int i = 0; i < szSources; i++) {
        interference.add(newReg, sources.get(i).getReg());
    }

    ssaMeth.onInsnsChanged();

    return newRegSpec;
}
 
Example 14
Source File: SsaRenamer.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Constructs an instance of the renamer
 *
 * @param ssaMeth {@code non-null;} un-renamed SSA method that will
 * be renamed.
 */
public SsaRenamer(SsaMethod ssaMeth) {
    ropRegCount = ssaMeth.getRegCount();

    this.ssaMeth = ssaMeth;

    /*
     * Reserve the first N registers in the SSA register space for
     * "version 0" registers.
     */
    nextSsaReg = ropRegCount;
    threshold = 0;
    startsForBlocks = new RegisterSpec[ssaMeth.getBlocks().size()][];

    ssaRegToLocalItems = new ArrayList<LocalItem>();

    if (DEBUG) {
        ssaRegToRopReg = new IntList(ropRegCount);
    }

    /*
     * Appel 19.7
     *
     * Initialization:
     *   for each variable a        // register i
     *      Count[a] <- 0           // nextSsaReg, flattened
     *      Stack[a] <- 0           // versionStack
     *      push 0 onto Stack[a]
     *
     */

    // top entry for the version stack is version 0
    RegisterSpec[] initialRegMapping = new RegisterSpec[ropRegCount];
    for (int i = 0; i < ropRegCount; i++) {
        // everyone starts with a version 0 register
        initialRegMapping[i] = RegisterSpec.make(i, Type.VOID);

        if (DEBUG) {
            ssaRegToRopReg.add(i);
        }
    }

    // Initial state for entry block
    startsForBlocks[ssaMeth.getEntryBlockIndex()] = initialRegMapping;
}
 
Example 15
Source File: ConstCollector.java    From buck with Apache License 2.0 4 votes vote down vote up
/**
 * Applies the optimization.
 */
private void run() {
    int regSz = ssaMeth.getRegCount();

    ArrayList<TypedConstant> constantList
            = getConstsSortedByCountUse();

    int toCollect = Math.min(constantList.size(), MAX_COLLECTED_CONSTANTS);

    SsaBasicBlock start = ssaMeth.getEntryBlock();

    // Constant to new register containing the constant
    HashMap<TypedConstant, RegisterSpec> newRegs
            = new HashMap<TypedConstant, RegisterSpec> (toCollect);

    for (int i = 0; i < toCollect; i++) {
        TypedConstant cst = constantList.get(i);
        RegisterSpec result
                = RegisterSpec.make(ssaMeth.makeNewSsaReg(), cst);

        Rop constRop = Rops.opConst(cst);

        if (constRop.getBranchingness() == Rop.BRANCH_NONE) {
            start.addInsnToHead(
                    new PlainCstInsn(Rops.opConst(cst),
                            SourcePosition.NO_INFO, result,
                            RegisterSpecList.EMPTY, cst));
        } else {
            // We need two new basic blocks along with the new insn
            SsaBasicBlock entryBlock = ssaMeth.getEntryBlock();
            SsaBasicBlock successorBlock
                    = entryBlock.getPrimarySuccessor();

            // Insert a block containing the const insn.
            SsaBasicBlock constBlock
                    = entryBlock.insertNewSuccessor(successorBlock);

            constBlock.replaceLastInsn(
                    new ThrowingCstInsn(constRop, SourcePosition.NO_INFO,
                            RegisterSpecList.EMPTY,
                            StdTypeList.EMPTY, cst));

            // Insert a block containing the move-result-pseudo insn.

            SsaBasicBlock resultBlock
                    = constBlock.insertNewSuccessor(successorBlock);
            PlainInsn insn
                = new PlainInsn(
                        Rops.opMoveResultPseudo(result.getTypeBearer()),
                        SourcePosition.NO_INFO,
                        result, RegisterSpecList.EMPTY);

            resultBlock.addInsnToHead(insn);
        }

        newRegs.put(cst, result);
    }

    updateConstUses(newRegs, regSz);
}
 
Example 16
Source File: ConstCollector.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Applies the optimization.
 */
private void run() {
    int regSz = ssaMeth.getRegCount();

    ArrayList<TypedConstant> constantList
            = getConstsSortedByCountUse();

    int toCollect = Math.min(constantList.size(), MAX_COLLECTED_CONSTANTS);

    SsaBasicBlock start = ssaMeth.getEntryBlock();

    // Constant to new register containing the constant
    HashMap<TypedConstant, RegisterSpec> newRegs
            = new HashMap<TypedConstant, RegisterSpec> (toCollect);

    for (int i = 0; i < toCollect; i++) {
        TypedConstant cst = constantList.get(i);
        RegisterSpec result
                = RegisterSpec.make(ssaMeth.makeNewSsaReg(), cst);

        Rop constRop = Rops.opConst(cst);

        if (constRop.getBranchingness() == Rop.BRANCH_NONE) {
            start.addInsnToHead(
                    new PlainCstInsn(Rops.opConst(cst),
                            SourcePosition.NO_INFO, result,
                            RegisterSpecList.EMPTY, cst));
        } else {
            // We need two new basic blocks along with the new insn
            SsaBasicBlock entryBlock = ssaMeth.getEntryBlock();
            SsaBasicBlock successorBlock
                    = entryBlock.getPrimarySuccessor();

            // Insert a block containing the const insn.
            SsaBasicBlock constBlock
                    = entryBlock.insertNewSuccessor(successorBlock);

            constBlock.replaceLastInsn(
                    new ThrowingCstInsn(constRop, SourcePosition.NO_INFO,
                            RegisterSpecList.EMPTY,
                            StdTypeList.EMPTY, cst));

            // Insert a block containing the move-result-pseudo insn.

            SsaBasicBlock resultBlock
                    = constBlock.insertNewSuccessor(successorBlock);
            PlainInsn insn
                = new PlainInsn(
                        Rops.opMoveResultPseudo(result.getTypeBearer()),
                        SourcePosition.NO_INFO,
                        result, RegisterSpecList.EMPTY);

            resultBlock.addInsnToHead(insn);
        }

        newRegs.put(cst, result);
    }

    updateConstUses(newRegs, regSz);
}
 
Example 17
Source File: RegisterAllocator.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Inserts a move instruction for a specified SSA register before a
 * specified instruction, creating a new SSA register and adjusting the
 * interference graph in the process. The insn currently must be the
 * last insn in a block.
 *
 * @param insn {@code non-null;} insn to insert move before, must
 * be last insn in block
 * @param reg {@code non-null;} SSA register to duplicate
 * @return {@code non-null;} spec of new SSA register created by move
 */
protected final RegisterSpec insertMoveBefore(SsaInsn insn,
        RegisterSpec reg) {
    SsaBasicBlock block = insn.getBlock();
    ArrayList<SsaInsn> insns = block.getInsns();
    int insnIndex = insns.indexOf(insn);

    if (insnIndex < 0) {
        throw new IllegalArgumentException (
                "specified insn is not in this block");
    }

    if (insnIndex != insns.size() - 1) {
        /*
         * Presently, the interference updater only works when
         * adding before the last insn, and the last insn must have no
         * result
         */
        throw new IllegalArgumentException(
                "Adding move here not supported:" + insn.toHuman());
    }

    /*
     * Get new register and make new move instruction.
     */

    // The new result must not have an associated local variable.
    RegisterSpec newRegSpec = RegisterSpec.make(ssaMeth.makeNewSsaReg(),
            reg.getTypeBearer());

    SsaInsn toAdd = SsaInsn.makeFromRop(
            new PlainInsn(Rops.opMove(newRegSpec.getType()),
                    SourcePosition.NO_INFO, newRegSpec,
                    RegisterSpecList.make(reg)), block);

    insns.add(insnIndex, toAdd);

    int newReg = newRegSpec.getReg();

    /*
     * Adjust interference graph based on what's live out of the current
     * block and what's used by the final instruction.
     */

    IntSet liveOut = block.getLiveOutRegs();
    IntIterator liveOutIter = liveOut.iterator();

    while (liveOutIter.hasNext()) {
        interference.add(newReg, liveOutIter.next());
    }

    // Everything that's a source in the last insn interferes.
    RegisterSpecList sources = insn.getSources();
    int szSources = sources.size();

    for (int i = 0; i < szSources; i++) {
        interference.add(newReg, sources.get(i).getReg());
    }

    ssaMeth.onInsnsChanged();

    return newRegSpec;
}
 
Example 18
Source File: SsaRenamer.java    From Box with Apache License 2.0 4 votes vote down vote up
/**
 * Constructs an instance of the renamer
 *
 * @param ssaMeth {@code non-null;} un-renamed SSA method that will
 * be renamed.
 */
public SsaRenamer(SsaMethod ssaMeth) {
    ropRegCount = ssaMeth.getRegCount();

    this.ssaMeth = ssaMeth;

    /*
     * Reserve the first N registers in the SSA register space for
     * "version 0" registers.
     */
    nextSsaReg = ropRegCount;
    threshold = 0;
    startsForBlocks = new RegisterSpec[ssaMeth.getBlocks().size()][];

    ssaRegToLocalItems = new ArrayList<LocalItem>();

    if (DEBUG) {
        ssaRegToRopReg = new IntList(ropRegCount);
    }

    /*
     * Appel 19.7
     *
     * Initialization:
     *   for each variable a        // register i
     *      Count[a] <- 0           // nextSsaReg, flattened
     *      Stack[a] <- 0           // versionStack
     *      push 0 onto Stack[a]
     *
     */

    // top entry for the version stack is version 0
    RegisterSpec[] initialRegMapping = new RegisterSpec[ropRegCount];
    for (int i = 0; i < ropRegCount; i++) {
        // everyone starts with a version 0 register
        initialRegMapping[i] = RegisterSpec.make(i, Type.VOID);

        if (DEBUG) {
            ssaRegToRopReg.add(i);
        }
    }

    // Initial state for entry block
    startsForBlocks[ssaMeth.getEntryBlockIndex()] = initialRegMapping;
}
 
Example 19
Source File: EscapeAnalysis.java    From buck with Apache License 2.0 4 votes vote down vote up
/**
 * Replaces the use for a scalar replaceable array. Gets and puts become
 * move instructions, and array lengths and fills are handled. Can also
 * identify ArrayIndexOutOfBounds exceptions and throw them if detected.
 *
 * @param use {@code non-null;} move result instruction for array
 * @param prev {@code non-null;} instruction for instantiating new array
 * @param newRegs {@code non-null;} mapping of array indices to new
 * registers
 * @param deletedInsns {@code non-null;} set of instructions marked for
 * deletion
 */
private void replaceUse(SsaInsn use, SsaInsn prev,
                            ArrayList<RegisterSpec> newRegs,
                            HashSet<SsaInsn> deletedInsns) {
    int index;
    int length = newRegs.size();
    SsaInsn next;
    RegisterSpecList sources;
    RegisterSpec source, result;
    CstLiteralBits indexReg;

    switch (use.getOpcode().getOpcode()) {
        case RegOps.AGET:
            // Replace array gets with moves
            next = getMoveForInsn(use);
            sources = use.getSources();
            indexReg = ((CstLiteralBits) sources.get(1).getTypeBearer());
            index = indexReg.getIntBits();
            if (index < length) {
                source = newRegs.get(index);
                result = source.withReg(next.getResult().getReg());
                insertPlainInsnBefore(next, RegisterSpecList.make(source),
                                          result, RegOps.MOVE, null);
            } else {
                // Throw an exception if the index is out of bounds
                insertExceptionThrow(next, sources.get(1), deletedInsns);
                deletedInsns.add(next.getBlock().getInsns().get(2));
            }
            deletedInsns.add(next);
            break;
        case RegOps.APUT:
            // Replace array puts with moves
            sources = use.getSources();
            indexReg = ((CstLiteralBits) sources.get(2).getTypeBearer());
            index = indexReg.getIntBits();
            if (index < length) {
                source = sources.get(0);
                result = source.withReg(newRegs.get(index).getReg());
                insertPlainInsnBefore(use, RegisterSpecList.make(source),
                                          result, RegOps.MOVE, null);
                // Update the newReg entry to mark value as unknown now
                newRegs.set(index, result.withSimpleType());
            } else {
                // Throw an exception if the index is out of bounds
                insertExceptionThrow(use, sources.get(2), deletedInsns);
            }
            break;
        case RegOps.ARRAY_LENGTH:
            // Replace array lengths with const instructions
            TypeBearer lengthReg = prev.getSources().get(0).getTypeBearer();
            //CstInteger lengthReg = CstInteger.make(length);
            next = getMoveForInsn(use);
            insertPlainInsnBefore(next, RegisterSpecList.EMPTY,
                                      next.getResult(), RegOps.CONST,
                                      (Constant) lengthReg);
            deletedInsns.add(next);
            break;
        case RegOps.MARK_LOCAL:
            // Remove mark local instructions
            break;
        case RegOps.FILL_ARRAY_DATA:
            // Create const instructions for each fill value
            Insn ropUse = use.getOriginalRopInsn();
            FillArrayDataInsn fill = (FillArrayDataInsn) ropUse;
            ArrayList<Constant> constList = fill.getInitValues();
            for (int i = 0; i < length; i++) {
                RegisterSpec newFill =
                    RegisterSpec.make(newRegs.get(i).getReg(),
                                          (TypeBearer) constList.get(i));
                insertPlainInsnBefore(use, RegisterSpecList.EMPTY, newFill,
                                          RegOps.CONST, constList.get(i));
                // Update the newRegs to hold the new const value
                newRegs.set(i, newFill);
            }
            break;
        default:
    }
}
 
Example 20
Source File: SsaRenamer.java    From buck with Apache License 2.0 4 votes vote down vote up
/**
 * Constructs an instance of the renamer
 *
 * @param ssaMeth {@code non-null;} un-renamed SSA method that will
 * be renamed.
 */
public SsaRenamer(SsaMethod ssaMeth) {
    ropRegCount = ssaMeth.getRegCount();

    this.ssaMeth = ssaMeth;

    /*
     * Reserve the first N registers in the SSA register space for
     * "version 0" registers.
     */
    nextSsaReg = ropRegCount;
    threshold = 0;
    startsForBlocks = new RegisterSpec[ssaMeth.getBlocks().size()][];

    ssaRegToLocalItems = new ArrayList<LocalItem>();

    if (DEBUG) {
        ssaRegToRopReg = new IntList(ropRegCount);
    }

    /*
     * Appel 19.7
     *
     * Initialization:
     *   for each variable a        // register i
     *      Count[a] <- 0           // nextSsaReg, flattened
     *      Stack[a] <- 0           // versionStack
     *      push 0 onto Stack[a]
     *
     */

    // top entry for the version stack is version 0
    RegisterSpec[] initialRegMapping = new RegisterSpec[ropRegCount];
    for (int i = 0; i < ropRegCount; i++) {
        // everyone starts with a version 0 register
        initialRegMapping[i] = RegisterSpec.make(i, Type.VOID);

        if (DEBUG) {
            ssaRegToRopReg.add(i);
        }
    }

    // Initial state for entry block
    startsForBlocks[ssaMeth.getEntryBlockIndex()] = initialRegMapping;
}