| 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 188 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 199 void ThreadHeapStats::decreaseAllocatedSpace(size_t delta) { | 199 void ThreadHeapStats::decreaseAllocatedSpace(size_t delta) { |
| 200 atomicSubtract(&m_allocatedSpace, static_cast<long>(delta)); | 200 atomicSubtract(&m_allocatedSpace, static_cast<long>(delta)); |
| 201 ProcessHeap::decreaseTotalAllocatedSpace(delta); | 201 ProcessHeap::decreaseTotalAllocatedSpace(delta); |
| 202 } | 202 } |
| 203 | 203 |
| 204 ThreadHeap::ThreadHeap() | 204 ThreadHeap::ThreadHeap() |
| 205 : m_regionTree(WTF::makeUnique<RegionTree>()), | 205 : m_regionTree(WTF::makeUnique<RegionTree>()), |
| 206 m_heapDoesNotContainCache(WTF::wrapUnique(new HeapDoesNotContainCache)), | 206 m_heapDoesNotContainCache(WTF::wrapUnique(new HeapDoesNotContainCache)), |
| 207 m_safePointBarrier(WTF::makeUnique<SafePointBarrier>()), | 207 m_safePointBarrier(WTF::makeUnique<SafePointBarrier>()), |
| 208 m_freePagePool(WTF::wrapUnique(new FreePagePool)), | 208 m_freePagePool(WTF::wrapUnique(new FreePagePool)), |
| 209 m_orphanedPagePool(WTF::wrapUnique(new OrphanedPagePool)), | |
| 210 m_markingStack(CallbackStack::create()), | 209 m_markingStack(CallbackStack::create()), |
| 211 m_postMarkingCallbackStack(CallbackStack::create()), | 210 m_postMarkingCallbackStack(CallbackStack::create()), |
| 212 m_globalWeakCallbackStack(CallbackStack::create()), | 211 m_globalWeakCallbackStack(CallbackStack::create()), |
| 213 m_ephemeronStack(CallbackStack::create()) { | 212 m_ephemeronStack(CallbackStack::create()) { |
| 214 if (ThreadState::current()->isMainThread()) | 213 if (ThreadState::current()->isMainThread()) |
| 215 s_mainThreadHeap = this; | 214 s_mainThreadHeap = this; |
| 216 | 215 |
| 217 MutexLocker locker(ThreadHeap::allHeapsMutex()); | 216 MutexLocker locker(ThreadHeap::allHeapsMutex()); |
| 218 allHeaps().insert(this); | 217 allHeaps().insert(this); |
| 219 } | 218 } |
| (...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 292 Address ThreadHeap::checkAndMarkPointer(Visitor* visitor, Address address) { | 291 Address ThreadHeap::checkAndMarkPointer(Visitor* visitor, Address address) { |
| 293 ASSERT(ThreadState::current()->isInGC()); | 292 ASSERT(ThreadState::current()->isInGC()); |
| 294 | 293 |
| 295 #if !DCHECK_IS_ON() | 294 #if !DCHECK_IS_ON() |
| 296 if (m_heapDoesNotContainCache->lookup(address)) | 295 if (m_heapDoesNotContainCache->lookup(address)) |
| 297 return nullptr; | 296 return nullptr; |
| 298 #endif | 297 #endif |
| 299 | 298 |
| 300 if (BasePage* page = lookupPageForAddress(address)) { | 299 if (BasePage* page = lookupPageForAddress(address)) { |
| 301 ASSERT(page->contains(address)); | 300 ASSERT(page->contains(address)); |
| 302 ASSERT(!page->orphaned()); | |
| 303 ASSERT(!m_heapDoesNotContainCache->lookup(address)); | 301 ASSERT(!m_heapDoesNotContainCache->lookup(address)); |
| 304 DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap()); | 302 DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap()); |
| 305 page->checkAndMarkPointer(visitor, address); | 303 page->checkAndMarkPointer(visitor, address); |
| 306 return address; | 304 return address; |
| 307 } | 305 } |
| 308 | 306 |
| 309 #if !DCHECK_IS_ON() | 307 #if !DCHECK_IS_ON() |
| 310 m_heapDoesNotContainCache->addEntry(address); | 308 m_heapDoesNotContainCache->addEntry(address); |
| 311 #else | 309 #else |
| 312 if (!m_heapDoesNotContainCache->lookup(address)) | 310 if (!m_heapDoesNotContainCache->lookup(address)) |
| 313 m_heapDoesNotContainCache->addEntry(address); | 311 m_heapDoesNotContainCache->addEntry(address); |
| 314 #endif | 312 #endif |
| 315 return nullptr; | 313 return nullptr; |
| 316 } | 314 } |
| 317 | 315 |
| 318 #if DCHECK_IS_ON() | 316 #if DCHECK_IS_ON() |
| 319 // To support unit testing of the marking of off-heap root references | 317 // To support unit testing of the marking of off-heap root references |
| 320 // into the heap, provide a checkAndMarkPointer() version with an | 318 // into the heap, provide a checkAndMarkPointer() version with an |
| 321 // extra notification argument. | 319 // extra notification argument. |
| 322 Address ThreadHeap::checkAndMarkPointer( | 320 Address ThreadHeap::checkAndMarkPointer( |
| 323 Visitor* visitor, | 321 Visitor* visitor, |
| 324 Address address, | 322 Address address, |
| 325 MarkedPointerCallbackForTesting callback) { | 323 MarkedPointerCallbackForTesting callback) { |
| 326 DCHECK(ThreadState::current()->isInGC()); | 324 DCHECK(ThreadState::current()->isInGC()); |
| 327 | 325 |
| 328 if (BasePage* page = lookupPageForAddress(address)) { | 326 if (BasePage* page = lookupPageForAddress(address)) { |
| 329 DCHECK(page->contains(address)); | 327 DCHECK(page->contains(address)); |
| 330 DCHECK(!page->orphaned()); | |
| 331 DCHECK(!m_heapDoesNotContainCache->lookup(address)); | 328 DCHECK(!m_heapDoesNotContainCache->lookup(address)); |
| 332 DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap()); | 329 DCHECK(&visitor->heap() == &page->arena()->getThreadState()->heap()); |
| 333 page->checkAndMarkPointer(visitor, address, callback); | 330 page->checkAndMarkPointer(visitor, address, callback); |
| 334 return address; | 331 return address; |
| 335 } | 332 } |
| 336 if (!m_heapDoesNotContainCache->lookup(address)) | 333 if (!m_heapDoesNotContainCache->lookup(address)) |
| 337 m_heapDoesNotContainCache->addEntry(address); | 334 m_heapDoesNotContainCache->addEntry(address); |
| 338 return nullptr; | 335 return nullptr; |
| 339 } | 336 } |
| 340 #endif | 337 #endif |
| 341 | 338 |
| 342 void ThreadHeap::pushTraceCallback(void* object, TraceCallback callback) { | 339 void ThreadHeap::pushTraceCallback(void* object, TraceCallback callback) { |
| 343 ASSERT(ThreadState::current()->isInGC()); | 340 ASSERT(ThreadState::current()->isInGC()); |
| 344 | 341 |
| 345 // Trace should never reach an orphaned page. | |
| 346 ASSERT(!getOrphanedPagePool()->contains(object)); | |
| 347 CallbackStack::Item* slot = m_markingStack->allocateEntry(); | 342 CallbackStack::Item* slot = m_markingStack->allocateEntry(); |
| 348 *slot = CallbackStack::Item(object, callback); | 343 *slot = CallbackStack::Item(object, callback); |
| 349 } | 344 } |
| 350 | 345 |
| 351 bool ThreadHeap::popAndInvokeTraceCallback(Visitor* visitor) { | 346 bool ThreadHeap::popAndInvokeTraceCallback(Visitor* visitor) { |
| 352 CallbackStack::Item* item = m_markingStack->pop(); | 347 CallbackStack::Item* item = m_markingStack->pop(); |
| 353 if (!item) | 348 if (!item) |
| 354 return false; | 349 return false; |
| 355 item->call(visitor); | 350 item->call(visitor); |
| 356 return true; | 351 return true; |
| 357 } | 352 } |
| 358 | 353 |
| 359 void ThreadHeap::pushPostMarkingCallback(void* object, TraceCallback callback) { | 354 void ThreadHeap::pushPostMarkingCallback(void* object, TraceCallback callback) { |
| 360 ASSERT(ThreadState::current()->isInGC()); | 355 ASSERT(ThreadState::current()->isInGC()); |
| 361 | 356 |
| 362 // Trace should never reach an orphaned page. | |
| 363 ASSERT(!getOrphanedPagePool()->contains(object)); | |
| 364 CallbackStack::Item* slot = m_postMarkingCallbackStack->allocateEntry(); | 357 CallbackStack::Item* slot = m_postMarkingCallbackStack->allocateEntry(); |
| 365 *slot = CallbackStack::Item(object, callback); | 358 *slot = CallbackStack::Item(object, callback); |
| 366 } | 359 } |
| 367 | 360 |
| 368 bool ThreadHeap::popAndInvokePostMarkingCallback(Visitor* visitor) { | 361 bool ThreadHeap::popAndInvokePostMarkingCallback(Visitor* visitor) { |
| 369 if (CallbackStack::Item* item = m_postMarkingCallbackStack->pop()) { | 362 if (CallbackStack::Item* item = m_postMarkingCallbackStack->pop()) { |
| 370 item->call(visitor); | 363 item->call(visitor); |
| 371 return true; | 364 return true; |
| 372 } | 365 } |
| 373 return false; | 366 return false; |
| 374 } | 367 } |
| 375 | 368 |
| 376 void ThreadHeap::pushGlobalWeakCallback(void** cell, WeakCallback callback) { | 369 void ThreadHeap::pushGlobalWeakCallback(void** cell, WeakCallback callback) { |
| 377 ASSERT(ThreadState::current()->isInGC()); | 370 ASSERT(ThreadState::current()->isInGC()); |
| 378 | 371 |
| 379 // Trace should never reach an orphaned page. | |
| 380 ASSERT(!getOrphanedPagePool()->contains(cell)); | |
| 381 CallbackStack::Item* slot = m_globalWeakCallbackStack->allocateEntry(); | 372 CallbackStack::Item* slot = m_globalWeakCallbackStack->allocateEntry(); |
| 382 *slot = CallbackStack::Item(cell, callback); | 373 *slot = CallbackStack::Item(cell, callback); |
| 383 } | 374 } |
| 384 | 375 |
| 385 void ThreadHeap::pushThreadLocalWeakCallback(void* closure, | 376 void ThreadHeap::pushThreadLocalWeakCallback(void* closure, |
| 386 void* object, | 377 void* object, |
| 387 WeakCallback callback) { | 378 WeakCallback callback) { |
| 388 ASSERT(ThreadState::current()->isInGC()); | 379 ASSERT(ThreadState::current()->isInGC()); |
| 389 | 380 |
| 390 // Trace should never reach an orphaned page. | |
| 391 ASSERT(!getOrphanedPagePool()->contains(object)); | |
| 392 ThreadState* state = pageFromObject(object)->arena()->getThreadState(); | 381 ThreadState* state = pageFromObject(object)->arena()->getThreadState(); |
| 393 state->pushThreadLocalWeakCallback(closure, callback); | 382 state->pushThreadLocalWeakCallback(closure, callback); |
| 394 } | 383 } |
| 395 | 384 |
| 396 bool ThreadHeap::popAndInvokeGlobalWeakCallback(Visitor* visitor) { | 385 bool ThreadHeap::popAndInvokeGlobalWeakCallback(Visitor* visitor) { |
| 397 if (CallbackStack::Item* item = m_globalWeakCallbackStack->pop()) { | 386 if (CallbackStack::Item* item = m_globalWeakCallbackStack->pop()) { |
| 398 item->call(visitor); | 387 item->call(visitor); |
| 399 return true; | 388 return true; |
| 400 } | 389 } |
| 401 return false; | 390 return false; |
| 402 } | 391 } |
| 403 | 392 |
| 404 void ThreadHeap::registerWeakTable(void* table, | 393 void ThreadHeap::registerWeakTable(void* table, |
| 405 EphemeronCallback iterationCallback, | 394 EphemeronCallback iterationCallback, |
| 406 EphemeronCallback iterationDoneCallback) { | 395 EphemeronCallback iterationDoneCallback) { |
| 407 ASSERT(ThreadState::current()->isInGC()); | 396 ASSERT(ThreadState::current()->isInGC()); |
| 408 | 397 |
| 409 // Trace should never reach an orphaned page. | |
| 410 ASSERT(!getOrphanedPagePool()->contains(table)); | |
| 411 CallbackStack::Item* slot = m_ephemeronStack->allocateEntry(); | 398 CallbackStack::Item* slot = m_ephemeronStack->allocateEntry(); |
| 412 *slot = CallbackStack::Item(table, iterationCallback); | 399 *slot = CallbackStack::Item(table, iterationCallback); |
| 413 | 400 |
| 414 // Register a post-marking callback to tell the tables that | 401 // Register a post-marking callback to tell the tables that |
| 415 // ephemeron iteration is complete. | 402 // ephemeron iteration is complete. |
| 416 pushPostMarkingCallback(table, iterationDoneCallback); | 403 pushPostMarkingCallback(table, iterationDoneCallback); |
| 417 } | 404 } |
| 418 | 405 |
| 419 #if DCHECK_IS_ON() | 406 #if DCHECK_IS_ON() |
| 420 bool ThreadHeap::weakTableRegistered(const void* table) { | 407 bool ThreadHeap::weakTableRegistered(const void* table) { |
| (...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 } | 642 } |
| 656 | 643 |
| 657 void ThreadHeap::leaveSafePoint(ThreadState* threadState, | 644 void ThreadHeap::leaveSafePoint(ThreadState* threadState, |
| 658 SafePointAwareMutexLocker* locker) { | 645 SafePointAwareMutexLocker* locker) { |
| 659 m_safePointBarrier->leaveSafePoint(threadState, locker); | 646 m_safePointBarrier->leaveSafePoint(threadState, locker); |
| 660 } | 647 } |
| 661 | 648 |
| 662 BasePage* ThreadHeap::lookupPageForAddress(Address address) { | 649 BasePage* ThreadHeap::lookupPageForAddress(Address address) { |
| 663 ASSERT(ThreadState::current()->isInGC()); | 650 ASSERT(ThreadState::current()->isInGC()); |
| 664 if (PageMemoryRegion* region = m_regionTree->lookup(address)) { | 651 if (PageMemoryRegion* region = m_regionTree->lookup(address)) { |
| 665 BasePage* page = region->pageFromAddress(address); | 652 return region->pageFromAddress(address); |
| 666 return page && !page->orphaned() ? page : nullptr; | |
| 667 } | 653 } |
| 668 return nullptr; | 654 return nullptr; |
| 669 } | 655 } |
| 670 | 656 |
| 671 void ThreadHeap::resetHeapCounters() { | 657 void ThreadHeap::resetHeapCounters() { |
| 672 ASSERT(ThreadState::current()->isInGC()); | 658 ASSERT(ThreadState::current()->isInGC()); |
| 673 | 659 |
| 674 ThreadHeap::reportMemoryUsageForTracing(); | 660 ThreadHeap::reportMemoryUsageForTracing(); |
| 675 | 661 |
| 676 ProcessHeap::decreaseTotalAllocatedObjectSize(m_stats.allocatedObjectSize()); | 662 ProcessHeap::decreaseTotalAllocatedObjectSize(m_stats.allocatedObjectSize()); |
| 677 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); | 663 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); |
| 678 | 664 |
| 679 m_stats.reset(); | 665 m_stats.reset(); |
| 680 for (ThreadState* state : m_threads) | 666 for (ThreadState* state : m_threads) |
| 681 state->resetHeapCounters(); | 667 state->resetHeapCounters(); |
| 682 } | 668 } |
| 683 | 669 |
| 684 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; | 670 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; |
| 685 | 671 |
| 686 } // namespace blink | 672 } // namespace blink |
| OLD | NEW |