diff options
Diffstat (limited to 'src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h')
-rw-r--r-- | src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h | 153 |
1 files changed, 69 insertions, 84 deletions
diff --git a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h index 0ecff19..7f7a679 100644 --- a/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h +++ b/src/3rdparty/javascriptcore/JavaScriptCore/runtime/Collector.h @@ -28,9 +28,9 @@ #include <wtf/HashSet.h> #include <wtf/Noncopyable.h> #include <wtf/OwnPtr.h> +#include <wtf/StdLibExtras.h> #include <wtf/Threading.h> -// This is supremely lame that we require pthreads to build on windows. #if ENABLE(JSC_MULTIPLE_THREADS) #include <pthread.h> #endif @@ -47,19 +47,21 @@ namespace JSC { class MarkStack; enum OperationInProgress { NoOperation, Allocation, Collection }; - enum HeapType { PrimaryHeap, NumberHeap }; - template <HeapType> class CollectorHeapIterator; + class LiveObjectIterator; struct CollectorHeap { + size_t nextBlock; + size_t nextCell; CollectorBlock** blocks; + + void* nextNumber; + size_t numBlocks; size_t usedBlocks; - size_t firstBlockWithPossibleSpace; - size_t numLiveObjects; - size_t numLiveObjectsAtLastCollect; size_t extraCost; + bool didShrink; OperationInProgress operationInProgress; }; @@ -67,36 +69,27 @@ namespace JSC { class Heap : public Noncopyable { public: class Thread; - typedef CollectorHeapIterator<PrimaryHeap> iterator; void destroy(); -#ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE - // We can inline these functions because everything is compiled as - // one file, so the heapAllocate template definitions are available. - // However, allocateNumber is used via jsNumberCell outside JavaScriptCore. - // Thus allocateNumber needs to provide a non-inline version too. - void* inlineAllocateNumber(size_t s) { return heapAllocate<NumberHeap>(s); } - void* inlineAllocate(size_t s) { return heapAllocate<PrimaryHeap>(s); } -#endif void* allocateNumber(size_t); void* allocate(size_t); - bool collect(); bool isBusy(); // true if an allocation or collection is in progress + void collectAllGarbage(); - static const size_t minExtraCostSize = 256; + static const size_t minExtraCost = 256; + static const size_t maxExtraCost = 1024 * 1024; void reportExtraMemoryCost(size_t cost); - size_t objectCount(); + size_t objectCount() const; struct Statistics { size_t size; size_t free; }; Statistics statistics() const; - void setGCProtectNeedsLocking(); void protect(JSValue); void unprotect(JSValue); @@ -120,13 +113,12 @@ namespace JSC { JSGlobalData* globalData() const { return m_globalData; } static bool isNumber(JSCell*); - // Iterators for the object heap. - iterator primaryHeapBegin(); - iterator primaryHeapEnd(); + LiveObjectIterator primaryHeapBegin(); + LiveObjectIterator primaryHeapEnd(); private: - template <HeapType heapType> void* heapAllocate(size_t); - template <HeapType heapType> size_t sweep(); + void reset(); + void sweep(); static CollectorBlock* cellBlock(const JSCell*); static size_t cellOffset(const JSCell*); @@ -134,12 +126,22 @@ namespace JSC { Heap(JSGlobalData*); ~Heap(); - template <HeapType heapType> NEVER_INLINE CollectorBlock* allocateBlock(); - template <HeapType heapType> NEVER_INLINE void freeBlock(size_t); - NEVER_INLINE void freeBlock(CollectorBlock*); - void freeBlocks(CollectorHeap*); + NEVER_INLINE CollectorBlock* allocateBlock(); + NEVER_INLINE void freeBlock(size_t); + NEVER_INLINE void freeBlockPtr(CollectorBlock*); + void freeBlocks(); + void resizeBlocks(); + void growBlocks(size_t neededBlocks); + void shrinkBlocks(size_t neededBlocks); + void clearMarkBits(); + void clearMarkBits(CollectorBlock*); + size_t markedCells(size_t startBlock = 0, size_t startCell = 0) const; void recordExtraCost(size_t); + + void addToStatistics(Statistics&) const; + + void markRoots(); void markProtectedObjects(MarkStack&); void markCurrentThreadConservatively(MarkStack&); void markCurrentThreadConservativelyInternal(MarkStack&); @@ -148,10 +150,8 @@ namespace JSC { typedef HashCountedSet<JSCell*> ProtectCountSet; - CollectorHeap primaryHeap; - CollectorHeap numberHeap; + CollectorHeap m_heap; - OwnPtr<Mutex> m_protectedValuesMutex; // Only non-null if the client explicitly requested it via setGCPrtotectNeedsLocking(). ProtectCountSet m_protectedValues; HashSet<MarkedArgumentBuffer*>* m_markListSet; @@ -181,7 +181,7 @@ namespace JSC { #endif template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; -#if PLATFORM(WINCE) || PLATFORM(SYMBIAN) +#if OS(WINCE) || OS(SYMBIAN) const size_t BLOCK_SIZE = 64 * 1024; // 64k #else const size_t BLOCK_SIZE = 64 * 4096; // 256k @@ -196,87 +196,60 @@ namespace JSC { const size_t SMALL_CELL_SIZE = CELL_SIZE / 2; const size_t CELL_MASK = CELL_SIZE - 1; const size_t CELL_ALIGN_MASK = ~CELL_MASK; - const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2); - const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK; + 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. + const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8; const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t); - + struct CollectorBitmap { uint32_t bits[BITMAP_WORDS]; bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } void clearAll() { memset(bits, 0, sizeof(bits)); } + size_t count(size_t startCell = 0) + { + size_t result = 0; + for ( ; (startCell & 0x1F) != 0; ++startCell) { + if (get(startCell)) + ++result; + } + for (size_t i = startCell >> 5; i < BITMAP_WORDS; ++i) + result += WTF::bitCount(bits[i]); + return result; + } + size_t isEmpty() // Much more efficient than testing count() == 0. + { + for (size_t i = 0; i < BITMAP_WORDS; ++i) + if (bits[i] != 0) + return false; + return true; + } }; struct CollectorCell { - union { - double memory[CELL_ARRAY_LENGTH]; - struct { - void* zeroIfFree; - ptrdiff_t next; - } freeCell; - } u; - }; - - struct SmallCollectorCell { - union { - double memory[CELL_ARRAY_LENGTH / 2]; - struct { - void* zeroIfFree; - ptrdiff_t next; - } freeCell; - } u; + double memory[CELL_ARRAY_LENGTH]; }; class CollectorBlock { public: CollectorCell cells[CELLS_PER_BLOCK]; - uint32_t usedCells; - CollectorCell* freeList; - CollectorBitmap marked; - Heap* heap; - HeapType type; - }; - - class SmallCellCollectorBlock { - public: - SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK]; - uint32_t usedCells; - SmallCollectorCell* freeList; CollectorBitmap marked; Heap* heap; - HeapType type; }; - - template <HeapType heapType> struct HeapConstants; - template <> struct HeapConstants<PrimaryHeap> { + struct HeapConstants { static const size_t cellSize = CELL_SIZE; static const size_t cellsPerBlock = CELLS_PER_BLOCK; - static const size_t bitmapShift = 0; typedef CollectorCell Cell; typedef CollectorBlock Block; }; - template <> struct HeapConstants<NumberHeap> { - static const size_t cellSize = SMALL_CELL_SIZE; - static const size_t cellsPerBlock = SMALL_CELLS_PER_BLOCK; - static const size_t bitmapShift = 1; - typedef SmallCollectorCell Cell; - typedef SmallCellCollectorBlock Block; - }; - inline CollectorBlock* Heap::cellBlock(const JSCell* cell) { return reinterpret_cast<CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK); } - inline bool Heap::isNumber(JSCell* cell) - { - return Heap::cellBlock(cell)->type == NumberHeap; - } - inline size_t Heap::cellOffset(const JSCell* cell) { return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE; @@ -294,8 +267,20 @@ namespace JSC { inline void Heap::reportExtraMemoryCost(size_t cost) { - if (cost > minExtraCostSize) - recordExtraCost(cost / (CELL_SIZE * 2)); + if (cost > minExtraCost) + recordExtraCost(cost); + } + + inline void* Heap::allocateNumber(size_t s) + { + if (void* result = m_heap.nextNumber) { + m_heap.nextNumber = 0; + return result; + } + + void* result = allocate(s); + m_heap.nextNumber = static_cast<char*>(result) + (CELL_SIZE / 2); + return result; } } // namespace JSC |