| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
| 3 * | 3 * |
| 4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
| 5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
| 6 * met: | 6 * met: |
| 7 * | 7 * |
| 8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
| 9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
| 10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
| (...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 182 void ThreadHeapStats::decreaseAllocatedSpace(size_t delta) { | 182 void ThreadHeapStats::decreaseAllocatedSpace(size_t delta) { |
| 183 atomicSubtract(&m_allocatedSpace, static_cast<long>(delta)); | 183 atomicSubtract(&m_allocatedSpace, static_cast<long>(delta)); |
| 184 ProcessHeap::decreaseTotalAllocatedSpace(delta); | 184 ProcessHeap::decreaseTotalAllocatedSpace(delta); |
| 185 } | 185 } |
| 186 | 186 |
| 187 ThreadHeap::ThreadHeap() | 187 ThreadHeap::ThreadHeap() |
| 188 : m_regionTree(WTF::makeUnique<RegionTree>()), | 188 : m_regionTree(WTF::makeUnique<RegionTree>()), |
| 189 m_heapDoesNotContainCache(WTF::wrapUnique(new HeapDoesNotContainCache)), | 189 m_heapDoesNotContainCache(WTF::wrapUnique(new HeapDoesNotContainCache)), |
| 190 m_safePointBarrier(WTF::makeUnique<SafePointBarrier>()), | 190 m_safePointBarrier(WTF::makeUnique<SafePointBarrier>()), |
| 191 m_freePagePool(WTF::wrapUnique(new FreePagePool)), | 191 m_freePagePool(WTF::wrapUnique(new FreePagePool)), |
| 192 m_orphanedPagePool(WTF::wrapUnique(new OrphanedPagePool)), | |
| 193 m_markingStack(CallbackStack::create()), | 192 m_markingStack(CallbackStack::create()), |
| 194 m_postMarkingCallbackStack(CallbackStack::create()), | 193 m_postMarkingCallbackStack(CallbackStack::create()), |
| 195 m_globalWeakCallbackStack(CallbackStack::create()), | 194 m_globalWeakCallbackStack(CallbackStack::create()), |
| 196 m_ephemeronStack(CallbackStack::create()) { | 195 m_ephemeronStack(CallbackStack::create()) { |
| 197 if (ThreadState::current()->isMainThread()) | 196 if (ThreadState::current()->isMainThread()) |
| 198 s_mainThreadHeap = this; | 197 s_mainThreadHeap = this; |
| 199 | 198 |
| 200 MutexLocker locker(ThreadHeap::allHeapsMutex()); | 199 MutexLocker locker(ThreadHeap::allHeapsMutex()); |
| 201 allHeaps().insert(this); | 200 allHeaps().insert(this); |
| 202 } | 201 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 Address ThreadHeap::checkAndMarkPointer(Visitor* visitor, Address address) { | 274 Address ThreadHeap::checkAndMarkPointer(Visitor* visitor, Address address) { |
| 276 ASSERT(ThreadState::current()->isInGC()); | 275 ASSERT(ThreadState::current()->isInGC()); |
| 277 | 276 |
| 278 #if !DCHECK_IS_ON() | 277 #if !DCHECK_IS_ON() |
| 279 if (m_heapDoesNotContainCache->lookup(address)) | 278 if (m_heapDoesNotContainCache->lookup(address)) |
| 280 return nullptr; | 279 return nullptr; |
| 281 #endif | 280 #endif |
| 282 | 281 |
| 283 if (BasePage* page = lookupPageForAddress(address)) { | 282 if (BasePage* page = lookupPageForAddress(address)) { |
| 284 ASSERT(page->contains(address)); | 283 ASSERT(page->contains(address)); |
| 285 ASSERT(!page->orphaned()); | |
| 286 ASSERT(!m_heapDoesNotContainCache->lookup(address)); | 284 ASSERT(!m_heapDoesNotContainCache->lookup(address)); |
| 287 DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap()); | 285 DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap()); |
| 288 page->checkAndMarkPointer(visitor, address); | 286 page->checkAndMarkPointer(visitor, address); |
| 289 return address; | 287 return address; |
| 290 } | 288 } |
| 291 | 289 |
| 292 #if !DCHECK_IS_ON() | 290 #if !DCHECK_IS_ON() |
| 293 m_heapDoesNotContainCache->addEntry(address); | 291 m_heapDoesNotContainCache->addEntry(address); |
| 294 #else | 292 #else |
| 295 if (!m_heapDoesNotContainCache->lookup(address)) | 293 if (!m_heapDoesNotContainCache->lookup(address)) |
| 296 m_heapDoesNotContainCache->addEntry(address); | 294 m_heapDoesNotContainCache->addEntry(address); |
| 297 #endif | 295 #endif |
| 298 return nullptr; | 296 return nullptr; |
| 299 } | 297 } |
| 300 | 298 |
| 301 #if DCHECK_IS_ON() | 299 #if DCHECK_IS_ON() |
| 302 // To support unit testing of the marking of off-heap root references | 300 // To support unit testing of the marking of off-heap root references |
| 303 // into the heap, provide a checkAndMarkPointer() version with an | 301 // into the heap, provide a checkAndMarkPointer() version with an |
| 304 // extra notification argument. | 302 // extra notification argument. |
| 305 Address ThreadHeap::checkAndMarkPointer( | 303 Address ThreadHeap::checkAndMarkPointer( |
| 306 Visitor* visitor, | 304 Visitor* visitor, |
| 307 Address address, | 305 Address address, |
| 308 MarkedPointerCallbackForTesting callback) { | 306 MarkedPointerCallbackForTesting callback) { |
| 309 DCHECK(ThreadState::current()->isInGC()); | 307 DCHECK(ThreadState::current()->isInGC()); |
| 310 | 308 |
| 311 if (BasePage* page = lookupPageForAddress(address)) { | 309 if (BasePage* page = lookupPageForAddress(address)) { |
| 312 DCHECK(page->contains(address)); | 310 DCHECK(page->contains(address)); |
| 313 DCHECK(!page->orphaned()); | |
| 314 DCHECK(!m_heapDoesNotContainCache->lookup(address)); | 311 DCHECK(!m_heapDoesNotContainCache->lookup(address)); |
| 315 DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap()); | 312 DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap()); |
| 316 page->checkAndMarkPointer(visitor, address, callback); | 313 page->checkAndMarkPointer(visitor, address, callback); |
| 317 return address; | 314 return address; |
| 318 } | 315 } |
| 319 if (!m_heapDoesNotContainCache->lookup(address)) | 316 if (!m_heapDoesNotContainCache->lookup(address)) |
| 320 m_heapDoesNotContainCache->addEntry(address); | 317 m_heapDoesNotContainCache->addEntry(address); |
| 321 return nullptr; | 318 return nullptr; |
| 322 } | 319 } |
| 323 #endif | 320 #endif |
| 324 | 321 |
| 325 void ThreadHeap::pushTraceCallback(void* object, TraceCallback callback) { | 322 void ThreadHeap::pushTraceCallback(void* object, TraceCallback callback) { |
| 326 ASSERT(ThreadState::current()->isInGC()); | 323 ASSERT(ThreadState::current()->isInGC()); |
| 327 | 324 |
| 328 // Trace should never reach an orphaned page. | |
| 329 ASSERT(!getOrphanedPagePool()->contains(object)); | |
| 330 CallbackStack::Item* slot = m_markingStack->allocateEntry(); | 325 CallbackStack::Item* slot = m_markingStack->allocateEntry(); |
| 331 *slot = CallbackStack::Item(object, callback); | 326 *slot = CallbackStack::Item(object, callback); |
| 332 } | 327 } |
| 333 | 328 |
| 334 bool ThreadHeap::popAndInvokeTraceCallback(Visitor* visitor) { | 329 bool ThreadHeap::popAndInvokeTraceCallback(Visitor* visitor) { |
| 335 CallbackStack::Item* item = m_markingStack->pop(); | 330 CallbackStack::Item* item = m_markingStack->pop(); |
| 336 if (!item) | 331 if (!item) |
| 337 return false; | 332 return false; |
| 338 item->call(visitor); | 333 item->call(visitor); |
| 339 return true; | 334 return true; |
| 340 } | 335 } |
| 341 | 336 |
| 342 void ThreadHeap::pushPostMarkingCallback(void* object, TraceCallback callback) { | 337 void ThreadHeap::pushPostMarkingCallback(void* object, TraceCallback callback) { |
| 343 ASSERT(ThreadState::current()->isInGC()); | 338 ASSERT(ThreadState::current()->isInGC()); |
| 344 | 339 |
| 345 // Trace should never reach an orphaned page. | |
| 346 ASSERT(!getOrphanedPagePool()->contains(object)); | |
| 347 CallbackStack::Item* slot = m_postMarkingCallbackStack->allocateEntry(); | 340 CallbackStack::Item* slot = m_postMarkingCallbackStack->allocateEntry(); |
| 348 *slot = CallbackStack::Item(object, callback); | 341 *slot = CallbackStack::Item(object, callback); |
| 349 } | 342 } |
| 350 | 343 |
| 351 bool ThreadHeap::popAndInvokePostMarkingCallback(Visitor* visitor) { | 344 bool ThreadHeap::popAndInvokePostMarkingCallback(Visitor* visitor) { |
| 352 if (CallbackStack::Item* item = m_postMarkingCallbackStack->pop()) { | 345 if (CallbackStack::Item* item = m_postMarkingCallbackStack->pop()) { |
| 353 item->call(visitor); | 346 item->call(visitor); |
| 354 return true; | 347 return true; |
| 355 } | 348 } |
| 356 return false; | 349 return false; |
| 357 } | 350 } |
| 358 | 351 |
| 359 void ThreadHeap::pushGlobalWeakCallback(void** cell, WeakCallback callback) { | 352 void ThreadHeap::pushGlobalWeakCallback(void** cell, WeakCallback callback) { |
| 360 ASSERT(ThreadState::current()->isInGC()); | 353 ASSERT(ThreadState::current()->isInGC()); |
| 361 | 354 |
| 362 // Trace should never reach an orphaned page. | |
| 363 ASSERT(!getOrphanedPagePool()->contains(cell)); | |
| 364 CallbackStack::Item* slot = m_globalWeakCallbackStack->allocateEntry(); | 355 CallbackStack::Item* slot = m_globalWeakCallbackStack->allocateEntry(); |
| 365 *slot = CallbackStack::Item(cell, callback); | 356 *slot = CallbackStack::Item(cell, callback); |
| 366 } | 357 } |
| 367 | 358 |
| 368 void ThreadHeap::pushThreadLocalWeakCallback(void* closure, | 359 void ThreadHeap::pushThreadLocalWeakCallback(void* closure, |
| 369 void* object, | 360 void* object, |
| 370 WeakCallback callback) { | 361 WeakCallback callback) { |
| 371 ASSERT(ThreadState::current()->isInGC()); | 362 ASSERT(ThreadState::current()->isInGC()); |
| 372 | 363 |
| 373 // Trace should never reach an orphaned page. | |
| 374 ASSERT(!getOrphanedPagePool()->contains(object)); | |
| 375 ThreadState* state = pageFromObject(object)->arena()->getThreadState(); | 364 ThreadState* state = pageFromObject(object)->arena()->getThreadState(); |
| 376 state->pushThreadLocalWeakCallback(closure, callback); | 365 state->pushThreadLocalWeakCallback(closure, callback); |
| 377 } | 366 } |
| 378 | 367 |
| 379 bool ThreadHeap::popAndInvokeGlobalWeakCallback(Visitor* visitor) { | 368 bool ThreadHeap::popAndInvokeGlobalWeakCallback(Visitor* visitor) { |
| 380 if (CallbackStack::Item* item = m_globalWeakCallbackStack->pop()) { | 369 if (CallbackStack::Item* item = m_globalWeakCallbackStack->pop()) { |
| 381 item->call(visitor); | 370 item->call(visitor); |
| 382 return true; | 371 return true; |
| 383 } | 372 } |
| 384 return false; | 373 return false; |
| 385 } | 374 } |
| 386 | 375 |
| 387 void ThreadHeap::registerWeakTable(void* table, | 376 void ThreadHeap::registerWeakTable(void* table, |
| 388 EphemeronCallback iterationCallback, | 377 EphemeronCallback iterationCallback, |
| 389 EphemeronCallback iterationDoneCallback) { | 378 EphemeronCallback iterationDoneCallback) { |
| 390 ASSERT(ThreadState::current()->isInGC()); | 379 ASSERT(ThreadState::current()->isInGC()); |
| 391 | 380 |
| 392 // Trace should never reach an orphaned page. | |
| 393 ASSERT(!getOrphanedPagePool()->contains(table)); | |
| 394 CallbackStack::Item* slot = m_ephemeronStack->allocateEntry(); | 381 CallbackStack::Item* slot = m_ephemeronStack->allocateEntry(); |
| 395 *slot = CallbackStack::Item(table, iterationCallback); | 382 *slot = CallbackStack::Item(table, iterationCallback); |
| 396 | 383 |
| 397 // Register a post-marking callback to tell the tables that | 384 // Register a post-marking callback to tell the tables that |
| 398 // ephemeron iteration is complete. | 385 // ephemeron iteration is complete. |
| 399 pushPostMarkingCallback(table, iterationDoneCallback); | 386 pushPostMarkingCallback(table, iterationDoneCallback); |
| 400 } | 387 } |
| 401 | 388 |
| 402 #if DCHECK_IS_ON() | 389 #if DCHECK_IS_ON() |
| 403 bool ThreadHeap::weakTableRegistered(const void* table) { | 390 bool ThreadHeap::weakTableRegistered(const void* table) { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 638 } | 625 } |
| 639 | 626 |
| 640 void ThreadHeap::leaveSafePoint(ThreadState* threadState, | 627 void ThreadHeap::leaveSafePoint(ThreadState* threadState, |
| 641 SafePointAwareMutexLocker* locker) { | 628 SafePointAwareMutexLocker* locker) { |
| 642 m_safePointBarrier->leaveSafePoint(threadState, locker); | 629 m_safePointBarrier->leaveSafePoint(threadState, locker); |
| 643 } | 630 } |
| 644 | 631 |
| 645 BasePage* ThreadHeap::lookupPageForAddress(Address address) { | 632 BasePage* ThreadHeap::lookupPageForAddress(Address address) { |
| 646 ASSERT(ThreadState::current()->isInGC()); | 633 ASSERT(ThreadState::current()->isInGC()); |
| 647 if (PageMemoryRegion* region = m_regionTree->lookup(address)) { | 634 if (PageMemoryRegion* region = m_regionTree->lookup(address)) { |
| 648 BasePage* page = region->pageFromAddress(address); | 635 return region->pageFromAddress(address); |
| 649 return page && !page->orphaned() ? page : nullptr; | |
| 650 } | 636 } |
| 651 return nullptr; | 637 return nullptr; |
| 652 } | 638 } |
| 653 | 639 |
| 654 void ThreadHeap::resetHeapCounters() { | 640 void ThreadHeap::resetHeapCounters() { |
| 655 ASSERT(ThreadState::current()->isInGC()); | 641 ASSERT(ThreadState::current()->isInGC()); |
| 656 | 642 |
| 657 ThreadHeap::reportMemoryUsageForTracing(); | 643 ThreadHeap::reportMemoryUsageForTracing(); |
| 658 | 644 |
| 659 ProcessHeap::decreaseTotalAllocatedObjectSize(m_stats.allocatedObjectSize()); | 645 ProcessHeap::decreaseTotalAllocatedObjectSize(m_stats.allocatedObjectSize()); |
| 660 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); | 646 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); |
| 661 | 647 |
| 662 m_stats.reset(); | 648 m_stats.reset(); |
| 663 for (ThreadState* state : m_threads) | 649 for (ThreadState* state : m_threads) |
| 664 state->resetHeapCounters(); | 650 state->resetHeapCounters(); |
| 665 } | 651 } |
| 666 | 652 |
| 667 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; | 653 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; |
| 668 | 654 |
| 669 } // namespace blink | 655 } // namespace blink |
| OLD | NEW |