Changeset 114698 in webkit


Ignore:
Timestamp:
Apr 19, 2012 5:05:37 PM (12 years ago)
Author:
mhahnenberg@apple.com
Message:

We're collecting pathologically due to small allocations
https://bugs.webkit.org/show_bug.cgi?id=84404

Reviewed by Geoffrey Garen.

No change in performance on run-jsc-benchmarks.

  • dfg/DFGSpeculativeJIT.h: Replacing m_firstFreeCell with m_freeList.

(JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):

  • heap/CopiedSpace.cpp: Getting rid of any water mark related stuff, since it's no

longer useful.
(JSC::CopiedSpace::CopiedSpace):
(JSC::CopiedSpace::tryAllocateSlowCase): We now only call didAllocate here rather than
carrying out a somewhat complicated accounting job for our old water mark throughout CopiedSpace.
(JSC::CopiedSpace::tryAllocateOversize): Call the new didAllocate to notify the Heap of
newly allocated stuff.
(JSC::CopiedSpace::tryReallocateOversize):
(JSC::CopiedSpace::doneFillingBlock):
(JSC::CopiedSpace::doneCopying):
(JSC::CopiedSpace::destroy):

  • heap/CopiedSpace.h:

(CopiedSpace):

  • heap/CopiedSpaceInlineMethods.h:

(JSC::CopiedSpace::startedCopying):

  • heap/Heap.cpp: Removed water mark related stuff, replaced with new bytesAllocated and

bytesAllocatedLimit to track how much memory has been allocated since the last collection.
(JSC::Heap::Heap):
(JSC::Heap::reportExtraMemoryCostSlowCase):
(JSC::Heap::collect): We now set the new limit of bytes that we can allocate before triggering
a collection to be the size of the Heap after the previous collection. Thus, we still have our
2x allocation amount.
(JSC::Heap::didAllocate): Notifies the GC activity timer of how many bytes have been allocated
thus far and then adds the new number of bytes to the current total.
(JSC):

  • heap/Heap.h: Removed water mark related stuff.

(JSC::Heap::notifyIsSafeToCollect):
(Heap):
(JSC::Heap::shouldCollect):
(JSC):

  • heap/MarkedAllocator.cpp:

(JSC::MarkedAllocator::tryAllocateHelper): Refactored to use MarkedBlock's new FreeList struct.
(JSC::MarkedAllocator::allocateSlowCase):
(JSC::MarkedAllocator::addBlock):

  • heap/MarkedAllocator.h:

(MarkedAllocator):
(JSC::MarkedAllocator::MarkedAllocator):
(JSC::MarkedAllocator::allocate):
(JSC::MarkedAllocator::zapFreeList): Refactored to take in a FreeList instead of a FreeCell.

  • heap/MarkedBlock.cpp:

(JSC::MarkedBlock::specializedSweep):
(JSC::MarkedBlock::sweep):
(JSC::MarkedBlock::sweepHelper):
(JSC::MarkedBlock::zapFreeList):

  • heap/MarkedBlock.h:

(FreeList): Added a new struct that keeps track of the current MarkedAllocator's
free list including the number of bytes of stuff in the free list so that when the free list is
exhausted, the correct amount can be reported to Heap.
(MarkedBlock):
(JSC::MarkedBlock::FreeList::FreeList):
(JSC):

  • heap/MarkedSpace.cpp: Removing all water mark related stuff.

(JSC::MarkedSpace::MarkedSpace):
(JSC::MarkedSpace::resetAllocators):

  • heap/MarkedSpace.h:

(MarkedSpace):
(JSC):

  • heap/WeakSet.cpp:

(JSC::WeakSet::findAllocator): Refactored to use the didAllocate interface with the Heap. This
function still needs work though now that the Heap knows how many bytes have been allocated
since the last collection.

  • jit/JITInlineMethods.h: Refactored to use MarkedBlock's new FreeList struct.

(JSC::JIT::emitAllocateBasicJSObject): Ditto.

  • llint/LowLevelInterpreter.asm: Ditto.
  • runtime/GCActivityCallback.cpp:

(JSC::DefaultGCActivityCallback::didAllocate):

  • runtime/GCActivityCallback.h:

(JSC::GCActivityCallback::didAllocate): Renamed willAllocate to didAllocate to indicate that
the allocation that is being reported has already taken place.
(DefaultGCActivityCallback):

  • runtime/GCActivityCallbackCF.cpp:

(JSC):
(JSC::DefaultGCActivityCallback::didAllocate): Refactored to return early if the amount of
allocation since the last collection is not above a threshold (initially arbitrarily chosen to
be 128KB).

Location:
trunk/Source/JavaScriptCore
Files:
19 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/JavaScriptCore/ChangeLog

    r114695 r114698  
     12012-04-19  Mark Hahnenberg  <mhahnenberg@apple.com>
     2
     3        We're collecting pathologically due to small allocations
     4        https://bugs.webkit.org/show_bug.cgi?id=84404
     5
     6        Reviewed by Geoffrey Garen.
     7
     8        No change in performance on run-jsc-benchmarks.
     9
     10        * dfg/DFGSpeculativeJIT.h: Replacing m_firstFreeCell with m_freeList.
     11        (JSC::DFG::SpeculativeJIT::emitAllocateBasicJSObject):
     12        * heap/CopiedSpace.cpp: Getting rid of any water mark related stuff, since it's no
     13        longer useful.
     14        (JSC::CopiedSpace::CopiedSpace):
     15        (JSC::CopiedSpace::tryAllocateSlowCase): We now only call didAllocate here rather than
     16        carrying out a somewhat complicated accounting job for our old water mark throughout CopiedSpace.
     17        (JSC::CopiedSpace::tryAllocateOversize):  Call the new didAllocate to notify the Heap of
     18        newly allocated stuff.
     19        (JSC::CopiedSpace::tryReallocateOversize):
     20        (JSC::CopiedSpace::doneFillingBlock):
     21        (JSC::CopiedSpace::doneCopying):
     22        (JSC::CopiedSpace::destroy):
     23        * heap/CopiedSpace.h:
     24        (CopiedSpace):
     25        * heap/CopiedSpaceInlineMethods.h:
     26        (JSC::CopiedSpace::startedCopying):
     27        * heap/Heap.cpp: Removed water mark related stuff, replaced with new bytesAllocated and
     28        bytesAllocatedLimit to track how much memory has been allocated since the last collection.
     29        (JSC::Heap::Heap):
     30        (JSC::Heap::reportExtraMemoryCostSlowCase):
     31        (JSC::Heap::collect): We now set the new limit of bytes that we can allocate before triggering
     32        a collection to be the size of the Heap after the previous collection. Thus, we still have our
     33        2x allocation amount.
     34        (JSC::Heap::didAllocate): Notifies the GC activity timer of how many bytes have been allocated
     35        thus far and then adds the new number of bytes to the current total.
     36        (JSC):
     37        * heap/Heap.h: Removed water mark related stuff.
     38        (JSC::Heap::notifyIsSafeToCollect):
     39        (Heap):
     40        (JSC::Heap::shouldCollect):
     41        (JSC):
     42        * heap/MarkedAllocator.cpp:
     43        (JSC::MarkedAllocator::tryAllocateHelper): Refactored to use MarkedBlock's new FreeList struct.
     44        (JSC::MarkedAllocator::allocateSlowCase):
     45        (JSC::MarkedAllocator::addBlock):
     46        * heap/MarkedAllocator.h:
     47        (MarkedAllocator):
     48        (JSC::MarkedAllocator::MarkedAllocator):
     49        (JSC::MarkedAllocator::allocate):
     50        (JSC::MarkedAllocator::zapFreeList): Refactored to take in a FreeList instead of a FreeCell.
     51        * heap/MarkedBlock.cpp:
     52        (JSC::MarkedBlock::specializedSweep):
     53        (JSC::MarkedBlock::sweep):
     54        (JSC::MarkedBlock::sweepHelper):
     55        (JSC::MarkedBlock::zapFreeList):
     56        * heap/MarkedBlock.h:
     57        (FreeList): Added a new struct that keeps track of the current MarkedAllocator's
     58        free list including the number of bytes of stuff in the free list so that when the free list is
     59        exhausted, the correct amount can be reported to Heap.
     60        (MarkedBlock):
     61        (JSC::MarkedBlock::FreeList::FreeList):
     62        (JSC):
     63        * heap/MarkedSpace.cpp: Removing all water mark related stuff.
     64        (JSC::MarkedSpace::MarkedSpace):
     65        (JSC::MarkedSpace::resetAllocators):
     66        * heap/MarkedSpace.h:
     67        (MarkedSpace):
     68        (JSC):
     69        * heap/WeakSet.cpp:
     70        (JSC::WeakSet::findAllocator): Refactored to use the didAllocate interface with the Heap. This
     71        function still needs work though now that the Heap knows how many bytes have been allocated
     72        since the last collection.
     73        * jit/JITInlineMethods.h: Refactored to use MarkedBlock's new FreeList struct.
     74        (JSC::JIT::emitAllocateBasicJSObject): Ditto.
     75        * llint/LowLevelInterpreter.asm: Ditto.
     76        * runtime/GCActivityCallback.cpp:
     77        (JSC::DefaultGCActivityCallback::didAllocate):
     78        * runtime/GCActivityCallback.h:
     79        (JSC::GCActivityCallback::didAllocate): Renamed willAllocate to didAllocate to indicate that
     80        the allocation that is being reported has already taken place.
     81        (DefaultGCActivityCallback):
     82        * runtime/GCActivityCallbackCF.cpp:
     83        (JSC):
     84        (JSC::DefaultGCActivityCallback::didAllocate): Refactored to return early if the amount of
     85        allocation since the last collection is not above a threshold (initially arbitrarily chosen to
     86        be 128KB).
     87
    1882012-04-19  Filip Pizlo  <fpizlo@apple.com>
    289
  • trunk/Source/JavaScriptCore/dfg/DFGSpeculativeJIT.h

    r114675 r114698  
    17951795            allocator = &m_jit.globalData()->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
    17961796
    1797         m_jit.loadPtr(&allocator->m_firstFreeCell, resultGPR);
     1797        m_jit.loadPtr(&allocator->m_freeList.head, resultGPR);
    17981798        slowPath.append(m_jit.branchTestPtr(MacroAssembler::Zero, resultGPR));
    17991799       
     
    18071807        // Now that we have scratchGPR back, remove the object from the free list
    18081808        m_jit.loadPtr(MacroAssembler::Address(resultGPR), scratchGPR);
    1809         m_jit.storePtr(scratchGPR, &allocator->m_firstFreeCell);
     1809        m_jit.storePtr(scratchGPR, &allocator->m_freeList.head);
    18101810       
    18111811        // Initialize the object's classInfo pointer
  • trunk/Source/JavaScriptCore/heap/CopiedSpace.cpp

    r114511 r114698  
    3838    , m_inCopyingPhase(false)
    3939    , m_numberOfLoanedBlocks(0)
    40     , m_waterMark(0)
    4140{
    4241}
     
    5352CheckedBoolean CopiedSpace::tryAllocateSlowCase(size_t bytes, void** outPtr)
    5453{
    55     m_heap->activityCallback()->willAllocate();
    56    
    5754    if (isOversize(bytes))
    5855        return tryAllocateOversize(bytes, outPtr);
    5956   
    60     m_waterMark += m_allocator.currentCapacity();
     57    m_heap->didAllocate(m_allocator.currentCapacity());
    6158
    6259    if (!addNewBlock()) {
     
    8784    *outPtr = allocateFromBlock(block, bytes);
    8885
    89     m_waterMark += block->capacity();
     86    m_heap->didAllocate(blockSize);
    9087
    9188    return true;
     
    139136        CopiedBlock* oldBlock = oversizeBlockFor(oldPtr);
    140137        m_oversizeBlocks.remove(oldBlock);
    141         m_waterMark -= oldBlock->capacity();
    142138        oldBlock->m_allocation.deallocate();
    143139    }
     
    163159        m_toSpaceSet.add(block);
    164160        m_toSpaceFilter.add(reinterpret_cast<Bits>(block));
    165     }
    166 
    167     {
    168         MutexLocker locker(m_memoryStatsLock);
    169         m_waterMark += block->capacity();
    170161    }
    171162
     
    194185            block->m_isPinned = false;
    195186            m_toSpace->push(block);
    196             m_waterMark += block->capacity();
    197187            continue;
    198188        }
     
    212202            m_oversizeBlocks.remove(curr);
    213203            curr->m_allocation.deallocate();
    214         } else {
     204        } else
    215205            curr->m_isPinned = false;
    216             m_waterMark += curr->capacity();
    217         }
    218206        curr = next;
    219207    }
     
    282270        block->m_allocation.deallocate();
    283271    }
    284 
    285     m_waterMark = 0;
    286272}
    287273
  • trunk/Source/JavaScriptCore/heap/CopiedSpace.h

    r111877 r114698  
    6767    bool contains(void*, CopiedBlock*&);
    6868
    69     size_t waterMark() { return m_waterMark; }
    7069    size_t size();
    7170    size_t capacity();
     
    9392    static CopiedBlock* oversizeBlockFor(void* ptr);
    9493
    95     size_t calculateWaterMark();
    96 
    9794    Heap* m_heap;
    9895
     
    118115    size_t m_numberOfLoanedBlocks;
    119116
    120     Mutex m_memoryStatsLock;
    121     size_t m_waterMark;
    122 
    123117    static const size_t s_maxAllocationSize = 32 * KB;
    124118    static const size_t s_initialBlockNum = 16;
  • trunk/Source/JavaScriptCore/heap/CopiedSpaceInlineMethods.h

    r111877 r114698  
    5656    m_toSpaceFilter.reset();
    5757    m_allocator.startedCopying();
    58 
    59     m_waterMark = 0;
    6058
    6159    ASSERT(!m_inCopyingPhase);
  • trunk/Source/JavaScriptCore/heap/Heap.cpp

    r114511 r114698  
    314314    , m_minBytesPerCycle(heapSizeForHint(heapSize))
    315315    , m_lastFullGCSize(0)
    316     , m_highWaterMark(m_minBytesPerCycle)
     316    , m_bytesAllocatedLimit(m_minBytesPerCycle)
     317    , m_bytesAllocated(0)
    317318    , m_operationInProgress(NoOperation)
    318319    , m_objectSpace(this)
     
    466467    // collecting more frequently as long as it stays alive.
    467468
    468     addToWaterMark(cost);
     469    didAllocate(cost);
     470    if (shouldCollect())
     471        collect(DoNotSweep);
    469472}
    470473
     
    849852    }
    850853
    851     // To avoid pathological GC churn in large heaps, we set the allocation high
    852     // water mark to be proportional to the current size of the heap. The exact
    853     // proportion is a bit arbitrary. A 2X multiplier gives a 1:1 (heap size :
     854    // To avoid pathological GC churn in large heaps, we set the new allocation
     855    // limit to be the current size of the heap. This heuristic
     856    // is a bit arbitrary. Using the current size of the heap after this
     857    // collection gives us a 2X multiplier, which is a 1:1 (heap size :
    854858    // new bytes allocated) proportion, and seems to work well in benchmarks.
    855859    size_t newSize = size();
    856     size_t proportionalBytes = 2 * newSize;
    857860    if (fullGC) {
    858861        m_lastFullGCSize = newSize;
    859         m_highWaterMark = max(proportionalBytes, m_minBytesPerCycle);
    860     }
     862        m_bytesAllocatedLimit = max(newSize, m_minBytesPerCycle);
     863    }
     864    m_bytesAllocated = 0;
    861865    double lastGCEndTime = WTF::currentTime();
    862866    m_lastGCLength = lastGCEndTime - lastGCStartTime;
     
    885889{
    886890    return m_activityCallback.get();
     891}
     892
     893void Heap::didAllocate(size_t bytes)
     894{
     895    m_activityCallback->didAllocate(m_bytesAllocated);
     896    m_bytesAllocated += bytes;
    887897}
    888898
  • trunk/Source/JavaScriptCore/heap/Heap.h

    r114511 r114698  
    113113
    114114        void notifyIsSafeToCollect() { m_isSafeToCollect = true; }
     115
    115116        JS_EXPORT_PRIVATE void collectAllGarbage();
    116 
     117        enum SweepToggle { DoNotSweep, DoSweep };
     118        bool shouldCollect();
     119        void collect(SweepToggle);
    117120        void reportExtraMemoryCost(size_t cost);
    118121
     
    145148        void getConservativeRegisterRoots(HashSet<JSCell*>& roots);
    146149
    147         void addToWaterMark(size_t);
    148 
    149150        double lastGCLength() { return m_lastGCLength; }
    150151
    151152        JS_EXPORT_PRIVATE void discardAllCompiledCode();
     153
     154        void didAllocate(size_t);
    152155
    153156    private:
     
    164167        void* allocateWithoutDestructor(size_t);
    165168
    166         size_t waterMark();
    167         size_t highWaterMark();
    168         bool shouldCollect();
    169 
    170169        static const size_t minExtraCost = 256;
    171170        static const size_t maxExtraCost = 1024 * 1024;
     
    193192        void finalizeUnconditionalFinalizers();
    194193       
    195         enum SweepToggle { DoNotSweep, DoSweep };
    196         void collect(SweepToggle);
    197194        void shrink();
    198195        void releaseFreeBlocks();
     
    209206        const size_t m_minBytesPerCycle;
    210207        size_t m_lastFullGCSize;
    211         size_t m_highWaterMark;
     208
     209        size_t m_bytesAllocatedLimit;
     210        size_t m_bytesAllocated;
    212211       
    213212        OperationInProgress m_operationInProgress;
     
    258257        return m_objectSpace.nurseryWaterMark() >= m_minBytesPerCycle && m_isSafeToCollect;
    259258#else
    260         return waterMark() >= highWaterMark() && m_isSafeToCollect;
     259        return m_bytesAllocated > m_bytesAllocatedLimit && m_isSafeToCollect;
    261260#endif
    262261    }
     
    292291    {
    293292        MarkedBlock::blockFor(cell)->setMarked(cell);
    294     }
    295 
    296     inline size_t Heap::waterMark()
    297     {
    298         return m_objectSpace.waterMark() + m_storageSpace.waterMark();
    299     }
    300 
    301     inline size_t Heap::highWaterMark()
    302     {
    303         return m_highWaterMark;
    304     }
    305 
    306     inline void Heap::addToWaterMark(size_t size)
    307     {
    308         m_objectSpace.addToWaterMark(size);
    309         if (waterMark() > highWaterMark())
    310             collect(DoNotSweep);
    311293    }
    312294
  • trunk/Source/JavaScriptCore/heap/MarkedAllocator.cpp

    r114511 r114698  
    99inline void* MarkedAllocator::tryAllocateHelper()
    1010{
    11     MarkedBlock::FreeCell* firstFreeCell = m_firstFreeCell;
    12     if (!firstFreeCell) {
     11    if (!m_freeList.head) {
    1312        for (MarkedBlock*& block = m_currentBlock; block; block = static_cast<MarkedBlock*>(block->next())) {
    14             firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList);
    15             if (firstFreeCell)
     13            m_freeList = block->sweep(MarkedBlock::SweepToFreeList);
     14            if (m_freeList.head)
    1615                break;
    17             m_markedSpace->didConsumeFreeList(block);
    1816            block->didConsumeFreeList();
    1917        }
    2018       
    21         if (!firstFreeCell)
     19        if (!m_freeList.head)
    2220            return 0;
    2321    }
    2422   
    25     ASSERT(firstFreeCell);
    26     m_firstFreeCell = firstFreeCell->next;
    27     return firstFreeCell;
     23    MarkedBlock::FreeCell* head = m_freeList.head;
     24    m_freeList.head = head->next;
     25    ASSERT(head);
     26    return head;
    2827}
    2928   
     
    4342#endif
    4443   
    45     m_heap->activityCallback()->willAllocate();
     44    ASSERT(!m_freeList.head);
     45    m_heap->didAllocate(m_freeList.bytes);
    4646   
    4747    void* result = tryAllocate();
     
    7272        return result;
    7373   
    74     ASSERT(m_heap->waterMark() < m_heap->highWaterMark());
     74    ASSERT(!m_heap->shouldCollect());
    7575   
    7676    addBlock(allocateBlock(AllocationMustSucceed));
     
    109109{
    110110    ASSERT(!m_currentBlock);
    111     ASSERT(!m_firstFreeCell);
     111    ASSERT(!m_freeList.head);
    112112   
    113113    m_blockList.append(block);
    114114    m_currentBlock = block;
    115     m_firstFreeCell = block->sweep(MarkedBlock::SweepToFreeList);
     115    m_freeList = block->sweep(MarkedBlock::SweepToFreeList);
    116116}
    117117
  • trunk/Source/JavaScriptCore/heap/MarkedAllocator.h

    r108444 r114698  
    4242    MarkedBlock* allocateBlock(AllocationEffort);
    4343   
    44     MarkedBlock::FreeCell* m_firstFreeCell;
     44    MarkedBlock::FreeList m_freeList;
    4545    MarkedBlock* m_currentBlock;
    4646    DoublyLinkedList<HeapBlock> m_blockList;
     
    5252
    5353inline MarkedAllocator::MarkedAllocator()
    54     : m_firstFreeCell(0)
    55     , m_currentBlock(0)
     54    : m_currentBlock(0)
    5655    , m_cellSize(0)
    5756    , m_cellsNeedDestruction(true)
     
    7170inline void* MarkedAllocator::allocate()
    7271{
    73     MarkedBlock::FreeCell* firstFreeCell = m_firstFreeCell;
     72    MarkedBlock::FreeCell* head = m_freeList.head;
    7473    // This is a light-weight fast path to cover the most common case.
    75     if (UNLIKELY(!firstFreeCell))
     74    if (UNLIKELY(!head))
    7675        return allocateSlowCase();
    7776   
    78     m_firstFreeCell = firstFreeCell->next;
    79     return firstFreeCell;
     77    m_freeList.head = head->next;
     78    return head;
    8079}
    8180
     
    8887{
    8988    if (!m_currentBlock) {
    90         ASSERT(!m_firstFreeCell);
     89        ASSERT(!m_freeList.head);
    9190        return;
    9291    }
    9392   
    94     m_currentBlock->zapFreeList(m_firstFreeCell);
    95     m_firstFreeCell = 0;
     93    m_currentBlock->zapFreeList(m_freeList);
     94    m_freeList.head = 0;
    9695}
    9796
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.cpp

    r107495 r114698  
    7878
    7979template<MarkedBlock::BlockState blockState, MarkedBlock::SweepMode sweepMode, bool destructorCallNeeded>
    80 MarkedBlock::FreeCell* MarkedBlock::specializedSweep()
     80MarkedBlock::FreeList MarkedBlock::specializedSweep()
    8181{
    8282    ASSERT(blockState != Allocated && blockState != FreeListed);
     
    8787    // order of the free list.
    8888    FreeCell* head = 0;
     89    size_t count = 0;
    8990    for (size_t i = firstAtom(); i < m_endAtom; i += m_atomsPerCell) {
    9091        if (blockState == Marked && m_marks.get(i))
     
    102103            freeCell->next = head;
    103104            head = freeCell;
     105            ++count;
    104106        }
    105107    }
    106108
    107109    m_state = ((sweepMode == SweepToFreeList) ? FreeListed : Zapped);
    108     return head;
    109 }
    110 
    111 MarkedBlock::FreeCell* MarkedBlock::sweep(SweepMode sweepMode)
     110    return FreeList(head, count * cellSize());
     111}
     112
     113MarkedBlock::FreeList MarkedBlock::sweep(SweepMode sweepMode)
    112114{
    113115    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
    114116
    115117    if (sweepMode == SweepOnly && !m_cellsNeedDestruction)
    116         return 0;
     118        return FreeList();
    117119
    118120    if (m_cellsNeedDestruction)
     
    122124
    123125template<bool destructorCallNeeded>
    124 MarkedBlock::FreeCell* MarkedBlock::sweepHelper(SweepMode sweepMode)
     126MarkedBlock::FreeList MarkedBlock::sweepHelper(SweepMode sweepMode)
    125127{
    126128    switch (m_state) {
     
    131133        // Happens when a block transitions to fully allocated.
    132134        ASSERT(sweepMode == SweepToFreeList);
    133         return 0;
     135        return FreeList();
    134136    case Allocated:
    135137        ASSERT_NOT_REACHED();
    136         return 0;
     138        return FreeList();
    137139    case Marked:
    138140        return sweepMode == SweepToFreeList
     
    146148
    147149    ASSERT_NOT_REACHED();
    148     return 0;
    149 }
    150 
    151 void MarkedBlock::zapFreeList(FreeCell* firstFreeCell)
     150    return FreeList();
     151}
     152
     153void MarkedBlock::zapFreeList(const FreeList& freeList)
    152154{
    153155    HEAP_LOG_BLOCK_STATE_TRANSITION(this);
     156    FreeCell* head = freeList.head;
    154157
    155158    if (m_state == Marked) {
     
    160163        // Hence if the block is Marked we need to leave it Marked.
    161164       
    162         ASSERT(!firstFreeCell);
     165        ASSERT(!head);
    163166       
    164167        return;
     
    177180        // non-zero vtables, which is consistent with the block being zapped.
    178181       
    179         ASSERT(!firstFreeCell);
     182        ASSERT(!head);
    180183       
    181184        return;
     
    189192   
    190193    FreeCell* next;
    191     for (FreeCell* current = firstFreeCell; current; current = next) {
     194    for (FreeCell* current = head; current; current = next) {
    192195        next = current->next;
    193196        reinterpret_cast<JSCell*>(current)->zap();
  • trunk/Source/JavaScriptCore/heap/MarkedBlock.h

    r110134 r114698  
    8888        };
    8989       
     90        struct FreeList {
     91            FreeCell* head;
     92            size_t bytes;
     93
     94            FreeList();
     95            FreeList(FreeCell*, size_t);
     96        };
     97
    9098        struct VoidFunctor {
    9199            typedef void ReturnType;
     
    106114
    107115        enum SweepMode { SweepOnly, SweepToFreeList };
    108         FreeCell* sweep(SweepMode = SweepOnly);
     116        FreeList sweep(SweepMode = SweepOnly);
    109117
    110118        // While allocating from a free list, MarkedBlock temporarily has bogus
     
    112120        // of these functions:
    113121        void didConsumeFreeList(); // Call this once you've allocated all the items in the free list.
    114         void zapFreeList(FreeCell* firstFreeCell); // Call this to undo the free list.
     122        void zapFreeList(const FreeList&); // Call this to undo the free list.
    115123
    116124        void clearMarks();
     
    164172
    165173        enum BlockState { New, FreeListed, Allocated, Marked, Zapped };
    166         template<bool destructorCallNeeded> FreeCell* sweepHelper(SweepMode = SweepOnly);
     174        template<bool destructorCallNeeded> FreeList sweepHelper(SweepMode = SweepOnly);
    167175
    168176        typedef char Atom[atomSize];
     
    172180        size_t atomNumber(const void*);
    173181        void callDestructor(JSCell*);
    174         template<BlockState, SweepMode, bool destructorCallNeeded> FreeCell* specializedSweep();
     182        template<BlockState, SweepMode, bool destructorCallNeeded> FreeList specializedSweep();
    175183       
    176184#if ENABLE(GGC)
     
    189197        Heap* m_heap;
    190198    };
     199
     200    inline MarkedBlock::FreeList::FreeList()
     201        : head(0)
     202        , bytes(0)
     203    {
     204    }
     205
     206    inline MarkedBlock::FreeList::FreeList(FreeCell* head, size_t bytes)
     207        : head(head)
     208        , bytes(bytes)
     209    {
     210    }
    191211
    192212    inline size_t MarkedBlock::firstAtom()
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.cpp

    r113141 r114698  
    3232
    3333MarkedSpace::MarkedSpace(Heap* heap)
    34     : m_waterMark(0)
    35     , m_heap(heap)
     34    : m_heap(heap)
    3635{
    3736    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
     
    4847void MarkedSpace::resetAllocators()
    4948{
    50     m_waterMark = 0;
    51 
    5249    for (size_t cellSize = preciseStep; cellSize <= preciseCutoff; cellSize += preciseStep) {
    5350        allocatorFor(cellSize).reset();
  • trunk/Source/JavaScriptCore/heap/MarkedSpace.h

    r113141 r114698  
    6666    void canonicalizeCellLivenessData();
    6767
    68     size_t waterMark();
    69     void addToWaterMark(size_t);
    70 
    7168    typedef HashSet<MarkedBlock*>::iterator BlockIterator;
    7269   
     
    103100    Subspace m_normalSpace;
    104101
    105     size_t m_waterMark;
    106102    Heap* m_heap;
    107103    MarkedBlockSet m_blocks;
    108104};
    109 
    110 inline size_t MarkedSpace::waterMark()
    111 {
    112     return m_waterMark;
    113 }
    114 
    115 inline void MarkedSpace::addToWaterMark(size_t size)
    116 {
    117     m_waterMark += size;
    118 }
    119105
    120106template<typename Functor> inline typename Functor::ReturnType MarkedSpace::forEachCell(Functor& functor)
     
    198184}
    199185
    200 inline void MarkedSpace::didConsumeFreeList(MarkedBlock* block)
    201 {
    202     m_waterMark += block->capacity();
    203 }
    204 
    205186} // namespace JSC
    206187
  • trunk/Source/JavaScriptCore/heap/WeakSet.cpp

    r113508 r114698  
    8585        return allocator;
    8686
    87     m_heap->addToWaterMark(WeakBlock::blockSize);
     87    // FIXME: This reporting of the amount allocated isn't quite accurate and
     88    // probably should be reworked eventually.
     89    m_heap->didAllocate(WeakBlock::blockSize);
     90    if (m_heap->shouldCollect()) {
     91        m_heap->collect(Heap::DoNotSweep);
    8892
    89     // addToWaterMark() may cause a GC, so try again.
    90     if (WeakBlock::FreeCell* allocator = tryFindAllocator())
    91         return allocator;
     93        if (WeakBlock::FreeCell* allocator = tryFindAllocator())
     94            return allocator;
     95    }
    9296
    9397    return addAllocator();
  • trunk/Source/JavaScriptCore/jit/JITInlineMethods.h

    r114539 r114698  
    415415    else
    416416        allocator = &m_globalData->heap.allocatorForObjectWithoutDestructor(sizeof(ClassType));
    417     loadPtr(&allocator->m_firstFreeCell, result);
     417    loadPtr(&allocator->m_freeList.head, result);
    418418    addSlowCase(branchTestPtr(Zero, result));
    419419
    420420    // remove the object from the free list
    421421    loadPtr(Address(result), storagePtr);
    422     storePtr(storagePtr, &allocator->m_firstFreeCell);
     422    storePtr(storagePtr, &allocator->m_freeList.head);
    423423
    424424    // initialize the object's structure
  • trunk/Source/JavaScriptCore/llint/LowLevelInterpreter.asm

    r113930 r114698  
    292292            sizeClassIndex * sizeof MarkedAllocator
    293293       
     294        const offsetOfFirstFreeCell =
     295            MarkedAllocator::m_freeList +
     296            MarkedBlock::FreeList::head
     297
    294298        # FIXME: we can get the global data in one load from the stack.
    295299        loadp CodeBlock[cfr], scratch1
    296300        loadp CodeBlock::m_globalData[scratch1], scratch1
    297301       
    298         # Get the object from the free list.    
    299         loadp offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1], result
     302        # Get the object from the free list.   
     303        loadp offsetOfMySizeClass + offsetOfFirstFreeCell[scratch1], result
    300304        btpz result, slowCase
    301305       
    302306        # Remove the object from the free list.
    303307        loadp [result], scratch2
    304         storep scratch2, offsetOfMySizeClass + MarkedAllocator::m_firstFreeCell[scratch1]
     308        storep scratch2, offsetOfMySizeClass + offsetOfFirstFreeCell[scratch1]
    305309   
    306310        # Initialize the object.
  • trunk/Source/JavaScriptCore/runtime/GCActivityCallback.cpp

    r114511 r114698  
    4343}
    4444
    45 void DefaultGCActivityCallback::willAllocate()
     45void DefaultGCActivityCallback::didAllocate(size_t)
    4646{
    4747}
  • trunk/Source/JavaScriptCore/runtime/GCActivityCallback.h

    r114511 r114698  
    4444public:
    4545    virtual ~GCActivityCallback() { }
    46     virtual void willAllocate() { }
     46    virtual void didAllocate(size_t) { }
    4747    virtual void didCollect() { }
    4848    virtual void didAbandonObjectGraph() { }
     
    6262    virtual ~DefaultGCActivityCallback();
    6363
    64     virtual void willAllocate();
     64    virtual void didAllocate(size_t);
    6565    virtual void didCollect();
    6666    virtual void didAbandonObjectGraph();
  • trunk/Source/JavaScriptCore/runtime/GCActivityCallbackCF.cpp

    r114511 r114698  
    5858const CFTimeInterval decade = 60 * 60 * 24 * 365 * 10;
    5959const CFTimeInterval hour = 60 * 60;
     60const size_t minBytesBeforeCollect = 128 * KB;
    6061
    6162void DefaultGCActivityCallbackPlatformData::timerDidFire(CFRunLoopTimerRef, void *info)
     
    114115}
    115116
    116 void DefaultGCActivityCallback::willAllocate()
     117void DefaultGCActivityCallback::didAllocate(size_t bytes)
    117118{
     119    if (bytes < minBytesBeforeCollect)
     120        return;
    118121    scheduleTimer(d.get());
    119122}
Note: See TracChangeset for help on using the changeset viewer.