Example #1
0
  /**
   * 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;

    /*
     * Iterate over the instructions, adding information for each place
     * that the active variable set changes.
     */

    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);
      }
    }
  }