Changeset 119633 in webkit


Ignore:
Timestamp:
Jun 6, 2012 4:11:09 PM (12 years ago)
Author:
msaboff@apple.com
Message:

ENH: Add Logging to GC Marking Phase
https://bugs.webkit.org/show_bug.cgi?id=88364

Reviewed by Filip Pizlo.

Source/JavaScriptCore:

Log GC marking to stderr or a file. The logging in controlled
with the define ENABLE_OBJECT_MARK_LOGGING in wtf/Platform.h.
If DATA_LOG_TO_FILE in wtf/DataLog.cpp is set to 1, output is
logged to a file otherwise it is logged to stderr.

When logging is enabled, the GC is built single threaded since the
log output from the various threads isn't buffered and output in a
thread safe manner.

  • heap/Heap.cpp:

(JSC::Heap::markRoots):

  • heap/MarkStack.cpp:

(JSC::MarkStackThreadSharedData::resetChildren):
(JSC::MarkStackThreadSharedData::childVisitCount):
(JSC::MarkStackThreadSharedData::markingThreadMain):
(JSC::MarkStackThreadSharedData::markingThreadStartFunc):
(JSC::MarkStackThreadSharedData::MarkStackThreadSharedData):
(JSC::MarkStackThreadSharedData::reset):

  • heap/MarkStack.h:

(MarkStackThreadSharedData):
(MarkStack):
(JSC::MarkStack::sharedData):
(JSC::MarkStack::resetChildCount):
(JSC::MarkStack::childCount):
(JSC::MarkStack::incrementChildCount):

  • runtime/JSArray.cpp:

(JSC::JSArray::visitChildren):

  • runtime/JSCell.cpp:

(JSC::JSCell::className):

  • runtime/JSCell.h:

(JSCell):
(JSC::JSCell::visitChildren):

  • runtime/JSString.cpp:

(JSC::JSString::visitChildren):

  • runtime/JSString.h:

(JSString):

  • runtime/Structure.h:

(JSC::MarkStack::internalAppend):

Source/WTF:

  • wtf/DataLog.cpp:

(WTF::dataLogString): Additional method to support GC Mark logging.

  • wtf/DataLog.h:
  • wtf/Platform.h: New ENABLE_OBJECT_MARK_LOGGING flag macro.
Location:
trunk/Source
Files:
14 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r119623 r119633  
     12012-06-06  Michael Saboff  <msaboff@apple.com>
     2
     3        ENH: Add Logging to GC Marking Phase
     4        https://bugs.webkit.org/show_bug.cgi?id=88364
     5
     6        Reviewed by Filip Pizlo.
     7
     8        Log GC marking to stderr or a file.  The logging in controlled
     9        with the define ENABLE_OBJECT_MARK_LOGGING in wtf/Platform.h.
     10        If DATA_LOG_TO_FILE in wtf/DataLog.cpp is set to 1, output is
     11        logged to a file otherwise it is logged to stderr.
     12
     13        When logging is enabled, the GC is built single threaded since the
     14        log output from the various threads isn't buffered and output in a
     15        thread safe manner.
     16
     17        * heap/Heap.cpp:
     18        (JSC::Heap::markRoots):
     19        * heap/MarkStack.cpp:
     20        (JSC::MarkStackThreadSharedData::resetChildren):
     21        (JSC::MarkStackThreadSharedData::childVisitCount):
     22        (JSC::MarkStackThreadSharedData::markingThreadMain):
     23        (JSC::MarkStackThreadSharedData::markingThreadStartFunc):
     24        (JSC::MarkStackThreadSharedData::MarkStackThreadSharedData):
     25        (JSC::MarkStackThreadSharedData::reset):
     26        * heap/MarkStack.h:
     27        (MarkStackThreadSharedData):
     28        (MarkStack):
     29        (JSC::MarkStack::sharedData):
     30        (JSC::MarkStack::resetChildCount):
     31        (JSC::MarkStack::childCount):
     32        (JSC::MarkStack::incrementChildCount):
     33        * runtime/JSArray.cpp:
     34        (JSC::JSArray::visitChildren):
     35        * runtime/JSCell.cpp:
     36        (JSC::JSCell::className):
     37        * runtime/JSCell.h:
     38        (JSCell):
     39        (JSC::JSCell::visitChildren):
     40        * runtime/JSString.cpp:
     41        (JSC::JSString::visitChildren):
     42        * runtime/JSString.h:
     43        (JSString):
     44        * runtime/Structure.h:
     45        (JSC::MarkStack::internalAppend):
     46
    1472012-06-06  Gavin Barraclough  <barraclough@apple.com>
    248
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r119518 r119633  
    422422    ASSERT(isValidThreadState(m_globalData));
    423423
     424#if ENABLE(OBJECT_MARK_LOGGING)
     425    double gcStartTime = WTF::currentTime();
     426#endif
     427
    424428    void* dummy;
    425429   
     
    485489        {
    486490            GCPHASE(VisitMachineRoots);
     491            MARK_LOG_ROOT(visitor, "C++ Stack");
    487492            visitor.append(machineThreadRoots);
    488493            visitor.donateAndDrain();
     
    490495        {
    491496            GCPHASE(VisitRegisterFileRoots);
     497            MARK_LOG_ROOT(visitor, "Register File");
    492498            visitor.append(registerFileRoots);
    493499            visitor.donateAndDrain();
     
    496502        {
    497503            GCPHASE(VisitScratchBufferRoots);
     504            MARK_LOG_ROOT(visitor, "Scratch Buffers");
    498505            visitor.append(scratchBufferRoots);
    499506            visitor.donateAndDrain();
     
    502509        {
    503510            GCPHASE(VisitProtectedObjects);
     511            MARK_LOG_ROOT(visitor, "Protected Objects");
    504512            markProtectedObjects(heapRootVisitor);
    505513            visitor.donateAndDrain();
     
    507515        {
    508516            GCPHASE(VisitTempSortVectors);
     517            MARK_LOG_ROOT(visitor, "Temp Sort Vectors");
    509518            markTempSortVectors(heapRootVisitor);
    510519            visitor.donateAndDrain();
     
    514523            GCPHASE(MarkingArgumentBuffers);
    515524            if (m_markListSet && m_markListSet->size()) {
     525                MARK_LOG_ROOT(visitor, "Argument Buffers");
    516526                MarkedArgumentBuffer::markLists(heapRootVisitor, *m_markListSet);
    517527                visitor.donateAndDrain();
     
    520530        if (m_globalData->exception) {
    521531            GCPHASE(MarkingException);
     532            MARK_LOG_ROOT(visitor, "Exceptions");
    522533            heapRootVisitor.visit(&m_globalData->exception);
    523534            visitor.donateAndDrain();
     
    526537        {
    527538            GCPHASE(VisitStrongHandles);
     539            MARK_LOG_ROOT(visitor, "Strong Handles");
    528540            m_handleSet.visitStrongHandles(heapRootVisitor);
    529541            visitor.donateAndDrain();
     
    532544        {
    533545            GCPHASE(HandleStack);
     546            MARK_LOG_ROOT(visitor, "Handle Stack");
    534547            m_handleStack.visit(heapRootVisitor);
    535548            visitor.donateAndDrain();
     
    538551        {
    539552            GCPHASE(TraceCodeBlocks);
     553            MARK_LOG_ROOT(visitor, "Trace Code Blocks");
    540554            m_dfgCodeBlocks.traceMarkedCodeBlocks(visitor);
    541555            visitor.donateAndDrain();
     
    554568    {
    555569        GCPHASE(VisitingLiveWeakHandles);
     570        MARK_LOG_ROOT(visitor, "Live Weak Handles");
    556571        while (true) {
    557572            m_objectSpace.visitWeakSets(heapRootVisitor);
     
    572587
    573588    visitor.doneCopying();
     589#if ENABLE(OBJECT_MARK_LOGGING)
     590    size_t visitCount = visitor.visitCount();
     591#if ENABLE(PARALLEL_GC)
     592    visitCount += m_sharedData.childVisitCount();
     593#endif
     594    MARK_LOG_MESSAGE2("\nNumber of live Objects after full GC %lu, took %.6f secs\n", visitCount, WTF::currentTime() - gcStartTime);
     595#endif
     596
    574597    visitor.reset();
    575598    m_sharedData.reset();
     599#if ENABLE(PARALLEL_GC)
     600    m_sharedData.resetChildren();
     601#endif
    576602    m_storageSpace.doneCopying();
    577603
  • trunk/Source/JavaScriptCore/heap/MarkStack.cpp

    r117013 r119633  
    3737#include "ScopeChain.h"
    3838#include "Structure.h"
     39#include "UString.h"
    3940#include "WriteBarrier.h"
    4041#include <wtf/DataLog.h>
     
    220221
    221222#if ENABLE(PARALLEL_GC)
    222 void MarkStackThreadSharedData::markingThreadMain()
     223void MarkStackThreadSharedData::resetChildren()
     224{
     225    for (unsigned i = 0; i < m_markingThreadsMarkStack.size(); ++i)
     226       m_markingThreadsMarkStack[i]->reset();
     227}   
     228
     229size_t MarkStackThreadSharedData::childVisitCount()
     230{       
     231    unsigned long result = 0;
     232    for (unsigned i = 0; i < m_markingThreadsMarkStack.size(); ++i)
     233        result += m_markingThreadsMarkStack[i]->visitCount();
     234    return result;
     235}
     236
     237void MarkStackThreadSharedData::markingThreadMain(SlotVisitor* slotVisitor)
    223238{
    224239    WTF::registerGCThread();
    225240    {
    226         SlotVisitor slotVisitor(*this);
    227         ParallelModeEnabler enabler(slotVisitor);
    228         slotVisitor.drainFromShared(SlotVisitor::SlaveDrain);
    229     }
    230 }
    231 
    232 void MarkStackThreadSharedData::markingThreadStartFunc(void* shared)
    233 {
    234     static_cast<MarkStackThreadSharedData*>(shared)->markingThreadMain();
     241        ParallelModeEnabler enabler(*slotVisitor);
     242        slotVisitor->drainFromShared(SlotVisitor::SlaveDrain);
     243    }
     244    delete slotVisitor;
     245}
     246
     247void MarkStackThreadSharedData::markingThreadStartFunc(void* myVisitor)
     248{               
     249    SlotVisitor* slotVisitor = static_cast<SlotVisitor*>(myVisitor);
     250
     251    slotVisitor->sharedData().markingThreadMain(slotVisitor);
    235252}
    236253#endif
     
    245262#if ENABLE(PARALLEL_GC)
    246263    for (unsigned i = 1; i < Options::numberOfGCMarkers; ++i) {
    247         m_markingThreads.append(createThread(markingThreadStartFunc, this, "JavaScriptCore::Marking"));
     264        SlotVisitor* slotVisitor = new SlotVisitor(*this);
     265        m_markingThreadsMarkStack.append(slotVisitor);
     266        m_markingThreads.append(createThread(markingThreadStartFunc, slotVisitor, "JavaScriptCore::Marking"));
    248267        ASSERT(m_markingThreads.last());
    249268    }
     
    277296    ASSERT(m_opaqueRoots.isEmpty());
    278297#endif
    279    
    280298    m_weakReferenceHarvesters.removeAll();
    281299}
  • trunk/Source/JavaScriptCore/heap/MarkStack.h

    r116822 r119633  
    3535#include "VTableSpectrum.h"
    3636#include "WeakReferenceHarvester.h"
     37#include <wtf/DataLog.h>
     38#include <wtf/Forward.h>
    3739#include <wtf/HashMap.h>
    3840#include <wtf/HashSet.h>
     
    4143#include <wtf/OSAllocator.h>
    4244#include <wtf/PageBlock.h>
     45#include <wtf/text/StringHash.h>
     46
     47#if ENABLE(OBJECT_MARK_LOGGING)
     48#define MARK_LOG_MESSAGE0(message) dataLog(message)
     49#define MARK_LOG_MESSAGE1(message, arg1) dataLog(message, arg1)
     50#define MARK_LOG_MESSAGE2(message, arg1, arg2) dataLog(message, arg1, arg2)
     51#define MARK_LOG_ROOT(visitor, rootName) \
     52    dataLog("\n%s: ", rootName); \
     53    (visitor).resetChildCount()
     54#define MARK_LOG_PARENT(visitor, parent) \
     55    dataLog("\n%p (%s): ", parent, parent->className() ? parent->className() : "unknown"); \
     56    (visitor).resetChildCount()
     57#define MARK_LOG_CHILD(visitor, child) \
     58    if ((visitor).childCount()) \
     59    dataLogString(", "); \
     60    dataLog("%p", child); \
     61    (visitor).incrementChildCount()
     62#else
     63#define MARK_LOG_MESSAGE0(message) do { } while (false)
     64#define MARK_LOG_MESSAGE1(message, arg1) do { } while (false)
     65#define MARK_LOG_MESSAGE2(message, arg1, arg2) do { } while (false)
     66#define MARK_LOG_ROOT(visitor, rootName) do { } while (false)
     67#define MARK_LOG_PARENT(visitor, parent) do { } while (false)
     68#define MARK_LOG_CHILD(visitor, child) do { } while (false)
     69#endif
    4370
    4471namespace JSC {
     
    172199       
    173200        void reset();
     201
     202#if ENABLE(PARALLEL_GC)
     203        void resetChildren();
     204        size_t childVisitCount();
     205        size_t childDupStrings();
     206#endif
    174207   
    175208    private:
     
    178211
    179212#if ENABLE(PARALLEL_GC)
    180         void markingThreadMain();
     213        void markingThreadMain(SlotVisitor*);
    181214        static void markingThreadStartFunc(void* heap);
    182215#endif
     
    188221       
    189222        Vector<ThreadIdentifier> m_markingThreads;
     223        Vector<MarkStack*> m_markingThreadsMarkStack;
    190224       
    191225        Mutex m_markingLock;
     
    222256        bool containsOpaqueRoot(void*);
    223257        int opaqueRootCount();
    224        
     258
     259        MarkStackThreadSharedData& sharedData() { return m_shared; }
    225260        bool isEmpty() { return m_stack.isEmpty(); }
    226261
     
    242277            m_shared.m_unconditionalFinalizers.addThreadSafe(unconditionalFinalizer);
    243278        }
     279
     280#if ENABLE(OBJECT_MARK_LOGGING)
     281        inline void resetChildCount() { m_logChildCount = 0; }
     282        inline unsigned childCount() { return m_logChildCount; }
     283        inline void incrementChildCount() { m_logChildCount++; }
     284#endif
    244285
    245286    protected:
     
    284325       
    285326        MarkStackThreadSharedData& m_shared;
     327
     328#if ENABLE(OBJECT_MARK_LOGGING)
     329        unsigned m_logChildCount;
     330#endif
    286331    };
    287332
  • trunk/Source/JavaScriptCore/runtime/JSArray.cpp

    r116828 r119633  
    13721372
    13731373    if (thisObject->m_storage) {
     1374        MARK_LOG_MESSAGE1("[%u]: ", thisObject->length());
     1375
    13741376        ArrayStorage* storage = thisObject->m_storage;
    13751377        void* baseStorage = storage->m_allocBase;
  • trunk/Source/JavaScriptCore/runtime/JSCell.cpp

    r116828 r119633  
    185185}
    186186
     187const char* JSCell::className()
     188{
     189    return classInfo()->className;
     190}
     191
    187192void JSCell::getPropertyNames(JSObject*, ExecState*, PropertyNameArray&, EnumerationMode)
    188193{
  • trunk/Source/JavaScriptCore/runtime/JSCell.h

    r117646 r119633  
    8585        void clearStructure() { m_structure.clear(); }
    8686
     87        const char* className();
     88
    8789        // Extracting the value.
    8890        JS_EXPORT_PRIVATE bool getString(ExecState* exec, UString&) const;
     
    198200    inline void JSCell::visitChildren(JSCell* cell, SlotVisitor& visitor)
    199201    {
     202        MARK_LOG_PARENT(visitor, cell);
     203
    200204        visitor.append(&cell->m_structure);
    201205    }
  • trunk/Source/JavaScriptCore/runtime/JSString.cpp

    r118616 r119633  
    5757    Base::visitChildren(thisObject, visitor);
    5858   
     59    MARK_LOG_MESSAGE1("[%u]: ", thisObject->length());
     60
     61#if ENABLE(OBJECT_MARK_LOGGING)
     62    if (!thisObject->isRope()) {
     63        WTF::StringImpl* ourImpl = thisObject->m_value.impl();
     64        if (ourImpl->is8Bit())
     65            MARK_LOG_MESSAGE1("[8 %p]", ourImpl->characters8());
     66        else
     67            MARK_LOG_MESSAGE1("[16 %p]", ourImpl->characters16());
     68    } else
     69        MARK_LOG_MESSAGE0("[rope]: ");
     70#endif
     71
    5972    if (thisObject->isRope())
    6073        static_cast<JSRopeString*>(thisObject)->visitFibers(visitor);
  • trunk/Source/JavaScriptCore/runtime/JSString.h

    r119016 r119633  
    6868        friend class SpecializedThunkJIT;
    6969        friend class JSRopeString;
     70        friend class SlotVisitor;
    7071        friend struct ThunkHelpers;
    7172
  • trunk/Source/JavaScriptCore/runtime/Structure.h

    r118555 r119633  
    383383        validate(cell);
    384384#endif
    385         m_visitCount++;
    386385        if (Heap::testAndSetMarked(cell) || !cell->structure())
    387386            return;
    388        
     387
     388        m_visitCount++;
     389       
     390        MARK_LOG_CHILD(*this, cell);
     391
    389392        // Should never attempt to mark something that is zapped.
    390393        ASSERT(!cell->isZapped());
  • trunk/Source/WTF/ChangeLog

    r119593 r119633  
     12012-06-06  Michael Saboff  <msaboff@apple.com>
     2
     3        ENH: Add Logging to GC Marking Phase
     4        https://bugs.webkit.org/show_bug.cgi?id=88364
     5
     6        Reviewed by Filip Pizlo.
     7
     8        * wtf/DataLog.cpp:
     9        (WTF::dataLogString): Additional method to support GC Mark logging.
     10        * wtf/DataLog.h:
     11        * wtf/Platform.h: New ENABLE_OBJECT_MARK_LOGGING flag macro.
     12
    1132012-06-06  Andy Wingo  <wingo@igalia.com>
    214
  • trunk/Source/WTF/wtf/DataLog.cpp

    r111778 r119633  
    9696}
    9797
     98void dataLogString(const char* str)
     99{
     100    fputs(str, dataFile());
     101}
     102
    98103} // namespace WTF
    99104
  • trunk/Source/WTF/wtf/DataLog.h

    r119157 r119633  
    3838WTF_EXPORT_PRIVATE void dataLogV(const char* format, va_list) WTF_ATTRIBUTE_PRINTF(1, 0);
    3939WTF_EXPORT_PRIVATE void dataLog(const char* format, ...) WTF_ATTRIBUTE_PRINTF(1, 2);
     40WTF_EXPORT_PRIVATE void dataLogString(const char*);
    4041
    4142} // namespace WTF
    4243
    4344using WTF::dataLog;
     45using WTF::dataLogString;
    4446
    4547#endif // DataLog_h
  • trunk/Source/WTF/wtf/Platform.h

    r119593 r119633  
    10731073#endif
    10741074
    1075 #if !defined(ENABLE_PARALLEL_GC) && (PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || PLATFORM(BLACKBERRY)) && ENABLE(COMPARE_AND_SWAP)
     1075#define ENABLE_OBJECT_MARK_LOGGING 0
     1076
     1077#if !defined(ENABLE_PARALLEL_GC) && !ENABLE(OBJECT_MARK_LOGGING) && (PLATFORM(MAC) || PLATFORM(IOS) || PLATFORM(QT) || PLATFORM(BLACKBERRY)) && ENABLE(COMPARE_AND_SWAP)
    10761078#define ENABLE_PARALLEL_GC 1
    10771079#endif
Note: See TracChangeset for help on using the changeset viewer.