Changeset 154821 in webkit


Ignore:
Timestamp:
Aug 29, 2013 10:41:44 AM (11 years ago)
Author:
mark.lam@apple.com
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:
  • 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.
Location:
trunk/Source/JavaScriptCore
Files:
1 deleted
9 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r154817 r154821  
     12013-08-29  Mark Lam  <mark.lam@apple.com>
     2
     3        Change StackIterator to not require writes to the JS stack.
     4        https://bugs.webkit.org/show_bug.cgi?id=119657.
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        * GNUmakefile.list.am:
     9        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     10        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     11        * JavaScriptCore.xcodeproj/project.pbxproj:
     12        * interpreter/CallFrame.h:
     13        - Removed references to StackIteratorPrivate.h.
     14        * interpreter/StackIterator.cpp:
     15        (JSC::StackIterator::numberOfFrames):
     16        (JSC::StackIterator::gotoFrameAtIndex):
     17        (JSC::StackIterator::gotoNextFrame):
     18        (JSC::StackIterator::resetIterator):
     19        (JSC::StackIterator::find):
     20        (JSC::StackIterator::readFrame):
     21        (JSC::StackIterator::readNonInlinedFrame):
     22        - Reads in the current CallFrame's data for non-inlined frames.
     23        (JSC::inlinedFrameOffset):
     24        - Convenience function to compute the inlined frame offset based on the
     25          CodeOrigin. If the offset is 0, then we're looking at the physical frame.
     26          Otherwise, it's an inlined frame.
     27        (JSC::StackIterator::readInlinedFrame):
     28        - Determines the inlined frame's caller frame. Will read in the caller
     29          frame if it is also an inlined frame i.e. we haven't reached the
     30          outer most frame yet. Otherwise, will call readNonInlinedFrame() to
     31          read on the outer most frame.
     32          This is based on the old StackIterator::Frame::logicalFrame().
     33        (JSC::StackIterator::updateFrame):
     34        - Reads the data of the caller frame of the current one. This function
     35          is renamed and moved from the old StackIterator::Frame::logicalCallerFrame(),
     36          but is now simplified because it delegates to the readInlinedFrame()
     37          to get the caller for inlined frames.
     38        (JSC::StackIterator::Frame::arguments):
     39        - Fixed to use the inlined frame versions of Arguments::create() and
     40          Arguments::tearOff() when the frame is an inlined frame.
     41        (JSC::StackIterator::Frame::print):
     42        (debugPrintCallFrame):
     43        (debugPrintStack):
     44        - Because sometimes, we want to see the whole stack while debugging.
     45        * interpreter/StackIterator.h:
     46        (JSC::StackIterator::Frame::argumentCount):
     47        (JSC::StackIterator::Frame::callerFrame):
     48        (JSC::StackIterator::Frame::callee):
     49        (JSC::StackIterator::Frame::scope):
     50        (JSC::StackIterator::Frame::codeBlock):
     51        (JSC::StackIterator::Frame::bytecodeOffset):
     52        (JSC::StackIterator::Frame::inlinedFrameInfo):
     53        (JSC::StackIterator::Frame::isJSFrame):
     54        (JSC::StackIterator::Frame::isInlinedFrame):
     55        (JSC::StackIterator::Frame::callFrame):
     56        (JSC::StackIterator::Frame::Frame):
     57        (JSC::StackIterator::Frame::~Frame):
     58        - StackIterator::Frame now caches commonly used accessed values from
     59          the CallFrame. It still delegates argument queries to the CallFrame.
     60        (JSC::StackIterator::operator*):
     61        (JSC::StackIterator::operator->):
     62        (JSC::StackIterator::operator!=):
     63        (JSC::StackIterator::operator++):
     64        (JSC::StackIterator::end):
     65        (JSC::StackIterator::operator==):
     66        * interpreter/StackIteratorPrivate.h: Removed.
     67
    1682013-08-29  Chris Curtis  <chris_curtis@apple.com>
    269
  • trunk/Source/JavaScriptCore/GNUmakefile.list.am

    r154814 r154821  
    582582        Source/JavaScriptCore/interpreter/StackIterator.cpp \
    583583        Source/JavaScriptCore/interpreter/StackIterator.h \
    584         Source/JavaScriptCore/interpreter/StackIteratorPrivate.h \
    585584        Source/JavaScriptCore/interpreter/VMInspector.cpp \
    586585        Source/JavaScriptCore/interpreter/VMInspector.h \
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r154814 r154821  
    730730    <ClInclude Include="..\interpreter\Register.h" />
    731731    <ClInclude Include="..\interpreter\StackIterator.h" />
    732     <ClInclude Include="..\interpreter\StackIteratorPrivate.h" />
    733732    <ClInclude Include="..\interpreter\VMInspector.h" />
    734733    <ClInclude Include="..\jit\ClosureCallStubRoutine.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r154638 r154821  
    13141314      <Filter>interpreter</Filter>
    13151315    </ClInclude>
    1316     <ClInclude Include="..\interpreter\StackIteratorPrivate.h">
    1317       <Filter>interpreter</Filter>
    1318     </ClInclude>
    13191316    <ClInclude Include="..\interpreter\VMInspector.h">
    13201317      <Filter>interpreter</Filter>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r154814 r154821  
    906906                A7C1EAF117987AB600299DB2 /* StackIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7C1EAEC17987AB600299DB2 /* StackIterator.cpp */; };
    907907                A7C1EAF217987AB600299DB2 /* StackIterator.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C1EAED17987AB600299DB2 /* StackIterator.h */; settings = {ATTRIBUTES = (Private, ); }; };
    908                 A7C1EAF317987AB600299DB2 /* StackIteratorPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = A7C1EAEE17987AB600299DB2 /* StackIteratorPrivate.h */; settings = {ATTRIBUTES = (Private, ); }; };
    909908                A7D89CF217A0B8CC00773AD8 /* DFGBasicBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D89CE317A0B8CC00773AD8 /* DFGBasicBlock.cpp */; };
    910909                A7D89CF317A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = A7D89CE417A0B8CC00773AD8 /* DFGBlockInsertionSet.cpp */; };
     
    20792078                A7C1EAEC17987AB600299DB2 /* StackIterator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackIterator.cpp; sourceTree = "<group>"; };
    20802079                A7C1EAED17987AB600299DB2 /* StackIterator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackIterator.h; sourceTree = "<group>"; };
    2081                 A7C1EAEE17987AB600299DB2 /* StackIteratorPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackIteratorPrivate.h; sourceTree = "<group>"; };
    20822080                A7C225CC139981F100FF1662 /* KeywordLookupGenerator.py */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.python; path = KeywordLookupGenerator.py; sourceTree = "<group>"; };
    20832081                A7C225CD1399849C00FF1662 /* KeywordLookup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeywordLookup.h; sourceTree = "<group>"; };
     
    26062604                                A7C1EAEC17987AB600299DB2 /* StackIterator.cpp */,
    26072605                                A7C1EAED17987AB600299DB2 /* StackIterator.h */,
    2608                                 A7C1EAEE17987AB600299DB2 /* StackIteratorPrivate.h */,
    26092606                                FE4A331D15BD2E07006F54F3 /* VMInspector.cpp */,
    26102607                                FE4A331E15BD2E07006F54F3 /* VMInspector.h */,
     
    42824279                                0FD82E54141DAEEE00179C94 /* SpeculatedType.h in Headers */,
    42834280                                A7C1EAF217987AB600299DB2 /* StackIterator.h in Headers */,
    4284                                 A7C1EAF317987AB600299DB2 /* StackIteratorPrivate.h in Headers */,
    42854281                                14DF04DA16B3996D0016A513 /* StaticPropertyAnalysis.h in Headers */,
    42864282                                14CA958B16AB50DE00938A06 /* StaticPropertyAnalyzer.h in Headers */,
  • trunk/Source/JavaScriptCore/interpreter/CallFrame.cpp

    r153218 r154821  
    112112}
    113113
    114 StackIterator::Frame* CallFrame::end()
    115 {
    116     return StackIterator::end();
    117 }
    118 
    119 }
     114} // namespace JSC
  • trunk/Source/JavaScriptCore/interpreter/CallFrame.h

    r154797 r154821  
    2929#include "MacroAssemblerCodeRef.h"
    3030#include "Register.h"
    31 #include "StackIteratorPrivate.h"
     31#include "StackIterator.h"
    3232
    3333namespace JSC  {
     
    284284        JS_EXPORT_PRIVATE StackIterator begin(StackIterator::FrameFilter = 0);
    285285        JS_EXPORT_PRIVATE StackIterator find(JSFunction* calleeFunctionObj, StackIterator::FrameFilter = 0);
    286         JS_EXPORT_PRIVATE StackIterator::Frame* end();
     286        StackIterator end() { return StackIterator::end(); }
    287287
    288288    private:
  • trunk/Source/JavaScriptCore/interpreter/StackIterator.cpp

    r153825 r154821  
    3030#include "CallFrameInlines.h"
    3131#include "Executable.h"
     32#include "Interpreter.h"
    3233#include "Operations.h"
    3334#include <wtf/DataLog.h>
     
    3940    , m_filter(filter)
    4041{
    41     ASSERT(startFrame);
    4242    resetIterator();
    4343}
     
    4747    int savedFrameIndex = m_frameIndex;
    4848    resetIterator();
    49     while (m_frame)
    50         gotoNextFrame();
     49    while (m_frame.callFrame())
     50        gotoNextFrameWithFilter();
    5151    size_t numberOfFrames = m_frameIndex;
    5252
     
    5959void StackIterator::gotoFrameAtIndex(size_t index)
    6060{
    61     while (m_frame && (m_frameIndex != index))
     61    while (m_frame.callFrame() && (m_frameIndex != index))
     62        gotoNextFrameWithFilter();
     63}
     64
     65void StackIterator::gotoNextFrame()
     66{
     67#if ENABLE(DFG_JIT)
     68    if (m_frame.isInlinedFrame()) {
     69        InlineCallFrame* inlineCallFrame = m_frame.inlineCallFrame();
     70        CodeOrigin* callerCodeOrigin = &inlineCallFrame->caller;
     71        readInlinedFrame(m_frame.callFrame(), callerCodeOrigin);
     72
     73    } else
     74#endif // ENABLE(DFG_JIT)
     75        readFrame(m_frame.callerFrame());
     76}
     77
     78void StackIterator::gotoNextFrameWithFilter()
     79{
     80    ASSERT(m_frame.callFrame());
     81    while (m_frame.callFrame()) {
    6282        gotoNextFrame();
    63 }
    64 
    65 void StackIterator::gotoNextFrame()
    66 {
    67     Frame* frame = m_frame;
    68     while (frame) {
    69         frame = frame->logicalCallerFrame();
    70         if (!frame || !m_filter || !m_filter(frame))
     83        if (!m_frame.callFrame() || !m_filter || !m_filter(&m_frame))
    7184            break;
    7285    }
    73     m_frame = frame;
    7486    m_frameIndex++;
    7587}
     
    7890{
    7991    m_frameIndex = 0;
    80     m_frame = Frame::create(m_startFrame);
    81     m_frame = m_frame->logicalFrame();
     92    readFrame(m_startFrame);
     93}
     94
     95StackIterator StackIterator::end()
     96{
     97    return StackIterator(0, 0);
    8298}
    8399
     
    86102    ASSERT(functionObj);
    87103    JSObject* targetCallee = jsDynamicCast<JSObject*>(functionObj);
    88     while (m_frame) {
    89         if (m_frame->callee() == targetCallee)
     104    while (m_frame.callFrame()) {
     105        if (m_frame.callee() == targetCallee)
    90106            break;
    91         gotoNextFrame();
    92     }
    93 }
     107        gotoNextFrameWithFilter();
     108    }
     109}
     110
     111void StackIterator::readFrame(CallFrame* callFrame)
     112{
     113    ASSERT(!callFrame->hasHostCallFrameFlag());
     114    if (!callFrame) {
     115        m_frame.setToEnd();
     116        return;
     117    }
     118
     119#if !ENABLE(DFG_JIT)
     120    readNonInlinedFrame(callFrame);
     121
     122#else // !ENABLE(DFG_JIT)
     123    // If the frame doesn't have a code block, then it's not a DFG frame.
     124    // Hence, we're not at an inlined frame.
     125    CodeBlock* codeBlock = callFrame->codeBlock();
     126    if (!codeBlock) {
     127        readNonInlinedFrame(callFrame);
     128        return;
     129    }
     130
     131    // If the code block does not have any code origins, then there's no
     132    // inlining. Hence, we're not at an inlined frame.
     133    if (!codeBlock->hasCodeOrigins()) {
     134        readNonInlinedFrame(callFrame);
     135        return;
     136    }
     137
     138    unsigned index = callFrame->locationAsCodeOriginIndex();
     139    ASSERT(codeBlock->canGetCodeOrigin(index));
     140    if (!codeBlock->canGetCodeOrigin(index)) {
     141        // See assertion above. In release builds, we try to protect ourselves
     142        // from crashing even though stack walking will be goofed up.
     143        m_frame.setToEnd();
     144        return;
     145    }
     146
     147    CodeOrigin codeOrigin = codeBlock->codeOrigin(index);
     148    if (!codeOrigin.inlineCallFrame) {
     149        readNonInlinedFrame(callFrame, &codeOrigin);
     150        return;
     151    }
     152
     153    readInlinedFrame(callFrame, &codeOrigin);
     154#endif // !ENABLE(DFG_JIT)
     155}
     156
     157void StackIterator::readNonInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
     158{
     159    m_frame.m_callFrame = callFrame;
     160    m_frame.m_argumentCountIncludingThis = callFrame->argumentCountIncludingThis();
     161    m_frame.m_callerFrame = callFrame->callerFrame()->removeHostCallFrameFlag();
     162    m_frame.m_callee = callFrame->callee();
     163    m_frame.m_scope = callFrame->scope();
     164    m_frame.m_codeBlock = callFrame->codeBlock();
     165    m_frame.m_bytecodeOffset = !m_frame.codeBlock() ? 0
     166        : codeOrigin ? codeOrigin->bytecodeIndex
     167        : callFrame->locationAsBytecodeOffset();
     168#if ENABLE(DFG_JIT)
     169    m_frame.m_inlineCallFrame = 0;
     170#endif
     171}
     172
     173#if ENABLE(DFG_JIT)
     174static unsigned inlinedFrameOffset(CodeOrigin* codeOrigin)
     175{
     176    InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame;
     177    unsigned frameOffset = inlineCallFrame ? inlineCallFrame->stackOffset : 0;
     178    return frameOffset;
     179}
     180
     181void StackIterator::readInlinedFrame(CallFrame* callFrame, CodeOrigin* codeOrigin)
     182{
     183    ASSERT(codeOrigin);
     184    ASSERT(!callFrame->hasHostCallFrameFlag());
     185
     186    unsigned frameOffset = inlinedFrameOffset(codeOrigin);
     187    bool isInlined = !!frameOffset;
     188    if (isInlined) {
     189        InlineCallFrame* inlineCallFrame = codeOrigin->inlineCallFrame;
     190
     191        m_frame.m_callFrame = callFrame;
     192        m_frame.m_inlineCallFrame = inlineCallFrame;
     193        m_frame.m_argumentCountIncludingThis = inlineCallFrame->arguments.size();
     194        m_frame.m_codeBlock = inlineCallFrame->baselineCodeBlock();
     195        m_frame.m_bytecodeOffset = codeOrigin->bytecodeIndex;
     196
     197        JSFunction* callee = inlineCallFrame->callee.get();
     198        if (callee) {
     199            m_frame.m_scope = callee->scope();
     200            m_frame.m_callee = callee;
     201        } else {
     202            CallFrame* inlinedFrame = callFrame + frameOffset;
     203            m_frame.m_scope = inlinedFrame->scope();
     204            m_frame.m_callee = inlinedFrame->callee();
     205        }
     206        ASSERT(m_frame.scope());
     207        ASSERT(m_frame.callee());
     208
     209        // The callerFrame just needs to be non-null to indicate that we
     210        // haven't reached the last frame yet. Setting it to the root
     211        // frame (i.e. the callFrame that this inlined frame is called from)
     212        // would work just fine.
     213        m_frame.m_callerFrame = callFrame;
     214        return;
     215    }
     216
     217    readNonInlinedFrame(callFrame, codeOrigin);
     218}
     219#endif // ENABLE(DFG_JIT)
    94220
    95221StackIterator::Frame::CodeType StackIterator::Frame::codeType() const
     
    176302}
    177303
    178 unsigned StackIterator::Frame::bytecodeOffset()
    179 {
    180     if (!isJSFrame())
    181         return 0;
    182 #if ENABLE(DFG_JIT)
    183     if (hasLocationAsCodeOriginIndex())
    184         return bytecodeOffsetFromCodeOriginIndex();
    185 #endif
    186     return locationAsBytecodeOffset();
    187 }
    188 
    189304Arguments* StackIterator::Frame::arguments()
    190305{
    191     CallFrame* callFrame = this->callFrame();
    192     Arguments* arguments = Arguments::create(vm(), callFrame);
    193     arguments->tearOff(callFrame);
     306    ASSERT(m_callFrame);
     307    CallFrame* physicalFrame = m_callFrame;
     308    VM& vm = physicalFrame->vm();
     309    Arguments* arguments;
     310#if ENABLE(DFG_JIT)
     311    if (isInlinedFrame()) {
     312        ASSERT(m_inlineCallFrame);
     313        arguments = Arguments::create(vm, physicalFrame, m_inlineCallFrame);
     314        arguments->tearOff(physicalFrame, m_inlineCallFrame);
     315    } else
     316#endif
     317    {
     318        arguments = Arguments::create(vm, physicalFrame);
     319        arguments->tearOff(physicalFrame);
     320    }
    194321    return arguments;
    195322}
     
    222349}
    223350
    224 
    225 StackIterator::Frame* StackIterator::Frame::logicalFrame()
    226 {
    227 #if !ENABLE(DFG_JIT)
    228     return this;
    229 
    230 #else // !ENABLE(DFG_JIT)
    231     if (isInlinedFrame())
    232         return this;
    233 
    234     // If I don't have a code block, then I'm not DFG code, so I'm the true call frame.
    235     CodeBlock* codeBlock = this->codeBlock();
    236     if (!codeBlock)
    237         return this;
    238 
    239     // If the code block does not have any code origins, then there was no inlining, so
    240     // I'm done.
    241     if (!codeBlock->hasCodeOrigins())
    242         return this;
    243    
    244     CodeBlock* outerMostCodeBlock = codeBlock;
    245     unsigned index = locationAsCodeOriginIndex();
    246     ASSERT(outerMostCodeBlock->canGetCodeOrigin(index));
    247     if (!outerMostCodeBlock->canGetCodeOrigin(index)) {
    248         // See above. In release builds, we try to protect ourselves from crashing even
    249         // though stack walking will be goofed up.
    250         return 0;
    251     }
    252 
    253     CodeOrigin codeOrigin = outerMostCodeBlock->codeOrigin(index);
    254     if (!codeOrigin.inlineCallFrame)
    255         return this; // Not currently in inlined code.
    256 
    257     // We've got inlined frames. So, reify them so that the iterator can walk through them.
    258     CallFrame* currFrame = this->callFrame();
    259     CallFrame* innerMostLogicalFrame = currFrame + codeOrigin.inlineCallFrame->stackOffset;
    260 
    261     CallFrame* logicalFrame = innerMostLogicalFrame;
    262     while (logicalFrame != currFrame) {
    263         InlineCallFrame* inlinedFrameInfo = codeOrigin.inlineCallFrame;
    264        
    265         // Fill in the logical (i.e. inlined) frame
    266         logicalFrame->setCodeBlock(inlinedFrameInfo->baselineCodeBlock());
    267         logicalFrame->setInlineCallFrame(inlinedFrameInfo);
    268         logicalFrame->setArgumentCountIncludingThis(inlinedFrameInfo->arguments.size());
    269         logicalFrame->setLocationAsBytecodeOffset(codeOrigin.bytecodeIndex);
    270         logicalFrame->setIsInlinedFrame();
    271 
    272         JSFunction* callee = inlinedFrameInfo->callee.get();
    273         if (callee) {
    274             logicalFrame->setScope(callee->scope());
    275             logicalFrame->setCallee(callee);
    276         }
    277        
    278         CodeOrigin* callerCodeOrigin = &inlinedFrameInfo->caller;
    279         InlineCallFrame* callerInlinedFrameInfo = callerCodeOrigin->inlineCallFrame;
    280         unsigned callerFrameOffset = callerInlinedFrameInfo ? callerInlinedFrameInfo->stackOffset : 0;
    281         CallFrame* callerFrame = currFrame + callerFrameOffset;
    282         logicalFrame->setCallerFrame(callerFrame);
    283 
    284         codeOrigin = *callerCodeOrigin;
    285         logicalFrame = callerFrame;
    286     }
    287    
    288     ASSERT(!innerMostLogicalFrame->hasHostCallFrameFlag());
    289     return Frame::create(innerMostLogicalFrame);
    290 #endif // !ENABLE(DFG_JIT)
    291 }
    292 
    293 StackIterator::Frame* StackIterator::Frame::logicalCallerFrame()
    294 {
    295     Frame* callerFrame = create(this->callerFrame()->removeHostCallFrameFlag());
    296 #if !ENABLE(DFG_JIT)
    297     return callerFrame;
    298 
    299 #else // !ENABLE(DFG_JIT)
    300     if (!isJSFrame() || !callerFrame)
    301         return callerFrame;
    302 
    303     // If I am known to be an inlined frame, then I've been reified already and
    304     // have my caller.
    305     if (isInlinedFrame())
    306         return callerFrame;
    307    
    308     // I am not an inlined frame. So the question is: is my caller a CallFrame
    309     // that has inlines or a CallFrame that doesn't?
    310 
    311     // If my caller is not a JS frame, it cannot have inlines, and we're done.
    312     if (!callerFrame->isJSFrame())
    313         return callerFrame;
    314 
    315     ASSERT(!callerFrame->isInlinedFrame());
    316     return callerFrame->logicalFrame();
    317 
    318 #endif // !ENABLE(DFG_JIT)
     351void StackIterator::Frame::setToEnd()
     352{
     353    m_callFrame = 0;
     354#if ENABLE(DFG_JIT)
     355    m_inlineCallFrame = 0;
     356#endif
    319357}
    320358
     
    370408    printif(i, "frame %p {\n", this);
    371409
     410    CallFrame* callFrame = m_callFrame;
    372411    CallFrame* callerFrame = this->callerFrame();
    373     void* returnPC = hasReturnPC() ? this->returnPC().value() : 0;
     412    void* returnPC = callFrame->hasReturnPC() ? callFrame->returnPC().value() : 0;
    374413
    375414    printif(i, "   name '%s'\n", functionName().utf8().data());
    376415    printif(i, "   sourceURL '%s'\n", sourceURL().utf8().data());
    377416    printif(i, "   hostFlag %d\n", callerFrame->hasHostCallFrameFlag());
     417
     418#if ENABLE(DFG_JIT)
    378419    printif(i, "   isInlinedFrame %d\n", isInlinedFrame());
    379 
    380420    if (isInlinedFrame())
    381         printif(i, "   InlineCallFrame %p\n", this->inlineCallFrame());
     421        printif(i, "   InlineCallFrame %p\n", m_inlineCallFrame);
     422#endif
    382423
    383424    printif(i, "   callee %p\n", callee());
    384425    printif(i, "   returnPC %p\n", returnPC);
    385426    printif(i, "   callerFrame %p\n", callerFrame->removeHostCallFrameFlag());
    386     printif(i, "   logicalCallerFrame %p\n", logicalCallerFrame());
    387     printif(i, "   rawLocationBits %u 0x%x\n", locationAsRawBits(), locationAsRawBits());
     427    unsigned locationRawBits = callFrame->locationAsRawBits();
     428    printif(i, "   rawLocationBits %u 0x%x\n", locationRawBits, locationRawBits);
    388429    printif(i, "   codeBlock %p\n", codeBlock);
    389430    if (codeBlock) {
    390431        JITCode::JITType jitType = codeBlock->jitType();
    391         if (hasLocationAsBytecodeOffset()) {
    392             unsigned bytecodeOffset = locationAsBytecodeOffset();
     432        if (callFrame->hasLocationAsBytecodeOffset()) {
     433            unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
    393434            printif(i, "      bytecodeOffset %u %p / %zu\n", bytecodeOffset, reinterpret_cast<void*>(bytecodeOffset), codeBlock->instructions().size());
    394435#if ENABLE(DFG_JIT)
    395436        } else {
    396             unsigned codeOriginIndex = locationAsCodeOriginIndex();
     437            unsigned codeOriginIndex = callFrame->locationAsCodeOriginIndex();
    397438            printif(i, "      codeOriginIdex %u %p / %zu\n", codeOriginIndex, reinterpret_cast<void*>(codeOriginIndex), codeBlock->codeOrigins().size());
    398439#endif
     
    420461
    421462#ifndef NDEBUG
    422 // For use in the debugger
     463// For debugging use
    423464void debugPrintCallFrame(JSC::CallFrame*);
     465void debugPrintStack(JSC::CallFrame* topCallFrame);
    424466
    425467void debugPrintCallFrame(JSC::CallFrame* callFrame)
     
    427469    if (!callFrame)
    428470        return;
    429     JSC::StackIterator::Frame* frame = JSC::StackIterator::Frame::create(callFrame);
    430     frame->print(2);
     471    JSC::StackIterator iter = callFrame->begin();
     472    iter->print(2);
     473}
     474
     475void debugPrintStack(JSC::CallFrame* topCallFrame)
     476{
     477    if (!topCallFrame)
     478        return;
     479    JSC::StackIterator iter = topCallFrame->begin();
     480    for (; iter != topCallFrame->end(); ++iter)
     481        iter->print(2);
    431482}
    432483#endif // !NDEBUG
  • trunk/Source/JavaScriptCore/interpreter/StackIterator.h

    r153218 r154821  
    2727#define StackIterator_h
    2828
    29 #include "CallFrame.h"
    30 #include "Interpreter.h"
    31 #include "StackIteratorPrivate.h"
     29#include <wtf/text/WTFString.h>
    3230
    3331namespace JSC {
    3432
     33struct CodeOrigin;
     34struct InlineCallFrame;
     35
    3536class Arguments;
     37class CodeBlock;
     38class ExecState;
     39class JSFunction;
     40class JSObject;
     41class JSScope;
    3642
    37 class StackIterator::Frame : public CallFrame {
     43typedef ExecState CallFrame;
     44
     45class StackIterator {
    3846public:
    39     enum CodeType {
    40         Global = StackFrameGlobalCode,
    41         Eval = StackFrameEvalCode,
    42         Function = StackFrameFunctionCode,
    43         Native = StackFrameNativeCode
     47    class Frame {
     48    public:
     49        enum CodeType {
     50            Global,
     51            Eval,
     52            Function,
     53            Native
     54        };
     55
     56        size_t argumentCountIncludingThis() const { return m_argumentCountIncludingThis; }
     57        CallFrame* callerFrame() const { return m_callerFrame; }
     58        JSObject* callee() const { return m_callee; }
     59        JSScope* scope() const { return m_scope; }
     60        CodeBlock* codeBlock() const { return m_codeBlock; }
     61        unsigned bytecodeOffset() const { return m_bytecodeOffset; }
     62#if ENABLE(DFG_JIT)
     63        InlineCallFrame* inlineCallFrame() const { return m_inlineCallFrame; }
     64#endif
     65
     66        bool isJSFrame() const { return !!codeBlock(); }
     67#if ENABLE(DFG_JIT)
     68        bool isInlinedFrame() const { return !!m_inlineCallFrame; }
     69#endif
     70
     71        JS_EXPORT_PRIVATE String functionName();
     72        JS_EXPORT_PRIVATE String sourceURL();
     73        JS_EXPORT_PRIVATE String toString();
     74
     75        CodeType codeType() const;
     76        JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
     77
     78        Arguments* arguments();
     79        CallFrame* callFrame() const { return m_callFrame; }
     80   
     81#ifndef NDEBUG
     82        JS_EXPORT_PRIVATE void print(int indentLevel);
     83#endif
     84
     85    private:
     86        Frame() { }
     87        ~Frame() { }
     88
     89        void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
     90#if ENABLE(DFG_JIT)
     91        void setToEnd();
     92#endif
     93
     94        size_t m_argumentCountIncludingThis;
     95        CallFrame* m_callerFrame;
     96        JSObject* m_callee;
     97        JSScope* m_scope;
     98        CodeBlock* m_codeBlock;
     99        unsigned m_bytecodeOffset;
     100#if ENABLE(DFG_JIT)
     101        InlineCallFrame* m_inlineCallFrame;
     102#endif
     103
     104        CallFrame* m_callFrame;
     105
     106        friend class StackIterator;
    44107    };
    45108
    46     static Frame* create(CallFrame* f) { return reinterpret_cast<Frame*>(f); }
     109    typedef bool (*FrameFilter)(Frame*);
    47110
    48     bool isJSFrame() const { return !!codeBlock(); }
     111    JS_EXPORT_PRIVATE size_t numberOfFrames();
    49112
    50     JS_EXPORT_PRIVATE String functionName();
    51     JS_EXPORT_PRIVATE String sourceURL();
    52     JS_EXPORT_PRIVATE String toString();
     113    Frame& operator*() { return m_frame; }
     114    ALWAYS_INLINE Frame* operator->() { return &m_frame; }
    53115
    54     CodeType codeType() const;
    55     unsigned bytecodeOffset();
    56     JS_EXPORT_PRIVATE void computeLineAndColumn(unsigned& line, unsigned& column);
     116    inline bool operator==(const StackIterator&);
     117    bool operator!=(const StackIterator& other) { return !(*this == other); }
     118    void operator++() { gotoNextFrameWithFilter(); }
     119    void find(JSFunction*);
    57120
    58     Arguments* arguments();
    59     CallFrame* callFrame() { return reinterpret_cast<CallFrame*>(this); }
    60    
    61     Frame* logicalFrame();
    62     Frame* logicalCallerFrame();
     121private:
     122    JS_EXPORT_PRIVATE StackIterator(CallFrame* startFrame, FrameFilter = 0);
    63123
    64 #ifndef NDEBUG
    65     JS_EXPORT_PRIVATE void print(int indentLevel);
     124    JS_EXPORT_PRIVATE static StackIterator end();
     125    void gotoFrameAtIndex(size_t frameIndex);
     126    void gotoNextFrame();
     127    JS_EXPORT_PRIVATE void gotoNextFrameWithFilter();
     128    void resetIterator();
     129
     130    void readFrame(CallFrame*);
     131    void readNonInlinedFrame(CallFrame*, CodeOrigin* = 0);
     132#if ENABLE(DFG_JIT)
     133    void readInlinedFrame(CallFrame*, CodeOrigin*);
    66134#endif
    67135
    68 private:
    69     Frame();
    70     ~Frame();
     136    CallFrame* m_startFrame;
     137    size_t m_frameIndex;
     138    FrameFilter m_filter;
     139    Frame m_frame;
    71140
    72     void retrieveExpressionInfo(int& divot, int& startOffset, int& endOffset, unsigned& line, unsigned& column);
     141    friend class ExecState;
    73142};
     143
     144inline bool StackIterator::operator==(const StackIterator& other)
     145{
     146    return (m_frame.callFrame() == other.m_frame.callFrame())
     147#if ENABLE(DFG_JIT)
     148        && (m_frame.inlineCallFrame() == other.m_frame.inlineCallFrame())
     149#endif
     150        ;
     151}
    74152
    75153} // namespace JSC
Note: See TracChangeset for help on using the changeset viewer.