Esempio n. 1
0
  /**
   * Inserts mark-locals if necessary when changing a register. If the definition of {@code origReg}
   * is associated with a local variable, then insert a mark-local for {@code newReg} just below it.
   * We expect the definition of {@code origReg} to ultimately be removed by the dead code
   * eliminator
   *
   * @param origReg {@code non-null;} original register
   * @param newReg {@code non-null;} new register that will replace {@code origReg}
   */
  private void fixLocalAssignment(RegisterSpec origReg, RegisterSpec newReg) {
    for (SsaInsn use : ssaMeth.getUseListForRegister(origReg.getReg())) {
      RegisterSpec localAssignment = use.getLocalAssignment();
      if (localAssignment == null) {
        continue;
      }

      if (use.getResult() == null) {
        /*
         * This is a mark-local. it will be updated when all uses are
         * updated.
         */
        continue;
      }

      LocalItem local = localAssignment.getLocalItem();

      // Un-associate original use.
      use.setResultLocal(null);

      // Now add a mark-local to the new reg immediately after.
      newReg = newReg.withLocalItem(local);

      SsaInsn newInsn =
          SsaInsn.makeFromRop(
              new PlainInsn(
                  Rops.opMarkLocal(newReg),
                  SourcePosition.NO_INFO,
                  null,
                  RegisterSpecList.make(newReg)),
              use.getBlock());

      ArrayList<SsaInsn> insns = use.getBlock().getInsns();

      insns.add(insns.indexOf(use) + 1, newInsn);
    }
  }
Esempio n. 2
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);
      }
    }
  }