Example #1
0
  private Instr[] prepareInstructionsForInterpretation() {
    checkRelinearization();

    if (linearizedInstrArray != null) return linearizedInstrArray; // Already prepared

    try {
      buildLinearization(); // FIXME: compiler passes should have done this
      depends(linearization());
    } catch (RuntimeException e) {
      LOG.error("Error linearizing cfg: ", e);
      CFG c = cfg();
      LOG.error("\nGraph:\n" + c.toStringGraph());
      LOG.error("\nInstructions:\n" + c.toStringInstrs());
      throw e;
    }

    // Set up IPCs
    HashMap<Label, Integer> labelIPCMap = new HashMap<Label, Integer>();
    List<Instr> newInstrs = new ArrayList<Instr>();
    int ipc = 0;
    for (BasicBlock b : linearizedBBList) {
      labelIPCMap.put(b.getLabel(), ipc);
      List<Instr> bbInstrs = b.getInstrs();
      int bbInstrsLength = bbInstrs.size();
      for (int i = 0; i < bbInstrsLength; i++) {
        Instr instr = bbInstrs.get(i);

        if (instr instanceof Specializeable) {
          instr = ((Specializeable) instr).specializeForInterpretation();
          bbInstrs.set(i, instr);
        }

        if (!(instr instanceof ReceiveSelfInstr)) {
          newInstrs.add(instr);
          ipc++;
        }
      }
    }

    // Set up label PCs
    setupLabelPCs(labelIPCMap);

    // Exit BB ipc
    cfg().getExitBB().getLabel().setTargetPC(ipc + 1);

    linearizedInstrArray = newInstrs.toArray(new Instr[newInstrs.size()]);
    return linearizedInstrArray;
  }
Example #2
0
 public CFG buildCFG() {
   cfg = new CFG(this);
   cfg.build(instrList);
   // Clear out instruction list after CFG has been built.
   this.instrList = null;
   return cfg;
 }
Example #3
0
  /** Run any necessary passes to get the IR ready for compilation */
  public Tuple<Instr[], Map<Integer, Label[]>> prepareForCompilation() {
    // Build CFG and run compiler passes, if necessary
    if (getCFG() == null) runCompilerPasses();

    // Add this always since we dont re-JIT a previously
    // JIT-ted closure.  But, check if there are other
    // smarts available to us and eliminate adding this
    // code to every closure there is.
    //
    // Add a global ensure block to catch uncaught breaks
    // and throw a LocalJumpError.
    if (this instanceof IRClosure && ((IRClosure) this).addGEBForUncaughtBreaks()) {
      this.relinearizeCFG = true;
    }

    try {
      buildLinearization(); // FIXME: compiler passes should have done this
      depends(linearization());
    } catch (RuntimeException e) {
      LOG.error("Error linearizing cfg: ", e);
      CFG c = cfg();
      LOG.error("\nGraph:\n" + c.toStringGraph());
      LOG.error("\nInstructions:\n" + c.toStringInstrs());
      throw e;
    }

    // Set up IPCs
    // FIXME: Would be nice to collapse duplicate labels; for now, using Label[]
    HashMap<Integer, Label[]> ipcLabelMap = new HashMap<Integer, Label[]>();
    List<Instr> newInstrs = new ArrayList<Instr>();
    int ipc = 0;
    for (BasicBlock b : linearizedBBList) {
      Label l = b.getLabel();
      ipcLabelMap.put(ipc, catLabels(ipcLabelMap.get(ipc), l));
      for (Instr i : b.getInstrs()) {
        if (!(i instanceof ReceiveSelfInstr)) {
          newInstrs.add(i);
          ipc++;
        }
      }
    }

    return new Tuple<Instr[], Map<Integer, Label[]>>(
        newInstrs.toArray(new Instr[newInstrs.size()]), ipcLabelMap);
  }
Example #4
0
  //
  // This can help use eliminate writes to %block that are not used since this is
  // a special local-variable, not programmer-defined local-variable
  public void computeScopeFlags() {
    if (flagsComputed) {
      return;
    }

    // init
    canModifyCode = true;
    canCaptureCallersBinding = false;
    usesZSuper = false;
    usesEval = false;
    usesBackrefOrLastline = false;
    // NOTE: bindingHasEscaped is the crucial flag and it effectively is
    // unconditionally true whenever it has a call that receives a closure.
    // See CallInstr.computeRequiresCallersBindingFlag
    bindingHasEscaped =
        (this instanceof IREvalScript); // for eval scopes, bindings are considered escaped ...
    hasBreakInstrs = false;
    hasNonlocalReturns = false;
    canReceiveBreaks = false;
    canReceiveNonlocalReturns = false;

    // recompute flags -- we could be calling this method different times
    // definitely once after ir generation and local optimizations propagates constants locally
    // but potentially at a later time after doing ssa generation and constant propagation
    if (cfg == null) {
      computeScopeFlags(false, getInstrs());
    } else {
      boolean receivesClosureArg = false;
      for (BasicBlock b : cfg.getBasicBlocks()) {
        receivesClosureArg = computeScopeFlags(receivesClosureArg, b.getInstrs());
      }
    }

    // Compute flags for nested closures (recursively) and set derived flags.
    for (IRClosure cl : getClosures()) {
      cl.computeScopeFlags();
      if (cl.hasBreakInstrs || cl.canReceiveBreaks) {
        canReceiveBreaks = true;
      }
      if (cl.hasNonlocalReturns || cl.canReceiveNonlocalReturns) {
        canReceiveNonlocalReturns = true;
      }
      if (cl.usesZSuper()) {
        usesZSuper = true;
      }
    }

    flagsComputed = true;
  }
Example #5
0
  // SSS FIXME: Extremely inefficient
  public int getEnsurerPC(Instr excInstr) {
    depends(cfg());

    for (BasicBlock b : linearizedBBList) {
      for (Instr i : b.getInstrs()) {
        if (i == excInstr) {
          BasicBlock ensurerBB = cfg.getEnsurerBBFor(b);
          return (ensurerBB == null) ? -1 : ensurerBB.getLabel().getTargetPC();
        }
      }
    }

    // SSS FIXME: Cannot happen! Throw runtime exception
    LOG.error("Fell through looking for ensurer ipc for " + excInstr);
    return -1;
  }
Example #6
0
  public void resetState() {
    relinearizeCFG = true;
    linearizedInstrArray = null;
    cfg.resetState();

    // reset flags
    flagsComputed = false;
    canModifyCode = true;
    canCaptureCallersBinding = true;
    bindingHasEscaped = true;
    usesEval = true;
    usesZSuper = true;
    hasBreakInstrs = false;
    hasNonlocalReturns = false;
    canReceiveBreaks = false;
    canReceiveNonlocalReturns = false;

    // Reset dataflow problems state
    resetDFProblemsState();
  }
  public void unbox(Map<Variable, TemporaryLocalVariable> unboxMap) {
    // System.out.println("BB : " + basicBlock + " in " + this.problem.getScope().getName());
    // System.out.println("-- known types on entry:");
    // for (Variable v: inState.types.keySet()) {
    //     if (inState.types.get(v) != Object.class) {
    //         System.out.println(v + "-->" + inState.types.get(v));
    //     }
    // }
    // System.out.print("-- unboxed vars on entry:");
    // for (Variable v: inState.unboxedVars) {
    //     System.out.print(" " + v);
    // }
    // System.out.println("------");
    // System.out.print("-- unboxed vars on exit:");
    // for (Variable v: outState.unboxedVars) {
    //     System.out.print(" " + v);
    // }
    // System.out.println("------");

    // Compute UNION(unboxedVarsIn(all-successors)) - this.unboxedVarsOut
    // All vars in this new set have to be unboxed on exit from this BB
    boolean scopeBindingHasEscaped = problem.getScope().bindingHasEscaped();
    Set<Variable> succUnboxedVars = new HashSet<Variable>();
    CFG cfg = problem.getScope().cfg();

    for (Edge e : cfg.getOutgoingEdges(basicBlock)) {
      BasicBlock b = (BasicBlock) e.getDestination().getData();
      if (b != cfg.getExitBB()) {
        UnboxableOpsAnalysisNode x = (UnboxableOpsAnalysisNode) problem.getFlowGraphNode(b);
        succUnboxedVars.addAll(x.inState.unboxedVars);
      }
    }

    succUnboxedVars.removeAll(outState.unboxedVars);

    // Only worry about vars live on exit from the BB
    LiveVariablesProblem lvp =
        (LiveVariablesProblem) problem.getScope().getDataFlowSolution(DataFlowConstants.LVP_NAME);
    BitSet liveVarsSet = ((LiveVariableNode) lvp.getFlowGraphNode(basicBlock)).getLiveInBitSet();

    // Rescue node, if any
    IRScope scope = this.problem.getScope();
    boolean isClosure = scope instanceof IRClosure;

    List<Instr> newInstrs = new ArrayList<Instr>();
    boolean unboxedLiveVars = false;

    initSolution();

    for (Instr i : basicBlock.getInstrs()) {
      Variable dst = null;
      boolean dirtied = false;
      boolean hitDFBarrier = false;
      // System.out.println("ORIG: " + i);
      if (i.getOperation().transfersControl()) {
        // Add unboxing instrs.
        for (Variable v : succUnboxedVars) {
          if (liveVarsSet.get(lvp.getDFVar(v).getId())) {
            // System.out.println("suv: UNBOXING for " + v);
            newInstrs.add(new UnboxFloatInstr(getUnboxedVar(unboxMap, v), v));
            tmpState.unboxedVars.add(v);
          }
        }
        unboxedLiveVars = true;
      } else {
        if (i instanceof ResultInstr) {
          dst = ((ResultInstr) i).getResult();
        }

        if (i instanceof CopyInstr) {
          // Copies are easy
          Operand src = ((CopyInstr) i).getSource();
          Class srcType = getOperandType(tmpState, src);
          setOperandType(tmpState, dst, srcType);

          // If we have an unboxed type for 'src', we can leave this unboxed.
          //
          // FIXME: However, if 'src' is a constant, this could unnecessarily
          // leave 'src' unboxed and lead to a boxing instruction further down
          // at the use site of 'dst'. This indicates that leaving this unboxed
          // should ideally be done 'on-demand'. This indicates that this could
          // be a backward-flow algo OR that this algo should be run on a
          // dataflow graph / SSA graph.
          if (srcType == Float.class) {
            Operand unboxedSrc =
                src instanceof Variable ? getUnboxedVar(unboxMap, (Variable) src) : src;
            TemporaryLocalVariable unboxedDst = getUnboxedVar(unboxMap, dst);
            newInstrs.add(new CopyInstr(Operation.COPY_UNBOXED, unboxedDst, unboxedSrc));
            dirtied = true;
          }
        } else if (i instanceof CallBase) {
          // Process calls specially -- these are what we want to optimize!
          CallBase c = (CallBase) i;
          Operand o = c.getClosureArg(null);
          if (o == null) {
            MethAddr m = c.getMethodAddr();
            Operand r = c.getReceiver();
            Operand[] args = c.getCallArgs();
            if (args.length == 1 && m.resemblesALUOp()) {
              Operand a = args[0];
              Class receiverType = getOperandType(tmpState, r);
              Class argType = getOperandType(tmpState, a);
              // Optimistically assume that call is an ALU op
              if (receiverType == Float.class
                  || (receiverType == Fixnum.class && argType == Float.class)) {
                setOperandType(tmpState, dst, Float.class);
                r = getUnboxedOperand(tmpState.unboxedVars, unboxMap, r, newInstrs);
                a = getUnboxedOperand(tmpState.unboxedVars, unboxMap, a, newInstrs);
                TemporaryLocalVariable unboxedDst = getUnboxedVar(unboxMap, dst);
                newInstrs.add(new AluInstr(m.getUnboxedOp(Float.class), unboxedDst, r, a));
                dirtied = true;
              } else {
                if (receiverType == Fixnum.class && argType == Fixnum.class) {
                  setOperandType(tmpState, dst, Fixnum.class);
                } else {
                  setOperandType(tmpState, dst, Object.class);
                }

                if (c.targetRequiresCallersBinding()) {
                  hitDFBarrier = true;
                }
              }
            } else {
              setOperandType(tmpState, dst, Object.class);
            }
          } else {
            if (o instanceof WrappedIRClosure) {
              // Since binding can escape in arbitrary ways in the general case,
              // assume the worst for now. If we are guaranteed that the closure binding
              // is not used outside the closure itself, we can avoid worst-case behavior.
              hitDFBarrier = true;

              // Fetch the nested unboxing-analysis problem, creating one if necessary
              IRClosure cl = ((WrappedIRClosure) o).getClosure();
              UnboxableOpsAnalysisProblem subProblem =
                  (UnboxableOpsAnalysisProblem) cl.getDataFlowSolution(DataFlowConstants.UNBOXING);
              UnboxableOpsAnalysisNode exitNode =
                  (UnboxableOpsAnalysisNode) subProblem.getExitNode();

              // Compute solution
              subProblem.unbox();

              // Update types to MEET(new-state-on-exit, current-state)
              tmpState.computeMEETForTypes(exitNode.outState, true);

              // As for unboxed var state, since binding can escape in
              // arbitrary ways in the general case, assume the worst for now.
              // If we are guaranteed that the closure binding is not used
              // outside the closure itself, we can avoid worst-case behavior
              // and only clear vars that are modified in the closure.
              hitDFBarrier = true;
            } else {
              // Cannot analyze
              hitDFBarrier = true;
            }
          }
        } else {
          // We dont know how to optimize this instruction.
          // So, we assume we dont know type of the result.
          // TOP/class --> BOTTOM
          setOperandType(tmpState, dst, Object.class);
        }
      }

      if (dirtied) {
        tmpState.unboxedVars.add(dst);
        tmpState.unboxedDirtyVars.add(dst);
      } else {
        // Since the instruction didn't run in unboxed form,
        // dirty unboxed vars will have to get boxed here.
        boxRequiredVars(
            i, tmpState, unboxMap, dst, hasExceptionsRescued(), hitDFBarrier, newInstrs);
      }
    }

    // Add unboxing instrs.
    if (!unboxedLiveVars) {
      for (Variable v : succUnboxedVars) {
        if (liveVarsSet.get(lvp.getDFVar(v).getId())) {
          // System.out.println("suv: UNBOXING for " + v);
          newInstrs.add(new UnboxFloatInstr(getUnboxedVar(unboxMap, v), v));
        }
      }
    }

    /*
            System.out.println("------");
            for (Instr i : newInstrs) {
                System.out.println("NEW: " + i);
            }
    */

    basicBlock.replaceInstrs(newInstrs);
  }
  @Override
  public Object execute(IRScope scope, Object... data) {
    // IRScriptBody do not get explicit call protocol instructions right now.
    // They dont push/pop a frame and do other special things like run begin/end blocks.
    // So, for now, they go through the runtime stub in IRScriptBody.
    //
    // Add explicit frame and binding push/pop instrs ONLY for methods -- we cannot handle this in
    // closures and evals yet
    // If the scope uses $_ or $~ family of vars, has local load/stores, or if its binding has
    // escaped, we have
    // to allocate a dynamic scope for it and add binding push/pop instructions.
    if (explicitCallProtocolSupported(scope)) {
      StoreLocalVarPlacementProblem slvpp =
          (StoreLocalVarPlacementProblem)
              scope.getDataFlowSolution(StoreLocalVarPlacementProblem.NAME);
      boolean scopeHasLocalVarStores = false;
      boolean bindingHasEscaped = scope.bindingHasEscaped();

      CFG cfg = scope.cfg();

      if (slvpp != null && bindingHasEscaped) {
        scopeHasLocalVarStores = slvpp.scopeHasLocalVarStores();
      } else {
        // We dont require local-var load/stores to have been run.
        // If it is not run, we go conservative and add push/pop binding instrs. everywhere
        scopeHasLocalVarStores = bindingHasEscaped;
      }

      boolean requireFrame = doesItRequireFrame(scope, bindingHasEscaped);
      boolean requireBinding = !scope.getFlags().contains(IRFlags.DYNSCOPE_ELIMINATED);

      if (requireBinding || requireFrame) {
        BasicBlock entryBB = cfg.getEntryBB();
        // Push
        if (requireFrame) entryBB.addInstr(new PushFrameInstr(scope.getName()));
        if (requireBinding) entryBB.addInstr(new PushBindingInstr());

        // SSS FIXME: We are doing this conservatively.
        // Only scopes that have unrescued exceptions need a GEB.
        //
        // Allocate GEB if necessary for popping
        BasicBlock geb = cfg.getGlobalEnsureBB();
        if (geb == null) {
          Variable exc = scope.createTemporaryVariable();
          geb = new BasicBlock(cfg, Label.getGlobalEnsureBlockLabel());
          geb.addInstr(
              new ReceiveJRubyExceptionInstr(exc)); // JRuby Implementation exception handling
          geb.addInstr(new ThrowExceptionInstr(exc));
          cfg.addGlobalEnsureBB(geb);
        }

        // Pop on all scope-exit paths
        for (BasicBlock bb : cfg.getBasicBlocks()) {
          Instr i = null;
          ListIterator<Instr> instrs = bb.getInstrs().listIterator();
          while (instrs.hasNext()) {
            i = instrs.next();
            // Right now, we only support explicit call protocol on methods.
            // So, non-local returns and breaks don't get here.
            // Non-local-returns and breaks are tricky since they almost always
            // throw an exception and we don't multiple pops (once before the
            // return/break, and once when the exception is caught).
            if (!bb.isExitBB() && i instanceof ReturnBase) {
              // Add before the break/return
              instrs.previous();
              if (requireBinding) instrs.add(new PopBindingInstr());
              if (requireFrame) instrs.add(new PopFrameInstr());
              break;
            }
          }

          if (bb.isExitBB() && !bb.isEmpty()) {
            // Last instr could be a return -- so, move iterator one position back
            if (i != null && i instanceof ReturnBase) instrs.previous();
            if (requireBinding) instrs.add(new PopBindingInstr());
            if (requireFrame) instrs.add(new PopFrameInstr());
          }

          if (bb == geb) {
            // Add before throw-exception-instr which would be the last instr
            if (i != null) {
              // Assumption: Last instr should always be a control-transfer instruction
              assert i.getOperation().transfersControl()
                  : "Last instruction of GEB in scope: "
                      + scope
                      + " is "
                      + i
                      + ", not a control-xfer instruction";
              instrs.previous();
            }
            if (requireBinding) instrs.add(new PopBindingInstr());
            if (requireFrame) instrs.add(new PopFrameInstr());
          }
        }
      }

      // This scope has an explicit call protocol flag now
      scope.setExplicitCallProtocolFlag();
    }

    // FIXME: Useless for now
    // Run on all nested closures.
    for (IRClosure c : scope.getClosures()) run(c, false, true);

    // LVA information is no longer valid after the pass
    // FIXME: Grrr ... this seems broken to have to create a new object to invalidate
    (new LiveVariableAnalysis()).invalidate(scope);

    return null;
  }
  public void unbox(Map<Variable, TemporaryLocalVariable> unboxMap) {
    // System.out.println("BB : " + basicBlock + " in " + problem.getScope().getName());
    // System.out.println("-- known types on entry:");
    // for (Variable v: inState.types.keySet()) {
    //     if (inState.types.get(v) != Object.class) {
    //         System.out.println(v + "-->" + inState.types.get(v));
    //     }
    // }
    // System.out.print("-- unboxed vars on entry:");
    // for (Variable v: inState.unboxedVars) {
    //     System.out.print(" " + v);
    // }
    // System.out.println("------");
    // System.out.print("-- unboxed vars on exit:");
    // for (Variable v: outState.unboxedVars) {
    //     System.out.print(" " + v);
    // }
    // System.out.println("------");

    CFG cfg = getCFG();

    // Compute UNION(unboxedVarsIn(all-successors)) - this.unboxedVarsOut
    // All vars in this new set have to be unboxed on exit from this BB
    HashMap<Variable, Class> succUnboxedVars = new HashMap<Variable, Class>();
    for (BasicBlock b : cfg.getOutgoingDestinations(basicBlock)) {
      if (b.isExitBB()) continue;

      Map<Variable, Class> xVars = problem.getFlowGraphNode(b).inState.unboxedVars;
      for (Variable v2 : xVars.keySet()) {
        // VERY IMPORTANT: Pay attention!
        //
        // Technically, the successors of this node may not all agree on what
        // the unboxed type ought to be for 'v2'. For example, one successor might
        // want 'v2' in Fixnum form and other might want it in Float form. If that
        // happens, we have to add unboxing instructions for each of those expected
        // types. However, for now, we are going to punt and assume that our successors
        // agree on unboxed types for 'v2'.
        succUnboxedVars.put(v2, xVars.get(v2));
      }
    }

    // Same caveat as above applies here
    for (Variable v3 : outState.unboxedVars.keySet()) {
      succUnboxedVars.remove(v3);
    }

    // Only worry about vars live on exit from the BB
    LiveVariablesProblem lvp =
        (LiveVariablesProblem) problem.getScope().getDataFlowSolution(DataFlowConstants.LVP_NAME);
    BitSet liveVarsSet = lvp.getFlowGraphNode(basicBlock).getLiveInBitSet();

    List<Instr> newInstrs = new ArrayList<Instr>();
    boolean unboxedLiveVars = false;

    initSolution();

    for (Instr i : basicBlock.getInstrs()) {
      Variable dst = null;
      boolean dirtied = false;
      boolean hitDFBarrier = false;
      // System.out.println("ORIG: " + i);
      if (i.getOperation().transfersControl()) {
        // Add unboxing instrs.
        for (Variable v : succUnboxedVars.keySet()) {
          if (liveVarsSet.get(lvp.getDFVar(v))) {
            unboxVar(tmpState, succUnboxedVars.get(v), unboxMap, v, newInstrs);
          }
        }
        unboxedLiveVars = true;
      } else {
        if (i instanceof ResultInstr) {
          dst = ((ResultInstr) i).getResult();
        }

        if (i instanceof CopyInstr) {
          // Copies are easy
          Operand src = ((CopyInstr) i).getSource();
          Class srcType = getOperandType(tmpState, src);
          setOperandType(tmpState, dst, srcType);

          // If we have an unboxed type for 'src', we can leave this unboxed.
          //
          // FIXME: However, if 'src' is a constant, this could unnecessarily
          // leave 'src' unboxed and lead to a boxing instruction further down
          // at the use site of 'dst'. This indicates that leaving this unboxed
          // should ideally be done 'on-demand'. This indicates that this could
          // be a backward-flow algo OR that this algo should be run on a
          // dataflow graph / SSA graph.
          if (srcType == Float.class || srcType == Fixnum.class) {
            Operand unboxedSrc =
                src instanceof Variable ? getUnboxedVar(srcType, unboxMap, (Variable) src) : src;
            TemporaryLocalVariable unboxedDst = getUnboxedVar(srcType, unboxMap, dst);
            newInstrs.add(new CopyInstr(Operation.COPY, unboxedDst, unboxedSrc));
            tmpState.unboxedVars.put(dst, srcType);
            dirtied = true;
          }
        } else if (i instanceof ClosureAcceptingInstr) {
          Operand o = ((ClosureAcceptingInstr) i).getClosureArg();
          if (i instanceof CallBase && o == null) {
            CallBase c = (CallBase) i;
            MethAddr m = c.getMethodAddr();
            Operand r = c.getReceiver();
            Operand[] args = c.getCallArgs();
            if (dst != null && args.length == 1 && m.resemblesALUOp()) {
              Operand a = args[0];
              Class receiverType = getOperandType(tmpState, r);
              Class argType = getOperandType(tmpState, a);
              // Optimistically assume that call is an ALU op
              Operation unboxedOp;
              if ((receiverType == Float.class
                      || (receiverType == Fixnum.class && argType == Float.class))
                  && (unboxedOp = m.getUnboxedOp(Float.class)) != null) {
                dirtied = true;

                Class dstType = m.getUnboxedResultType(Float.class);
                setOperandType(tmpState, dst, dstType);
                tmpState.unboxedVars.put(dst, dstType);

                TemporaryLocalVariable unboxedDst = getUnboxedVar(dstType, unboxMap, dst);
                r = unboxOperand(tmpState, Float.class, unboxMap, r, newInstrs);
                a = unboxOperand(tmpState, Float.class, unboxMap, a, newInstrs);
                newInstrs.add(new AluInstr(unboxedOp, unboxedDst, r, a));
              } else if ((receiverType == Float.class
                      || (receiverType == Fixnum.class && argType == Fixnum.class))
                  && (unboxedOp = m.getUnboxedOp(Fixnum.class)) != null) {
                dirtied = true;

                Class dstType = m.getUnboxedResultType(Fixnum.class);
                setOperandType(tmpState, dst, dstType);
                tmpState.unboxedVars.put(dst, dstType);

                TemporaryLocalVariable unboxedDst = getUnboxedVar(dstType, unboxMap, dst);
                r = unboxOperand(tmpState, Fixnum.class, unboxMap, r, newInstrs);
                a = unboxOperand(tmpState, Fixnum.class, unboxMap, a, newInstrs);
                newInstrs.add(new AluInstr(unboxedOp, unboxedDst, r, a));
              } else {
                if (receiverType == Fixnum.class && argType == Fixnum.class) {
                  setOperandType(tmpState, dst, Fixnum.class);
                } else {
                  setOperandType(tmpState, dst, Object.class);
                }

                if (c.targetRequiresCallersBinding()) {
                  hitDFBarrier = true;
                }
              }
            } else {
              setOperandType(tmpState, dst, Object.class);
            }
          } else {
            if (o instanceof WrappedIRClosure) {
              // Since binding can escape in arbitrary ways in the general case,
              // assume the worst for now. If we are guaranteed that the closure binding
              // is not used outside the closure itself, we can avoid worst-case behavior.
              hitDFBarrier = true;

              // Fetch the nested unboxing-analysis problem, creating one if necessary
              IRClosure cl = ((WrappedIRClosure) o).getClosure();
              UnboxableOpsAnalysisProblem subProblem =
                  (UnboxableOpsAnalysisProblem) cl.getDataFlowSolution(DataFlowConstants.UNBOXING);
              UnboxableOpsAnalysisNode exitNode = subProblem.getExitNode();

              // Compute solution
              subProblem.unbox();

              // Update types to MEET(new-state-on-exit, current-state)
              tmpState.computeMEETForTypes(exitNode.outState, true);

              // As for unboxed var state, since binding can escape in
              // arbitrary ways in the general case, assume the worst for now.
              // If we are guaranteed that the closure binding is not used
              // outside the closure itself, we can avoid worst-case behavior
              // and only clear vars that are modified in the closure.
              hitDFBarrier = true;
            } else {
              // Cannot analyze
              hitDFBarrier = true;
            }
          }
        } else {
          // We dont know how to optimize this instruction.
          // So, we assume we dont know type of the result.
          // TOP/class --> BOTTOM
          setOperandType(tmpState, dst, Object.class);
        }
      }

      if (dirtied) {
        tmpState.unboxedDirtyVars.add(dst);
      } else {
        // Since the instruction didn't run in unboxed form,
        // dirty unboxed vars will have to get boxed here.
        boxRequiredVars(
            i, tmpState, unboxMap, dst, hasExceptionsRescued(), hitDFBarrier, newInstrs);
      }
    }

    // Add unboxing instrs.
    if (!unboxedLiveVars) {
      for (Variable v : succUnboxedVars.keySet()) {
        if (liveVarsSet.get(lvp.getDFVar(v))) {
          unboxVar(tmpState, succUnboxedVars.get(v), unboxMap, v, newInstrs);
        }
      }
    }

    /*
            System.out.println("------");
            for (Instr i : newInstrs) {
                System.out.println("NEW: " + i);
            }
    */

    basicBlock.replaceInstrs(newInstrs);
  }
Example #10
0
 public void buildCFG(List<Instr> instrList) {
   CFG newBuild = new CFG(this);
   newBuild.build(instrList);
   cfg = newBuild;
 }