X-Git-Url: https://git.saurik.com/apple/javascriptcore.git/blobdiff_plain/9dae56ea45a0f5f8136a5c93d6f3a7f99399ca73..a253471d7f8e4d91bf6ebabab00155c3b387d3d0:/interpreter/CallFrame.cpp diff --git a/interpreter/CallFrame.cpp b/interpreter/CallFrame.cpp index 1c74280..a5ffaee 100644 --- a/interpreter/CallFrame.cpp +++ b/interpreter/CallFrame.cpp @@ -27,12 +27,167 @@ #include "CallFrame.h" #include "CodeBlock.h" +#include "Interpreter.h" namespace JSC { -JSValuePtr CallFrame::thisValue() +#ifndef NDEBUG +void CallFrame::dumpCaller() { - return this[codeBlock()->thisRegister()].jsValue(this); + int signedLineNumber; + intptr_t sourceID; + UString urlString; + JSValue function; + + interpreter()->retrieveLastCaller(this, signedLineNumber, sourceID, urlString, function); + dataLog("Callpoint => %s:%d\n", urlString.utf8().data(), signedLineNumber); +} + +RegisterFile* CallFrame::registerFile() +{ + return &interpreter()->registerFile(); +} + +#endif + +#if USE(JSVALUE32_64) +unsigned CallFrame::bytecodeOffsetForNonDFGCode() const +{ + ASSERT(codeBlock()); + return currentVPC() - codeBlock()->instructions().begin(); +} + +void CallFrame::setBytecodeOffsetForNonDFGCode(unsigned offset) +{ + ASSERT(codeBlock()); + setCurrentVPC(codeBlock()->instructions().begin() + offset); +} +#else +Instruction* CallFrame::currentVPC() const +{ + return codeBlock()->instructions().begin() + bytecodeOffsetForNonDFGCode(); +} +void CallFrame::setCurrentVPC(Instruction* vpc) +{ + setBytecodeOffsetForNonDFGCode(vpc - codeBlock()->instructions().begin()); +} +#endif + +#if ENABLE(DFG_JIT) +bool CallFrame::isInlineCallFrameSlow() +{ + if (!callee()) + return false; + JSCell* calleeAsFunctionCell = getJSFunction(callee()); + if (!calleeAsFunctionCell) + return false; + JSFunction* calleeAsFunction = jsCast(calleeAsFunctionCell); + return calleeAsFunction->executable() != codeBlock()->ownerExecutable(); +} + +CallFrame* CallFrame::trueCallFrame(AbstractPC pc) +{ + // Am I an inline call frame? If so, we're done. + if (isInlineCallFrame()) + return this; + + // If I don't have a code block, then I'm not DFG code, so I'm the true call frame. + CodeBlock* machineCodeBlock = codeBlock(); + if (!machineCodeBlock) + return this; + + // If the code block does not have any code origins, then there was no inlining, so + // I'm done. + if (!machineCodeBlock->hasCodeOrigins()) + return this; + + // At this point the PC must be due either to the DFG, or it must be unset. + ASSERT(pc.hasJITReturnAddress() || !pc); + + // Try to determine the CodeOrigin. If we don't have a pc set then the only way + // that this makes sense is if the CodeOrigin index was set in the call frame. + // FIXME: Note that you will see "Not currently in inlined code" comments below. + // Currently, we do not record code origins for code that is not inlined, because + // the only thing that we use code origins for is determining the inline stack. + // But in the future, we'll want to use this same functionality (having a code + // origin mapping for any calls out of JIT code) to determine the PC at any point + // in the stack even if not in inlined code. When that happens, the code below + // will have to change the way it detects the presence of inlining: it will always + // get a code origin, but sometimes, that code origin will not have an inline call + // frame. In that case, this method should bail and return this. + CodeOrigin codeOrigin; + if (pc.isSet()) { + ReturnAddressPtr currentReturnPC = pc.jitReturnAddress(); + + bool hasCodeOrigin = machineCodeBlock->codeOriginForReturn(currentReturnPC, codeOrigin); + ASSERT_UNUSED(hasCodeOrigin, hasCodeOrigin); + } else { + unsigned index = codeOriginIndexForDFG(); + codeOrigin = machineCodeBlock->codeOrigin(index); + } + + if (!codeOrigin.inlineCallFrame) + return this; // Not currently in inlined code. + + for (InlineCallFrame* inlineCallFrame = codeOrigin.inlineCallFrame; inlineCallFrame;) { + InlineCallFrame* nextInlineCallFrame = inlineCallFrame->caller.inlineCallFrame; + + CallFrame* inlinedCaller = this + inlineCallFrame->stackOffset; + + JSFunction* calleeAsFunction = inlineCallFrame->callee.get(); + + // Fill in the inlinedCaller + inlinedCaller->setCodeBlock(machineCodeBlock); + + inlinedCaller->setScopeChain(calleeAsFunction->scope()); + if (nextInlineCallFrame) + inlinedCaller->setCallerFrame(this + nextInlineCallFrame->stackOffset); + else + inlinedCaller->setCallerFrame(this); + + inlinedCaller->setInlineCallFrame(inlineCallFrame); + inlinedCaller->setArgumentCountIncludingThis(inlineCallFrame->arguments.size()); + inlinedCaller->setCallee(calleeAsFunction); + + inlineCallFrame = nextInlineCallFrame; + } + + return this + codeOrigin.inlineCallFrame->stackOffset; +} + +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()->removeHostCallFrameFlag(); + + // 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 (!hasReturnPC() || returnAddressIsInCtiTrampoline(returnPC())) + return machineCaller->trueCallFrameFromVMCode()->removeHostCallFrameFlag(); + + return machineCaller->trueCallFrame(returnPC())->removeHostCallFrameFlag(); +} +#endif + +Register* CallFrame::frameExtentInternal() +{ + CodeBlock* codeBlock = this->codeBlock(); + ASSERT(codeBlock); + return registers() + codeBlock->m_numCalleeRegisters; } }