void Heap::collectAllGarbageIfNotDoneRecently() { if (!m_fullActivityCallback) { collectAllGarbage(); return; } if (m_fullActivityCallback->didSyncGCRecently()) { // A synchronous GC was already requested recently so we merely accelerate next collection. reportAbandonedObjectGraph(); return; } m_fullActivityCallback->setDidSyncGCRecently(); collectAllGarbage(); }
void Heap::reportExtraMemoryCostSlowCase(size_t cost) { // Our frequency of garbage collection tries to balance memory use against speed // by collecting based on the number of newly created values. However, for values // that hold on to a great deal of memory that's not in the form of other JS values, // that is not good enough - in some cases a lot of those objects can pile up and // use crazy amounts of memory without a GC happening. So we track these extra // memory costs. Only unusually large objects are noted, and we only keep track // of this extra cost until the next GC. In garbage collected languages, most values // are either very short lived temporaries, or have extremely long lifetimes. So // if a large value survives one garbage collection, there is not much point to // collecting more frequently as long as it stays alive. if (m_extraCost > maxExtraCost && m_extraCost > m_objectSpace.highWaterMark() / 2) collectAllGarbage(); m_extraCost += cost; }
void* Heap::allocate(NewSpace::SizeClass& sizeClass) { #if COLLECT_ON_EVERY_ALLOCATION collectAllGarbage(); ASSERT(m_operationInProgress == NoOperation); #endif m_operationInProgress = Allocation; void* result = m_newSpace.allocate(sizeClass); m_operationInProgress = NoOperation; if (result) return result; if (m_newSpace.waterMark() < m_newSpace.highWaterMark()) { m_newSpace.addBlock(sizeClass, allocateBlock(sizeClass.cellSize)); return allocate(sizeClass); } collect(DoNotSweep); return allocate(sizeClass); }
void* Heap::allocateSlowCase(size_t bytes) { ASSERT(globalData()->identifierTable == wtfThreadData().currentIdentifierTable()); ASSERT(JSLock::lockCount() > 0); ASSERT(JSLock::currentThreadIsHoldingLock()); ASSERT(bytes <= MarkedSpace::maxCellSize); ASSERT(m_operationInProgress == NoOperation); #if COLLECT_ON_EVERY_SLOW_ALLOCATION collectAllGarbage(); ASSERT(m_operationInProgress == NoOperation); #endif reset(DoNotSweep); m_operationInProgress = Allocation; void* result = m_markedSpace.allocate(bytes); m_operationInProgress = NoOperation; ASSERT(result); return result; }