Esempio n. 1
0
void TraceBuilder::updateTrackedState(IRInstruction* inst) {
  // We don't track state for any trace other than the main trace.
  if (m_savedTraces.size() > 0) return;

  Opcode opc = inst->op();
  // Update tracked state of local values/types, stack/frame pointer, CSE, etc.

  // kill tracked memory values
  if (inst->mayModifyRefs()) {
    m_refCountedMemValue = nullptr;
  }

  switch (opc) {
  case DefInlineFP:    trackDefInlineFP(inst);  break;
  case InlineReturn:   trackInlineReturn(inst); break;

  case InlineFPAnchor: m_needsFPAnchor = true;  break;

  case Call:
    m_spValue = inst->dst();
    m_frameSpansCall = true;
    // A call pops the ActRec and pushes a return value.
    m_spOffset -= kNumActRecCells;
    m_spOffset += 1;
    assert(m_spOffset >= 0);
    killCse();
    killLocalsForCall();
    break;

  case CallArray:
    m_spValue = inst->dst();
    m_frameSpansCall = true;
    // A CallArray pops the ActRec an array arg and pushes a return value.
    m_spOffset -= kNumActRecCells;
    assert(m_spOffset >= 0);
    killCse();
    killLocalsForCall();
    break;

  case ContEnter:
    killCse();
    killLocalsForCall();
    break;

  case DefFP:
  case FreeActRec:
    m_fpValue = inst->dst();
    break;

  case ReDefGeneratorSP:
    m_spValue = inst->dst();
    break;

  case ReDefSP:
    m_spValue = inst->dst();
    m_spOffset = inst->extra<ReDefSP>()->offset;
    break;

  case DefInlineSP:
  case DefSP:
    m_spValue = inst->dst();
    m_spOffset = inst->extra<StackOffset>()->offset;
    break;

  case AssertStk:
  case AssertStkVal:
  case CastStk:
  case CoerceStk:
  case CheckStk:
  case GuardStk:
  case ExceptionBarrier:
    m_spValue = inst->dst();
    break;

  case SpillStack: {
    m_spValue = inst->dst();
    // Push the spilled values but adjust for the popped values
    int64_t stackAdjustment = inst->src(1)->getValInt();
    m_spOffset -= stackAdjustment;
    m_spOffset += spillValueCells(inst);
    break;
  }

  case SpillFrame:
  case CufIterSpillFrame:
    m_spValue = inst->dst();
    m_spOffset += kNumActRecCells;
    break;

  case InterpOne:
  case InterpOneCF: {
    m_spValue = inst->dst();
    auto const& extra = *inst->extra<InterpOneData>();
    int64_t stackAdjustment = extra.cellsPopped - extra.cellsPushed;
    // push the return value if any and adjust for the popped values
    m_spOffset -= stackAdjustment;
    break;
  }

  case StElem:
  case StProp:
  case StPropNT:
    // fall through to StMem; stored value is the same arg number (2)
  case StMem:
  case StMemNT:
    m_refCountedMemValue = inst->src(2);
    break;

  case LdMem:
  case LdProp:
  case LdElem:
  case LdRef:
  case ArrayGet:
  case VectorGet:
  case PairGet:
  case MapGet:
  case StableMapGet:
    m_refCountedMemValue = inst->dst();
    break;

  case StRefNT:
  case StRef: {
    m_refCountedMemValue = inst->src(2);
    SSATmp* newRef = inst->dst();
    SSATmp* prevRef = inst->src(0);
    // update other tracked locals that also contain prevRef
    updateLocalRefValues(prevRef, newRef);
    break;
  }

  case StLocNT:
  case StLoc:
    setLocalValue(inst->extra<LocalId>()->locId, inst->src(1));
    break;

  case LdLoc:
    setLocalValue(inst->extra<LdLoc>()->locId, inst->dst());
    break;

  case OverrideLoc:
    // If changing the inner type of a boxed local, also drop the
    // information about inner types for any other boxed locals.
    if (inst->typeParam().isBoxed()) dropLocalRefsInnerTypes();
    setLocalType(inst->extra<LocalId>()->locId, inst->typeParam());
    break;

  case AssertLoc:
  case GuardLoc:
  case CheckLoc:
    m_fpValue = inst->dst();
    refineLocalType(inst->extra<LocalId>()->locId, inst->typeParam());
    break;

  case OverrideLocVal:
    setLocalValue(inst->extra<LocalId>()->locId, inst->src(1));
    break;

  case SmashLocals:
    clearLocals();
    break;

  case IterInitK:
  case WIterInitK:
    // kill the locals to which this instruction stores iter's key and value
    killLocalValue(inst->src(3)->getValInt());
    killLocalValue(inst->src(4)->getValInt());
    break;

  case IterInit:
  case WIterInit:
    // kill the local to which this instruction stores iter's value
    killLocalValue(inst->src(3)->getValInt());
    break;

  case IterNextK:
  case WIterNextK:
    // kill the locals to which this instruction stores iter's key and value
    killLocalValue(inst->src(2)->getValInt());
    killLocalValue(inst->src(3)->getValInt());
    break;

  case IterNext:
  case WIterNext:
    // kill the local to which this instruction stores iter's value
    killLocalValue(inst->src(2)->getValInt());
    break;

  case LdThis:
    m_thisIsAvailable = true;
    break;

  default:
    break;
  }

  if (MInstrEffects::supported(inst)) {
    MInstrEffects::get(inst,
                       [&](uint32_t id, SSATmp* val) { // storeLocalValue
                         setLocalValue(id, val);
                       },
                       [&](uint32_t id, Type t) { // setLocalType
                         setLocalType(id, t);
                       });
  }

  if (inst->modifiesStack()) {
    m_spValue = inst->modifiedStkPtr();
  }

  // update the CSE table
  if (m_enableCse && inst->canCSE()) {
    cseInsert(inst);
  }

  // if the instruction kills any of its sources, remove them from the
  // CSE table
  if (inst->killsSources()) {
    for (int i = 0; i < inst->numSrcs(); ++i) {
      if (inst->killsSource(i)) {
        cseKill(inst->src(i));
      }
    }
  }

  // save a copy of the current state for each successor.
  if (Block* target = inst->taken()) saveState(target);
}
void TraceBuilder::updateTrackedState(IRInstruction* inst) {
  Opcode opc = inst->op();
  // Update tracked state of local values/types, stack/frame pointer, CSE, etc.

  // kill tracked memory values
  if (inst->mayModifyRefs()) {
    m_refCountedMemValue = nullptr;
  }

  switch (opc) {
    case Call:
      m_spValue = inst->getDst();
      // A call pops the ActRec and pushes a return value.
      m_spOffset -= kNumActRecCells;
      m_spOffset += 1;
      assert(m_spOffset >= 0);
      killCse();
      killLocals();
      break;

    case CallArray:
      m_spValue = inst->getDst();
      // A CallArray pops the ActRec an array arg and pushes a return value.
      m_spOffset -= kNumActRecCells;
      assert(m_spOffset >= 0);
      killCse();
      killLocals();
      break;

    case ContEnter:
      killCse();
      killLocals();
      break;

    case DefFP:
    case FreeActRec:
      m_fpValue = inst->getDst();
      break;

    case ReDefGeneratorSP:
    case DefSP:
    case ReDefSP:
      m_spValue = inst->getDst();
      m_spOffset = inst->getExtra<StackOffset>()->offset;
      break;

    case AssertStk:
    case CastStk:
    case GuardStk:
    case ExceptionBarrier:
      m_spValue = inst->getDst();
      break;

    case SpillStack: {
      m_spValue = inst->getDst();
      // Push the spilled values but adjust for the popped values
      int64_t stackAdjustment = inst->getSrc(1)->getValInt();
      m_spOffset -= stackAdjustment;
      m_spOffset += spillValueCells(inst);
      break;
    }

    case SpillFrame:
      m_spValue = inst->getDst();
      m_spOffset += kNumActRecCells;
      break;

    case NewObj:
    case NewObjCached:
      m_spValue = inst->getDst();
      // new obj leaves the new object and an actrec on the stack
      m_spOffset += kNumActRecCells + 1;
      break;

    case NewObjNoCtorCached:
      m_spValue = inst->getDst();
      m_spOffset += 1;
      break;

    case InterpOne: {
      m_spValue = inst->getDst();
      int64_t stackAdjustment = inst->getSrc(3)->getValInt();
      Type resultType = inst->getTypeParam();
      // push the return value if any and adjust for the popped values
      m_spOffset -= stackAdjustment;
      break;
    }

    case StProp:
    case StPropNT:
      // fall through to StMem; stored value is the same arg number (2)
    case StMem:
    case StMemNT:
      m_refCountedMemValue = inst->getSrc(2);
      break;

    case LdMem:
    case LdProp:
    case LdRef:
      m_refCountedMemValue = inst->getDst();
      break;

    case StRefNT:
    case StRef: {
      m_refCountedMemValue = inst->getSrc(2);
      SSATmp* newRef = inst->getDst();
      SSATmp* prevRef = inst->getSrc(0);
      // update other tracked locals that also contain prevRef
      updateLocalRefValues(prevRef, newRef);
      break;
    }

    case StLocNT:
    case StLoc:
      setLocalValue(inst->getExtra<LocalId>()->locId,
                    inst->getSrc(1));
      break;

    case LdLoc:
      setLocalValue(inst->getExtra<LdLoc>()->locId, inst->getDst());
      break;

    case OverrideLoc:
      // If changing the inner type of a boxed local, also drop the
      // information about inner types for any other boxed locals.
      if (inst->getTypeParam().isBoxed()) {
        dropLocalRefsInnerTypes();
      }
      // fallthrough
    case AssertLoc:
    case GuardLoc:
      setLocalType(inst->getExtra<LocalId>()->locId,
                   inst->getTypeParam());
      break;

    case IterInitK:
      // kill the locals to which this instruction stores iter's key and value
      killLocalValue(inst->getSrc(3)->getValInt());
      killLocalValue(inst->getSrc(4)->getValInt());
      break;

    case IterInit:
      // kill the local to which this instruction stores iter's value
      killLocalValue(inst->getSrc(3)->getValInt());
      break;

    case IterNextK:
      // kill the locals to which this instruction stores iter's key and value
      killLocalValue(inst->getSrc(2)->getValInt());
      killLocalValue(inst->getSrc(3)->getValInt());
      break;

    case IterNext:
      // kill the local to which this instruction stores iter's value
      killLocalValue(inst->getSrc(2)->getValInt());
      break;

    case LdThis:
      m_thisIsAvailable = true;
      break;

    default:
      break;
  }

  if (VectorEffects::supported(inst)) {
    VectorEffects::get(inst,
                       [&](uint32_t id, SSATmp* val) { // storeLocalValue
                         setLocalValue(id, val);
                       },
                       [&](uint32_t id, Type t) { // setLocalType
                         setLocalType(id, t);
                       });
  }

  if (inst->modifiesStack()) {
    m_spValue = inst->modifiedStkPtr();
  }

  // update the CSE table
  if (m_enableCse && inst->canCSE()) {
    cseInsert(inst);
  }

  // if the instruction kills any of its sources, remove them from the
  // CSE table
  if (inst->killsSources()) {
    for (int i = 0; i < inst->getNumSrcs(); ++i) {
      if (inst->killsSource(i)) {
        cseKill(inst->getSrc(i));
      }
    }
  }

  // save a copy of the current state for each successor.
  if (Block* target = inst->getTaken()) saveState(target);
}