| /* |
| * 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 |
| |
| } |