com.android.dx.ssa.SsaBasicBlock Java Examples

The following examples show how to use com.android.dx.ssa.SsaBasicBlock. 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: LivenessAnalyzer.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Ensures that all the phi result registers for all the phis in the
 * same basic block interfere with each other, and also that a phi's source
 * registers interfere with the result registers from other phis. This is needed since
 * the dead code remover has allowed through "dead-end phis" whose
 * results are not used except as local assignments. Without this step,
 * a the result of a dead-end phi might be assigned the same register
 * as the result of another phi, and the phi removal move scheduler may
 * generate moves that over-write the live result.
 *
 * @param ssaMeth {@code non-null;} method to process
 * @param interference {@code non-null;} interference graph
 */
private static void coInterferePhis(SsaMethod ssaMeth,
        InterferenceGraph interference) {
    for (SsaBasicBlock b : ssaMeth.getBlocks()) {
        List<SsaInsn> phis = b.getPhiInsns();

        int szPhis = phis.size();

        for (int i = 0; i < szPhis; i++) {
            for (int j = 0; j < szPhis; j++) {
                if (i == j) {
                    continue;
                }

                SsaInsn first = phis.get(i);
                SsaInsn second = phis.get(j);
                coInterferePhiRegisters(interference, first.getResult(), second.getSources());
                coInterferePhiRegisters(interference, second.getResult(), first.getSources());
                interference.add(first.getResult().getReg(), second.getResult().getReg());
            }
        }
    }
}
 
Example #2
Source File: LivenessAnalyzer.java    From J2ME-Loader with Apache License 2.0 6 votes vote down vote up
/**
 * Ensures that all the phi result registers for all the phis in the
 * same basic block interfere with each other. This is needed since
 * the dead code remover has allowed through "dead-end phis" whose
 * results are not used except as local assignments. Without this step,
 * a the result of a dead-end phi might be assigned the same register
 * as the result of another phi, and the phi removal move scheduler may
 * generate moves that over-write the live result.
 *
 * @param ssaMeth {@code non-null;} method to pricess
 * @param interference {@code non-null;} interference graph
 */
private static void coInterferePhis(SsaMethod ssaMeth,
        InterferenceGraph interference) {
    for (SsaBasicBlock b : ssaMeth.getBlocks()) {
        List<SsaInsn> phis = b.getPhiInsns();

        int szPhis = phis.size();

        for (int i = 0; i < szPhis; i++) {
            for (int j = 0; j < szPhis; j++) {
                if (i == j) {
                    continue;
                }

                interference.add(phis.get(i).getResult().getReg(),
                    phis.get(j).getResult().getReg());
            }
        }
    }
}
 
Example #3
Source File: SsaToRop.java    From J2ME-Loader with Apache License 2.0 6 votes vote down vote up
/**
  * Removes all blocks containing only GOTOs from the control flow.
  * Although much of this work will be done later when converting
  * from rop to dex, not all simplification cases can be handled
  * there. Furthermore, any no-op block between the exit block and
  * blocks containing the real return or throw statements must be
  * removed.
  */
 private void removeEmptyGotos() {
     final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

     ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() {
         @Override
public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) {
             ArrayList<SsaInsn> insns = b.getInsns();

             if ((insns.size() == 1)
                     && (insns.get(0).getOpcode() == Rops.GOTO)) {
                 BitSet preds = (BitSet) b.getPredecessors().clone();

                 for (int i = preds.nextSetBit(0); i >= 0;
                         i = preds.nextSetBit(i + 1)) {
                     SsaBasicBlock pb = blocks.get(i);
                     pb.replaceSuccessor(b.getIndex(),
                             b.getPrimarySuccessorIndex());
                 }
             }
         }
     });
 }
 
Example #4
Source File: SsaToRop.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Removes all blocks containing only GOTOs from the control flow.
 * Although much of this work will be done later when converting
 * from rop to dex, not all simplification cases can be handled
 * there. Furthermore, any no-op block between the exit block and
 * blocks containing the real return or throw statements must be
 * removed.
 */
private void removeEmptyGotos() {
    final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() {
        @Override
        public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) {
            ArrayList<SsaInsn> insns = b.getInsns();

            if ((insns.size() == 1)
                    && (insns.get(0).getOpcode() == Rops.GOTO)) {
                BitSet preds = (BitSet) b.getPredecessors().clone();

                for (int i = preds.nextSetBit(0); i >= 0;
                        i = preds.nextSetBit(i + 1)) {
                    SsaBasicBlock pb = blocks.get(i);
                    pb.replaceSuccessor(b.getIndex(),
                            b.getPrimarySuccessorIndex());
                }
            }
        }
    });
}
 
Example #5
Source File: LivenessAnalyzer.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Ensures that all the phi result registers for all the phis in the
 * same basic block interfere with each other, and also that a phi's source
 * registers interfere with the result registers from other phis. This is needed since
 * the dead code remover has allowed through "dead-end phis" whose
 * results are not used except as local assignments. Without this step,
 * a the result of a dead-end phi might be assigned the same register
 * as the result of another phi, and the phi removal move scheduler may
 * generate moves that over-write the live result.
 *
 * @param ssaMeth {@code non-null;} method to process
 * @param interference {@code non-null;} interference graph
 */
private static void coInterferePhis(SsaMethod ssaMeth,
        InterferenceGraph interference) {
    for (SsaBasicBlock b : ssaMeth.getBlocks()) {
        List<SsaInsn> phis = b.getPhiInsns();

        int szPhis = phis.size();

        for (int i = 0; i < szPhis; i++) {
            for (int j = 0; j < szPhis; j++) {
                if (i == j) {
                    continue;
                }

                SsaInsn first = phis.get(i);
                SsaInsn second = phis.get(j);
                coInterferePhiRegisters(interference, first.getResult(), second.getSources());
                coInterferePhiRegisters(interference, second.getResult(), first.getSources());
                interference.add(first.getResult().getReg(), second.getResult().getReg());
            }
        }
    }
}
 
Example #6
Source File: LivenessAnalyzer.java    From buck with Apache License 2.0 6 votes vote down vote up
/**
 * Ensures that all the phi result registers for all the phis in the
 * same basic block interfere with each other. This is needed since
 * the dead code remover has allowed through "dead-end phis" whose
 * results are not used except as local assignments. Without this step,
 * a the result of a dead-end phi might be assigned the same register
 * as the result of another phi, and the phi removal move scheduler may
 * generate moves that over-write the live result.
 *
 * @param ssaMeth {@code non-null;} method to pricess
 * @param interference {@code non-null;} interference graph
 */
private static void coInterferePhis(SsaMethod ssaMeth,
        InterferenceGraph interference) {
    for (SsaBasicBlock b : ssaMeth.getBlocks()) {
        List<SsaInsn> phis = b.getPhiInsns();

        int szPhis = phis.size();

        for (int i = 0; i < szPhis; i++) {
            for (int j = 0; j < szPhis; j++) {
                if (i == j) {
                    continue;
                }

                interference.add(phis.get(i).getResult().getReg(),
                    phis.get(j).getResult().getReg());
            }
        }
    }
}
 
Example #7
Source File: SsaToRop.java    From buck with Apache License 2.0 6 votes vote down vote up
/**
 * Removes all blocks containing only GOTOs from the control flow.
 * Although much of this work will be done later when converting
 * from rop to dex, not all simplification cases can be handled
 * there. Furthermore, any no-op block between the exit block and
 * blocks containing the real return or throw statements must be
 * removed.
 */
private void removeEmptyGotos() {
    final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() {
        public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) {
            ArrayList<SsaInsn> insns = b.getInsns();

            if ((insns.size() == 1)
                    && (insns.get(0).getOpcode() == Rops.GOTO)) {
                BitSet preds = (BitSet) b.getPredecessors().clone();

                for (int i = preds.nextSetBit(0); i >= 0;
                        i = preds.nextSetBit(i + 1)) {
                    SsaBasicBlock pb = blocks.get(i);
                    pb.replaceSuccessor(b.getIndex(),
                            b.getPrimarySuccessorIndex());
                }
            }
        }
    });
}
 
Example #8
Source File: SsaToRop.java    From Box with Apache License 2.0 6 votes vote down vote up
/**
 * Removes all blocks containing only GOTOs from the control flow.
 * Although much of this work will be done later when converting
 * from rop to dex, not all simplification cases can be handled
 * there. Furthermore, any no-op block between the exit block and
 * blocks containing the real return or throw statements must be
 * removed.
 */
private void removeEmptyGotos() {
    final ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    ssaMeth.forEachBlockDepthFirst(false, new SsaBasicBlock.Visitor() {
        @Override
        public void visitBlock(SsaBasicBlock b, SsaBasicBlock parent) {
            ArrayList<SsaInsn> insns = b.getInsns();

            if ((insns.size() == 1)
                    && (insns.get(0).getOpcode() == Rops.GOTO)) {
                BitSet preds = (BitSet) b.getPredecessors().clone();

                for (int i = preds.nextSetBit(0); i >= 0;
                        i = preds.nextSetBit(i + 1)) {
                    SsaBasicBlock pb = blocks.get(i);
                    pb.replaceSuccessor(b.getIndex(),
                            b.getPrimarySuccessorIndex());
                }
            }
        }
    });
}
 
Example #9
Source File: SsaToRop.java    From buck with Apache License 2.0 5 votes vote down vote up
public void visitPhiInsn(PhiInsn insn) {
    RegisterSpecList sources = insn.getSources();
    RegisterSpec result = insn.getResult();
    int sz = sources.size();

    for (int i = 0; i < sz; i++) {
        RegisterSpec source = sources.get(i);
        SsaBasicBlock predBlock = blocks.get(
                insn.predBlockIndexForSourcesIndex(i));

        predBlock.addMoveToEnd(result, source);
    }
}
 
Example #10
Source File: SsaToRop.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * @return rop-form basic block list
 */
private BasicBlockList convertBasicBlocks() {
    ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();

    ssaMeth.computeReachability();
    int ropBlockCount = ssaMeth.getCountReachableBlocks();

    // Don't count the exit block, if it exists and is reachable.
    ropBlockCount -= (exitBlock != null && exitBlock.isReachable()) ? 1 : 0;

    BasicBlockList result = new BasicBlockList(ropBlockCount);

    // Convert all the reachable blocks except the exit block.
    int ropBlockIndex = 0;
    for (SsaBasicBlock b : blocks) {
        if (b.isReachable() && b != exitBlock) {
            result.set(ropBlockIndex++, convertBasicBlock(b));
        }
    }

    // The exit block, which is discarded, must do nothing.
    if (exitBlock != null && exitBlock.getInsns().size() != 0) {
        throw new RuntimeException(
                "Exit block must have no insns when leaving SSA form");
    }

    return result;
}
 
Example #11
Source File: LivenessAnalyzer.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * From Appel algorithm 19.17.
 */
public void run() {
    List<SsaInsn> useList = ssaMeth.getUseListForRegister(regV);

    for (SsaInsn insn : useList) {
        nextFunction = NextFunction.DONE;

        if (insn instanceof PhiInsn) {
            // If s is a phi-function with V as it's ith argument.
            PhiInsn phi = (PhiInsn) insn;

            for (SsaBasicBlock pred :
                     phi.predBlocksForReg(regV, ssaMeth)) {
                blockN = pred;

                nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
                handleTailRecursion();
            }
        } else {
            blockN = insn.getBlock();
            statementIndex = blockN.getInsns().indexOf(insn);

            if (statementIndex < 0) {
                throw new RuntimeException(
                        "insn not found in it's own block");
            }

            nextFunction = NextFunction.LIVE_IN_AT_STATEMENT;
            handleTailRecursion();
        }
    }

    int nextLiveOutBlock;
    while ((nextLiveOutBlock = liveOutBlocks.nextSetBit(0)) >= 0) {
        blockN = ssaMeth.getBlocks().get(nextLiveOutBlock);
        liveOutBlocks.clear(nextLiveOutBlock);
        nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
        handleTailRecursion();
    }
}
 
Example #12
Source File: SsaToRop.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Validates that a basic block is a valid end predecessor. It must
 * end in a RETURN or a THROW. Throws a runtime exception on error.
 *
 * @param b {@code non-null;} block to validate
 * @throws RuntimeException on error
 */
private void verifyValidExitPredecessor(SsaBasicBlock b) {
    ArrayList<SsaInsn> insns = b.getInsns();
    SsaInsn lastInsn = insns.get(insns.size() - 1);
    Rop opcode = lastInsn.getOpcode();

    if (opcode.getBranchingness() != Rop.BRANCH_RETURN
            && opcode != Rops.THROW) {
        throw new RuntimeException("Exit predecessor must end"
                + " in valid exit statement.");
    }
}
 
Example #13
Source File: SsaToRop.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * Converts a single basic block to rop form.
 *
 * @param block SSA block to process
 * @return {@code non-null;} ROP block
 */
private BasicBlock convertBasicBlock(SsaBasicBlock block) {
    IntList successorList = block.getRopLabelSuccessorList();
    int primarySuccessorLabel = block.getPrimarySuccessorRopLabel();

    // Filter out any reference to the SSA form's exit block.

    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();
    int exitRopLabel = (exitBlock == null) ? -1 : exitBlock.getRopLabel();

    if (successorList.contains(exitRopLabel)) {
        if (successorList.size() > 1) {
            throw new RuntimeException(
                    "Exit predecessor must have no other successors"
                            + Hex.u2(block.getRopLabel()));
        } else {
            successorList = IntList.EMPTY;
            primarySuccessorLabel = -1;

            verifyValidExitPredecessor(block);
        }
    }

    successorList.setImmutable();

    BasicBlock result = new BasicBlock(
            block.getRopLabel(), convertInsns(block.getInsns()),
            successorList,
            primarySuccessorLabel);

    return result;
}
 
Example #14
Source File: SsaToRop.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * Validates that a basic block is a valid end predecessor. It must
 * end in a RETURN or a THROW. Throws a runtime exception on error.
 *
 * @param b {@code non-null;} block to validate
 * @throws RuntimeException on error
 */
private void verifyValidExitPredecessor(SsaBasicBlock b) {
    ArrayList<SsaInsn> insns = b.getInsns();
    SsaInsn lastInsn = insns.get(insns.size() - 1);
    Rop opcode = lastInsn.getOpcode();

    if (opcode.getBranchingness() != Rop.BRANCH_RETURN
            && opcode != Rops.THROW) {
        throw new RuntimeException("Exit predecessor must end"
                + " in valid exit statement.");
    }
}
 
Example #15
Source File: SsaToRop.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * @return rop-form basic block list
 */
private BasicBlockList convertBasicBlocks() {
    ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();

    ssaMeth.computeReachability();
    int ropBlockCount = ssaMeth.getCountReachableBlocks();

    // Don't count the exit block, if it exists and is reachable.
    ropBlockCount -= (exitBlock != null && exitBlock.isReachable()) ? 1 : 0;

    BasicBlockList result = new BasicBlockList(ropBlockCount);

    // Convert all the reachable blocks except the exit block.
    int ropBlockIndex = 0;
    for (SsaBasicBlock b : blocks) {
        if (b.isReachable() && b != exitBlock) {
            result.set(ropBlockIndex++, convertBasicBlock(b));
        }
    }

    // The exit block, which is discarded, must do nothing.
    if (exitBlock != null && exitBlock.getInsns().size() != 0) {
        throw new RuntimeException(
                "Exit block must have no insns when leaving SSA form");
    }

    return result;
}
 
Example #16
Source File: SsaToRop.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
@Override
public void visitPhiInsn(PhiInsn insn) {
          RegisterSpecList sources = insn.getSources();
          RegisterSpec result = insn.getResult();
          int sz = sources.size();

          for (int i = 0; i < sz; i++) {
              RegisterSpec source = sources.get(i);
              SsaBasicBlock predBlock = blocks.get(
                      insn.predBlockIndexForSourcesIndex(i));

              predBlock.addMoveToEnd(result, source);
          }
      }
 
Example #17
Source File: LivenessAnalyzer.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * From Appel algorithm 19.17.
 */
public void run() {
    List<SsaInsn> useList = ssaMeth.getUseListForRegister(regV);

    for (SsaInsn insn : useList) {
        nextFunction = NextFunction.DONE;

        if (insn instanceof PhiInsn) {
            // If s is a phi-function with V as it's ith argument.
            PhiInsn phi = (PhiInsn) insn;

            for (SsaBasicBlock pred :
                     phi.predBlocksForReg(regV, ssaMeth)) {
                blockN = pred;

                nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
                handleTailRecursion();
            }
        } else {
            blockN = insn.getBlock();
            statementIndex = blockN.getInsns().indexOf(insn);

            if (statementIndex < 0) {
                throw new RuntimeException(
                        "insn not found in it's own block");
            }

            nextFunction = NextFunction.LIVE_IN_AT_STATEMENT;
            handleTailRecursion();
        }
    }

    int nextLiveOutBlock;
    while ((nextLiveOutBlock = liveOutBlocks.nextSetBit(0)) >= 0) {
        blockN = ssaMeth.getBlocks().get(nextLiveOutBlock);
        liveOutBlocks.clear(nextLiveOutBlock);
        nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
        handleTailRecursion();
    }
}
 
Example #18
Source File: SsaToRop.java    From buck with Apache License 2.0 5 votes vote down vote up
/**
 * Converts a single basic block to rop form.
 *
 * @param block SSA block to process
 * @return {@code non-null;} ROP block
 */
private BasicBlock convertBasicBlock(SsaBasicBlock block) {
    IntList successorList = block.getRopLabelSuccessorList();
    int primarySuccessorLabel = block.getPrimarySuccessorRopLabel();

    // Filter out any reference to the SSA form's exit block.

    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();
    int exitRopLabel = (exitBlock == null) ? -1 : exitBlock.getRopLabel();

    if (successorList.contains(exitRopLabel)) {
        if (successorList.size() > 1) {
            throw new RuntimeException(
                    "Exit predecessor must have no other successors"
                            + Hex.u2(block.getRopLabel()));
        } else {
            successorList = IntList.EMPTY;
            primarySuccessorLabel = -1;

            verifyValidExitPredecessor(block);
        }
    }

    successorList.setImmutable();

    BasicBlock result = new BasicBlock(
            block.getRopLabel(), convertInsns(block.getInsns()),
            successorList,
            primarySuccessorLabel);

    return result;
}
 
Example #19
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Converts a single basic block to rop form.
 *
 * @param block SSA block to process
 * @return {@code non-null;} ROP block
 */
private BasicBlock convertBasicBlock(SsaBasicBlock block) {
    IntList successorList = block.getRopLabelSuccessorList();
    int primarySuccessorLabel = block.getPrimarySuccessorRopLabel();

    // Filter out any reference to the SSA form's exit block.

    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();
    int exitRopLabel = (exitBlock == null) ? -1 : exitBlock.getRopLabel();

    if (successorList.contains(exitRopLabel)) {
        if (successorList.size() > 1) {
            throw new RuntimeException(
                    "Exit predecessor must have no other successors"
                            + Hex.u2(block.getRopLabel()));
        } else {
            successorList = IntList.EMPTY;
            primarySuccessorLabel = -1;

            verifyValidExitPredecessor(block);
        }
    }

    successorList.setImmutable();

    BasicBlock result = new BasicBlock(
            block.getRopLabel(), convertInsns(block.getInsns()),
            successorList,
            primarySuccessorLabel);

    return result;
}
 
Example #20
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
@Override
public void visitPhiInsn(PhiInsn insn) {
    RegisterSpecList sources = insn.getSources();
    RegisterSpec result = insn.getResult();
    int sz = sources.size();

    for (int i = 0; i < sz; i++) {
        RegisterSpec source = sources.get(i);
        SsaBasicBlock predBlock = blocks.get(
                insn.predBlockIndexForSourcesIndex(i));

        predBlock.addMoveToEnd(result, source);
    }
}
 
Example #21
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * @return rop-form basic block list
 */
private BasicBlockList convertBasicBlocks() {
    ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();

    BitSet reachable = ssaMeth.computeReachability();
    int ropBlockCount = reachable.cardinality();

    // Don't count the exit block, if it exists and is reachable.
    if (exitBlock != null && reachable.get(exitBlock.getIndex())) {
        ropBlockCount -= 1;
    }

    BasicBlockList result = new BasicBlockList(ropBlockCount);

    // Convert all the reachable blocks except the exit block.
    int ropBlockIndex = 0;
    for (SsaBasicBlock b : blocks) {
        if (reachable.get(b.getIndex()) && b != exitBlock) {
            result.set(ropBlockIndex++, convertBasicBlock(b));
        }
    }

    // The exit block, which is discarded, must do nothing.
    if (exitBlock != null && !exitBlock.getInsns().isEmpty()) {
        throw new RuntimeException(
                "Exit block must have no insns when leaving SSA form");
    }

    return result;
}
 
Example #22
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Validates that a basic block is a valid end predecessor. It must
 * end in a RETURN or a THROW. Throws a runtime exception on error.
 *
 * @param b {@code non-null;} block to validate
 * @throws RuntimeException on error
 */
private void verifyValidExitPredecessor(SsaBasicBlock b) {
    ArrayList<SsaInsn> insns = b.getInsns();
    SsaInsn lastInsn = insns.get(insns.size() - 1);
    Rop opcode = lastInsn.getOpcode();

    if (opcode.getBranchingness() != Rop.BRANCH_RETURN
            && opcode != Rops.THROW) {
        throw new RuntimeException("Exit predecessor must end"
                + " in valid exit statement.");
    }
}
 
Example #23
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Converts a single basic block to rop form.
 *
 * @param block SSA block to process
 * @return {@code non-null;} ROP block
 */
private BasicBlock convertBasicBlock(SsaBasicBlock block) {
    IntList successorList = block.getRopLabelSuccessorList();
    int primarySuccessorLabel = block.getPrimarySuccessorRopLabel();

    // Filter out any reference to the SSA form's exit block.

    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();
    int exitRopLabel = (exitBlock == null) ? -1 : exitBlock.getRopLabel();

    if (successorList.contains(exitRopLabel)) {
        if (successorList.size() > 1) {
            throw new RuntimeException(
                    "Exit predecessor must have no other successors"
                            + Hex.u2(block.getRopLabel()));
        } else {
            successorList = IntList.EMPTY;
            primarySuccessorLabel = -1;

            verifyValidExitPredecessor(block);
        }
    }

    successorList.setImmutable();

    BasicBlock result = new BasicBlock(
            block.getRopLabel(), convertInsns(block.getInsns()),
            successorList,
            primarySuccessorLabel);

    return result;
}
 
Example #24
Source File: LivenessAnalyzer.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * From Appel algorithm 19.17.
 */
public void run() {
    List<SsaInsn> useList = ssaMeth.getUseListForRegister(regV);

    for (SsaInsn insn : useList) {
        nextFunction = NextFunction.DONE;

        if (insn instanceof PhiInsn) {
            // If s is a phi-function with V as it's ith argument.
            PhiInsn phi = (PhiInsn) insn;

            for (SsaBasicBlock pred :
                     phi.predBlocksForReg(regV, ssaMeth)) {
                blockN = pred;

                nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
                handleTailRecursion();
            }
        } else {
            blockN = insn.getBlock();
            statementIndex = blockN.getInsns().indexOf(insn);

            if (statementIndex < 0) {
                throw new RuntimeException(
                        "insn not found in it's own block");
            }

            nextFunction = NextFunction.LIVE_IN_AT_STATEMENT;
            handleTailRecursion();
        }
    }

    int nextLiveOutBlock;
    while ((nextLiveOutBlock = liveOutBlocks.nextSetBit(0)) >= 0) {
        blockN = ssaMeth.getBlocks().get(nextLiveOutBlock);
        liveOutBlocks.clear(nextLiveOutBlock);
        nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
        handleTailRecursion();
    }
}
 
Example #25
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
@Override
public void visitPhiInsn(PhiInsn insn) {
    RegisterSpecList sources = insn.getSources();
    RegisterSpec result = insn.getResult();
    int sz = sources.size();

    for (int i = 0; i < sz; i++) {
        RegisterSpec source = sources.get(i);
        SsaBasicBlock predBlock = blocks.get(
                insn.predBlockIndexForSourcesIndex(i));

        predBlock.addMoveToEnd(result, source);
    }
}
 
Example #26
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * @return rop-form basic block list
 */
private BasicBlockList convertBasicBlocks() {
    ArrayList<SsaBasicBlock> blocks = ssaMeth.getBlocks();

    // Exit block may be null.
    SsaBasicBlock exitBlock = ssaMeth.getExitBlock();

    BitSet reachable = ssaMeth.computeReachability();
    int ropBlockCount = reachable.cardinality();

    // Don't count the exit block, if it exists and is reachable.
    if (exitBlock != null && reachable.get(exitBlock.getIndex())) {
        ropBlockCount -= 1;
    }

    BasicBlockList result = new BasicBlockList(ropBlockCount);

    // Convert all the reachable blocks except the exit block.
    int ropBlockIndex = 0;
    for (SsaBasicBlock b : blocks) {
        if (reachable.get(b.getIndex()) && b != exitBlock) {
            result.set(ropBlockIndex++, convertBasicBlock(b));
        }
    }

    // The exit block, which is discarded, must do nothing.
    if (exitBlock != null && !exitBlock.getInsns().isEmpty()) {
        throw new RuntimeException(
                "Exit block must have no insns when leaving SSA form");
    }

    return result;
}
 
Example #27
Source File: SsaToRop.java    From Box with Apache License 2.0 5 votes vote down vote up
/**
 * Validates that a basic block is a valid end predecessor. It must
 * end in a RETURN or a THROW. Throws a runtime exception on error.
 *
 * @param b {@code non-null;} block to validate
 * @throws RuntimeException on error
 */
private void verifyValidExitPredecessor(SsaBasicBlock b) {
    ArrayList<SsaInsn> insns = b.getInsns();
    SsaInsn lastInsn = insns.get(insns.size() - 1);
    Rop opcode = lastInsn.getOpcode();

    if (opcode.getBranchingness() != Rop.BRANCH_RETURN
            && opcode != Rops.THROW) {
        throw new RuntimeException("Exit predecessor must end"
                + " in valid exit statement.");
    }
}
 
Example #28
Source File: LivenessAnalyzer.java    From J2ME-Loader with Apache License 2.0 5 votes vote down vote up
/**
 * From Appel algorithm 19.17.
 */
public void run() {
    List<SsaInsn> useList = ssaMeth.getUseListForRegister(regV);

    for (SsaInsn insn : useList) {
        nextFunction = NextFunction.DONE;

        if (insn instanceof PhiInsn) {
            // If s is a phi-function with V as it's ith argument.
            PhiInsn phi = (PhiInsn) insn;

            for (SsaBasicBlock pred :
                     phi.predBlocksForReg(regV, ssaMeth)) {
                blockN = pred;

                nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
                handleTailRecursion();
            }
        } else {
            blockN = insn.getBlock();
            statementIndex = blockN.getInsns().indexOf(insn);

            if (statementIndex < 0) {
                throw new RuntimeException(
                        "insn not found in it's own block");
            }

            nextFunction = NextFunction.LIVE_IN_AT_STATEMENT;
            handleTailRecursion();
        }
    }

    int nextLiveOutBlock;
    while ((nextLiveOutBlock = liveOutBlocks.nextSetBit(0)) >= 0) {
        blockN = ssaMeth.getBlocks().get(nextLiveOutBlock);
        liveOutBlocks.clear(nextLiveOutBlock);
        nextFunction = NextFunction.LIVE_OUT_AT_BLOCK;
        handleTailRecursion();
    }
}
 
Example #29
Source File: SsaToRop.java    From Box with Apache License 2.0 4 votes vote down vote up
public PhiVisitor(ArrayList<SsaBasicBlock> blocks) {
    this.blocks = blocks;
}
 
Example #30
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;
}