Changeset 96738 in webkit for trunk/Source/JavaScriptCore/heap


Ignore:
Timestamp:
Oct 5, 2011, 12:07:18 PM (14 years ago)
Author:
[email protected]
Message:

Add rudimentary filtering to write barriers
https://bugs.webkit.org/show_bug.cgi?id=69392

Reviewed by Filip Pizlo.

../../../../Volumes/Data/git/WebKit/OpenSource/Source/JavaScriptCore:

Add approximate filtering for write barriers based on the
target's mark bit. Also add some macros to support dumping
GC phase timings.

  • dfg/DFGJITCodeGenerator.cpp:

(JSC::DFG::JITCodeGenerator::markCellCard):

  • heap/Heap.cpp:

(JSC::GCTimer::GCTimerScope::GCTimerScope):
(JSC::GCTimer::GCTimerScope::~GCTimerScope):
(JSC::Heap::markRoots):
(JSC::Heap::collect):

Add phase timing information.

  • heap/MarkedBlock.h:

(JSC::MarkedBlock::offsetOfMarks):
(JSC::MarkedBlock::gatherDirtyCells):

  • jit/JITPropertyAccess.cpp:

(JSC::JIT::emitWriteBarrier):

../../../../Volumes/Data/git/WebKit/OpenSource/Tools:

When we're recording gc phase times Heap.o picks up
some exit time destructors, so we'll just ignore Heap.o
in this check.

  • Scripts/check-for-exit-time-destructors:
Location:
trunk/Source/JavaScriptCore/heap
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r96432 r96738  
    4444static const size_t largeHeapSize = 16 * 1024 * 1024;
    4545static const size_t smallHeapSize = 512 * 1024;
     46
     47#if ENABLE(GC_LOGGING)
     48   
     49struct GCTimer {
     50    GCTimer(const char* name)
     51        : m_time(0)
     52        , m_min(100000000)
     53        , m_max(0)
     54        , m_count(0)
     55        , m_name(name)
     56    {
     57    }
     58    ~GCTimer()
     59    {
     60        printf("%s: %.2lfms (avg. %.2lf, min. %.2lf, max. %.2lf)\n", m_name, m_time * 1000, m_time * 1000 / m_count, m_min*1000, m_max*1000);
     61    }
     62    double m_time;
     63    double m_min;
     64    double m_max;
     65    size_t m_count;
     66    const char* m_name;
     67};
     68
     69struct GCTimerScope {
     70    GCTimerScope(GCTimer* timer)
     71        : m_timer(timer)
     72        , m_start(WTF::currentTime())
     73    {
     74    }
     75    ~GCTimerScope()
     76    {
     77        double delta = WTF::currentTime() - m_start;
     78        if (delta < m_timer->m_min)
     79            m_timer->m_min = delta;
     80        if (delta > m_timer->m_max)
     81            m_timer->m_max = delta;
     82        m_timer->m_count++;
     83        m_timer->m_time += delta;
     84    }
     85    GCTimer* m_timer;
     86    double m_start;
     87};
     88
     89#define GCPHASE(name) static GCTimer name##Timer(#name); GCTimerScope name##TimerScope(&name##Timer)
     90#define COND_GCPHASE(cond, name1, name2) static GCTimer name1##Timer(#name1); static GCTimer name2##Timer(#name2); GCTimerScope name1##CondTimerScope(cond ? &name1##Timer : &name2##Timer)
     91
     92#else
     93
     94#define GCPHASE(name) do { } while (false)
     95#define COND_GCPHASE(cond, name1, name2) do { } while (false)
     96
     97#endif
    4698
    4799static size_t heapSizeForHint(HeapSize heapSize)
     
    457509void Heap::markRoots(bool fullGC)
    458510{
     511    COND_GCPHASE(fullGC, MarkFullRoots, MarkYoungRoots);
    459512    UNUSED_PARAM(fullGC);
    460513    ASSERT(isValidThreadState(m_globalData));
     
    468521    // gathering uses the mark bits to determine whether a reference is valid.
    469522    ConservativeRoots machineThreadRoots(&m_objectSpace.blocks());
    470     m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy);
     523    {
     524        GCPHASE(GatherConservativeRoots);
     525        m_machineThreads.gatherConservativeRoots(machineThreadRoots, &dummy);
     526    }
    471527
    472528    ConservativeRoots registerFileRoots(&m_objectSpace.blocks());
    473529    m_jettisonedCodeBlocks.clearMarks();
    474     registerFile().gatherConservativeRoots(registerFileRoots, m_jettisonedCodeBlocks);
     530    {
     531        GCPHASE(GatherRegisterFileRoots);
     532        registerFile().gatherConservativeRoots(registerFileRoots, m_jettisonedCodeBlocks);
     533    }
    475534    m_jettisonedCodeBlocks.deleteUnmarkedCodeBlocks();
    476535#if ENABLE(GGC)
    477536    MarkedBlock::DirtyCellVector dirtyCells;
    478     if (!fullGC)
     537    if (!fullGC) {
     538        GCPHASE(GatheringDirtyCells);
    479539        m_objectSpace.gatherDirtyCells(dirtyCells);
    480     else
     540    } else
    481541#endif
     542    {
     543        GCPHASE(clearMarks);
    482544        clearMarks();
    483 
     545    }
    484546
    485547    SlotVisitor& visitor = m_slotVisitor;
     
    487549
    488550#if ENABLE(GGC)
    489     size_t dirtyCellCount = dirtyCells.size();
    490     for (size_t i = 0; i < dirtyCellCount; i++) {
    491         heapRootVisitor.visitChildren(dirtyCells[i]);
     551    if (size_t dirtyCellCount = dirtyCells.size()) {
     552        GCPHASE(VisitDirtyCells);
     553        for (size_t i = 0; i < dirtyCellCount; i++) {
     554            heapRootVisitor.visitChildren(dirtyCells[i]);
     555            visitor.drain();
     556        }
     557    }
     558#endif
     559
     560    {
     561        GCPHASE(VisitMachineRoots);
     562        visitor.append(machineThreadRoots);
    492563        visitor.drain();
    493564    }
    494 #endif
    495 
    496     visitor.append(machineThreadRoots);
    497     visitor.drain();
    498 
    499     visitor.append(registerFileRoots);
    500     visitor.drain();
    501 
    502     markProtectedObjects(heapRootVisitor);
    503     visitor.drain();
    504    
    505     markTempSortVectors(heapRootVisitor);
    506     visitor.drain();
    507 
    508     if (m_markListSet && m_markListSet->size())
    509         MarkedArgumentBuffer::markLists(heapRootVisitor, *m_markListSet);
    510     if (m_globalData->exception)
     565    {
     566        GCPHASE(VisitRegisterFileRoots);
     567        visitor.append(registerFileRoots);
     568        visitor.drain();
     569    }
     570    {
     571        GCPHASE(VisitProtectedObjects);
     572        markProtectedObjects(heapRootVisitor);
     573        visitor.drain();
     574    }
     575    {
     576        GCPHASE(VisitTempSortVectors);
     577        markTempSortVectors(heapRootVisitor);
     578        visitor.drain();
     579    }
     580
     581    {
     582        GCPHASE(MarkingArgumentBuffers);
     583        if (m_markListSet && m_markListSet->size()) {
     584            MarkedArgumentBuffer::markLists(heapRootVisitor, *m_markListSet);
     585            visitor.drain();
     586        }
     587    }
     588    if (m_globalData->exception) {
     589        GCPHASE(MarkingException);
    511590        heapRootVisitor.visit(&m_globalData->exception);
    512     visitor.drain();
    513 
    514     m_handleHeap.visitStrongHandles(heapRootVisitor);
    515     visitor.drain();
    516 
    517     m_handleStack.visit(heapRootVisitor);
    518     visitor.drain();
    519    
    520     m_jettisonedCodeBlocks.traceCodeBlocks(visitor);
    521     visitor.drain();
     591        visitor.drain();
     592    }
     593   
     594    {
     595        GCPHASE(VisitStrongHandles);
     596        m_handleHeap.visitStrongHandles(heapRootVisitor);
     597        visitor.drain();
     598    }
     599   
     600    {
     601        GCPHASE(HandleStack);
     602        m_handleStack.visit(heapRootVisitor);
     603        visitor.drain();
     604    }
     605   
     606    {
     607        GCPHASE(TraceCodeBlocks);
     608        m_jettisonedCodeBlocks.traceCodeBlocks(visitor);
     609        visitor.drain();
     610    }
    522611
    523612    // Weak handles must be marked last, because their owners use the set of
    524613    // opaque roots to determine reachability.
    525     int lastOpaqueRootCount;
    526     do {
    527         lastOpaqueRootCount = visitor.opaqueRootCount();
    528         m_handleHeap.visitWeakHandles(heapRootVisitor);
    529         visitor.drain();
    530     // If the set of opaque roots has grown, more weak handles may have become reachable.
    531     } while (lastOpaqueRootCount != visitor.opaqueRootCount());
    532 
     614    {
     615        GCPHASE(VisitingWeakHandles);
     616        int lastOpaqueRootCount;
     617        do {
     618            lastOpaqueRootCount = visitor.opaqueRootCount();
     619            m_handleHeap.visitWeakHandles(heapRootVisitor);
     620            visitor.drain();
     621            // If the set of opaque roots has grown, more weak handles may have become reachable.
     622        } while (lastOpaqueRootCount != visitor.opaqueRootCount());
     623    }
    533624    visitor.reset();
    534625
     
    598689void Heap::collect(SweepToggle sweepToggle)
    599690{
     691    GCPHASE(Collect);
    600692    ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable());
    601693    ASSERT(m_isSafeToCollect);
    602694    JAVASCRIPTCORE_GC_BEGIN();
     695#if ENABLE(GGC)
    603696    bool fullGC = sweepToggle == DoSweep;
    604697    if (!fullGC)
    605698        fullGC = (capacity() > 4 * m_lastFullGCSize); 
    606     canonicalizeCellLivenessData();
     699#else
     700    bool fullGC = true;
     701#endif
     702    {
     703        GCPHASE(Canonicalize);
     704        canonicalizeCellLivenessData();
     705    }
    607706
    608707    markRoots(fullGC);
    609708
    610     harvestWeakReferences();
    611     m_handleHeap.finalizeWeakHandles();
    612     m_globalData->smallStrings.finalizeSmallStrings();
     709    {
     710        GCPHASE(HarvestWeakReferences);
     711        harvestWeakReferences();
     712        m_handleHeap.finalizeWeakHandles();
     713        m_globalData->smallStrings.finalizeSmallStrings();
     714    }
    613715
    614716    JAVASCRIPTCORE_GC_MARKED();
    615    
    616     resetAllocator();
     717
     718    {
     719        GCPHASE(ResetAllocator);
     720        resetAllocator();
     721    }
    617722
    618723    if (sweepToggle == DoSweep) {
     724        GCPHASE(Sweeping);
    619725        sweep();
    620726        shrink();
     
    625731    // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size :
    626732    // new bytes allocated) proportion, and seems to work well in benchmarks.
    627     size_t proportionalBytes = 2 * size();
    628     if (fullGC)
    629         m_lastFullGCSize = proportionalBytes / 2;
    630    
    631     m_objectSpace.setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle));
     733    size_t newSize = size();
     734    size_t proportionalBytes = 2 * newSize;
     735    if (fullGC) {
     736        m_lastFullGCSize = newSize;
     737        m_objectSpace.setHighWaterMark(max(proportionalBytes, m_minBytesPerCycle));
     738    }
    632739    JAVASCRIPTCORE_GC_END();
    633740
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.h

    r96372 r96738  
    7070        // object the heap will commonly allocate is four words.
    7171        static const size_t atomSize = 4 * sizeof(void*);
     72        static const size_t atomShift = 5;
    7273        static const size_t blockSize = 16 * KB;
    7374        static const size_t blockMask = ~(blockSize - 1); // blockSize must be a power of two.
    7475
    7576        static const size_t atomsPerBlock = blockSize / atomSize; // ~0.4% overhead
     77        static const size_t atomMask = atomsPerBlock - 1;
    7678        static const int cardShift = 10; // This is log2 of bytes per card.
    7779        static const size_t bytesPerCard = 1 << cardShift;
     
    140142        {
    141143            return OBJECT_OFFSETOF(MarkedBlock, m_cards);
     144        }
     145
     146        static inline size_t offsetOfMarks()
     147        {
     148            return OBJECT_OFFSETOF(MarkedBlock, m_marks);
    142149        }
    143150
     
    312319void MarkedBlock::gatherDirtyCells(DirtyCellVector& dirtyCells)
    313320{
    314     COMPILE_ASSERT(m_cards.cardCount == cardCount, MarkedBlockCardCountsMatch);
     321    COMPILE_ASSERT((int)m_cards.cardCount == (int)cardCount, MarkedBlockCardCountsMatch);
    315322
    316323    ASSERT(m_state != New && m_state != FreeListed);
Note: See TracChangeset for help on using the changeset viewer.