void StackVisitor::readFrame(CallFrame* callFrame) { if (!callFrame) { m_frame.setToEnd(); return; } if (callFrame->isAnyWasmCallee()) { readNonInlinedFrame(callFrame); return; } #if !ENABLE(DFG_JIT) readNonInlinedFrame(callFrame); #else // !ENABLE(DFG_JIT) // If the frame doesn't have a code block, then it's not a DFG frame. // Hence, we're not at an inlined frame. CodeBlock* codeBlock = callFrame->codeBlock(); if (!codeBlock) { readNonInlinedFrame(callFrame); return; } // If the code block does not have any code origins, then there's no // inlining. Hence, we're not at an inlined frame. if (!codeBlock->hasCodeOrigins()) { readNonInlinedFrame(callFrame); return; } CallSiteIndex index = callFrame->callSiteIndex(); ASSERT(codeBlock->canGetCodeOrigin(index)); if (!codeBlock->canGetCodeOrigin(index)) { // See assertion above. In release builds, we try to protect ourselves // from crashing even though stack walking will be goofed up. m_frame.setToEnd(); return; } CodeOrigin codeOrigin = codeBlock->codeOrigin(index); if (!codeOrigin.inlineCallFrame) { readNonInlinedFrame(callFrame, &codeOrigin); return; } readInlinedFrame(callFrame, &codeOrigin); #endif // !ENABLE(DFG_JIT) }
void StackVisitor::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin) { ASSERT(codeOrigin); int frameOffset = inlinedFrameOffset(codeOrigin); bool isInlined = !!frameOffset; if (isInlined) { InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame; m_frame.m_callFrame = callFrame; m_frame.m_inlineCallFrame = inlineCallFrame; if (inlineCallFrame->argumentCountRegister.isValid()) m_frame.m_argumentCountIncludingThis = callFrame->r(inlineCallFrame->argumentCountRegister.offset()).unboxedInt32(); else m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size(); m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock(); m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex; JSFunction* callee = inlineCallFrame->calleeForCallFrame(callFrame); m_frame.m_callee = callee; ASSERT(m_frame.callee()); // The callerFrame just needs to be non-null to indicate that we // haven't reached the last frame yet. Setting it to the root // frame (i.e. the callFrame that this inlined frame is called from) // would work just fine. m_frame.m_callerFrame = callFrame; return; } readNonInlinedFrame(callFrame, codeOrigin); }
void StackVisitor::unwindToMachineCodeBlockFrame() { #if ENABLE(DFG_JIT) if (m_frame.isInlinedFrame()) { CodeOrigin codeOrigin = m_frame.inlineCallFrame()->directCaller; while (codeOrigin.inlineCallFrame) codeOrigin = codeOrigin.inlineCallFrame->directCaller; readNonInlinedFrame(m_frame.callFrame(), &codeOrigin); } #endif }
void StackIterator::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin) { ASSERT(codeOrigin); ASSERT(!callFrame->hasHostCallFrameFlag()); unsigned frameOffset = inlinedFrameOffset(codeOrigin); bool isInlined = !!frameOffset; if (isInlined) { InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame; m_frame.m_callFrame = callFrame; m_frame.m_inlineCallFrame = inlineCallFrame; m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size(); m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock(); m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex; JSFunction* callee = inlineCallFrame->callee.get(); if (callee) { m_frame.m_scope = callee->scope(); m_frame.m_callee = callee; } else { CallFrame* inlinedFrame = callFrame + frameOffset; m_frame.m_scope = inlinedFrame->scope(); m_frame.m_callee = inlinedFrame->callee(); } ASSERT(m_frame.scope()); ASSERT(m_frame.callee()); // The callerFrame just needs to be non-null to indicate that we // haven't reached the last frame yet. Setting it to the root // frame (i.e. the callFrame that this inlined frame is called from) // would work just fine. m_frame.m_callerFrame = callFrame; return; } readNonInlinedFrame(callFrame, codeOrigin); }