Changeset 34360 in webkit for trunk/JavaScriptCore/kjs/collector.h
- Timestamp:
- Jun 4, 2008, 9:29:49 AM (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/JavaScriptCore/kjs/collector.h
r34088 r34360 1 // -*- c-basic-offset: 2 -*-2 1 /* 3 * This file is part of the KDE libraries4 2 * Copyright (C) 1999-2000 Harri Porten ([email protected]) 5 3 * Copyright (C) 2001 Peter Kelly ([email protected]) … … 30 28 namespace KJS { 31 29 32 class JSCell;33 class JSValue;34 class CollectorBlock;35 36 class Collector {37 public:38 class Thread;39 enum HeapType { PrimaryHeap, NumberHeap };30 class JSCell; 31 class JSValue; 32 class CollectorBlock; 33 34 class Collector { 35 public: 36 class Thread; 37 enum HeapType { PrimaryHeap, NumberHeap }; 40 38 41 39 #ifdef JAVASCRIPTCORE_BUILDING_ALL_IN_ONE_FILE 42 // We can inline these functions because everything is compiled as43 // one file, so the heapAllocate template definitions are available.44 // However, allocateNumber is used via jsNumberCell outside JavaScriptCore.45 // Thus allocateNumber needs to provide a non-inline version too.46 static void* allocate(size_t s) { return heapAllocate<PrimaryHeap>(s); }47 static void* inlineAllocateNumber(size_t s) { return heapAllocate<NumberHeap>(s); }40 // We can inline these functions because everything is compiled as 41 // one file, so the heapAllocate template definitions are available. 42 // However, allocateNumber is used via jsNumberCell outside JavaScriptCore. 43 // Thus allocateNumber needs to provide a non-inline version too. 44 static void* allocate(size_t s) { return heapAllocate<PrimaryHeap>(s); } 45 static void* inlineAllocateNumber(size_t s) { return heapAllocate<NumberHeap>(s); } 48 46 #else 49 static void* allocate(size_t);47 static void* allocate(size_t); 50 48 #endif 51 static void* allocateNumber(size_t s); 52 53 static bool collect(); 54 static bool isBusy(); // true if an allocation or collection is in progress 55 56 static const size_t minExtraCostSize = 256; 57 58 static void reportExtraMemoryCost(size_t cost); 59 60 static size_t size(); 61 62 static void protect(JSValue*); 63 static void unprotect(JSValue*); 64 65 static void collectOnMainThreadOnly(JSValue*); 66 67 static size_t globalObjectCount(); 68 static size_t protectedObjectCount(); 69 static size_t protectedGlobalObjectCount(); 70 static HashCountedSet<const char*>* protectedObjectTypeCounts(); 71 72 static void registerThread(); 73 74 static void registerAsMainThread(); 75 76 static bool isCellMarked(const JSCell*); 77 static void markCell(JSCell*); 78 79 static void markStackObjectsConservatively(void* start, void* end); 80 81 private: 82 template <Collector::HeapType heapType> static void* heapAllocate(size_t s); 83 template <Collector::HeapType heapType> static size_t sweep(bool); 84 static const CollectorBlock* cellBlock(const JSCell*); 85 static CollectorBlock* cellBlock(JSCell*); 86 static size_t cellOffset(const JSCell*); 87 88 Collector(); 89 90 static void recordExtraCost(size_t); 91 static void markProtectedObjects(); 92 static void markMainThreadOnlyObjects(); 93 static void markCurrentThreadConservatively(); 94 static void markCurrentThreadConservativelyInternal(); 95 static void markOtherThreadConservatively(Thread*); 96 static void markStackObjectsConservatively(); 97 98 static size_t mainThreadOnlyObjectCount; 99 static bool memoryFull; 100 }; 101 102 // tunable parameters 103 template<size_t bytesPerWord> struct CellSize; 104 105 // cell size needs to be a power of two for certain optimizations in collector.cpp 106 template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; }; // 32-bit 107 template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; // 64-bit 108 const size_t BLOCK_SIZE = 16 * 4096; // 64k 49 static void* allocateNumber(size_t s); 50 51 static bool collect(); 52 static bool isBusy(); // true if an allocation or collection is in progress 53 54 static const size_t minExtraCostSize = 256; 55 56 static void reportExtraMemoryCost(size_t cost); 57 58 static size_t size(); 59 60 static void protect(JSValue*); 61 static void unprotect(JSValue*); 62 63 static void collectOnMainThreadOnly(JSValue*); 64 65 static size_t globalObjectCount(); 66 static size_t protectedObjectCount(); 67 static size_t protectedGlobalObjectCount(); 68 static HashCountedSet<const char*>* protectedObjectTypeCounts(); 69 70 static void registerThread(); 71 72 static void registerAsMainThread(); 73 74 static bool isCellMarked(const JSCell*); 75 static void markCell(JSCell*); 76 77 static void markStackObjectsConservatively(void* start, void* end); 78 79 private: 80 template <Collector::HeapType heapType> static void* heapAllocate(size_t s); 81 template <Collector::HeapType heapType> static size_t sweep(bool); 82 static const CollectorBlock* cellBlock(const JSCell*); 83 static CollectorBlock* cellBlock(JSCell*); 84 static size_t cellOffset(const JSCell*); 85 86 Collector(); 87 88 static void recordExtraCost(size_t); 89 static void markProtectedObjects(); 90 static void markMainThreadOnlyObjects(); 91 static void markCurrentThreadConservatively(); 92 static void markCurrentThreadConservativelyInternal(); 93 static void markOtherThreadConservatively(Thread*); 94 static void markStackObjectsConservatively(); 95 96 static size_t mainThreadOnlyObjectCount; 97 static bool memoryFull; 98 }; 99 100 // tunable parameters 101 template<size_t bytesPerWord> struct CellSize; 102 103 // cell size needs to be a power of two for certain optimizations in collector.cpp 104 template<> struct CellSize<sizeof(uint32_t)> { static const size_t m_value = 32; }; // 32-bit 105 template<> struct CellSize<sizeof(uint64_t)> { static const size_t m_value = 64; }; // 64-bit 106 const size_t BLOCK_SIZE = 16 * 4096; // 64k 107 108 // derived constants 109 const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1; 110 const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK; 111 const size_t MINIMUM_CELL_SIZE = CellSize<sizeof(void*)>::m_value; 112 const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0); 113 const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double); 114 const size_t SMALL_CELL_SIZE = CELL_SIZE / 2; 115 const size_t CELL_MASK = CELL_SIZE - 1; 116 const size_t CELL_ALIGN_MASK = ~CELL_MASK; 117 const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2); 118 const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK; 119 const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8; 120 const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t); 109 121 110 // derived constants 111 const size_t BLOCK_OFFSET_MASK = BLOCK_SIZE - 1; 112 const size_t BLOCK_MASK = ~BLOCK_OFFSET_MASK; 113 const size_t MINIMUM_CELL_SIZE = CellSize<sizeof(void*)>::m_value; 114 const size_t CELL_ARRAY_LENGTH = (MINIMUM_CELL_SIZE / sizeof(double)) + (MINIMUM_CELL_SIZE % sizeof(double) != 0 ? sizeof(double) : 0); 115 const size_t CELL_SIZE = CELL_ARRAY_LENGTH * sizeof(double); 116 const size_t SMALL_CELL_SIZE = CELL_SIZE / 2; 117 const size_t CELL_MASK = CELL_SIZE - 1; 118 const size_t CELL_ALIGN_MASK = ~CELL_MASK; 119 const size_t CELLS_PER_BLOCK = (BLOCK_SIZE * 8 - sizeof(uint32_t) * 8 - sizeof(void *) * 8 - 2 * (7 + 3 * 8)) / (CELL_SIZE * 8 + 2); 120 const size_t SMALL_CELLS_PER_BLOCK = 2 * CELLS_PER_BLOCK; 121 const size_t BITMAP_SIZE = (CELLS_PER_BLOCK + 7) / 8; 122 const size_t BITMAP_WORDS = (BITMAP_SIZE + 3) / sizeof(uint32_t); 122 struct CollectorBitmap { 123 uint32_t bits[BITMAP_WORDS]; 124 bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } 125 void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } 126 void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } 127 void clearAll() { memset(bits, 0, sizeof(bits)); } 128 }; 123 129 124 struct CollectorBitmap { 125 uint32_t bits[BITMAP_WORDS]; 126 bool get(size_t n) const { return !!(bits[n >> 5] & (1 << (n & 0x1F))); } 127 void set(size_t n) { bits[n >> 5] |= (1 << (n & 0x1F)); } 128 void clear(size_t n) { bits[n >> 5] &= ~(1 << (n & 0x1F)); } 129 void clearAll() { memset(bits, 0, sizeof(bits)); } 130 }; 131 132 struct CollectorCell { 133 union { 134 double memory[CELL_ARRAY_LENGTH]; 135 struct { 136 void* zeroIfFree; 137 ptrdiff_t next; 138 } freeCell; 139 } u; 140 }; 141 142 struct SmallCollectorCell { 143 union { 144 double memory[CELL_ARRAY_LENGTH / 2]; 145 struct { 146 void* zeroIfFree; 147 ptrdiff_t next; 148 } freeCell; 149 } u; 150 }; 151 152 class CollectorBlock { 153 public: 154 CollectorCell cells[CELLS_PER_BLOCK]; 155 uint32_t usedCells; 156 CollectorCell* freeList; 157 CollectorBitmap marked; 158 CollectorBitmap collectOnMainThreadOnly; 159 }; 160 161 class SmallCellCollectorBlock { 162 public: 163 SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK]; 164 uint32_t usedCells; 165 SmallCollectorCell* freeList; 166 CollectorBitmap marked; 167 CollectorBitmap collectOnMainThreadOnly; 168 }; 169 170 enum OperationInProgress { NoOperation, Allocation, Collection }; 171 172 struct CollectorHeap { 173 CollectorBlock** blocks; 174 size_t numBlocks; 175 size_t usedBlocks; 176 size_t firstBlockWithPossibleSpace; 177 178 size_t numLiveObjects; 179 size_t numLiveObjectsAtLastCollect; 180 size_t extraCost; 181 182 OperationInProgress operationInProgress; 183 }; 184 185 inline const CollectorBlock* Collector::cellBlock(const JSCell* cell) 186 { 187 return reinterpret_cast<const CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK); 188 } 189 190 inline CollectorBlock* Collector::cellBlock(JSCell* cell) 191 { 192 return const_cast<CollectorBlock*>(cellBlock(const_cast<const JSCell*>(cell))); 193 } 194 195 inline size_t Collector::cellOffset(const JSCell* cell) 196 { 197 return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE; 198 } 199 200 inline bool Collector::isCellMarked(const JSCell* cell) 201 { 202 return cellBlock(cell)->marked.get(cellOffset(cell)); 203 } 204 205 inline void Collector::markCell(JSCell* cell) 206 { 207 cellBlock(cell)->marked.set(cellOffset(cell)); 208 } 209 210 inline void Collector::reportExtraMemoryCost(size_t cost) 211 { 212 if (cost > minExtraCostSize) 213 recordExtraCost(cost / (CELL_SIZE * 2)); 214 } 130 struct CollectorCell { 131 union { 132 double memory[CELL_ARRAY_LENGTH]; 133 struct { 134 void* zeroIfFree; 135 ptrdiff_t next; 136 } freeCell; 137 } u; 138 }; 139 140 struct SmallCollectorCell { 141 union { 142 double memory[CELL_ARRAY_LENGTH / 2]; 143 struct { 144 void* zeroIfFree; 145 ptrdiff_t next; 146 } freeCell; 147 } u; 148 }; 149 150 class CollectorBlock { 151 public: 152 CollectorCell cells[CELLS_PER_BLOCK]; 153 uint32_t usedCells; 154 CollectorCell* freeList; 155 CollectorBitmap marked; 156 CollectorBitmap collectOnMainThreadOnly; 157 }; 158 159 class SmallCellCollectorBlock { 160 public: 161 SmallCollectorCell cells[SMALL_CELLS_PER_BLOCK]; 162 uint32_t usedCells; 163 SmallCollectorCell* freeList; 164 CollectorBitmap marked; 165 CollectorBitmap collectOnMainThreadOnly; 166 }; 167 168 enum OperationInProgress { NoOperation, Allocation, Collection }; 169 170 struct CollectorHeap { 171 CollectorBlock** blocks; 172 size_t numBlocks; 173 size_t usedBlocks; 174 size_t firstBlockWithPossibleSpace; 175 176 size_t numLiveObjects; 177 size_t numLiveObjectsAtLastCollect; 178 size_t extraCost; 179 180 OperationInProgress operationInProgress; 181 }; 182 183 inline const CollectorBlock* Collector::cellBlock(const JSCell* cell) 184 { 185 return reinterpret_cast<const CollectorBlock*>(reinterpret_cast<uintptr_t>(cell) & BLOCK_MASK); 186 } 187 188 inline CollectorBlock* Collector::cellBlock(JSCell* cell) 189 { 190 return const_cast<CollectorBlock*>(cellBlock(const_cast<const JSCell*>(cell))); 191 } 192 193 inline size_t Collector::cellOffset(const JSCell* cell) 194 { 195 return (reinterpret_cast<uintptr_t>(cell) & BLOCK_OFFSET_MASK) / CELL_SIZE; 196 } 197 198 inline bool Collector::isCellMarked(const JSCell* cell) 199 { 200 return cellBlock(cell)->marked.get(cellOffset(cell)); 201 } 202 203 inline void Collector::markCell(JSCell* cell) 204 { 205 cellBlock(cell)->marked.set(cellOffset(cell)); 206 } 207 208 inline void Collector::reportExtraMemoryCost(size_t cost) 209 { 210 if (cost > minExtraCostSize) 211 recordExtraCost(cost / (CELL_SIZE * 2)); 212 } 215 213 216 214 } // namespace KJS
Note:
See TracChangeset
for help on using the changeset viewer.