CallFrame* CallFrame::trueCallerFrame() { // this -> The callee; this is either an inlined callee in which case it already has // a pointer to the true caller. Otherwise it contains current PC in the machine // caller. // // machineCaller -> The caller according to the machine, which may be zero or // more frames above the true caller due to inlining. // Am I an inline call frame? If so, we're done. if (isInlineCallFrame()) return callerFrame(); // I am a machine call frame, so the question is: is my caller a machine call frame // that has inlines or a machine call frame that doesn't? CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag(); if (!machineCaller) return 0; ASSERT(!machineCaller->isInlineCallFrame()); // Figure out how we want to get the current code location. if (hasHostCallFrameFlag() || returnAddressIsInCtiTrampoline(returnPC())) return machineCaller->trueCallFrameFromVMCode(); return machineCaller->trueCallFrame(returnPC()); }
CallFrame* CallFrame::trueCallerFrameSlow() { // this -> The callee; this is either an inlined callee in which case it already has // a pointer to the true caller. Otherwise it contains current PC in the machine // caller. // // machineCaller -> The caller according to the machine, which may be zero or // more frames above the true caller due to inlining. // // trueCaller -> The real caller. // Am I an inline call frame? If so, we're done. if (isInlineCallFrame()) return callerFrame(); // I am a machine call frame, so the question is: is my caller a machine call frame // that has inlines or a machine call frame that doesn't? CallFrame* machineCaller = callerFrame()->removeHostCallFrameFlag(); if (!machineCaller) return 0; ASSERT(!machineCaller->isInlineCallFrame()); if (!machineCaller->codeBlock() || !machineCaller->codeBlock()->hasCodeOrigins()) return machineCaller; // No inlining, so machineCaller == trueCaller // Figure out where the caller frame would have gone relative to the machine // caller, and rematerialize it. Do so for the entire inline stack. CodeOrigin codeOrigin = machineCaller->codeBlock()->codeOriginForReturn(returnPC()); for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) { InlineCallFrame* nextInlineCallFrame = inlineCallFrame = inlineCallFrame->caller.inlineCallFrame; CallFrame* inlinedCaller = machineCaller + inlineCallFrame->stackOffset; JSObject* callee = machineCaller->registers()[inlineCallFrame->calleeVR].function(); JSCell* calleeAsFunctionCell = getJSFunction(callee); ASSERT(calleeAsFunctionCell); JSFunction* calleeAsFunction = asFunction(calleeAsFunctionCell); // Fill in the inlinedCaller inlinedCaller->setCodeBlock(machineCaller->codeBlock()); inlinedCaller->setScopeChain(calleeAsFunction->scope()); if (nextInlineCallFrame) inlinedCaller->setCallerFrame(machineCaller + nextInlineCallFrame->stackOffset); else inlinedCaller->setCallerFrame(machineCaller); inlinedCaller->setInlineCallFrame(inlineCallFrame); inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->numArgumentsIncludingThis); inlinedCaller->setCallee(callee); inlineCallFrame = nextInlineCallFrame; } return machineCaller + codeOrigin.inlineCallFrame->stackOffset; }
void CallFrame::dump(PrintStream& out) { if (CodeBlock* codeBlock = this->codeBlock()) { out.print(codeBlock->inferredName(), "#", codeBlock->hashAsStringIfPossible(), " [", codeBlock->jitType(), "]"); out.print("("); thisValue().dumpForBacktrace(out); for (size_t i = 0; i < argumentCount(); ++i) { out.print(", "); JSValue value = argument(i); value.dumpForBacktrace(out); } out.print(")"); return; } out.print(returnPC()); }