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