Commit fd86164a authored by mark.lam@apple.com's avatar mark.lam@apple.com

Change StackIterator to not require writes to the JS stack.

https://bugs.webkit.org/show_bug.cgi?id=119657.

Reviewed by Geoffrey Garen.

* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* interpreter/CallFrame.h:
- Removed references to StackIteratorPrivate.h.
* interpreter/StackIterator.cpp:
(JSC::StackIterator::numberOfFrames):
(JSC::StackIterator::gotoFrameAtIndex):
(JSC::StackIterator::gotoNextFrame):
(JSC::StackIterator::resetIterator):
(JSC::StackIterator::find):
(JSC::StackIterator::readFrame):
(JSC::StackIterator::readNonInlinedFrame):
- Reads in the current CallFrame's data for non-inlined frames.
(JSC::inlinedFrameOffset):
- Convenience function to compute the inlined frame offset based on the
  CodeOrigin. If the offset is 0, then we're looking at the physical frame.
  Otherwise, it's an inlined frame.
(JSC::StackIterator::readInlinedFrame):
- Determines the inlined frame's caller frame. Will read in the caller
  frame if it is also an inlined frame i.e. we haven't reached the
  outer most frame yet. Otherwise, will call readNonInlinedFrame() to
  read on the outer most frame.
  This is based on the old StackIterator::Frame::logicalFrame().
(JSC::StackIterator::updateFrame):
- Reads the data of the caller frame of the current one. This function
  is renamed and moved from the old StackIterator::Frame::logicalCallerFrame(),
  but is now simplified because it delegates to the readInlinedFrame()
  to get the caller for inlined frames.
(JSC::StackIterator::Frame::arguments):
- Fixed to use the inlined frame versions of Arguments::create() and
  Arguments::tearOff() when the frame is an inlined frame.
(JSC::StackIterator::Frame::print):
(debugPrintCallFrame):
(debugPrintStack):
- Because sometimes, we want to see the whole stack while debugging.
* interpreter/StackIterator.h:
(JSC::StackIterator::Frame::argumentCount):
(JSC::StackIterator::Frame::callerFrame):
(JSC::StackIterator::Frame::callee):
(JSC::StackIterator::Frame::scope):
(JSC::StackIterator::Frame::codeBlock):
(JSC::StackIterator::Frame::bytecodeOffset):
(JSC::StackIterator::Frame::inlinedFrameInfo):
(JSC::StackIterator::Frame::isJSFrame):
(JSC::StackIterator::Frame::isInlinedFrame):
(JSC::StackIterator::Frame::callFrame):
(JSC::StackIterator::Frame::Frame):
(JSC::StackIterator::Frame::~Frame):
- StackIterator::Frame now caches commonly used accessed values from
  the CallFrame. It still delegates argument queries to the CallFrame.
(JSC::StackIterator::operator*):
(JSC::StackIterator::operator->):
(JSC::StackIterator::operator!=):
(JSC::StackIterator::operator++):
(JSC::StackIterator::end):
(JSC::StackIterator::operator==):
* interpreter/StackIteratorPrivate.h: Removed.



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@154821 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 619fc75d
2013-08-29 Mark Lam <mark.lam@apple.com>
Change StackIterator to not require writes to the JS stack.
https://bugs.webkit.org/show_bug.cgi?id=119657.
Reviewed by Geoffrey Garen.
* GNUmakefile.list.am:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
* JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
* JavaScriptCore.xcodeproj/project.pbxproj:
* interpreter/CallFrame.h:
- Removed references to StackIteratorPrivate.h.
* interpreter/StackIterator.cpp:
(JSC::StackIterator::numberOfFrames):
(JSC::StackIterator::gotoFrameAtIndex):
(JSC::StackIterator::gotoNextFrame):
(JSC::StackIterator::resetIterator):
(JSC::StackIterator::find):
(JSC::StackIterator::readFrame):
(JSC::StackIterator::readNonInlinedFrame):
- Reads in the current CallFrame's data for non-inlined frames.
(JSC::inlinedFrameOffset):
- Convenience function to compute the inlined frame offset based on the
CodeOrigin. If the offset is 0, then we're looking at the physical frame.
Otherwise, it's an inlined frame.
(JSC::StackIterator::readInlinedFrame):
- Determines the inlined frame's caller frame. Will read in the caller
frame if it is also an inlined frame i.e. we haven't reached the
outer most frame yet. Otherwise, will call readNonInlinedFrame() to
read on the outer most frame.
This is based on the old StackIterator::Frame::logicalFrame().
(JSC::StackIterator::updateFrame):
- Reads the data of the caller frame of the current one. This function
is renamed and moved from the old StackIterator::Frame::logicalCallerFrame(),
but is now simplified because it delegates to the readInlinedFrame()
to get the caller for inlined frames.
(JSC::StackIterator::Frame::arguments):
- Fixed to use the inlined frame versions of Arguments::create() and
Arguments::tearOff() when the frame is an inlined frame.
(JSC::StackIterator::Frame::print):
(debugPrintCallFrame):
(debugPrintStack):
- Because sometimes, we want to see the whole stack while debugging.
* interpreter/StackIterator.h:
(JSC::StackIterator::Frame::argumentCount):
(JSC::StackIterator::Frame::callerFrame):
(JSC::StackIterator::Frame::callee):
(JSC::StackIterator::Frame::scope):
(JSC::StackIterator::Frame::codeBlock):
(JSC::StackIterator::Frame::bytecodeOffset):
(JSC::StackIterator::Frame::inlinedFrameInfo):
(JSC::StackIterator::Frame::isJSFrame):
(JSC::StackIterator::Frame::isInlinedFrame):
(JSC::StackIterator::Frame::callFrame):
(JSC::StackIterator::Frame::Frame):
(JSC::StackIterator::Frame::~Frame):
- StackIterator::Frame now caches commonly used accessed values from
the CallFrame. It still delegates argument queries to the CallFrame.
(JSC::StackIterator::operator*):
(JSC::StackIterator::operator->):
(JSC::StackIterator::operator!=):
(JSC::StackIterator::operator++):
(JSC::StackIterator::end):
(JSC::StackIterator::operator==):
* interpreter/StackIteratorPrivate.h: Removed.
2013-08-29 Chris Curtis <chris_curtis@apple.com>
VM::throwException() crashes reproducibly in testapi with !ENABLE(JIT)
......
......@@ -581,7 +581,6 @@ javascriptcore_sources += \
Source/JavaScriptCore/interpreter/Register.h \
Source/JavaScriptCore/interpreter/StackIterator.cpp \
Source/JavaScriptCore/interpreter/StackIterator.h \
Source/JavaScriptCore/interpreter/StackIteratorPrivate.h \
Source/JavaScriptCore/interpreter/VMInspector.cpp \
Source/JavaScriptCore/interpreter/VMInspector.h \
Source/JavaScriptCore/JavaScriptCorePrefix.h \
......
......@@ -729,7 +729,6 @@
<ClInclude Include="..\interpreter\JSStackInlines.h" />
<ClInclude Include="..\interpreter\Register.h" />
<ClInclude Include="..\interpreter\StackIterator.h" />
<ClInclude Include="..\interpreter\StackIteratorPrivate.h" />
<ClInclude Include="..\interpreter\VMInspector.h" />
<ClInclude Include="..\jit\ClosureCallStubRoutine.h" />
<ClInclude Include="..\jit\CompactJITCodeMap.h" />
......@@ -1025,4 +1024,4 @@
<ImportGroup Label="ExtensionTargets">
<Import Project="$(VCTargetsPath)\BuildCustomizations\masm.targets" />
</ImportGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -1313,9 +1313,6 @@
<ClInclude Include="..\interpreter\StackIterator.h">
<Filter>interpreter</Filter>
</ClInclude>
<ClInclude Include="..\interpreter\StackIteratorPrivate.h">
<Filter>interpreter</Filter>
</ClInclude>
<ClInclude Include="..\interpreter\VMInspector.h">
<Filter>interpreter</Filter>
</ClInclude>
......@@ -2228,4 +2225,4 @@
<Filter>jit</Filter>
</MASM>
</ItemGroup>
</Project>
\ No newline at end of file
</Project>
......@@ -905,7 +905,6 @@
A7C1EAF017987AB600299DB2 /* JSStackInlines.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C1EAEB17987AB600299DB2 /* JSStackInlines.h */; };
A7C1EAF117987AB600299DB2 /* StackIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C1EAEC17987AB600299DB2 /* StackIterator.cpp */; };
A7C1EAF217987AB600299DB2 /* StackIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C1EAED17987AB600299DB2 /* StackIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7C1EAF317987AB600299DB2 /* StackIteratorPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C1EAEE17987AB600299DB2 /* StackIteratorPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
A7D89CF217A0B8CC00773AD8 /* DFGBasicBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D89CE317A0B8CC00773AD8 /* DFGBasicBlock.cpp */; };
A7D89CF317A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D89CE417A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp */; };
A7D89CF417A0B8CC00773AD8 /* DFGBlockInsertionSet.h in Headers */ = {isa = PBXBuildFile; fileRef = A7D89CE517A0B8CC00773AD8 /* DFGBlockInsertionSet.h */; settings = {ATTRIBUTES = (Private, ); }; };
......@@ -2078,7 +2077,6 @@
A7C1EAEB17987AB600299DB2 /* JSStackInlines.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStackInlines.h; sourceTree = "<group>"; };
A7C1EAEC17987AB600299DB2 /* StackIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackIterator.cpp; sourceTree = "<group>"; };
A7C1EAED17987AB600299DB2 /* StackIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackIterator.h; sourceTree = "<group>"; };
A7C1EAEE17987AB600299DB2 /* StackIteratorPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackIteratorPrivate.h; sourceTree = "<group>"; };
A7C225CC139981F100FF1662 /* KeywordLookupGenerator.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = KeywordLookupGenerator.py; sourceTree = "<group>"; };
A7C225CD1399849C00FF1662 /* KeywordLookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeywordLookup.h; sourceTree = "<group>"; };
A7D89CE317A0B8CC00773AD8 /* DFGBasicBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = DFGBasicBlock.cpp; path = dfg/DFGBasicBlock.cpp; sourceTree = "<group>"; };
......@@ -2605,7 +2603,6 @@
149B24FF0D8AF6D1009CB8C7 /* Register.h */,
A7C1EAEC17987AB600299DB2 /* StackIterator.cpp */,
A7C1EAED17987AB600299DB2 /* StackIterator.h */,
A7C1EAEE17987AB600299DB2 /* StackIteratorPrivate.h */,
FE4A331D15BD2E07006F54F3 /* VMInspector.cpp */,
FE4A331E15BD2E07006F54F3 /* VMInspector.h */,
);
......@@ -4281,7 +4278,6 @@
0F5541B21613C1FB00CE3E25 /* SpecialPointer.h in Headers */,
0FD82E54141DAEEE00179C94 /* SpeculatedType.h in Headers */,
A7C1EAF217987AB600299DB2 /* StackIterator.h in Headers */,
A7C1EAF317987AB600299DB2 /* StackIteratorPrivate.h in Headers */,
14DF04DA16B3996D0016A513 /* StaticPropertyAnalysis.h in Headers */,
14CA958B16AB50DE00938A06 /* StaticPropertyAnalyzer.h in Headers */,
A730B6121250068F009D25B1 /* StrictEvalActivation.h in Headers */,
......
......@@ -111,9 +111,4 @@ StackIterator CallFrame::find(JSFunction* calleeFunctionObj, StackIterator::Fram
return iter;
}
StackIterator::Frame* CallFrame::end()
{
return StackIterator::end();
}
}
} // namespace JSC
......@@ -28,7 +28,7 @@
#include "JSStack.h"
#include "MacroAssemblerCodeRef.h"
#include "Register.h"
#include "StackIteratorPrivate.h"
#include "StackIterator.h"
namespace JSC {
......@@ -283,7 +283,7 @@ namespace JSC {
JS_EXPORT_PRIVATE StackIterator begin(StackIterator::FrameFilter = 0);
JS_EXPORT_PRIVATE StackIterator find(JSFunction* calleeFunctionObj, StackIterator::FrameFilter = 0);
JS_EXPORT_PRIVATE StackIterator::Frame* end();
StackIterator end() { return StackIterator::end(); }
private:
static const intptr_t HostCallFrameFlag = 1;
......
......@@ -29,6 +29,7 @@
#include "Arguments.h"
#include "CallFrameInlines.h"
#include "Executable.h"
#include "Interpreter.h"
#include "Operations.h"
#include <wtf/DataLog.h>
......@@ -38,7 +39,6 @@ StackIterator::StackIterator(CallFrame* startFrame, StackIterator::FrameFilter f
: m_startFrame(startFrame)
, m_filter(filter)
{
ASSERT(startFrame);
resetIterator();
}
......@@ -46,8 +46,8 @@ size_t StackIterator::numberOfFrames()
{
int savedFrameIndex = m_frameIndex;
resetIterator();
while (m_frame)
gotoNextFrame();
while (m_frame.callFrame())
gotoNextFrameWithFilter();
size_t numberOfFrames = m_frameIndex;
resetIterator();
......@@ -58,40 +58,166 @@ size_t StackIterator::numberOfFrames()
void StackIterator::gotoFrameAtIndex(size_t index)
{
while (m_frame && (m_frameIndex != index))
gotoNextFrame();
while (m_frame.callFrame() && (m_frameIndex != index))
gotoNextFrameWithFilter();
}
void StackIterator::gotoNextFrame()
{
Frame* frame = m_frame;
while (frame) {
frame = frame->logicalCallerFrame();
if (!frame || !m_filter || !m_filter(frame))
#if ENABLE(DFG_JIT)
if (m_frame.isInlinedFrame()) {
InlineCallFrame* inlineCallFrame = m_frame.inlineCallFrame();
CodeOrigin* callerCodeOrigin = &inlineCallFrame->caller;
readInlinedFrame(m_frame.callFrame(), callerCodeOrigin);
} else
#endif // ENABLE(DFG_JIT)
readFrame(m_frame.callerFrame());
}
void StackIterator::gotoNextFrameWithFilter()
{
ASSERT(m_frame.callFrame());
while (m_frame.callFrame()) {
gotoNextFrame();
if (!m_frame.callFrame() || !m_filter || !m_filter(&m_frame))
break;
}
m_frame = frame;
m_frameIndex++;
}
void StackIterator::resetIterator()
{
m_frameIndex = 0;
m_frame = Frame::create(m_startFrame);
m_frame = m_frame->logicalFrame();
readFrame(m_startFrame);
}
StackIterator StackIterator::end()
{
return StackIterator(0, 0);
}
void StackIterator::find(JSFunction* functionObj)
{
ASSERT(functionObj);
JSObject* targetCallee = jsDynamicCast<JSObject*>(functionObj);
while (m_frame) {
if (m_frame->callee() == targetCallee)
while (m_frame.callFrame()) {
if (m_frame.callee() == targetCallee)
break;
gotoNextFrame();
gotoNextFrameWithFilter();
}
}
void StackIterator::readFrame(CallFrame* callFrame)
{
ASSERT(!callFrame->hasHostCallFrameFlag());
if (!callFrame) {
m_frame.setToEnd();
return;
}
#if !ENABLE(DFG_JIT)
readNonInlinedFrame(callFrame);
#else // !ENABLE(DFG_JIT)
// If the frame doesn't have a code block, then it's not a DFG frame.
// Hence, we're not at an inlined frame.
CodeBlock* codeBlock = callFrame->codeBlock();
if (!codeBlock) {
readNonInlinedFrame(callFrame);
return;
}
// If the code block does not have any code origins, then there's no
// inlining. Hence, we're not at an inlined frame.
if (!codeBlock->hasCodeOrigins()) {
readNonInlinedFrame(callFrame);
return;
}
unsigned index = callFrame->locationAsCodeOriginIndex();
ASSERT(codeBlock->canGetCodeOrigin(index));
if (!codeBlock->canGetCodeOrigin(index)) {
// See assertion above. In release builds, we try to protect ourselves
// from crashing even though stack walking will be goofed up.
m_frame.setToEnd();
return;
}
CodeOrigin codeOrigin = codeBlock->codeOrigin(index);
if (!codeOrigin.inlineCallFrame) {
readNonInlinedFrame(callFrame, &codeOrigin);
return;
}
readInlinedFrame(callFrame, &codeOrigin);
#endif // !ENABLE(DFG_JIT)
}
void StackIterator::readNonInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
{
m_frame.m_callFrame = callFrame;
m_frame.m_argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
m_frame.m_callerFrame = callFrame->callerFrame()->removeHostCallFrameFlag();
m_frame.m_callee = callFrame->callee();
m_frame.m_scope = callFrame->scope();
m_frame.m_codeBlock = callFrame->codeBlock();
m_frame.m_bytecodeOffset = !m_frame.codeBlock() ? 0
: codeOrigin ? codeOrigin->bytecodeIndex
: callFrame->locationAsBytecodeOffset();
#if ENABLE(DFG_JIT)
m_frame.m_inlineCallFrame = 0;
#endif
}
#if ENABLE(DFG_JIT)
static unsigned inlinedFrameOffset(CodeOrigin* codeOrigin)
{
InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame;
unsigned frameOffset = inlineCallFrame ? inlineCallFrame->stackOffset : 0;
return frameOffset;
}
void StackIterator::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
{
ASSERT(codeOrigin);
ASSERT(!callFrame->hasHostCallFrameFlag());
unsigned frameOffset = inlinedFrameOffset(codeOrigin);
bool isInlined = !!frameOffset;
if (isInlined) {
InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame;
m_frame.m_callFrame = callFrame;
m_frame.m_inlineCallFrame = inlineCallFrame;
m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size();
m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock();
m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex;
JSFunction* callee = inlineCallFrame->callee.get();
if (callee) {
m_frame.m_scope = callee->scope();
m_frame.m_callee = callee;
} else {
CallFrame* inlinedFrame = callFrame + frameOffset;
m_frame.m_scope = inlinedFrame->scope();
m_frame.m_callee = inlinedFrame->callee();
}
ASSERT(m_frame.scope());
ASSERT(m_frame.callee());
// The callerFrame just needs to be non-null to indicate that we
// haven't reached the last frame yet. Setting it to the root
// frame (i.e. the callFrame that this inlined frame is called from)
// would work just fine.
m_frame.m_callerFrame = callFrame;
return;
}
readNonInlinedFrame(callFrame, codeOrigin);
}
#endif // ENABLE(DFG_JIT)
StackIterator::Frame::CodeType StackIterator::Frame::codeType() const
{
if (!isJSFrame())
......@@ -175,22 +301,23 @@ String StackIterator::Frame::toString()
return traceBuild.toString().impl();
}
unsigned StackIterator::Frame::bytecodeOffset()
Arguments* StackIterator::Frame::arguments()
{
if (!isJSFrame())
return 0;
ASSERT(m_callFrame);
CallFrame* physicalFrame = m_callFrame;
VM& vm = physicalFrame->vm();
Arguments* arguments;
#if ENABLE(DFG_JIT)
if (hasLocationAsCodeOriginIndex())
return bytecodeOffsetFromCodeOriginIndex();
if (isInlinedFrame()) {
ASSERT(m_inlineCallFrame);
arguments = Arguments::create(vm, physicalFrame, m_inlineCallFrame);
arguments->tearOff(physicalFrame, m_inlineCallFrame);
} else
#endif
return locationAsBytecodeOffset();
}
Arguments* StackIterator::Frame::arguments()
{
CallFrame* callFrame = this->callFrame();
Arguments* arguments = Arguments::create(vm(), callFrame);
arguments->tearOff(callFrame);
{
arguments = Arguments::create(vm, physicalFrame);
arguments->tearOff(physicalFrame);
}
return arguments;
}
......@@ -221,101 +348,12 @@ void StackIterator::Frame::retrieveExpressionInfo(int& divot, int& startOffset,
divot += codeBlock->sourceOffset();
}
StackIterator::Frame* StackIterator::Frame::logicalFrame()
{
#if !ENABLE(DFG_JIT)
return this;
#else // !ENABLE(DFG_JIT)
if (isInlinedFrame())
return this;
// If I don't have a code block, then I'm not DFG code, so I'm the true call frame.
CodeBlock* codeBlock = this->codeBlock();
if (!codeBlock)
return this;
// If the code block does not have any code origins, then there was no inlining, so
// I'm done.
if (!codeBlock->hasCodeOrigins())
return this;
CodeBlock* outerMostCodeBlock = codeBlock;
unsigned index = locationAsCodeOriginIndex();
ASSERT(outerMostCodeBlock->canGetCodeOrigin(index));
if (!outerMostCodeBlock->canGetCodeOrigin(index)) {
// See above. In release builds, we try to protect ourselves from crashing even
// though stack walking will be goofed up.
return 0;
}
CodeOrigin codeOrigin = outerMostCodeBlock->codeOrigin(index);
if (!codeOrigin.inlineCallFrame)
return this; // Not currently in inlined code.
// We've got inlined frames. So, reify them so that the iterator can walk through them.
CallFrame* currFrame = this->callFrame();
CallFrame* innerMostLogicalFrame = currFrame + codeOrigin.inlineCallFrame->stackOffset;
CallFrame* logicalFrame = innerMostLogicalFrame;
while (logicalFrame != currFrame) {
InlineCallFrame* inlinedFrameInfo = codeOrigin.inlineCallFrame;
// Fill in the logical (i.e. inlined) frame
logicalFrame->setCodeBlock(inlinedFrameInfo->baselineCodeBlock());
logicalFrame->setInlineCallFrame(inlinedFrameInfo);
logicalFrame->setArgumentCountIncludingThis(inlinedFrameInfo->arguments.size());
logicalFrame->setLocationAsBytecodeOffset(codeOrigin.bytecodeIndex);
logicalFrame->setIsInlinedFrame();
JSFunction* callee = inlinedFrameInfo->callee.get();
if (callee) {
logicalFrame->setScope(callee->scope());
logicalFrame->setCallee(callee);
}
CodeOrigin* callerCodeOrigin = &inlinedFrameInfo->caller;
InlineCallFrame* callerInlinedFrameInfo = callerCodeOrigin->inlineCallFrame;
unsigned callerFrameOffset = callerInlinedFrameInfo ? callerInlinedFrameInfo->stackOffset : 0;
CallFrame* callerFrame = currFrame + callerFrameOffset;
logicalFrame->setCallerFrame(callerFrame);
codeOrigin = *callerCodeOrigin;
logicalFrame = callerFrame;
}
ASSERT(!innerMostLogicalFrame->hasHostCallFrameFlag());
return Frame::create(innerMostLogicalFrame);
#endif // !ENABLE(DFG_JIT)
}
StackIterator::Frame* StackIterator::Frame::logicalCallerFrame()
void StackIterator::Frame::setToEnd()
{
Frame* callerFrame = create(this->callerFrame()->removeHostCallFrameFlag());
#if !ENABLE(DFG_JIT)
return callerFrame;
#else // !ENABLE(DFG_JIT)
if (!isJSFrame() || !callerFrame)
return callerFrame;
// If I am known to be an inlined frame, then I've been reified already and
// have my caller.
if (isInlinedFrame())
return callerFrame;
// I am not an inlined frame. So the question is: is my caller a CallFrame
// that has inlines or a CallFrame that doesn't?
// If my caller is not a JS frame, it cannot have inlines, and we're done.
if (!callerFrame->isJSFrame())
return callerFrame;
ASSERT(!callerFrame->isInlinedFrame());
return callerFrame->logicalFrame();
#endif // !ENABLE(DFG_JIT)
m_callFrame = 0;
#if ENABLE(DFG_JIT)
m_inlineCallFrame = 0;
#endif
}
#ifndef NDEBUG
......@@ -369,31 +407,34 @@ void StackIterator::Frame::print(int indentLevel)
CodeBlock* codeBlock = this->codeBlock();
printif(i, "frame %p {\n", this);
CallFrame* callFrame = m_callFrame;
CallFrame* callerFrame = this->callerFrame();
void* returnPC = hasReturnPC() ? this->returnPC().value() : 0;
void* returnPC = callFrame->hasReturnPC() ? callFrame->returnPC().value() : 0;
printif(i, " name '%s'\n", functionName().utf8().data());
printif(i, " sourceURL '%s'\n", sourceURL().utf8().data());
printif(i, " hostFlag %d\n", callerFrame->hasHostCallFrameFlag());
printif(i, " isInlinedFrame %d\n", isInlinedFrame());
#if ENABLE(DFG_JIT)
printif(i, " isInlinedFrame %d\n", isInlinedFrame());
if (isInlinedFrame())
printif(i, " InlineCallFrame %p\n", this->inlineCallFrame());
printif(i, " InlineCallFrame %p\n", m_inlineCallFrame);
#endif
printif(i, " callee %p\n", callee());
printif(i, " returnPC %p\n", returnPC);
printif(i, " callerFrame %p\n", callerFrame->removeHostCallFrameFlag());
printif(i, " logicalCallerFrame %p\n", logicalCallerFrame());
printif(i, " rawLocationBits %u 0x%x\n", locationAsRawBits(), locationAsRawBits());
unsigned locationRawBits = callFrame->locationAsRawBits();
printif(i, " rawLocationBits %u 0x%x\n", locationRawBits, locationRawBits);
printif(i, " codeBlock %p\n", codeBlock);
if (codeBlock) {
JITCode::JITType jitType = codeBlock->jitType();
if (hasLocationAsBytecodeOffset()) {
unsigned bytecodeOffset = locationAsBytecodeOffset();
if (callFrame->hasLocationAsBytecodeOffset()) {
unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
printif(i, " bytecodeOffset %u %p / %zu\n", bytecodeOffset, reinterpret_cast<void*>(bytecodeOffset), codeBlock->instructions().size());
#if ENABLE(DFG_JIT)
} else {
unsigned codeOriginIndex = locationAsCodeOriginIndex();
unsigned codeOriginIndex = callFrame->locationAsCodeOriginIndex();
printif(i, " codeOriginIdex %u %p / %zu\n", codeOriginIndex, reinterpret_cast<void*>(codeOriginIndex), codeBlock->codeOrigins().size());
#endif
}
......@@ -419,14 +460,24 @@ void StackIterator::Frame::print(int indentLevel)
} // namespace JSC
#ifndef NDEBUG
// For use in the debugger
// For debugging use
void debugPrintCallFrame(JSC::CallFrame*);
void debugPrintStack(JSC::CallFrame* topCallFrame);
void debugPrintCallFrame(JSC::CallFrame* callFrame)
{
if (!callFrame)
return;
JSC::StackIterator::Frame* frame = JSC::StackIterator::Frame::create(callFrame);
frame->print(2);
JSC::StackIterator iter = callFrame->begin();
iter->print(2);
}
void debugPrintStack(JSC::CallFrame* topCallFrame)
{
if (!topCallFrame)
return;
JSC::StackIterator iter = topCallFrame->begin();
for (; iter != topCallFrame->end(); ++iter)
iter->print(2);
}
#endif // !NDEBUG
......@@ -26,52 +26,130 @@
#ifndef StackIterator_h
#define StackIterator_h
#include "CallFrame.h"
#include "Interpreter.h"
#include "StackIteratorPrivate.h"
#include <wtf/text/WTFString.h>
namespace JSC {
struct CodeOrigin;
struct InlineCallFrame;
class Arguments;
class CodeBlock;
class ExecState;
class JSFunction;
class JSObject;
class JSScope;
class StackIterator::Frame : public CallFrame {
public:
enum CodeType {
Global = StackFrameGlobalCode,
Eval = StackFrameEvalCode,
Function = StackFrameFunctionCode,
Native = StackFrameNativeCode
};
typedef ExecState CallFrame;
static Frame* create(CallFrame* f) { return reinterpret_cast<Frame*>(f); }
class StackIterator {
public: