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


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

Tidy up card walking logic
https://bugs.webkit.org/show_bug.cgi?id=69883

Reviewed by Gavin Barraclough.

Special case common cell sizes when walking a block's
cards.

  • heap/CardSet.h:

(JSC::::testAndClear):

  • heap/Heap.cpp:

(JSC::GCTimer::GCCounter::GCCounter):
(JSC::GCTimer::GCCounter::count):
(JSC::GCTimer::GCCounter::~GCCounter):
(JSC::Heap::markRoots):

  • heap/MarkStack.cpp:

(JSC::MarkStack::reset):

  • heap/MarkStack.h:

(JSC::MarkStack::visitCount):
(JSC::MarkStack::MarkStack):
(JSC::MarkStack::append):

  • heap/MarkedBlock.h:

(JSC::MarkedBlock::gatherDirtyCellsWithSize):
(JSC::MarkedBlock::gatherDirtyCells):

  • runtime/Structure.h:

(JSC::MarkStack::internalAppend):

Location:
trunk/Source/JavaScriptCore/heap
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/heap/CardSet.h

    r96372 r97203  
    4848    uint8_t& cardForAtom(const void*);
    4949    bool isCardMarked(size_t);
    50     void clearCard(size_t);
     50    bool testAndClear(size_t);
    5151
    5252private:
     
    7979}
    8080
    81 template <size_t cardSize, size_t blockSize> void CardSet<cardSize, blockSize>::clearCard(size_t i)
     81template <size_t cardSize, size_t blockSize> bool CardSet<cardSize, blockSize>::testAndClear(size_t i)
    8282{
    8383    ASSERT(i < cardCount);
     84    bool result = m_cards[i];
    8485    m_cards[i] = 0;
     86    return result;
    8587}
    8688
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r96760 r97203  
    4444static const size_t largeHeapSize = 16 * 1024 * 1024;
    4545static const size_t smallHeapSize = 512 * 1024;
    46 
     46#define ENABLE_GC_LOGGING 1
    4747#if ENABLE(GC_LOGGING)
    48    
     48#if COMPILER(CLANG)
     49#define DEFINE_GC_LOGGING_GLOBAL(type, name, arguments) \
     50_Pragma("clang diagnostic push") \
     51_Pragma("clang diagnostic ignored \"-Wglobal-constructors\"") \
     52_Pragma("clang diagnostic ignored \"-Wexit-time-destructors\"") \
     53static type name arguments; \
     54_Pragma("clang diagnostic pop")
     55#else
     56#define DEFINE_GC_LOGGING_GLOBAL(type, name, arguments) \
     57static type name arguments;
     58#endif // COMPILER(CLANG)
     59
    4960struct GCTimer {
    5061    GCTimer(const char* name)
     
    8798};
    8899
    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 
     100struct GCCounter {
     101    GCCounter(const char* name)
     102        : m_name(name)
     103        , m_count(0)
     104        , m_total(0)
     105        , m_min(10000000)
     106        , m_max(0)
     107    {
     108    }
     109   
     110    void count(size_t amount)
     111    {
     112        m_count++;
     113        m_total += amount;
     114        if (amount < m_min)
     115            m_min = amount;
     116        if (amount > m_max)
     117            m_max = amount;
     118    }
     119    ~GCCounter()
     120    {
     121        printf("%s: %zu values (avg. %zu, min. %zu, max. %zu)\n", m_name, m_total, m_total / m_count, m_min, m_max);
     122    }
     123    const char* m_name;
     124    size_t m_count;
     125    size_t m_total;
     126    size_t m_min;
     127    size_t m_max;
     128};
     129
     130#define GCPHASE(name) DEFINE_GC_LOGGING_GLOBAL(GCTimer, name##Timer, (#name)); GCTimerScope name##TimerScope(&name##Timer)
     131#define COND_GCPHASE(cond, name1, name2) DEFINE_GC_LOGGING_GLOBAL(GCTimer, name1##Timer, (#name1)); DEFINE_GC_LOGGING_GLOBAL(GCTimer, name2##Timer, (#name2)); GCTimerScope name1##CondTimerScope(cond ? &name1##Timer : &name2##Timer)
     132#define GCCOUNTER(name, value) do { DEFINE_GC_LOGGING_GLOBAL(GCCounter, name##Counter, (#name)); name##Counter.count(value); } while (false)
     133   
    92134#else
    93135
    94136#define GCPHASE(name) do { } while (false)
    95137#define COND_GCPHASE(cond, name1, name2) do { } while (false)
    96 
     138#define GCCOUNTER(name, value) do { } while (false)
    97139#endif
    98140
     
    549591
    550592#if ENABLE(GGC)
    551     if (size_t dirtyCellCount = dirtyCells.size()) {
     593    {
     594        size_t dirtyCellCount = dirtyCells.size();
    552595        GCPHASE(VisitDirtyCells);
     596        GCCOUNTER(DirtyCellCount, dirtyCellCount);
    553597        for (size_t i = 0; i < dirtyCellCount; i++) {
    554598            heapRootVisitor.visitChildren(dirtyCells[i]);
     
    622666        } while (lastOpaqueRootCount != visitor.opaqueRootCount());
    623667    }
     668    GCCOUNTER(VisitedValueCount, visitor.visitCount());
    624669    visitor.reset();
    625670
  • trunk/Source/JavaScriptCore/heap/MarkStack.cpp

    r96372 r97203  
    3939void MarkStack::reset()
    4040{
     41    m_visitCount = 0;
    4142    m_values.shrinkAllocation(pageSize());
    4243    m_markSets.shrinkAllocation(pageSize());
  • trunk/Source/JavaScriptCore/heap/MarkStack.h

    r95901 r97203  
    104104        void reset();
    105105
     106        size_t visitCount() const { return m_visitCount; }
     107
    106108#if ENABLE(SIMPLE_HEAP_PROFILING)
    107109        VTableSpectrum m_visitedTypeCounts;
     
    140142        bool m_isDraining;
    141143#endif
     144    protected:
     145        size_t m_visitCount;
    142146    };
    143147
     
    149153        , m_isDraining(false)
    150154#endif
     155        , m_visitCount(0)
    151156    {
    152157    }
     
    265270        if (!count)
    266271            return;
     272        m_visitCount += count;
    267273#if ENABLE(GC_VALIDATION)
    268274        validateSet(slot, count);
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.h

    r96738 r97203  
    7676        static const size_t atomsPerBlock = blockSize / atomSize; // ~0.4% overhead
    7777        static const size_t atomMask = atomsPerBlock - 1;
    78         static const int cardShift = 10; // This is log2 of bytes per card.
     78        static const int cardShift = 8; // This is log2 of bytes per card.
    7979        static const size_t bytesPerCard = 1 << cardShift;
    8080        static const int cardCount = blockSize / bytesPerCard;
     
    151151        typedef Vector<JSCell*, 32> DirtyCellVector;
    152152        inline void gatherDirtyCells(DirtyCellVector&);
     153        template <int size> inline void gatherDirtyCellsWithSize(DirtyCellVector&);
    153154#endif
    154155
     
    317318
    318319#if ENABLE(GGC)
     320template <int _cellSize> void MarkedBlock::gatherDirtyCellsWithSize(DirtyCellVector& dirtyCells)
     321{
     322    if (m_cards.testAndClear(0)) {
     323        char* ptr = reinterpret_cast<char*>(&atoms()[firstAtom()]);
     324        const char* end = reinterpret_cast<char*>(this) + bytesPerCard;
     325        while (ptr < end) {
     326            JSCell* cell = reinterpret_cast<JSCell*>(ptr);
     327            if (isMarked(cell))
     328                dirtyCells.append(cell);
     329            ptr += _cellSize;
     330        }
     331    }
     332   
     333    const size_t cellOffset = firstAtom() * atomSize % _cellSize;
     334    for (size_t i = 1; i < m_cards.cardCount; i++) {
     335        if (!m_cards.testAndClear(i))
     336            continue;
     337        char* ptr = reinterpret_cast<char*>(this) + i * bytesPerCard + cellOffset;
     338        char* end = reinterpret_cast<char*>(this) + (i + 1) * bytesPerCard;
     339       
     340        while (ptr < end) {
     341            JSCell* cell = reinterpret_cast<JSCell*>(ptr);
     342            if (isMarked(cell))
     343                dirtyCells.append(cell);
     344            ptr += _cellSize;
     345        }
     346    }
     347}
     348
    319349void MarkedBlock::gatherDirtyCells(DirtyCellVector& dirtyCells)
    320350{
     
    331361   
    332362    size_t cellSize = this->cellSize();
     363    if (cellSize == 32) {
     364        gatherDirtyCellsWithSize<32>(dirtyCells);
     365        return;
     366    }
     367    if (cellSize == 64) {
     368        gatherDirtyCellsWithSize<64>(dirtyCells);
     369        return;
     370    }
     371
    333372    const size_t firstCellOffset = firstAtom() * atomSize % cellSize;
    334373   
    335     for (size_t i = 0; i < m_cards.cardCount; i++) {
    336         if (!m_cards.isCardMarked(i))
    337             continue;
    338         char* ptr = reinterpret_cast<char*>(this);
    339         if (i)
    340             ptr += firstCellOffset + cellSize * ((i * bytesPerCard + cellSize - 1 - firstCellOffset) / cellSize);
    341         else
    342             ptr += firstAtom() * atomSize;
    343         char* end = reinterpret_cast<char*>(this) + std::min((i + 1) * bytesPerCard, m_endAtom * atomSize);
    344        
     374    if (m_cards.testAndClear(0)) {
     375        char* ptr = reinterpret_cast<char*>(this) + firstAtom() * atomSize;
     376        char* end = reinterpret_cast<char*>(this) + bytesPerCard;
    345377        while (ptr < end) {
    346378            JSCell* cell = reinterpret_cast<JSCell*>(ptr);
    347             ASSERT(*addressOfCardFor(cell));
    348379            if (isMarked(cell))
    349380                dirtyCells.append(cell);
    350381            ptr += cellSize;
    351382        }
    352         m_cards.clearCard(i);
     383    }
     384    for (size_t i = 1; i < m_cards.cardCount; i++) {
     385        if (!m_cards.testAndClear(i))
     386            continue;
     387        char* ptr = reinterpret_cast<char*>(this) + firstCellOffset + cellSize * ((i * bytesPerCard + cellSize - 1 - firstCellOffset) / cellSize);
     388        char* end = reinterpret_cast<char*>(this) + std::min((i + 1) * bytesPerCard, m_endAtom * atomSize);
     389       
     390        while (ptr < end) {
     391            JSCell* cell = reinterpret_cast<JSCell*>(ptr);
     392            if (isMarked(cell))
     393                dirtyCells.append(cell);
     394            ptr += cellSize;
     395        }
    353396    }
    354397}
Note: See TracChangeset for help on using the changeset viewer.