void FrameState::update(const IRInstruction* inst) { FTRACE(3, "FrameState::update processing {}\n", *inst); if (auto* taken = inst->taken()) { // When we're building the IR, we append a conditional jump after // generating its target block: see emitJmpCondHelper, where we // call makeExit() before gen(JmpZero). It doesn't make sense to // update the target block state at this point, so don't. The // state doesn't have this problem during optimization passes, // because we'll always process the jump before the target block. if (!m_building || taken->empty()) save(taken); } auto const opc = inst->op(); getLocalEffects(inst, *this); switch (opc) { case DefInlineFP: trackDefInlineFP(inst); break; case InlineReturn: trackInlineReturn(inst); 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); clearCse(); 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); clearCse(); break; case ContEnter: clearCse(); break; case DefFP: case FreeActRec: m_fpValue = inst->dst(); break; case ReDefResumableSP: m_spValue = inst->dst(); break; case ReDefSP: m_spValue = inst->dst(); m_spOffset = inst->extra<ReDefSP>()->spOffset; break; case DefInlineSP: case DefSP: m_spValue = inst->dst(); m_spOffset = inst->extra<StackOffset>()->offset; break; case AssertStk: 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)->intVal(); 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 AssertLoc: case GuardLoc: case CheckLoc: m_fpValue = inst->dst(); break; case LdThis: m_thisAvailable = true; break; default: break; } 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 state for each block at the end. if (inst->isTerminal()) { save(inst->block()); } }
void FrameState::update(const IRInstruction* inst) { if (auto* taken = inst->taken()) { save(taken); } auto const opc = inst->op(); getLocalEffects(inst, *this); switch (opc) { case DefInlineFP: trackDefInlineFP(inst); break; case InlineReturn: trackInlineReturn(inst); 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); clearCse(); 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); clearCse(); break; case ContEnter: clearCse(); 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>()->spOffset; 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 AssertLoc: case GuardLoc: case CheckLoc: m_fpValue = inst->dst(); break; case LdThis: m_thisAvailable = true; break; default: break; } 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)); } } } }