Changeset 182927 in webkit


Ignore:
Timestamp:
Apr 16, 2015 5:25:14 PM (9 years ago)
Author:
mark.lam@apple.com
Message:

Add $vm debugging tool.
https://bugs.webkit.org/show_bug.cgi?id=143809

Reviewed by Geoffrey Garen.

For debugging VM bugs, it would be useful to be able to dump VM data structures
from JS code that we instrument. To this end, let's introduce a
JS_enableDollarVM option that, if true, installs an $vm property into each JS
global object at creation time. The $vm property refers to an object that
provides a collection of useful utility functions. For this initial
implementation, $vm will have the following:

crash() - trigger an intentional crash.

dfgTrue() - returns true if the current function is DFG compiled, else returns false.
jitTrue() - returns true if the current function is compiled by the baseline JIT, else returns false.
llintTrue() - returns true if the current function is interpreted by the LLINT, else returns false.

gc() - runs a full GC.
edenGC() - runs an eden GC.

codeBlockForFrame(frameNumber) - gets the codeBlock at the specified frame (0 = current, 1 = caller, etc).
printSourceFor(codeBlock) - prints the source code for the codeBlock.
printByteCodeFor(codeBlock) - prints the bytecode for the codeBlock.

print(str) - prints a string to dataLog output.
printCallFrame() - prints the current CallFrame.
printStack() - prints the JS stack.
printInternal(value) - prints the JSC internal info for the specified value.

With JS_enableDollarVM=true, JS code can use the above functions like so:

$vm.print("Using $vm features\n");

(JSC::CodeBlock::printCallOp):

  • FTL compiled functions don't like it when we try to compute the CallLinkStatus. Hence, we skip this step if we're dumping an FTL codeBlock.
  • heap/Heap.cpp:

(JSC::Heap::collectAndSweep):
(JSC::Heap::collectAllGarbage): Deleted.

  • heap/Heap.h:

(JSC::Heap::collectAllGarbage):

  • Add ability to do an Eden collection and sweep.
  • interpreter/StackVisitor.cpp:

(JSC::printIndents):
(JSC::log):
(JSC::logF):
(JSC::StackVisitor::Frame::print):
(JSC::jitTypeName): Deleted.
(JSC::printif): Deleted.

  • Modernize the implementation of StackVisitor::Frame::print(), and remove some now redundant code.
  • Also fix it so that it downgrades gracefully when encountering inlined DFG and compiled FTL functions.

(DebugPrintFrameFunctor::DebugPrintFrameFunctor): Deleted.
(DebugPrintFrameFunctor::operator()): Deleted.
(debugPrintCallFrame): Deleted.
(debugPrintStack): Deleted.

  • these have been moved into JSDollarVMPrototype.cpp.
  • interpreter/StackVisitor.h:
  • StackVisitor::Frame::print() is now enabled for release builds as well so that we can call it from $vm.
  • runtime/JSGlobalObject.cpp:

(JSC::JSGlobalObject::init):
(JSC::JSGlobalObject::visitChildren):

  • runtime/JSGlobalObject.h:
  • Added the $vm instance to global objects conditional on the JSC_enableDollarVM option.
  • runtime/Options.h:
  • Added the JSC_enableDollarVM option.
  • tools/JSDollarVM.cpp: Added.
  • tools/JSDollarVM.h: Added.

(JSC::JSDollarVM::createStructure):
(JSC::JSDollarVM::create):
(JSC::JSDollarVM::JSDollarVM):

  • tools/JSDollarVMPrototype.cpp: Added.
  • This file contains 2 sets of functions:
  1. a C++ implementation of debugging utility functions that are callable when doing debugging from lldb. To the extent possible, these functions try to be cautious and not cause unintended crashes should the user call them with the wrong info. Hence, they are designed to be robust rather than speedy.
  1. the native implementations of JS functions in the $vm object. Where there is overlapping functionality, these are built on top of the C++ functions above to do the work.

Note: it does not make sense for all of the $vm functions to have a C++
counterpart for lldb debugging. For example, the $vm.dfgTrue() function is
only useful for JS code, and works via the DFG intrinsics mechanism.
When doing debugging via lldb, the optimization level of the currently
executing JS function can be gotten by dumping the current CallFrame instead.

(JSC::currentThreadOwnsJSLock):
(JSC::ensureCurrentThreadOwnsJSLock):
(JSC::JSDollarVMPrototype::addFunction):
(JSC::functionCrash): - $vm.crash()
(JSC::functionDFGTrue): - $vm.dfgTrue()
(JSC::CallerFrameJITTypeFunctor::CallerFrameJITTypeFunctor):
(JSC::CallerFrameJITTypeFunctor::operator()):
(JSC::CallerFrameJITTypeFunctor::jitType):
(JSC::functionLLintTrue): - $vm.llintTrue()
(JSC::functionJITTrue): - $vm.jitTrue()
(JSC::gc):
(JSC::functionGC): - $vm.gc()
(JSC::edenGC):
(JSC::functionEdenGC): - $vm.edenGC()
(JSC::isValidCodeBlock):
(JSC::codeBlockForFrame):
(JSC::functionCodeBlockForFrame): - $vm.codeBlockForFrame(frameNumber)
(JSC::codeBlockFromArg):
(JSC::functionPrintSourceFor): - $vm.printSourceFor(codeBlock)
(JSC::functionPrintByteCodeFor): - $vm.printBytecodeFor(codeBlock)
(JSC::functionPrint): - $vm.print(str)
(JSC::PrintFrameFunctor::PrintFrameFunctor):
(JSC::PrintFrameFunctor::operator()):
(JSC::printCallFrame):
(JSC::printStack):
(JSC::functionPrintCallFrame): - $vm.printCallFrame()
(JSC::functionPrintStack): - $vm.printStack()
(JSC::printValue):
(JSC::functionPrintValue): - $vm.printValue()
(JSC::JSDollarVMPrototype::finishCreation):

  • tools/JSDollarVMPrototype.h: Added.

(JSC::JSDollarVMPrototype::create):
(JSC::JSDollarVMPrototype::createStructure):
(JSC::JSDollarVMPrototype::JSDollarVMPrototype):

Location:
trunk/Source/JavaScriptCore
Files:
4 added
13 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/CMakeLists.txt

    r182915 r182927  
    390390    tools/CodeProfiling.cpp
    391391    tools/FunctionOverrides.cpp
     392    tools/JSDollarVM.cpp
     393    tools/JSDollarVMPrototype.cpp
    392394
    393395    yarr/RegularExpression.cpp
  • trunk/Source/JavaScriptCore/ChangeLog

    r182921 r182927  
     12015-04-16  Mark Lam  <mark.lam@apple.com>
     2
     3        Add $vm debugging tool.
     4        https://bugs.webkit.org/show_bug.cgi?id=143809
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        For debugging VM bugs, it would be useful to be able to dump VM data structures
     9        from JS code that we instrument.  To this end, let's introduce a
     10        JS_enableDollarVM option that, if true, installs an $vm property into each JS
     11        global object at creation time.  The $vm property refers to an object that
     12        provides a collection of useful utility functions.  For this initial
     13        implementation, $vm will have the following:
     14
     15            crash() - trigger an intentional crash.
     16
     17            dfgTrue() - returns true if the current function is DFG compiled, else returns false.
     18            jitTrue() - returns true if the current function is compiled by the baseline JIT, else returns false.
     19            llintTrue() - returns true if the current function is interpreted by the LLINT, else returns false.
     20
     21            gc() - runs a full GC.
     22            edenGC() - runs an eden GC.
     23
     24            codeBlockForFrame(frameNumber) - gets the codeBlock at the specified frame (0 = current, 1 = caller, etc).
     25            printSourceFor(codeBlock) - prints the source code for the codeBlock.
     26            printByteCodeFor(codeBlock) - prints the bytecode for the codeBlock.
     27
     28            print(str) - prints a string to dataLog output.
     29            printCallFrame() - prints the current CallFrame.
     30            printStack() - prints the JS stack.
     31            printInternal(value) - prints the JSC internal info for the specified value.
     32
     33        With JS_enableDollarVM=true, JS code can use the above functions like so:
     34
     35            $vm.print("Using $vm features\n");
     36
     37        * CMakeLists.txt:
     38        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj:
     39        * JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters:
     40        * JavaScriptCore.xcodeproj/project.pbxproj:
     41        * bytecode/CodeBlock.cpp:
     42        (JSC::CodeBlock::printCallOp):
     43        - FTL compiled functions don't like it when we try to compute the CallLinkStatus.
     44          Hence, we skip this step if we're dumping an FTL codeBlock.
     45
     46        * heap/Heap.cpp:
     47        (JSC::Heap::collectAndSweep):
     48        (JSC::Heap::collectAllGarbage): Deleted.
     49        * heap/Heap.h:
     50        (JSC::Heap::collectAllGarbage):
     51        - Add ability to do an Eden collection and sweep.
     52
     53        * interpreter/StackVisitor.cpp:
     54        (JSC::printIndents):
     55        (JSC::log):
     56        (JSC::logF):
     57        (JSC::StackVisitor::Frame::print):
     58        (JSC::jitTypeName): Deleted.
     59        (JSC::printif): Deleted.
     60        - Modernize the implementation of StackVisitor::Frame::print(), and remove some
     61          now redundant code.
     62        - Also fix it so that it downgrades gracefully when encountering inlined DFG
     63          and compiled FTL functions.
     64
     65        (DebugPrintFrameFunctor::DebugPrintFrameFunctor): Deleted.
     66        (DebugPrintFrameFunctor::operator()): Deleted.
     67        (debugPrintCallFrame): Deleted.
     68        (debugPrintStack): Deleted.
     69        - these have been moved into JSDollarVMPrototype.cpp.
     70
     71        * interpreter/StackVisitor.h:
     72        - StackVisitor::Frame::print() is now enabled for release builds as well so that
     73          we can call it from $vm.
     74
     75        * runtime/JSGlobalObject.cpp:
     76        (JSC::JSGlobalObject::init):
     77        (JSC::JSGlobalObject::visitChildren):
     78        * runtime/JSGlobalObject.h:
     79        - Added the $vm instance to global objects conditional on the JSC_enableDollarVM
     80          option.
     81
     82        * runtime/Options.h:
     83        - Added the JSC_enableDollarVM option.
     84
     85        * tools/JSDollarVM.cpp: Added.
     86        * tools/JSDollarVM.h: Added.
     87        (JSC::JSDollarVM::createStructure):
     88        (JSC::JSDollarVM::create):
     89        (JSC::JSDollarVM::JSDollarVM):
     90
     91        * tools/JSDollarVMPrototype.cpp: Added.
     92        - This file contains 2 sets of functions:
     93
     94          a. a C++ implementation of debugging utility functions that are callable when
     95             doing debugging from lldb.  To the extent possible, these functions try to
     96             be cautious and not cause unintended crashes should the user call them with
     97             the wrong info.  Hence, they are designed to be robust rather than speedy.
     98
     99          b. the native implementations of JS functions in the $vm object.  Where there
     100             is overlapping functionality, these are built on top of the C++ functions
     101             above to do the work.
     102
     103          Note: it does not make sense for all of the $vm functions to have a C++
     104          counterpart for lldb debugging.  For example, the $vm.dfgTrue() function is
     105          only useful for JS code, and works via the DFG intrinsics mechanism.
     106          When doing debugging via lldb, the optimization level of the currently
     107          executing JS function can be gotten by dumping the current CallFrame instead.
     108
     109        (JSC::currentThreadOwnsJSLock):
     110        (JSC::ensureCurrentThreadOwnsJSLock):
     111        (JSC::JSDollarVMPrototype::addFunction):
     112        (JSC::functionCrash): - $vm.crash()
     113        (JSC::functionDFGTrue): - $vm.dfgTrue()
     114        (JSC::CallerFrameJITTypeFunctor::CallerFrameJITTypeFunctor):
     115        (JSC::CallerFrameJITTypeFunctor::operator()):
     116        (JSC::CallerFrameJITTypeFunctor::jitType):
     117        (JSC::functionLLintTrue): - $vm.llintTrue()
     118        (JSC::functionJITTrue): - $vm.jitTrue()
     119        (JSC::gc):
     120        (JSC::functionGC): - $vm.gc()
     121        (JSC::edenGC):
     122        (JSC::functionEdenGC): - $vm.edenGC()
     123        (JSC::isValidCodeBlock):
     124        (JSC::codeBlockForFrame):
     125        (JSC::functionCodeBlockForFrame): - $vm.codeBlockForFrame(frameNumber)
     126        (JSC::codeBlockFromArg):
     127        (JSC::functionPrintSourceFor): - $vm.printSourceFor(codeBlock)
     128        (JSC::functionPrintByteCodeFor): - $vm.printBytecodeFor(codeBlock)
     129        (JSC::functionPrint): - $vm.print(str)
     130        (JSC::PrintFrameFunctor::PrintFrameFunctor):
     131        (JSC::PrintFrameFunctor::operator()):
     132        (JSC::printCallFrame):
     133        (JSC::printStack):
     134        (JSC::functionPrintCallFrame): - $vm.printCallFrame()
     135        (JSC::functionPrintStack): - $vm.printStack()
     136        (JSC::printValue):
     137        (JSC::functionPrintValue): - $vm.printValue()
     138        (JSC::JSDollarVMPrototype::finishCreation):
     139        * tools/JSDollarVMPrototype.h: Added.
     140        (JSC::JSDollarVMPrototype::create):
     141        (JSC::JSDollarVMPrototype::createStructure):
     142        (JSC::JSDollarVMPrototype::JSDollarVMPrototype):
     143
    11442015-04-16  Geoffrey Garen  <ggaren@apple.com>
    2145
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj

    r182911 r182927  
    853853    <ClCompile Include="..\tools\CodeProfiling.cpp" />
    854854    <ClCompile Include="..\tools\FunctionOverrides.cpp" />
     855    <ClCompile Include="..\tools\JSDollarVM.cpp" />
     856    <ClCompile Include="..\tools\JSDollarVMPrototype.cpp" />
    855857    <ClCompile Include="..\yarr\RegularExpression.cpp" />
    856858    <ClCompile Include="..\yarr\YarrCanonicalizeUCS2.cpp" />
     
    16991701    <ClInclude Include="..\tools\CodeProfiling.h" />
    17001702    <ClInclude Include="..\tools\FunctionOverrides.h" />
     1703    <ClInclude Include="..\tools\JSDollarVM.h" />
     1704    <ClInclude Include="..\tools\JSDollarVMPrototype.h" />
    17011705    <ClInclude Include="..\tools\ProfileTreeNode.h" />
    17021706    <ClInclude Include="..\tools\TieredMMapArray.h" />
  • trunk/Source/JavaScriptCore/JavaScriptCore.vcxproj/JavaScriptCore.vcxproj.filters

    r182911 r182927  
    901901      <Filter>tools</Filter>
    902902    </ClCompile>
     903    <ClCompile Include="..\tools\JSDollarVM.cpp">
     904      <Filter>tools</Filter>
     905    </ClCompile>
     906    <ClCompile Include="..\tools\JSDollarVMPrototype.cpp">
     907      <Filter>tools</Filter>
     908    </ClCompile>
    903909    <ClCompile Include="..\yarr\RegularExpression.cpp">
    904910      <Filter>yarr</Filter>
     
    29712977    </ClInclude>
    29722978    <ClInclude Include="..\tools\FunctionOverrides.h">
     2979      <Filter>tools</Filter>
     2980    </ClInclude>
     2981    <ClInclude Include="..\tools\JSDollarVM.h">
     2982      <Filter>tools</Filter>
     2983    </ClInclude>
     2984    <ClInclude Include="..\tools\JSDollarVMPrototype.h">
    29732985      <Filter>tools</Filter>
    29742986    </ClInclude>
  • trunk/Source/JavaScriptCore/JavaScriptCore.xcodeproj/project.pbxproj

    r182911 r182927  
    16451645                FE4BFF2B1AD476E700088F87 /* FunctionOverrides.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */; };
    16461646                FE4BFF2C1AD476E700088F87 /* FunctionOverrides.h in Headers */ = {isa = PBXBuildFile; fileRef = FE4BFF2A1AD476E700088F87 /* FunctionOverrides.h */; };
     1647                FE384EE51ADDB7AD0055DE2C /* JSDollarVM.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */; };
     1648                FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */; settings = {ATTRIBUTES = (Private, ); }; };
     1649                FE384EE71ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE384EE31ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp */; };
     1650                FE384EE81ADDB7AD0055DE2C /* JSDollarVMPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = FE384EE41ADDB7AD0055DE2C /* JSDollarVMPrototype.h */; settings = {ATTRIBUTES = (Private, ); }; };
    16471651                FE5932A7183C5A2600A1ECCC /* VMEntryScope.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */; };
    16481652                FE5932A8183C5A2600A1ECCC /* VMEntryScope.h in Headers */ = {isa = PBXBuildFile; fileRef = FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */; settings = {ATTRIBUTES = (Private, ); }; };
     
    34213425                FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FunctionOverrides.cpp; sourceTree = "<group>"; };
    34223426                FE4BFF2A1AD476E700088F87 /* FunctionOverrides.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FunctionOverrides.h; sourceTree = "<group>"; };
     3427                FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVM.cpp; sourceTree = "<group>"; };
     3428                FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDollarVM.h; sourceTree = "<group>"; };
     3429                FE384EE31ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSDollarVMPrototype.cpp; sourceTree = "<group>"; };
     3430                FE384EE41ADDB7AD0055DE2C /* JSDollarVMPrototype.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSDollarVMPrototype.h; sourceTree = "<group>"; };
    34233431                FE5932A5183C5A2600A1ECCC /* VMEntryScope.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = VMEntryScope.cpp; sourceTree = "<group>"; };
    34243432                FE5932A6183C5A2600A1ECCC /* VMEntryScope.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VMEntryScope.h; sourceTree = "<group>"; };
     
    47474755                                FE4BFF291AD476E700088F87 /* FunctionOverrides.cpp */,
    47484756                                FE4BFF2A1AD476E700088F87 /* FunctionOverrides.h */,
     4757                                FE384EE11ADDB7AD0055DE2C /* JSDollarVM.cpp */,
     4758                                FE384EE21ADDB7AD0055DE2C /* JSDollarVM.h */,
     4759                                FE384EE31ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp */,
     4760                                FE384EE41ADDB7AD0055DE2C /* JSDollarVMPrototype.h */,
    47494761                                86B5822C14D22F5F00A9C306 /* ProfileTreeNode.h */,
    47504762                                86B5826A14D35D5100A9C306 /* TieredMMapArray.h */,
     
    55485560                                C4F4B6F31A05C944005CAB76 /* cpp_generator_templates.py in Headers */,
    55495561                                A5EF9B151A1D43FA00702E90 /* generate_cpp_backend_dispatcher_implementation.py in Headers */,
     5562                                FE384EE81ADDB7AD0055DE2C /* JSDollarVMPrototype.h in Headers */,
     5563                                FE384EE61ADDB7AD0055DE2C /* JSDollarVM.h in Headers */,
    55505564                                6AD2CB4D19B9140100065719 /* DebuggerEvalEnabler.h in Headers */,
    55515565                                658D3A5619638268003C45D6 /* VMEntryRecord.h in Headers */,
     
    70157029                                0FBE0F7216C1DB030082C5E8 /* DFGCPSRethreadingPhase.cpp in Sources */,
    70167030                                A7D89CF517A0B8CC00773AD8 /* DFGCriticalEdgeBreakingPhase.cpp in Sources */,
     7031                                FE384EE71ADDB7AD0055DE2C /* JSDollarVMPrototype.cpp in Sources */,
    70177032                                0FFFC95914EF90A600C72532 /* DFGCSEPhase.cpp in Sources */,
    70187033                                0F2FC77216E12F710038D976 /* DFGDCEPhase.cpp in Sources */,
     
    72707285                                0F2B66ED17B6B5AB00A7AE3F /* JSDataViewPrototype.cpp in Sources */,
    72717286                                0F2D4DE819832DAC007D4B19 /* ToThisStatus.cpp in Sources */,
     7287                                FE384EE51ADDB7AD0055DE2C /* JSDollarVM.cpp in Sources */,
    72727288                                978801401471AD920041B016 /* JSDateMath.cpp in Sources */,
    72737289                                0FE050171AA9091100D33B33 /* DirectArguments.cpp in Sources */,
  • trunk/Source/JavaScriptCore/bytecode/CodeBlock.cpp

    r182759 r182927  
    532532                out.printf(" jit(%p, exec %p)", target, target->executable());
    533533        }
    534         out.print(" status(", CallLinkStatus::computeFor(this, location, map), ")");
     534       
     535        if (jitType() != JITCode::FTLJIT)
     536            out.print(" status(", CallLinkStatus::computeFor(this, location, map), ")");
    535537#else
    536538        UNUSED_PARAM(map);
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r182347 r182927  
    993993}
    994994
    995 void Heap::collectAllGarbage()
     995void Heap::collectAndSweep(HeapOperation collectionType)
    996996{
    997997    if (!m_isSafeToCollect)
    998998        return;
    999999
    1000     collect(FullCollection);
     1000    collect(collectionType);
    10011001
    10021002    SamplingRegion samplingRegion("Garbage Collection: Sweeping");
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r182747 r182927  
    155155    bool isSafeToCollect() const { return m_isSafeToCollect; }
    156156
    157     JS_EXPORT_PRIVATE void collectAllGarbage();
     157    void collectAllGarbage() { collectAndSweep(FullCollection); }
     158    JS_EXPORT_PRIVATE void collectAndSweep(HeapOperation collectionType = AnyCollection);
    158159    bool shouldCollect();
    159160    JS_EXPORT_PRIVATE void collect(HeapOperation collectionType = AnyCollection);
  • trunk/Source/JavaScriptCore/interpreter/StackVisitor.cpp

    r182038 r182927  
    314314}
    315315
    316 #ifndef NDEBUG
    317 
    318 static const char* jitTypeName(JITCode::JITType jitType)
    319 {
    320     switch (jitType) {
    321     case JITCode::None: return "None";
    322     case JITCode::HostCallThunk: return "HostCallThunk";
    323     case JITCode::InterpreterThunk: return "InterpreterThunk";
    324     case JITCode::BaselineJIT: return "BaselineJIT";
    325     case JITCode::DFGJIT: return "DFGJIT";
    326     case JITCode::FTLJIT: return "FTLJIT";
    327     }
    328     return "<unknown>";
    329 }
    330 
    331316static void printIndents(int levels)
    332317{
     
    335320}
    336321
    337 static void printif(int indentLevels, const char* format, ...)
    338 {
    339     va_list argList;
    340     va_start(argList, format);
    341 
    342     if (indentLevels)
    343         printIndents(indentLevels);
     322template<typename... Types>
     323void log(unsigned indent, const Types&... values)
     324{
     325    printIndents(indent);
     326    dataLog(values...);
     327}
     328
     329template<typename... Types>
     330void logF(unsigned indent, const char* format, const Types&... values)
     331{
     332    printIndents(indent);
    344333
    345334#if COMPILER(CLANG) || COMPILER(GCC)
     
    349338#endif
    350339
    351     WTF::dataLogFV(format, argList);
     340    dataLogF(format, values...);
    352341
    353342#if COMPILER(CLANG) || COMPILER(GCC)
    354343#pragma GCC diagnostic pop
    355344#endif
    356 
    357     va_end(argList);
    358 }
    359 
    360 void StackVisitor::Frame::print(int indentLevel)
    361 {
    362     int i = indentLevel;
    363 
     345}
     346
     347void StackVisitor::Frame::print(int indent)
     348{
    364349    if (!this->callFrame()) {
    365         printif(i, "frame 0x0\n");
     350        log(indent, "frame 0x0\n");
    366351        return;
    367352    }
    368353
    369354    CodeBlock* codeBlock = this->codeBlock();
    370     printif(i, "frame %p {\n", this->callFrame());
    371 
    372     CallFrame* callFrame = m_callFrame;
    373     CallFrame* callerFrame = this->callerFrame();
    374     void* returnPC = callFrame->hasReturnPC() ? callFrame->returnPC().value() : nullptr;
    375 
    376     printif(i, "   name '%s'\n", functionName().utf8().data());
    377     printif(i, "   sourceURL '%s'\n", sourceURL().utf8().data());
    378 
    379 #if ENABLE(DFG_JIT)
    380     printif(i, "   isInlinedFrame %d\n", isInlinedFrame());
    381     if (isInlinedFrame())
    382         printif(i, "   InlineCallFrame %p\n", m_inlineCallFrame);
    383 #endif
    384 
    385     printif(i, "   callee %p\n", callee());
    386     printif(i, "   returnPC %p\n", returnPC);
    387     printif(i, "   callerFrame %p\n", callerFrame);
    388     unsigned locationRawBits = callFrame->locationAsRawBits();
    389     printif(i, "   rawLocationBits %u 0x%x\n", locationRawBits, locationRawBits);
    390     printif(i, "   codeBlock %p\n", codeBlock);
    391     if (codeBlock) {
    392         JITCode::JITType jitType = codeBlock->jitType();
    393         if (callFrame->hasLocationAsBytecodeOffset()) {
    394             unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
    395             printif(i, "      bytecodeOffset %u %p / %zu\n", bytecodeOffset, reinterpret_cast<void*>(bytecodeOffset), codeBlock->instructions().size());
    396 #if ENABLE(DFG_JIT)
    397         } else {
    398             unsigned codeOriginIndex = callFrame->locationAsCodeOriginIndex();
    399             printif(i, "      codeOriginIdex %u %p / %zu\n", codeOriginIndex, reinterpret_cast<void*>(codeOriginIndex), codeBlock->codeOrigins().size());
    400 #endif
     355    logF(indent, "frame %p {\n", this->callFrame());
     356
     357    {
     358        indent++;
     359
     360        CallFrame* callFrame = m_callFrame;
     361        CallFrame* callerFrame = this->callerFrame();
     362        void* returnPC = callFrame->hasReturnPC() ? callFrame->returnPC().value() : nullptr;
     363
     364        log(indent, "name: ", functionName(), "\n");
     365        log(indent, "sourceURL: ", sourceURL(), "\n");
     366
     367#if ENABLE(DFG_JIT)
     368        log(indent, "isInlinedFrame: ", isInlinedFrame(), "\n");
     369        if (isInlinedFrame())
     370            logF(indent, "InlineCallFrame: %p\n", m_inlineCallFrame);
     371#endif
     372
     373        logF(indent, "callee: %p\n", callee());
     374        logF(indent, "returnPC: %p\n", returnPC);
     375        logF(indent, "callerFrame: %p\n", callerFrame);
     376        unsigned locationRawBits = callFrame->locationAsRawBits();
     377        logF(indent, "rawLocationBits: %u 0x%x\n", locationRawBits, locationRawBits);
     378        logF(indent, "codeBlock: %p ", codeBlock);
     379        if (codeBlock)
     380            dataLog(*codeBlock);
     381        dataLog("\n");
     382        if (codeBlock && !isInlinedFrame()) {
     383            indent++;
     384
     385            if (callFrame->hasLocationAsBytecodeOffset()) {
     386                unsigned bytecodeOffset = callFrame->locationAsBytecodeOffset();
     387                log(indent, "bytecodeOffset: ", bytecodeOffset, " of ", codeBlock->instructions().size(), "\n");
     388#if ENABLE(DFG_JIT)
     389            } else {
     390                log(indent, "hasCodeOrigins: ", codeBlock->hasCodeOrigins(), "\n");
     391                if (codeBlock->hasCodeOrigins()) {
     392                    unsigned codeOriginIndex = callFrame->locationAsCodeOriginIndex();
     393                    log(indent, "codeOriginIndex: ", codeOriginIndex, " of ", codeBlock->codeOrigins().size(), "\n");
     394
     395                    JITCode::JITType jitType = codeBlock->jitType();
     396                    if (jitType != JITCode::FTLJIT) {
     397                        JITCode* jitCode = codeBlock->jitCode().get();
     398                        logF(indent, "jitCode: %p start %p end %p\n", jitCode, jitCode->start(), jitCode->end());
     399                    }
     400                }
     401#endif
     402            }
     403            unsigned line = 0;
     404            unsigned column = 0;
     405            computeLineAndColumn(line, column);
     406            log(indent, "line: ", line, "\n");
     407            log(indent, "column: ", column, "\n");
     408
     409            indent--;
    401410        }
    402         unsigned line = 0;
    403         unsigned column = 0;
    404         computeLineAndColumn(line, column);
    405         printif(i, "      line %d\n", line);
    406         printif(i, "      column %d\n", column);
    407         printif(i, "      jitType %d <%s> isOptimizingJIT %d\n", jitType, jitTypeName(jitType), JITCode::isOptimizingJIT(jitType));
    408 #if ENABLE(DFG_JIT)
    409         printif(i, "      hasCodeOrigins %d\n", codeBlock->hasCodeOrigins());
    410         if (codeBlock->hasCodeOrigins()) {
    411             JITCode* jitCode = codeBlock->jitCode().get();
    412             printif(i, "         jitCode %p start %p end %p\n", jitCode, jitCode->start(), jitCode->end());
    413         }
    414 #endif
    415     }
    416     printif(i, "}\n");
    417 }
    418 
    419 #endif // NDEBUG
     411        indent--;
     412    }
     413    log(indent, "}\n");
     414}
    420415
    421416} // namespace JSC
    422 
    423 #ifndef NDEBUG
    424 using JSC::StackVisitor;
    425 
    426 // For debugging use
    427 JS_EXPORT_PRIVATE void debugPrintCallFrame(JSC::CallFrame*);
    428 JS_EXPORT_PRIVATE void debugPrintStack(JSC::CallFrame* topCallFrame);
    429 
    430 class DebugPrintFrameFunctor {
    431 public:
    432     enum Action {
    433         PrintOne,
    434         PrintAll
    435     };
    436 
    437     DebugPrintFrameFunctor(Action action)
    438         : m_action(action)
    439     {
    440     }
    441 
    442     StackVisitor::Status operator()(StackVisitor& visitor)
    443     {
    444         visitor->print(2);
    445         return m_action == PrintAll ? StackVisitor::Continue : StackVisitor::Done;
    446     }
    447 
    448 private:
    449     Action m_action;
    450 };
    451 
    452 void debugPrintCallFrame(JSC::CallFrame* callFrame)
    453 {
    454     if (!callFrame)
    455         return;
    456     DebugPrintFrameFunctor functor(DebugPrintFrameFunctor::PrintOne);
    457     callFrame->iterate(functor);
    458 }
    459 
    460 void debugPrintStack(JSC::CallFrame* topCallFrame)
    461 {
    462     if (!topCallFrame)
    463         return;
    464     DebugPrintFrameFunctor functor(DebugPrintFrameFunctor::PrintAll);
    465     topCallFrame->iterate(functor);
    466 }
    467 
    468 #endif // !NDEBUG
  • trunk/Source/JavaScriptCore/interpreter/StackVisitor.h

    r181993 r182927  
    8383        CallFrame* callFrame() const { return m_callFrame; }
    8484       
    85 #ifndef NDEBUG
    8685        JS_EXPORT_PRIVATE void print(int indentLevel);
    87 #endif
    8886
    8987    private:
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.cpp

    r182911 r182927  
    6868#include "JSDataView.h"
    6969#include "JSDataViewPrototype.h"
     70#include "JSDollarVM.h"
     71#include "JSDollarVMPrototype.h"
    7072#include "JSFunction.h"
    7173#include "JSFunctionNameScope.h"
     
    451453    putDirectWithoutTransition(vm, Identifier::fromString(exec, "console"), consoleObject, DontEnum);
    452454
     455    if (UNLIKELY(Options::enableDollarVM())) {
     456        JSDollarVMPrototype* dollarVMPrototype = JSDollarVMPrototype::create(vm, this, JSDollarVMPrototype::createStructure(vm, this, m_objectPrototype.get()));
     457        m_dollarVMStructure.set(vm, this, JSDollarVM::createStructure(vm, this, dollarVMPrototype));
     458        JSDollarVM* dollarVM = JSDollarVM::create(vm, m_dollarVMStructure.get());
     459        putDirectWithoutTransition(vm, Identifier::fromString(exec, "$vm"), dollarVM, DontEnum);
     460    }
     461
    453462    resetPrototype(vm, prototype());
    454463}
     
    730739    visitor.append(&thisObject->m_regExpStructure);
    731740    visitor.append(&thisObject->m_consoleStructure);
     741    visitor.append(&thisObject->m_dollarVMStructure);
    732742    visitor.append(&thisObject->m_internalFunctionStructure);
    733743
  • trunk/Source/JavaScriptCore/runtime/JSGlobalObject.h

    r182911 r182927  
    232232    WriteBarrier<Structure> m_regExpStructure;
    233233    WriteBarrier<Structure> m_consoleStructure;
     234    WriteBarrier<Structure> m_dollarVMStructure;
    234235    WriteBarrier<Structure> m_internalFunctionStructure;
    235236   
  • trunk/Source/JavaScriptCore/runtime/Options.h

    r182903 r182927  
    307307    v(bool, verboseExecutableAllocationFuzz, false, nullptr) \
    308308    \
     309    v(bool, enableDollarVM, false, "installs the $vm debugging tool in global objects") \
    309310    v(optionString, functionOverrides, nullptr, "file with debugging overrides for function bodies") \
    310311
Note: See TracChangeset for help on using the changeset viewer.