blob: 6dba77898b1f155d429b35e7ae1c43d159f0acda [file] [log] [blame]
/*
* 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
}