Title: [154821] trunk/Source/_javascript_Core
Revision
154821
Author
[email protected]
Date
2013-08-29 10:41:44 -0700 (Thu, 29 Aug 2013)

Log Message

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.

Modified Paths

Removed Paths

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
-
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to