Changeset 52176 in webkit for trunk/JavaScriptCore/runtime


Ignore:
Timestamp:
Dec 15, 2009, 2:40:00 PM (15 years ago)
Author:
[email protected]
Message:

Removed the number heap, replacing it with a one-item free list for
numbers, taking advantage of the fact that two number cells fit inside
the space for one regular cell, and number cells don't require destruction.

Reviewed by Oliver Hunt.

SunSpider says 1.6% faster in JSVALUE32 mode (the only mode that
heap-allocates numbers).

SunSpider says 1.1% faster in JSVALUE32_64 mode. v8 says 0.8% faster
in JSVALUE32_64 mode. 10% speedup on bench-alloc-nonretained.js. 6%
speedup on bench-alloc-retained.js.

There's a lot of formulaic change in this patch, but not much substance.

(JSC::Debugger::recompileAllJSFunctions):

  • runtime/Collector.cpp:

(JSC::Heap::Heap):
(JSC::Heap::destroy):
(JSC::Heap::allocateBlock):
(JSC::Heap::freeBlock):
(JSC::Heap::freeBlockPtr):
(JSC::Heap::freeBlocks):
(JSC::Heap::recordExtraCost):
(JSC::Heap::allocate):
(JSC::Heap::resizeBlocks):
(JSC::Heap::growBlocks):
(JSC::Heap::shrinkBlocks):
(JSC::Heap::markConservatively):
(JSC::Heap::clearMarkBits):
(JSC::Heap::markedCells):
(JSC::Heap::sweep):
(JSC::Heap::markRoots):
(JSC::Heap::objectCount):
(JSC::Heap::addToStatistics):
(JSC::Heap::statistics):
(JSC::Heap::isBusy):
(JSC::Heap::reset):
(JSC::Heap::collectAllGarbage):
(JSC::Heap::primaryHeapBegin):
(JSC::Heap::primaryHeapEnd):

  • runtime/Collector.h:

(JSC::): Removed all code pertaining to the number heap, and changed all
heap template functions and classes to non-template functions and classes.

(JSC::Heap::allocateNumber): A new optimization to replace the number
heap: allocate half-sized number cells in pairs, returning the first
cell and caching the second cell for the next allocation.

  • runtime/CollectorHeapIterator.h:

(JSC::LiveObjectIterator::LiveObjectIterator):
(JSC::LiveObjectIterator::operator++):
(JSC::DeadObjectIterator::DeadObjectIterator):
(JSC::DeadObjectIterator::operator++):
(JSC::ObjectIterator::ObjectIterator):
(JSC::ObjectIterator::operator++):

  • runtime/JSCell.h:

(JSC::JSCell::isNumber): Removed all code pertaining to the number heap,
and changed all heap template functions and classes to non-template functions
and classes.

Location:
trunk/JavaScriptCore/runtime
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/JavaScriptCore/runtime/Collector.cpp

    r52090 r52176  
    170170#endif // PLATFORM(SYMBIAN)
    171171   
    172     memset(&primaryHeap, 0, sizeof(CollectorHeap));
    173     allocateBlock<PrimaryHeap>();
    174 
    175     memset(&numberHeap, 0, sizeof(CollectorHeap));
    176 #if USE(JSVALUE32)
    177     allocateBlock<NumberHeap>();
    178 #endif
     172    memset(&m_heap, 0, sizeof(CollectorHeap));
     173    allocateBlock();
    179174}
    180175
     
    199194    m_markListSet = 0;
    200195
    201     freeBlocks<PrimaryHeap>();
    202     freeBlocks<NumberHeap>();
     196    freeBlocks();
    203197
    204198#if ENABLE(JSC_MULTIPLE_THREADS)
     
    219213}
    220214
    221 template <HeapType heapType>
    222215NEVER_INLINE CollectorBlock* Heap::allocateBlock()
    223216{
     
    274267    CollectorBlock* block = reinterpret_cast<CollectorBlock*>(address);
    275268    block->heap = this;
    276     block->type = heapType;
    277     clearMarkBits<heapType>(block);
    278 
    279     // heapAllocate assumes that it's safe to call a destructor on any cell in the primary heap.
    280     if (heapType != NumberHeap) {
    281         Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get();
    282         for (size_t i = 0; i < HeapConstants<heapType>::cellsPerBlock; ++i)
    283             new (block->cells + i) JSCell(dummyMarkableCellStructure);
    284     }
     269    clearMarkBits(block);
     270
     271    Structure* dummyMarkableCellStructure = m_globalData->dummyMarkableCellStructure.get();
     272    for (size_t i = 0; i < HeapConstants::cellsPerBlock; ++i)
     273        new (block->cells + i) JSCell(dummyMarkableCellStructure);
    285274   
    286275    // Add block to blocks vector.
    287276
    288     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    289     size_t numBlocks = heap.numBlocks;
    290     if (heap.usedBlocks == numBlocks) {
     277    size_t numBlocks = m_heap.numBlocks;
     278    if (m_heap.usedBlocks == numBlocks) {
    291279        static const size_t maxNumBlocks = ULONG_MAX / sizeof(CollectorBlock*) / GROWTH_FACTOR;
    292280        if (numBlocks > maxNumBlocks)
    293281            CRASH();
    294282        numBlocks = max(MIN_ARRAY_SIZE, numBlocks * GROWTH_FACTOR);
    295         heap.numBlocks = numBlocks;
    296         heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, numBlocks * sizeof(CollectorBlock*)));
    297     }
    298     heap.blocks[heap.usedBlocks++] = block;
     283        m_heap.numBlocks = numBlocks;
     284        m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, numBlocks * sizeof(CollectorBlock*)));
     285    }
     286    m_heap.blocks[m_heap.usedBlocks++] = block;
    299287
    300288    return block;
    301289}
    302290
    303 template <HeapType heapType>
    304291NEVER_INLINE void Heap::freeBlock(size_t block)
    305292{
    306     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    307 
    308     if (heapType != NumberHeap) {
    309         ObjectIterator<heapType> it(heap, block);
    310         ObjectIterator<heapType> end(heap, block + 1);
    311         for ( ; it != end; ++it)
    312             (*it)->~JSCell();
    313     }
    314     freeBlock(heap.blocks[block]);
     293    ObjectIterator it(m_heap, block);
     294    ObjectIterator end(m_heap, block + 1);
     295    for ( ; it != end; ++it)
     296        (*it)->~JSCell();
     297    freeBlockPtr(m_heap.blocks[block]);
    315298
    316299    // swap with the last block so we compact as we go
    317     heap.blocks[block] = heap.blocks[heap.usedBlocks - 1];
    318     heap.usedBlocks--;
    319 
    320     if (heap.numBlocks > MIN_ARRAY_SIZE && heap.usedBlocks < heap.numBlocks / LOW_WATER_FACTOR) {
    321         heap.numBlocks = heap.numBlocks / GROWTH_FACTOR;
    322         heap.blocks = static_cast<CollectorBlock**>(fastRealloc(heap.blocks, heap.numBlocks * sizeof(CollectorBlock*)));
    323     }
    324 }
    325 
    326 NEVER_INLINE void Heap::freeBlock(CollectorBlock* block)
     300    m_heap.blocks[block] = m_heap.blocks[m_heap.usedBlocks - 1];
     301    m_heap.usedBlocks--;
     302
     303    if (m_heap.numBlocks > MIN_ARRAY_SIZE && m_heap.usedBlocks < m_heap.numBlocks / LOW_WATER_FACTOR) {
     304        m_heap.numBlocks = m_heap.numBlocks / GROWTH_FACTOR;
     305        m_heap.blocks = static_cast<CollectorBlock**>(fastRealloc(m_heap.blocks, m_heap.numBlocks * sizeof(CollectorBlock*)));
     306    }
     307}
     308
     309NEVER_INLINE void Heap::freeBlockPtr(CollectorBlock* block)
    327310{
    328311#if PLATFORM(DARWIN)   
     
    345328}
    346329
    347 template <HeapType heapType>
    348330void Heap::freeBlocks()
    349331{
    350     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    351 
    352     while (heap.usedBlocks)
    353         freeBlock<heapType>(0);
    354     fastFree(heap.blocks);
    355     memset(&heap, 0, sizeof(CollectorHeap));
     332    while (m_heap.usedBlocks)
     333        freeBlock(0);
     334    fastFree(m_heap.blocks);
     335    memset(&m_heap, 0, sizeof(CollectorHeap));
    356336}
    357337
     
    368348    // if a large value survives one garbage collection, there is not much point to
    369349    // collecting more frequently as long as it stays alive.
    370     // NOTE: we target the primaryHeap unconditionally as JSNumber doesn't modify cost
    371 
    372     if (primaryHeap.extraCost > maxExtraCost && primaryHeap.extraCost > primaryHeap.usedBlocks * BLOCK_SIZE / 2) {
     350
     351    if (m_heap.extraCost > maxExtraCost && m_heap.extraCost > m_heap.usedBlocks * BLOCK_SIZE / 2) {
    373352        // If the last iteration through the heap deallocated blocks, we need
    374353        // to clean up remaining garbage before marking. Otherwise, the conservative
    375354        // marking mechanism might follow a pointer to unmapped memory.
    376         if (primaryHeap.didShrink)
    377             sweep<PrimaryHeap>();
     355        if (m_heap.didShrink)
     356            sweep();
    378357        reset();
    379358    }
    380     primaryHeap.extraCost += cost;
    381 }
    382 
    383 template <HeapType heapType> ALWAYS_INLINE void* Heap::heapAllocate(size_t s)
    384 {
    385     typedef typename HeapConstants<heapType>::Block Block;
    386     typedef typename HeapConstants<heapType>::Cell Cell;
     359    m_heap.extraCost += cost;
     360}
     361
     362void* Heap::allocate(size_t s)
     363{
     364    typedef HeapConstants::Block Block;
     365    typedef HeapConstants::Cell Cell;
    387366   
    388     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    389 
    390367    ASSERT(JSLock::lockCount() > 0);
    391368    ASSERT(JSLock::currentThreadIsHoldingLock());
    392     ASSERT_UNUSED(s, s <= HeapConstants<heapType>::cellSize);
    393 
    394     ASSERT(heap.operationInProgress == NoOperation);
    395     ASSERT(heapType == PrimaryHeap || heap.extraCost == 0);
     369    ASSERT_UNUSED(s, s <= HeapConstants::cellSize);
     370
     371    ASSERT(m_heap.operationInProgress == NoOperation);
    396372
    397373#if COLLECT_ON_EVERY_ALLOCATION
    398374    collectAllGarbage();
    399     ASSERT(heap.operationInProgress == NoOperation);
     375    ASSERT(m_heap.operationInProgress == NoOperation);
    400376#endif
    401377
     
    405381
    406382    do {
    407         ASSERT(heap.nextBlock < heap.usedBlocks);
    408         Block* block = reinterpret_cast<Block*>(heap.blocks[heap.nextBlock]);
     383        ASSERT(m_heap.nextBlock < m_heap.usedBlocks);
     384        Block* block = reinterpret_cast<Block*>(m_heap.blocks[m_heap.nextBlock]);
    409385        do {
    410             ASSERT(heap.nextCell < HeapConstants<heapType>::cellsPerBlock);
    411             if (!block->marked.get(heap.nextCell >> HeapConstants<heapType>::bitmapShift)) { // Always false for the last cell in the block
    412                 Cell* cell = block->cells + heap.nextCell;
    413                 if (heapType != NumberHeap) {
    414                     heap.operationInProgress = Allocation;
    415                     JSCell* imp = reinterpret_cast<JSCell*>(cell);
    416                     imp->~JSCell();
    417                     heap.operationInProgress = NoOperation;
    418                 }
    419                 ++heap.nextCell;
     386            ASSERT(m_heap.nextCell < HeapConstants::cellsPerBlock);
     387            if (!block->marked.get(m_heap.nextCell)) { // Always false for the last cell in the block
     388                Cell* cell = block->cells + m_heap.nextCell;
     389
     390                m_heap.operationInProgress = Allocation;
     391                JSCell* imp = reinterpret_cast<JSCell*>(cell);
     392                imp->~JSCell();
     393                m_heap.operationInProgress = NoOperation;
     394
     395                ++m_heap.nextCell;
    420396                return cell;
    421397            }
    422         } while (++heap.nextCell != HeapConstants<heapType>::cellsPerBlock);
    423         heap.nextCell = 0;
    424     } while (++heap.nextBlock != heap.usedBlocks);
     398        } while (++m_heap.nextCell != HeapConstants::cellsPerBlock);
     399        m_heap.nextCell = 0;
     400    } while (++m_heap.nextBlock != m_heap.usedBlocks);
    425401
    426402    // Slow case: reached the end of the heap. Mark live objects and start over.
     
    430406}
    431407
    432 template <HeapType heapType>
    433408void Heap::resizeBlocks()
    434409{
    435     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    436 
    437     heap.didShrink = false;
    438 
    439     size_t usedCellCount = markedCells<heapType>();
     410    m_heap.didShrink = false;
     411
     412    size_t usedCellCount = markedCells();
    440413    size_t minCellCount = usedCellCount + max(ALLOCATIONS_PER_COLLECTION, usedCellCount);
    441     size_t minBlockCount = (minCellCount + HeapConstants<heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock;
     414    size_t minBlockCount = (minCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock;
    442415
    443416    size_t maxCellCount = 1.25f * minCellCount;
    444     size_t maxBlockCount = (maxCellCount + HeapConstants<heapType>::cellsPerBlock - 1) / HeapConstants<heapType>::cellsPerBlock;
    445 
    446     if (heap.usedBlocks < minBlockCount)
    447         growBlocks<heapType>(minBlockCount);
    448     else if (heap.usedBlocks > maxBlockCount)
    449         shrinkBlocks<heapType>(maxBlockCount);
    450 }
    451 
    452 template <HeapType heapType>
     417    size_t maxBlockCount = (maxCellCount + HeapConstants::cellsPerBlock - 1) / HeapConstants::cellsPerBlock;
     418
     419    if (m_heap.usedBlocks < minBlockCount)
     420        growBlocks(minBlockCount);
     421    else if (m_heap.usedBlocks > maxBlockCount)
     422        shrinkBlocks(maxBlockCount);
     423}
     424
    453425void Heap::growBlocks(size_t neededBlocks)
    454426{
    455     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    456     ASSERT(heap.usedBlocks < neededBlocks);
    457     while (heap.usedBlocks < neededBlocks)
    458         allocateBlock<heapType>();
    459 }
    460 
    461 template <HeapType heapType>
     427    ASSERT(m_heap.usedBlocks < neededBlocks);
     428    while (m_heap.usedBlocks < neededBlocks)
     429        allocateBlock();
     430}
     431
    462432void Heap::shrinkBlocks(size_t neededBlocks)
    463433{
    464     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    465     ASSERT(heap.usedBlocks > neededBlocks);
     434    ASSERT(m_heap.usedBlocks > neededBlocks);
    466435   
    467436    // Clear the always-on last bit, so isEmpty() isn't fooled by it.
    468     for (size_t i = 0; i < heap.usedBlocks; ++i)
    469         heap.blocks[i]->marked.clear((HeapConstants<heapType>::cellsPerBlock - 1) >> HeapConstants<heapType>::bitmapShift);
    470 
    471     for (size_t i = 0; i != heap.usedBlocks && heap.usedBlocks != neededBlocks; ) {
    472         if (heap.blocks[i]->marked.isEmpty()) {
    473             freeBlock<heapType>(i);
    474             heap.didShrink = true;
     437    for (size_t i = 0; i < m_heap.usedBlocks; ++i)
     438        m_heap.blocks[i]->marked.clear(HeapConstants::cellsPerBlock - 1);
     439
     440    for (size_t i = 0; i != m_heap.usedBlocks && m_heap.usedBlocks != neededBlocks; ) {
     441        if (m_heap.blocks[i]->marked.isEmpty()) {
     442            freeBlock(i);
     443            m_heap.didShrink = true;
    475444        } else
    476445            ++i;
     
    478447
    479448    // Reset the always-on last bit.
    480     for (size_t i = 0; i < heap.usedBlocks; ++i)
    481         heap.blocks[i]->marked.set((HeapConstants<heapType>::cellsPerBlock - 1) >> HeapConstants<heapType>::bitmapShift);
    482 }
    483 
    484 void* Heap::allocate(size_t s)
    485 {
    486     return heapAllocate<PrimaryHeap>(s);
    487 }
    488 
    489 void* Heap::allocateNumber(size_t s)
    490 {
    491     return heapAllocate<NumberHeap>(s);
     449    for (size_t i = 0; i < m_heap.usedBlocks; ++i)
     450        m_heap.blocks[i]->marked.set(HeapConstants::cellsPerBlock - 1);
    492451}
    493452
     
    765724    return isCellAligned(p) && p;
    766725}
    767 #endif
     726#endif // USE(JSVALUE32)
    768727
    769728void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
     
    782741    char** e = static_cast<char**>(end);
    783742
    784     CollectorBlock** primaryBlocks = primaryHeap.blocks;
    785 #if USE(JSVALUE32)
    786     CollectorBlock** numberBlocks = numberHeap.blocks;
    787 #endif
    788 
     743    CollectorBlock** blocks = m_heap.blocks;
    789744    while (p != e) {
    790745        char* x = *p++;
    791746        if (isPossibleCell(x)) {
    792             size_t usedPrimaryBlocks;
     747            size_t usedBlocks;
    793748            uintptr_t xAsBits = reinterpret_cast<uintptr_t>(x);
    794749            xAsBits &= CELL_ALIGN_MASK;
     
    800755
    801756            CollectorBlock* blockAddr = reinterpret_cast<CollectorBlock*>(xAsBits - offset);
    802 #if USE(JSVALUE32)
    803             // Mark the the number heap, we can mark these Cells directly to avoid the virtual call cost
    804             size_t usedNumberBlocks = numberHeap.usedBlocks;
    805             for (size_t block = 0; block < usedNumberBlocks; block++) {
    806                 if (numberBlocks[block] != blockAddr)
    807                     continue;
    808                 Heap::markCell(reinterpret_cast<JSCell*>(xAsBits));
    809                 goto endMarkLoop;
    810             }
    811 #endif
    812 
    813             // Mark the primary heap
    814             usedPrimaryBlocks = primaryHeap.usedBlocks;
    815             for (size_t block = 0; block < usedPrimaryBlocks; block++) {
    816                 if (primaryBlocks[block] != blockAddr)
     757            usedBlocks = m_heap.usedBlocks;
     758            for (size_t block = 0; block < usedBlocks; block++) {
     759                if (blocks[block] != blockAddr)
    817760                    continue;
    818761                markStack.append(reinterpret_cast<JSCell*>(xAsBits));
    819762                markStack.drain();
    820763            }
    821 #if USE(JSVALUE32)
    822         endMarkLoop:
    823             ;
    824 #endif
    825764        }
    826765    }
     
    10641003}
    10651004
    1066 template <HeapType heapType>
    10671005void Heap::clearMarkBits()
    10681006{
    1069     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    1070     for (size_t i = 0; i < heap.usedBlocks; ++i)
    1071         clearMarkBits<heapType>(heap.blocks[i]);
    1072 }
    1073 
    1074 template <HeapType heapType>
     1007    for (size_t i = 0; i < m_heap.usedBlocks; ++i)
     1008        clearMarkBits(m_heap.blocks[i]);
     1009}
     1010
    10751011void Heap::clearMarkBits(CollectorBlock* block)
    10761012{
    1077     // heapAllocate assumes that the last cell in every block is marked.
     1013    // allocate assumes that the last cell in every block is marked.
    10781014    block->marked.clearAll();
    1079     block->marked.set((HeapConstants<heapType>::cellsPerBlock - 1) >> HeapConstants<heapType>::bitmapShift);
    1080 }
    1081 
    1082 template <HeapType heapType>
     1015    block->marked.set(HeapConstants::cellsPerBlock - 1);
     1016}
     1017
    10831018size_t Heap::markedCells(size_t startBlock, size_t startCell) const
    10841019{
    1085     const CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    1086     ASSERT(startBlock <= heap.usedBlocks);
    1087     ASSERT(startCell < HeapConstants<heapType>::cellsPerBlock);
    1088 
    1089     if (startBlock >= heap.usedBlocks)
     1020    ASSERT(startBlock <= m_heap.usedBlocks);
     1021    ASSERT(startCell < HeapConstants::cellsPerBlock);
     1022
     1023    if (startBlock >= m_heap.usedBlocks)
    10901024        return 0;
    10911025
    10921026    size_t result = 0;
    1093     result += heap.blocks[startBlock]->marked.count(startCell);
    1094     for (size_t i = startBlock + 1; i < heap.usedBlocks; ++i)
    1095         result += heap.blocks[i]->marked.count();
     1027    result += m_heap.blocks[startBlock]->marked.count(startCell);
     1028    for (size_t i = startBlock + 1; i < m_heap.usedBlocks; ++i)
     1029        result += m_heap.blocks[i]->marked.count();
    10961030
    10971031    return result;
    10981032}
    10991033
    1100 template <HeapType heapType>
    11011034void Heap::sweep()
    11021035{
    1103     ASSERT(heapType != NumberHeap); // The number heap does not contain meaningful destructors.
    1104 
    1105     CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    1106 
    1107     ASSERT(heap.operationInProgress == NoOperation);
    1108     if (heap.operationInProgress != NoOperation)
     1036    ASSERT(m_heap.operationInProgress == NoOperation);
     1037    if (m_heap.operationInProgress != NoOperation)
    11091038        CRASH();
    1110     heap.operationInProgress = Collection;
     1039    m_heap.operationInProgress = Collection;
    11111040   
    11121041#if !ENABLE(JSC_ZOMBIES)
     
    11141043#endif
    11151044
    1116     DeadObjectIterator<heapType> it(heap, heap.nextBlock, heap.nextCell);
    1117     DeadObjectIterator<heapType> end(heap, heap.usedBlocks);
     1045    DeadObjectIterator it(m_heap, m_heap.nextBlock, m_heap.nextCell);
     1046    DeadObjectIterator end(m_heap, m_heap.usedBlocks);
    11181047    for ( ; it != end; ++it) {
    11191048        JSCell* cell = *it;
     
    11321061    }
    11331062
    1134     heap.operationInProgress = NoOperation;
     1063    m_heap.operationInProgress = NoOperation;
    11351064}
    11361065
     
    11441073#endif
    11451074
    1146     ASSERT((primaryHeap.operationInProgress == NoOperation) & (numberHeap.operationInProgress == NoOperation));
    1147     if (!((primaryHeap.operationInProgress == NoOperation) & (numberHeap.operationInProgress == NoOperation)))
     1075    ASSERT(m_heap.operationInProgress == NoOperation);
     1076    if (m_heap.operationInProgress != NoOperation)
    11481077        CRASH();
    11491078
    1150     primaryHeap.operationInProgress = Collection;
    1151     numberHeap.operationInProgress = Collection;
     1079    m_heap.operationInProgress = Collection;
    11521080
    11531081    MarkStack& markStack = m_globalData->markStack;
    11541082
    11551083    // Reset mark bits.
    1156     clearMarkBits<PrimaryHeap>();
    1157     clearMarkBits<NumberHeap>();
     1084    clearMarkBits();
    11581085
    11591086    // Mark stack roots.
     
    11781105    markStack.compact();
    11791106
    1180     primaryHeap.operationInProgress = NoOperation;
    1181     numberHeap.operationInProgress = NoOperation;
     1107    m_heap.operationInProgress = NoOperation;
    11821108}
    11831109
    11841110size_t Heap::objectCount() const
    11851111{
    1186     return objectCount<PrimaryHeap>() + objectCount<NumberHeap>();
    1187 }
    1188 
    1189 template <HeapType heapType>
    1190 size_t Heap::objectCount() const
    1191 {
    1192     const CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    1193 
    1194     return heap.nextBlock * HeapConstants<heapType>::cellsPerBlock // allocated full blocks
    1195            + heap.nextCell // allocated cells in current block
    1196            + markedCells<heapType>(heap.nextBlock, heap.nextCell) // marked cells in remainder of heap
    1197            - heap.usedBlocks; // 1 cell per block is a dummy sentinel
    1198 }
    1199 
    1200 template <HeapType heapType>
     1112    return m_heap.nextBlock * HeapConstants::cellsPerBlock // allocated full blocks
     1113           + m_heap.nextCell // allocated cells in current block
     1114           + markedCells(m_heap.nextBlock, m_heap.nextCell) // marked cells in remainder of m_heap
     1115           - m_heap.usedBlocks; // 1 cell per block is a dummy sentinel
     1116}
     1117
    12011118void Heap::addToStatistics(Heap::Statistics& statistics) const
    12021119{
    1203     const CollectorHeap& heap = heapType == PrimaryHeap ? primaryHeap : numberHeap;
    1204 
    1205     statistics.size += heap.usedBlocks * BLOCK_SIZE;
    1206     statistics.free += heap.usedBlocks * BLOCK_SIZE - (objectCount<heapType>() * HeapConstants<heapType>::cellSize);
     1120    statistics.size += m_heap.usedBlocks * BLOCK_SIZE;
     1121    statistics.free += m_heap.usedBlocks * BLOCK_SIZE - (objectCount() * HeapConstants::cellSize);
    12071122}
    12081123
     
    12101125{
    12111126    Statistics statistics = { 0, 0 };
    1212     addToStatistics<PrimaryHeap>(statistics);
    1213     addToStatistics<NumberHeap>(statistics);
     1127    addToStatistics(statistics);
    12141128    return statistics;
    12151129}
     
    12801194bool Heap::isBusy()
    12811195{
    1282     return (primaryHeap.operationInProgress != NoOperation) | (numberHeap.operationInProgress != NoOperation);
     1196    return m_heap.operationInProgress != NoOperation;
    12831197}
    12841198
     
    12911205    JAVASCRIPTCORE_GC_MARKED();
    12921206
    1293     primaryHeap.nextCell = 0;
    1294     primaryHeap.nextBlock = 0;
    1295     primaryHeap.extraCost = 0;
     1207    m_heap.nextCell = 0;
     1208    m_heap.nextBlock = 0;
     1209    m_heap.nextNumber = 0;
     1210    m_heap.extraCost = 0;
    12961211#if ENABLE(JSC_ZOMBIES)
    1297     sweep<PrimaryHeap>();
    1298 #endif
    1299     resizeBlocks<PrimaryHeap>();
    1300 
    1301 #if USE(JSVALUE32)
    1302     numberHeap.nextCell = 0;
    1303     numberHeap.nextBlock = 0;
    1304     resizeBlocks<NumberHeap>();
    1305 #endif
     1212    sweep();
     1213#endif
     1214    resizeBlocks();
    13061215
    13071216    JAVASCRIPTCORE_GC_END();
     
    13151224    // to clean up remaining garbage before marking. Otherwise, the conservative
    13161225    // marking mechanism might follow a pointer to unmapped memory.
    1317     if (primaryHeap.didShrink)
    1318         sweep<PrimaryHeap>();
     1226    if (m_heap.didShrink)
     1227        sweep();
    13191228
    13201229    markRoots();
     
    13221231    JAVASCRIPTCORE_GC_MARKED();
    13231232
    1324     primaryHeap.nextCell = 0;
    1325     primaryHeap.nextBlock = 0;
    1326     primaryHeap.extraCost = 0;
    1327     sweep<PrimaryHeap>();
    1328     resizeBlocks<PrimaryHeap>();
    1329 
    1330 #if USE(JSVALUE32)
    1331     numberHeap.nextCell = 0;
    1332     numberHeap.nextBlock = 0;
    1333     resizeBlocks<NumberHeap>();
    1334 #endif
     1233    m_heap.nextCell = 0;
     1234    m_heap.nextBlock = 0;
     1235    m_heap.nextNumber = 0;
     1236    m_heap.extraCost = 0;
     1237    sweep();
     1238    resizeBlocks();
    13351239
    13361240    JAVASCRIPTCORE_GC_END();
    13371241}
    13381242
    1339 LiveObjectIterator<PrimaryHeap> Heap::primaryHeapBegin()
    1340 {
    1341     return LiveObjectIterator<PrimaryHeap>(primaryHeap, 0);
    1342 }
    1343 
    1344 LiveObjectIterator<PrimaryHeap> Heap::primaryHeapEnd()
    1345 {
    1346     return LiveObjectIterator<PrimaryHeap>(primaryHeap, primaryHeap.usedBlocks);
     1243LiveObjectIterator Heap::primaryHeapBegin()
     1244{
     1245    return LiveObjectIterator(m_heap, 0);
     1246}
     1247
     1248LiveObjectIterator Heap::primaryHeapEnd()
     1249{
     1250    return LiveObjectIterator(m_heap, m_heap.usedBlocks);
    13471251}
    13481252
  • trunk/JavaScriptCore/runtime/Collector.h

    r52082 r52176  
    4848
    4949    enum OperationInProgress { NoOperation, Allocation, Collection };
    50     enum HeapType { PrimaryHeap, NumberHeap };
    51 
    52     template <HeapType> class LiveObjectIterator;
     50
     51    class LiveObjectIterator;
    5352
    5453    struct CollectorHeap {
    5554        size_t nextBlock;
    5655        size_t nextCell;
    57 
    5856        CollectorBlock** blocks;
     57       
     58        void* nextNumber;
     59
    5960        size_t numBlocks;
    6061        size_t usedBlocks;
    6162
    6263        size_t extraCost;
    63        
    6464        bool didShrink;
    6565
     
    114114        static bool isNumber(JSCell*);
    115115       
    116         LiveObjectIterator<PrimaryHeap> primaryHeapBegin();
    117         LiveObjectIterator<PrimaryHeap> primaryHeapEnd();
     116        LiveObjectIterator primaryHeapBegin();
     117        LiveObjectIterator primaryHeapEnd();
    118118
    119119    private:
    120         template <HeapType heapType> void* heapAllocate(size_t);
    121120        void reset();
    122         void collectRemainingGarbage();
    123         template <HeapType heapType> void sweep();
     121        void sweep();
    124122        static CollectorBlock* cellBlock(const JSCell*);
    125123        static size_t cellOffset(const JSCell*);
     
    129127        ~Heap();
    130128
    131         template <HeapType heapType> NEVER_INLINE CollectorBlock* allocateBlock();
    132         template <HeapType heapType> NEVER_INLINE void freeBlock(size_t);
    133         NEVER_INLINE void freeBlock(CollectorBlock*);
    134         template <HeapType heapType> void freeBlocks();
    135         template <HeapType heapType> void resizeBlocks();
    136         template <HeapType heapType> void growBlocks(size_t neededBlocks);
    137         template <HeapType heapType> void shrinkBlocks(size_t neededBlocks);
    138         template <HeapType heapType> void clearMarkBits();
    139         template <HeapType heapType> void clearMarkBits(CollectorBlock*);
    140         template <HeapType heapType> size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const;
     129        NEVER_INLINE CollectorBlock* allocateBlock();
     130        NEVER_INLINE void freeBlock(size_t);
     131        NEVER_INLINE void freeBlockPtr(CollectorBlock*);
     132        void freeBlocks();
     133        void resizeBlocks();
     134        void growBlocks(size_t neededBlocks);
     135        void shrinkBlocks(size_t neededBlocks);
     136        void clearMarkBits();
     137        void clearMarkBits(CollectorBlock*);
     138        size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const;
    141139
    142140        void recordExtraCost(size_t);
    143141
    144         template <HeapType heapType> void addToStatistics(Statistics&) const;
    145         template <HeapType heapType> size_t objectCount() const;
     142        void addToStatistics(Statistics&) const;
    146143
    147144        void markRoots();
     
    154151        typedef HashCountedSet<JSCell*> ProtectCountSet;
    155152
    156         CollectorHeap primaryHeap;
    157         CollectorHeap numberHeap;
     153        CollectorHeap m_heap;
    158154
    159155        ProtectCountSet m_protectedValues;
     
    201197    const size_t CELL_MASK = CELL_SIZE - 1;
    202198    const size_t CELL_ALIGN_MASK = ~CELL_MASK;
    203     const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*) - sizeof(HeapType)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells.
     199    const size_t CELLS_PER_BLOCK = (BLOCK_SIZE - sizeof(Heap*)) * 8 * CELL_SIZE / (8 * CELL_SIZE + 1) / CELL_SIZE; // one bitmap byte can represent 8 cells.
    204200   
    205     const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK;
    206201    const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8;
    207202    const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t);
     
    237232    };
    238233
    239     struct SmallCollectorCell {
    240         double memory[CELL_ARRAY_LENGTH / 2];
    241     };
    242 
    243234    class CollectorBlock {
    244235    public:
     
    246237        CollectorBitmap marked;
    247238        Heap* heap;
    248         HeapType type;
    249     };
    250 
    251     class SmallCellCollectorBlock {
    252     public:
    253         SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK];
    254         CollectorBitmap marked;
    255         Heap* heap;
    256         HeapType type;
    257     };
    258    
    259     template <HeapType heapType> struct HeapConstants;
    260 
    261     template <> struct HeapConstants<PrimaryHeap> {
     239    };
     240
     241    struct HeapConstants {
    262242        static const size_t cellSize = CELL_SIZE;
    263243        static const size_t cellsPerBlock = CELLS_PER_BLOCK;
    264         static const size_t bitmapShift = 0;
    265244        typedef CollectorCell Cell;
    266245        typedef CollectorBlock Block;
    267246    };
    268247
    269     template <> struct HeapConstants<NumberHeap> {
    270         static const size_t cellSize = SMALL_CELL_SIZE;
    271         static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK;
    272         static const size_t bitmapShift = 1;
    273         typedef SmallCollectorCell Cell;
    274         typedef SmallCellCollectorBlock Block;
    275     };
    276 
    277248    inline CollectorBlock* Heap::cellBlock(const JSCell* cell)
    278249    {
    279250        return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK);
    280     }
    281 
    282     inline bool Heap::isNumber(JSCell* cell)
    283     {
    284         return Heap::cellBlock(cell)->type == NumberHeap;
    285251    }
    286252
     
    305271            recordExtraCost(cost);
    306272    }
     273   
     274    inline void* Heap::allocateNumber(size_t s)
     275    {
     276        if (void* result = m_heap.nextNumber) {
     277            m_heap.nextNumber = 0;
     278            return result;
     279        }
     280
     281        void* result = allocate(s);
     282        m_heap.nextNumber = static_cast<char*>(result) + (CELL_SIZE / 2);
     283        return result;
     284    }
    307285
    308286} // namespace JSC
  • trunk/JavaScriptCore/runtime/CollectorHeapIterator.h

    r52082 r52176  
    4646    };
    4747
    48     template <HeapType heapType>
    4948    class LiveObjectIterator : public CollectorHeapIterator {
    5049    public:
    5150        LiveObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
    52         LiveObjectIterator<heapType>& operator++();
     51        LiveObjectIterator& operator++();
    5352    };
    5453
    55     template <HeapType heapType>
    5654    class DeadObjectIterator : public CollectorHeapIterator {
    5755    public:
    5856        DeadObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
    59         DeadObjectIterator<heapType>& operator++();
     57        DeadObjectIterator& operator++();
    6058    };
    6159
    62     template <HeapType heapType>
    6360    class ObjectIterator : public CollectorHeapIterator {
    6461    public:
    6562        ObjectIterator(CollectorHeap&, size_t startBlock, size_t startCell = 0);
    66         ObjectIterator<heapType>& operator++();
     63        ObjectIterator& operator++();
    6764    };
    6865
     
    9390    }
    9491
    95     template <HeapType heapType>
    96     inline LiveObjectIterator<heapType>::LiveObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
     92    inline LiveObjectIterator::LiveObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
    9793        : CollectorHeapIterator(heap, startBlock, startCell - 1)
    9894    {
     
    10096    }
    10197
    102     template <HeapType heapType>
    103     inline LiveObjectIterator<heapType>& LiveObjectIterator<heapType>::operator++()
     98    inline LiveObjectIterator& LiveObjectIterator::operator++()
    10499    {
    105100        if (m_block < m_heap.nextBlock || m_cell < m_heap.nextCell) {
    106             advance(HeapConstants<heapType>::cellsPerBlock);
     101            advance(HeapConstants::cellsPerBlock);
    107102            return *this;
    108103        }
    109104
    110105        do {
    111             advance(HeapConstants<heapType>::cellsPerBlock);
     106            advance(HeapConstants::cellsPerBlock);
    112107        } while (m_block < m_heap.usedBlocks && !m_heap.blocks[m_block]->marked.get(m_cell));
    113108        return *this;
    114109    }
    115110
    116     template <HeapType heapType>
    117     inline DeadObjectIterator<heapType>::DeadObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
     111    inline DeadObjectIterator::DeadObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
    118112        : CollectorHeapIterator(heap, startBlock, startCell - 1)
    119113    {
     
    121115    }
    122116
    123     template <HeapType heapType>
    124     inline DeadObjectIterator<heapType>& DeadObjectIterator<heapType>::operator++()
     117    inline DeadObjectIterator& DeadObjectIterator::operator++()
    125118    {
    126119        do {
    127             advance(HeapConstants<heapType>::cellsPerBlock);
     120            advance(HeapConstants::cellsPerBlock);
    128121            ASSERT(m_block > m_heap.nextBlock || (m_block == m_heap.nextBlock && m_cell >= m_heap.nextCell));
    129122        } while (m_block < m_heap.usedBlocks && m_heap.blocks[m_block]->marked.get(m_cell));
     
    131124    }
    132125
    133     template <HeapType heapType>
    134     inline ObjectIterator<heapType>::ObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
     126    inline ObjectIterator::ObjectIterator(CollectorHeap& heap, size_t startBlock, size_t startCell)
    135127        : CollectorHeapIterator(heap, startBlock, startCell - 1)
    136128    {
     
    138130    }
    139131
    140     template <HeapType heapType>
    141     inline ObjectIterator<heapType>& ObjectIterator<heapType>::operator++()
     132    inline ObjectIterator& ObjectIterator::operator++()
    142133    {
    143         advance(HeapConstants<heapType>::cellsPerBlock);
     134        advance(HeapConstants::cellsPerBlock);
    144135        return *this;
    145136    }
  • trunk/JavaScriptCore/runtime/JSCell.h

    r52082 r52176  
    134134    inline bool JSCell::isNumber() const
    135135    {
    136         return Heap::isNumber(const_cast<JSCell*>(this));
     136        return m_structure->typeInfo().type() == NumberType;
    137137    }
    138138#endif
Note: See TracChangeset for help on using the changeset viewer.