diff options
Diffstat (limited to 'Source/JavaScriptCore/interpreter/CallFrame.cpp')
-rw-r--r-- | Source/JavaScriptCore/interpreter/CallFrame.cpp | 123 |
1 files changed, 123 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/interpreter/CallFrame.cpp b/Source/JavaScriptCore/interpreter/CallFrame.cpp new file mode 100644 index 000000000..6dba77898 --- /dev/null +++ b/Source/JavaScriptCore/interpreter/CallFrame.cpp @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2008 Apple Inc. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "CallFrame.h" + +#include "CodeBlock.h" +#include "Interpreter.h" + +namespace JSC { + +#ifndef NDEBUG +void CallFrame::dumpCaller() +{ + int signedLineNumber; + intptr_t sourceID; + UString urlString; + JSValue function; + + interpreter()->retrieveLastCaller(this, signedLineNumber, sourceID, urlString, function); + printf("Callpoint => %s:%d\n", urlString.utf8().data(), signedLineNumber); +} + +RegisterFile* CallFrame::registerFile() +{ + return &interpreter()->registerFile(); +} + +#endif + +#if ENABLE(DFG_JIT) +bool CallFrame::isInlineCallFrameSlow() +{ + if (!callee()) + return false; + JSCell* calleeAsFunctionCell = getJSFunction(callee()); + if (!calleeAsFunctionCell) + return false; + JSFunction* calleeAsFunction = asFunction(calleeAsFunctionCell); + return calleeAsFunction->executable() != codeBlock()->ownerExecutable(); +} + +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. + // + // 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()) + return machineCaller; + if (!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->caller.inlineCallFrame; + + CallFrame* inlinedCaller = machineCaller + inlineCallFrame->stackOffset; + + JSFunction* calleeAsFunction = inlineCallFrame->callee.get(); + + // 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->arguments.size()); + inlinedCaller->setCallee(calleeAsFunction); + + inlineCallFrame = nextInlineCallFrame; + } + + return machineCaller + codeOrigin.inlineCallFrame->stackOffset; +} +#endif + +} |