Diff
Modified: trunk/Source/_javascript_Core/ChangeLog (154820 => 154821)
--- trunk/Source/_javascript_Core/ChangeLog 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/ChangeLog 2013-08-29 17:41:44 UTC (rev 154821)
@@ -1,3 +1,70 @@
+2013-08-29 Mark Lam <[email protected]>
+
+ 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:
+ * _javascript_Core.vcxproj/_javascript_Core.vcxproj:
+ * _javascript_Core.vcxproj/_javascript_Core.vcxproj.filters:
+ * _javascript_Core.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 <[email protected]>
VM::throwException() crashes reproducibly in testapi with !ENABLE(JIT)
Modified: trunk/Source/_javascript_Core/GNUmakefile.list.am (154820 => 154821)
--- trunk/Source/_javascript_Core/GNUmakefile.list.am 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/GNUmakefile.list.am 2013-08-29 17:41:44 UTC (rev 154821)
@@ -581,7 +581,6 @@
Source/_javascript_Core/interpreter/Register.h \
Source/_javascript_Core/interpreter/StackIterator.cpp \
Source/_javascript_Core/interpreter/StackIterator.h \
- Source/_javascript_Core/interpreter/StackIteratorPrivate.h \
Source/_javascript_Core/interpreter/VMInspector.cpp \
Source/_javascript_Core/interpreter/VMInspector.h \
Source/_javascript_Core/_javascript_CorePrefix.h \
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj (154820 => 154821)
--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj 2013-08-29 17:41:44 UTC (rev 154821)
@@ -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>
Modified: trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters (154820 => 154821)
--- trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/_javascript_Core.vcxproj/_javascript_Core.vcxproj.filters 2013-08-29 17:41:44 UTC (rev 154821)
@@ -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>
Modified: trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj (154820 => 154821)
--- trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/_javascript_Core.xcodeproj/project.pbxproj 2013-08-29 17:41:44 UTC (rev 154821)
@@ -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 */,
Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.cpp (154820 => 154821)
--- trunk/Source/_javascript_Core/interpreter/CallFrame.cpp 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.cpp 2013-08-29 17:41:44 UTC (rev 154821)
@@ -111,9 +111,4 @@
return iter;
}
-StackIterator::Frame* CallFrame::end()
-{
- return StackIterator::end();
-}
-
-}
+} // namespace JSC
Modified: trunk/Source/_javascript_Core/interpreter/CallFrame.h (154820 => 154821)
--- trunk/Source/_javascript_Core/interpreter/CallFrame.h 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/interpreter/CallFrame.h 2013-08-29 17:41:44 UTC (rev 154821)
@@ -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 @@
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;
Modified: trunk/Source/_javascript_Core/interpreter/StackIterator.cpp (154820 => 154821)
--- trunk/Source/_javascript_Core/interpreter/StackIterator.cpp 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/interpreter/StackIterator.cpp 2013-08-29 17:41:44 UTC (rev 154821)
@@ -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 @@
: m_startFrame(startFrame)
, m_filter(filter)
{
- ASSERT(startFrame);
resetIterator();
}
@@ -46,8 +46,8 @@
{
int savedFrameIndex = m_frameIndex;
resetIterator();
- while (m_frame)
- gotoNextFrame();
+ while (m_frame.callFrame())
+ gotoNextFrameWithFilter();
size_t numberOfFrames = m_frameIndex;
resetIterator();
@@ -58,40 +58,166 @@
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 @@
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,103 +348,14 @@
divot += codeBlock->sourceOffset();
}
-
-StackIterator::Frame* StackIterator::Frame::logicalFrame()
+void StackIterator::Frame::setToEnd()
{
-#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)
+ m_callFrame = 0;
+#if ENABLE(DFG_JIT)
+ m_inlineCallFrame = 0;
+#endif
}
-StackIterator::Frame* StackIterator::Frame::logicalCallerFrame()
-{
- 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)
-}
-
#ifndef NDEBUG
static const char* jitTypeName(JITCode::JITType jitType)
@@ -369,31 +407,34 @@
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());
+
+#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 @@
} // 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
Modified: trunk/Source/_javascript_Core/interpreter/StackIterator.h (154820 => 154821)
--- trunk/Source/_javascript_Core/interpreter/StackIterator.h 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/interpreter/StackIterator.h 2013-08-29 17:41:44 UTC (rev 154821)
@@ -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 {
+typedef ExecState CallFrame;
+
+class StackIterator {
public:
- enum CodeType {
- Global = StackFrameGlobalCode,
- Eval = StackFrameEvalCode,
- Function = StackFrameFunctionCode,
- Native = StackFrameNativeCode
- };
+ class Frame {
+ public:
+ enum CodeType {
+ Global,
+ Eval,
+ Function,
+ Native
+ };
- static Frame* create(CallFrame* f) { return reinterpret_cast<Frame*>(f); }
+ size_t argumentCountIncludingThis() const { return m_argumentCountIncludingThis; }
+ CallFrame* callerFrame() const { return m_callerFrame; }
+ JSObject* callee() const { return m_callee; }
+ JSScope* scope() const { return m_scope; }
+ CodeBlock* codeBlock() const { return m_codeBlock; }
+ unsigned bytecodeOffset() const { return m_bytecodeOffset; }
+#if ENABLE(DFG_JIT)
+ InlineCallFrame* inlineCallFrame() const { return m_inlineCallFrame; }
+#endif
- bool isJSFrame() const { return !!codeBlock(); }
+ bool isJSFrame() const { return !!codeBlock(); }
+#if ENABLE(DFG_JIT)
+ bool isInlinedFrame() const { return !!m_inlineCallFrame; }
+#endif
- JS_EXPORT_PRIVATE String functionName();
- JS_EXPORT_PRIVATE String sourceURL();
- JS_EXPORT_PRIVATE String toString();
+ JS_EXPORT_PRIVATE String functionName();
+ JS_EXPORT_PRIVATE String sourceURL();
+ JS_EXPORT_PRIVATE String toString();
- CodeType codeType() const;
- unsigned bytecodeOffset();
- JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
+ CodeType codeType() const;
+ JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
- Arguments* arguments();
- CallFrame* callFrame() { return reinterpret_cast<CallFrame*>(this); }
+ Arguments* arguments();
+ CallFrame* callFrame() const { return m_callFrame; }
- Frame* logicalFrame();
- Frame* logicalCallerFrame();
-
#ifndef NDEBUG
- JS_EXPORT_PRIVATE void print(int indentLevel);
+ JS_EXPORT_PRIVATE void print(int indentLevel);
#endif
+ private:
+ Frame() { }
+ ~Frame() { }
+
+ void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
+#if ENABLE(DFG_JIT)
+ void setToEnd();
+#endif
+
+ size_t m_argumentCountIncludingThis;
+ CallFrame* m_callerFrame;
+ JSObject* m_callee;
+ JSScope* m_scope;
+ CodeBlock* m_codeBlock;
+ unsigned m_bytecodeOffset;
+#if ENABLE(DFG_JIT)
+ InlineCallFrame* m_inlineCallFrame;
+#endif
+
+ CallFrame* m_callFrame;
+
+ friend class StackIterator;
+ };
+
+ typedef bool (*FrameFilter)(Frame*);
+
+ JS_EXPORT_PRIVATE size_t numberOfFrames();
+
+ Frame& operator*() { return m_frame; }
+ ALWAYS_INLINE Frame* operator->() { return &m_frame; }
+
+ inline bool operator==(const StackIterator&);
+ bool operator!=(const StackIterator& other) { return !(*this == other); }
+ void operator++() { gotoNextFrameWithFilter(); }
+ void find(JSFunction*);
+
private:
- Frame();
- ~Frame();
+ JS_EXPORT_PRIVATE StackIterator(CallFrame* startFrame, FrameFilter = 0);
- void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
+ JS_EXPORT_PRIVATE static StackIterator end();
+ void gotoFrameAtIndex(size_t frameIndex);
+ void gotoNextFrame();
+ JS_EXPORT_PRIVATE void gotoNextFrameWithFilter();
+ void resetIterator();
+
+ void readFrame(CallFrame*);
+ void readNonInlinedFrame(CallFrame*, CodeOrigin* = 0);
+#if ENABLE(DFG_JIT)
+ void readInlinedFrame(CallFrame*, CodeOrigin*);
+#endif
+
+ CallFrame* m_startFrame;
+ size_t m_frameIndex;
+ FrameFilter m_filter;
+ Frame m_frame;
+
+ friend class ExecState;
};
+inline bool StackIterator::operator==(const StackIterator& other)
+{
+ return (m_frame.callFrame() == other.m_frame.callFrame())
+#if ENABLE(DFG_JIT)
+ && (m_frame.inlineCallFrame() == other.m_frame.inlineCallFrame())
+#endif
+ ;
+}
+
} // namespace JSC
#endif // StackIterator_h
Deleted: trunk/Source/_javascript_Core/interpreter/StackIteratorPrivate.h (154820 => 154821)
--- trunk/Source/_javascript_Core/interpreter/StackIteratorPrivate.h 2013-08-29 17:35:01 UTC (rev 154820)
+++ trunk/Source/_javascript_Core/interpreter/StackIteratorPrivate.h 2013-08-29 17:41:44 UTC (rev 154821)
@@ -1,71 +0,0 @@
-/*
- * Copyright (C) 2013 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.
- */
-
-#ifndef StackIteratorPrivate_h
-#define StackIteratorPrivate_h
-
-namespace JSC {
-
-class ExecState;
-class JSFunction;
-class VM;
-
-typedef ExecState CallFrame;
-
-class StackIterator {
-public:
- class Frame;
- typedef bool (*FrameFilter)(Frame*);
-
- JS_EXPORT_PRIVATE size_t numberOfFrames();
-
- Frame& operator*() { return *m_frame; }
- ALWAYS_INLINE Frame* operator->() { return m_frame; }
-
- bool operator==(Frame* frame) { return m_frame == frame; }
- bool operator!=(Frame* frame) { return m_frame != frame; }
- void operator++() { gotoNextFrame(); }
- void find(JSFunction*);
-
-private:
- JS_EXPORT_PRIVATE StackIterator(CallFrame* startFrame, FrameFilter = 0);
-
- static Frame* end() { return 0; }
- void gotoFrameAtIndex(size_t frameIndex);
- JS_EXPORT_PRIVATE void gotoNextFrame();
- void resetIterator();
-
- CallFrame* m_startFrame;
- size_t m_frameIndex;
- Frame* m_frame;
- FrameFilter m_filter;
-
- friend class ExecState;
-};
-
-} // namespace JSC
-
-#endif // StackIteratorPrivate_h
-