Changeset 98937 in webkit for trunk/Source/JavaScriptCore/heap/MarkStack.h
- Timestamp:
- Oct 31, 2011, 11:43:37 PM (14 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/JavaScriptCore/heap/MarkStack.h
r97642 r98937 28 28 29 29 #include "HandleTypes.h" 30 #include "Heuristics.h" 30 31 #include "JSValue.h" 31 32 #include "Register.h" … … 44 45 class JSGlobalData; 45 46 class MarkStack; 47 class ParallelModeEnabler; 46 48 class Register; 49 class SlotVisitor; 47 50 template<typename T> class WriteBarrierBase; 48 51 template<typename T> class JITWriteBarrier; 49 52 53 struct MarkStackSegment { 54 MarkStackSegment* m_previous; 55 #if !ASSERT_DISABLED 56 size_t m_top; 57 #endif 58 59 const JSCell** data() 60 { 61 return bitwise_cast<const JSCell**>(this + 1); 62 } 63 64 static size_t capacityFromSize(size_t size) 65 { 66 return (size - sizeof(MarkStackSegment)) / sizeof(const JSCell*); 67 } 68 69 static size_t sizeFromCapacity(size_t capacity) 70 { 71 return sizeof(MarkStackSegment) + capacity * sizeof(const JSCell*); 72 } 73 }; 74 75 class MarkStackSegmentAllocator { 76 public: 77 MarkStackSegmentAllocator(); 78 ~MarkStackSegmentAllocator(); 79 80 MarkStackSegment* allocate(); 81 void release(MarkStackSegment*); 82 83 void shrinkReserve(); 84 85 private: 86 Mutex m_lock; 87 MarkStackSegment* m_nextFreeSegment; 88 }; 89 50 90 class MarkStackArray { 51 91 public: 52 MarkStackArray( );92 MarkStackArray(MarkStackSegmentAllocator&); 53 93 ~MarkStackArray(); 54 94 95 void append(const JSCell*); 96 97 bool canRemoveLast(); 98 const JSCell* removeLast(); 99 bool refill(); 100 101 bool isEmpty(); 102 103 bool canDonateSomeCells(); // Returns false if you should definitely not call doanteSomeCellsTo(). 104 bool donateSomeCellsTo(MarkStackArray& other); // Returns true if some cells were donated. 105 106 void stealSomeCellsFrom(MarkStackArray& other); 107 108 size_t size(); 109 110 private: 111 MarkStackSegment* m_topSegment; 112 55 113 void expand(); 56 void append(const JSCell*); 57 58 const JSCell* removeLast(); 59 60 bool isEmpty(); 61 62 void shrinkAllocation(size_t); 63 114 115 MarkStackSegmentAllocator& m_allocator; 116 117 size_t m_segmentCapacity; 118 size_t m_top; 119 size_t m_numberOfPreviousSegments; 120 121 size_t postIncTop() 122 { 123 size_t result = m_top++; 124 ASSERT(result == m_topSegment->m_top++); 125 return result; 126 } 127 128 size_t preDecTop() 129 { 130 size_t result = --m_top; 131 ASSERT(result == --m_topSegment->m_top); 132 return result; 133 } 134 135 void setTopForFullSegment() 136 { 137 ASSERT(m_topSegment->m_top == m_segmentCapacity); 138 m_top = m_segmentCapacity; 139 } 140 141 void setTopForEmptySegment() 142 { 143 ASSERT(!m_topSegment->m_top); 144 m_top = 0; 145 } 146 147 size_t top() 148 { 149 ASSERT(m_top == m_topSegment->m_top); 150 return m_top; 151 } 152 153 #if ASSERT_DISABLED 154 void validatePrevious() { } 155 #else 156 void validatePrevious() 157 { 158 unsigned count = 0; 159 for (MarkStackSegment* current = m_topSegment->m_previous; current; current = current->m_previous) 160 count++; 161 ASSERT(count == m_numberOfPreviousSegments); 162 } 163 #endif 164 }; 165 166 class MarkStackThreadSharedData { 167 public: 168 MarkStackThreadSharedData(JSGlobalData*); 169 ~MarkStackThreadSharedData(); 170 171 void reset(); 172 64 173 private: 65 const JSCell** m_data; 66 size_t m_top; 67 size_t m_capacity; 68 size_t m_allocated; 174 friend class MarkStack; 175 friend class SlotVisitor; 176 177 #if ENABLE(PARALLEL_GC) 178 void markingThreadMain(); 179 static void* markingThreadStartFunc(void* heap); 180 #endif 181 182 JSGlobalData* m_globalData; 183 184 MarkStackSegmentAllocator m_segmentAllocator; 185 186 Vector<ThreadIdentifier> m_markingThreads; 187 188 Mutex m_markingLock; 189 ThreadCondition m_markingCondition; 190 MarkStackArray m_sharedMarkStack; 191 unsigned m_numberOfActiveParallelMarkers; 192 bool m_parallelMarkersShouldExit; 193 194 Mutex m_opaqueRootsLock; 195 HashSet<void*> m_opaqueRoots; 196 197 Mutex m_weakReferenceHarvesterLock; 198 WeakReferenceHarvester* m_firstWeakReferenceHarvester; 69 199 }; 70 200 … … 74 204 75 205 public: 76 static void* allocateStack(size_t); 77 static void releaseStack(void*, size_t); 78 79 MarkStack(void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr); 206 MarkStack(MarkStackThreadSharedData&, void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr); 80 207 ~MarkStack(); 81 208 … … 89 216 void appendUnbarrieredPointer(T**); 90 217 91 booladdOpaqueRoot(void*);218 void addOpaqueRoot(void*); 92 219 bool containsOpaqueRoot(void*); 93 220 int opaqueRootCount(); … … 103 230 void addWeakReferenceHarvester(WeakReferenceHarvester* weakReferenceHarvester) 104 231 { 232 MutexLocker locker(m_shared.m_weakReferenceHarvesterLock); 105 233 if (weakReferenceHarvester->m_nextAndFlag & 1) 106 234 return; 107 weakReferenceHarvester->m_nextAndFlag = reinterpret_cast<uintptr_t>(m_ firstWeakReferenceHarvester) | 1;108 m_ firstWeakReferenceHarvester = weakReferenceHarvester;235 weakReferenceHarvester->m_nextAndFlag = reinterpret_cast<uintptr_t>(m_shared.m_firstWeakReferenceHarvester) | 1; 236 m_shared.m_firstWeakReferenceHarvester = weakReferenceHarvester; 109 237 } 110 238 … … 118 246 void internalAppend(JSCell*); 119 247 void internalAppend(JSValue); 120 248 249 void mergeOpaqueRoots(); 250 251 void mergeOpaqueRootsIfNecessary() 252 { 253 if (m_opaqueRoots.isEmpty()) 254 return; 255 mergeOpaqueRoots(); 256 } 257 258 void mergeOpaqueRootsIfProfitable() 259 { 260 if (static_cast<unsigned>(m_opaqueRoots.size()) < Heuristics::opaqueRootMergeThreshold) 261 return; 262 mergeOpaqueRoots(); 263 } 264 121 265 MarkStackArray m_stack; 122 266 void* m_jsArrayVPtr; … … 124 268 void* m_jsStringVPtr; 125 269 HashSet<void*> m_opaqueRoots; // Handle-owning data structures not visible to the garbage collector. 126 WeakReferenceHarvester* m_firstWeakReferenceHarvester;127 270 128 271 #if !ASSERT_DISABLED … … 132 275 #endif 133 276 protected: 277 friend class ParallelModeEnabler; 278 134 279 size_t m_visitCount; 135 }; 136 137 inline MarkStack::MarkStack(void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr) 138 : m_jsArrayVPtr(jsArrayVPtr) 280 bool m_isInParallelMode; 281 282 MarkStackThreadSharedData& m_shared; 283 }; 284 285 inline MarkStack::MarkStack(MarkStackThreadSharedData& shared, void* jsArrayVPtr, void* jsFinalObjectVPtr, void* jsStringVPtr) 286 : m_stack(shared.m_segmentAllocator) 287 , m_jsArrayVPtr(jsArrayVPtr) 139 288 , m_jsFinalObjectVPtr(jsFinalObjectVPtr) 140 289 , m_jsStringVPtr(jsStringVPtr) 141 , m_firstWeakReferenceHarvester(0)142 290 #if !ASSERT_DISABLED 143 291 , m_isCheckingForDefaultMarkViolation(false) … … 145 293 #endif 146 294 , m_visitCount(0) 295 , m_isInParallelMode(false) 296 , m_shared(shared) 147 297 { 148 298 } … … 153 303 } 154 304 155 inline bool MarkStack::addOpaqueRoot(void* root) 156 { 157 return m_opaqueRoots.add(root).second; 305 inline void MarkStack::addOpaqueRoot(void* root) 306 { 307 #if ENABLE(PARALLEL_GC) 308 if (Heuristics::numberOfGCMarkers == 1) { 309 // Put directly into the shared HashSet. 310 m_shared.m_opaqueRoots.add(root); 311 return; 312 } 313 // Put into the local set, but merge with the shared one every once in 314 // a while to make sure that the local sets don't grow too large. 315 mergeOpaqueRootsIfProfitable(); 316 m_opaqueRoots.add(root); 317 #else 318 m_opaqueRoots.add(root); 319 #endif 158 320 } 159 321 160 322 inline bool MarkStack::containsOpaqueRoot(void* root) 161 323 { 324 ASSERT(!m_isInParallelMode); 325 #if ENABLE(PARALLEL_GC) 326 ASSERT(m_opaqueRoots.isEmpty()); 327 return m_shared.m_opaqueRoots.contains(root); 328 #else 162 329 return m_opaqueRoots.contains(root); 330 #endif 163 331 } 164 332 165 333 inline int MarkStack::opaqueRootCount() 166 334 { 335 ASSERT(!m_isInParallelMode); 336 #if ENABLE(PARALLEL_GC) 337 ASSERT(m_opaqueRoots.isEmpty()); 338 return m_shared.m_opaqueRoots.size(); 339 #else 167 340 return m_opaqueRoots.size(); 168 } 169 170 inline void* MarkStack::allocateStack(size_t size) 171 { 172 return OSAllocator::reserveAndCommit(size); 173 } 174 175 inline void MarkStack::releaseStack(void* addr, size_t size) 176 { 177 OSAllocator::decommitAndRelease(addr, size); 341 #endif 178 342 } 179 343 180 344 inline void MarkStackArray::append(const JSCell* cell) 181 345 { 182 if (m_top == m_ capacity)346 if (m_top == m_segmentCapacity) 183 347 expand(); 184 m_data[m_top++] = cell; 348 m_topSegment->data()[postIncTop()] = cell; 349 } 350 351 inline bool MarkStackArray::canRemoveLast() 352 { 353 return !!m_top; 185 354 } 186 355 187 356 inline const JSCell* MarkStackArray::removeLast() 188 357 { 189 ASSERT(m_top); 190 return m_data[--m_top]; 191 } 192 358 return m_topSegment->data()[preDecTop()]; 359 } 360 193 361 inline bool MarkStackArray::isEmpty() 194 362 { 195 return !m_top; 363 if (m_top) 364 return false; 365 if (m_topSegment->m_previous) { 366 ASSERT(m_topSegment->m_previous->m_top == m_segmentCapacity); 367 return false; 368 } 369 return true; 370 } 371 372 inline bool MarkStackArray::canDonateSomeCells() 373 { 374 size_t numberOfCellsToKeep = Heuristics::minimumNumberOfCellsToKeep; 375 // Another check: see if we have enough cells to warrant donation. 376 if (m_top <= numberOfCellsToKeep) { 377 // This indicates that we might not want to donate anything; check if we have 378 // another full segment. If not, then don't donate. 379 if (!m_topSegment->m_previous) 380 return false; 381 382 ASSERT(m_topSegment->m_previous->m_top == m_segmentCapacity); 383 } 384 385 return true; 386 } 387 388 inline size_t MarkStackArray::size() 389 { 390 return m_top + m_segmentCapacity * m_numberOfPreviousSegments; 196 391 } 197 392 … … 235 430 } 236 431 237 class SlotVisitor; 432 class ParallelModeEnabler { 433 public: 434 ParallelModeEnabler(MarkStack& stack) 435 : m_stack(stack) 436 { 437 ASSERT(!m_stack.m_isInParallelMode); 438 m_stack.m_isInParallelMode = true; 439 } 440 441 ~ParallelModeEnabler() 442 { 443 ASSERT(m_stack.m_isInParallelMode); 444 m_stack.m_isInParallelMode = false; 445 } 446 447 private: 448 MarkStack& m_stack; 449 }; 238 450 239 451 } // namespace JSC
Note:
See TracChangeset
for help on using the changeset viewer.