Chromium Code Reviews| 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 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 139 atomicAdd(&m_allocatedSpace, static_cast<long>(delta)); | 139 atomicAdd(&m_allocatedSpace, static_cast<long>(delta)); |
| 140 ProcessHeap::increaseTotalAllocatedSpace(delta); | 140 ProcessHeap::increaseTotalAllocatedSpace(delta); |
| 141 } | 141 } |
| 142 | 142 |
| 143 void ThreadHeapStats::decreaseAllocatedSpace(size_t delta) { | 143 void ThreadHeapStats::decreaseAllocatedSpace(size_t delta) { |
| 144 atomicSubtract(&m_allocatedSpace, static_cast<long>(delta)); | 144 atomicSubtract(&m_allocatedSpace, static_cast<long>(delta)); |
| 145 ProcessHeap::decreaseTotalAllocatedSpace(delta); | 145 ProcessHeap::decreaseTotalAllocatedSpace(delta); |
| 146 } | 146 } |
| 147 | 147 |
| 148 ThreadHeap::ThreadHeap() | 148 ThreadHeap::ThreadHeap() |
| 149 : m_regionTree(WTF::makeUnique<RegionTree>()), | 149 : m_threadState(nullptr), |
| 150 m_regionTree(WTF::makeUnique<RegionTree>()), | |
| 150 m_heapDoesNotContainCache(WTF::wrapUnique(new HeapDoesNotContainCache)), | 151 m_heapDoesNotContainCache(WTF::wrapUnique(new HeapDoesNotContainCache)), |
| 151 m_safePointBarrier(WTF::makeUnique<SafePointBarrier>()), | 152 m_safePointBarrier(WTF::makeUnique<SafePointBarrier>()), |
| 152 m_freePagePool(WTF::wrapUnique(new PagePool)), | 153 m_freePagePool(WTF::wrapUnique(new PagePool)), |
| 153 m_markingStack(CallbackStack::create()), | 154 m_markingStack(CallbackStack::create()), |
| 154 m_postMarkingCallbackStack(CallbackStack::create()), | 155 m_postMarkingCallbackStack(CallbackStack::create()), |
| 155 m_globalWeakCallbackStack(CallbackStack::create()), | 156 m_globalWeakCallbackStack(CallbackStack::create()), |
| 156 m_ephemeronStack(CallbackStack::create()) { | 157 m_ephemeronStack(CallbackStack::create()) { |
| 157 if (ThreadState::current()->isMainThread()) | 158 if (ThreadState::current()->isMainThread()) |
| 158 s_mainThreadHeap = this; | 159 s_mainThreadHeap = this; |
| 159 | 160 |
| 160 MutexLocker locker(ThreadHeap::allHeapsMutex()); | 161 MutexLocker locker(ThreadHeap::allHeapsMutex()); |
| 161 allHeaps().insert(this); | 162 allHeaps().insert(this); |
| 162 } | 163 } |
| 163 | 164 |
| 164 ThreadHeap::~ThreadHeap() { | 165 ThreadHeap::~ThreadHeap() { |
| 165 MutexLocker locker(ThreadHeap::allHeapsMutex()); | 166 MutexLocker locker(ThreadHeap::allHeapsMutex()); |
| 166 allHeaps().remove(this); | 167 allHeaps().remove(this); |
| 167 } | 168 } |
| 168 | 169 |
| 169 RecursiveMutex& ThreadHeap::allHeapsMutex() { | 170 RecursiveMutex& ThreadHeap::allHeapsMutex() { |
| 170 DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, mutex, (new RecursiveMutex)); | 171 DEFINE_THREAD_SAFE_STATIC_LOCAL(RecursiveMutex, mutex, (new RecursiveMutex)); |
| 171 return mutex; | 172 return mutex; |
| 172 } | 173 } |
| 173 | 174 |
| 174 HashSet<ThreadHeap*>& ThreadHeap::allHeaps() { | 175 HashSet<ThreadHeap*>& ThreadHeap::allHeaps() { |
| 175 DEFINE_STATIC_LOCAL(HashSet<ThreadHeap*>, heaps, ()); | 176 DEFINE_STATIC_LOCAL(HashSet<ThreadHeap*>, heaps, ()); |
| 176 return heaps; | 177 return heaps; |
| 177 } | 178 } |
| 178 | 179 |
| 179 void ThreadHeap::attach(ThreadState* thread) { | 180 void ThreadHeap::attach(ThreadState* threadState) { |
| 180 MutexLocker locker(m_threadAttachMutex); | 181 DCHECK(!m_threadState); |
| 181 m_threads.insert(thread); | 182 m_threadState = threadState; |
| 182 } | 183 } |
| 183 | 184 |
| 184 void ThreadHeap::detach(ThreadState* thread) { | 185 void ThreadHeap::detach(ThreadState* threadState) { |
| 185 ASSERT(ThreadState::current() == thread); | 186 DCHECK(ThreadState::current() == threadState); |
| 186 bool isLastThread = false; | 187 DCHECK(m_threadState == threadState); |
| 187 { | 188 threadState->runTerminationGC(); |
| 188 // Grab the threadAttachMutex to ensure only one thread can shutdown at | 189 if (threadState->isMainThread()) |
| 189 // a time and that no other thread can do a global GC. It also allows | |
| 190 // safe iteration of the m_threads set which happens as part of | |
| 191 // thread local GC asserts. We enter a safepoint while waiting for the | |
| 192 // lock to avoid a dead-lock where another thread has already requested | |
| 193 // GC. | |
| 194 MutexLocker locker(m_threadAttachMutex); | |
| 195 thread->runTerminationGC(); | |
| 196 ASSERT(m_threads.contains(thread)); | |
| 197 m_threads.remove(thread); | |
| 198 isLastThread = m_threads.isEmpty(); | |
| 199 } | |
| 200 if (thread->isMainThread()) | |
| 201 DCHECK_EQ(heapStats().allocatedSpace(), 0u); | 190 DCHECK_EQ(heapStats().allocatedSpace(), 0u); |
| 202 if (isLastThread) | 191 delete this; |
|
sof
2017/02/15 08:26:32
Would it work for |ThreadState::m_heap| to be a |s
| |
| 203 delete this; | |
| 204 } | 192 } |
| 205 | 193 |
| 206 #if DCHECK_IS_ON() | 194 #if DCHECK_IS_ON() |
| 207 BasePage* ThreadHeap::findPageFromAddress(Address address) { | 195 BasePage* ThreadHeap::findPageFromAddress(Address address) { |
| 208 MutexLocker locker(m_threadAttachMutex); | 196 return m_threadState->findPageFromAddress(address); |
| 209 for (ThreadState* state : m_threads) { | |
| 210 if (BasePage* page = state->findPageFromAddress(address)) | |
| 211 return page; | |
| 212 } | |
| 213 return nullptr; | |
| 214 } | 197 } |
| 215 | 198 |
| 216 bool ThreadHeap::isAtSafePoint() { | 199 bool ThreadHeap::isAtSafePoint() { |
| 217 MutexLocker locker(m_threadAttachMutex); | 200 return m_threadState->isAtSafePoint(); |
| 218 for (ThreadState* state : m_threads) { | |
| 219 if (!state->isAtSafePoint()) | |
| 220 return false; | |
| 221 } | |
| 222 return true; | |
| 223 } | 201 } |
| 224 #endif | 202 #endif |
| 225 | 203 |
| 226 Address ThreadHeap::checkAndMarkPointer(Visitor* visitor, Address address) { | 204 Address ThreadHeap::checkAndMarkPointer(Visitor* visitor, Address address) { |
| 227 ASSERT(ThreadState::current()->isInGC()); | 205 ASSERT(ThreadState::current()->isInGC()); |
| 228 | 206 |
| 229 #if !DCHECK_IS_ON() | 207 #if !DCHECK_IS_ON() |
| 230 if (m_heapDoesNotContainCache->lookup(address)) | 208 if (m_heapDoesNotContainCache->lookup(address)) |
| 231 return nullptr; | 209 return nullptr; |
| 232 #endif | 210 #endif |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 364 | 342 |
| 365 void ThreadHeap::decommitCallbackStacks() { | 343 void ThreadHeap::decommitCallbackStacks() { |
| 366 m_markingStack->decommit(); | 344 m_markingStack->decommit(); |
| 367 m_postMarkingCallbackStack->decommit(); | 345 m_postMarkingCallbackStack->decommit(); |
| 368 m_globalWeakCallbackStack->decommit(); | 346 m_globalWeakCallbackStack->decommit(); |
| 369 m_ephemeronStack->decommit(); | 347 m_ephemeronStack->decommit(); |
| 370 } | 348 } |
| 371 | 349 |
| 372 void ThreadHeap::preGC() { | 350 void ThreadHeap::preGC() { |
| 373 ASSERT(!ThreadState::current()->isInGC()); | 351 ASSERT(!ThreadState::current()->isInGC()); |
| 374 for (ThreadState* state : m_threads) | 352 m_threadState->preGC(); |
| 375 state->preGC(); | |
| 376 } | 353 } |
| 377 | 354 |
| 378 void ThreadHeap::postGC(BlinkGC::GCType gcType) { | 355 void ThreadHeap::postGC(BlinkGC::GCType gcType) { |
| 379 ASSERT(ThreadState::current()->isInGC()); | 356 ASSERT(ThreadState::current()->isInGC()); |
| 380 for (ThreadState* state : m_threads) | 357 m_threadState->postGC(gcType); |
| 381 state->postGC(gcType); | |
| 382 } | 358 } |
| 383 | 359 |
| 384 void ThreadHeap::preSweep(BlinkGC::GCType gcType) { | 360 void ThreadHeap::preSweep(BlinkGC::GCType gcType) { |
| 385 for (ThreadState* state : m_threads) | 361 m_threadState->preSweep(gcType); |
| 386 state->preSweep(gcType); | |
| 387 } | 362 } |
| 388 | 363 |
| 389 void ThreadHeap::processMarkingStack(Visitor* visitor) { | 364 void ThreadHeap::processMarkingStack(Visitor* visitor) { |
| 390 // Ephemeron fixed point loop. | 365 // Ephemeron fixed point loop. |
| 391 do { | 366 do { |
| 392 { | 367 { |
| 393 // Iteratively mark all objects that are reachable from the objects | 368 // Iteratively mark all objects that are reachable from the objects |
| 394 // currently pushed onto the marking stack. | 369 // currently pushed onto the marking stack. |
| 395 TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThreaded"); | 370 TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThreaded"); |
| 396 while (popAndInvokeTraceCallback(visitor)) { | 371 while (popAndInvokeTraceCallback(visitor)) { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 528 "ThreadHeap::partitionAllocSizeAtLastGCKB", | 503 "ThreadHeap::partitionAllocSizeAtLastGCKB", |
| 529 std::min(heap.heapStats().partitionAllocSizeAtLastGC() / 1024, | 504 std::min(heap.heapStats().partitionAllocSizeAtLastGC() / 1024, |
| 530 static_cast<size_t>(INT_MAX))); | 505 static_cast<size_t>(INT_MAX))); |
| 531 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), | 506 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), |
| 532 "Partitions::totalSizeOfCommittedPagesKB", | 507 "Partitions::totalSizeOfCommittedPagesKB", |
| 533 std::min(WTF::Partitions::totalSizeOfCommittedPages() / 1024, | 508 std::min(WTF::Partitions::totalSizeOfCommittedPages() / 1024, |
| 534 static_cast<size_t>(INT_MAX))); | 509 static_cast<size_t>(INT_MAX))); |
| 535 } | 510 } |
| 536 | 511 |
| 537 size_t ThreadHeap::objectPayloadSizeForTesting() { | 512 size_t ThreadHeap::objectPayloadSizeForTesting() { |
| 538 // MEMO: is threadAttachMutex locked? | |
| 539 size_t objectPayloadSize = 0; | 513 size_t objectPayloadSize = 0; |
| 540 for (ThreadState* state : m_threads) { | 514 m_threadState->setGCState(ThreadState::GCRunning); |
| 541 state->setGCState(ThreadState::GCRunning); | 515 m_threadState->makeConsistentForGC(); |
| 542 state->makeConsistentForGC(); | 516 objectPayloadSize += m_threadState->objectPayloadSizeForTesting(); |
| 543 objectPayloadSize += state->objectPayloadSizeForTesting(); | 517 m_threadState->setGCState(ThreadState::Sweeping); |
| 544 state->setGCState(ThreadState::Sweeping); | 518 m_threadState->setGCState(ThreadState::NoGCScheduled); |
| 545 state->setGCState(ThreadState::NoGCScheduled); | |
| 546 } | |
| 547 return objectPayloadSize; | 519 return objectPayloadSize; |
| 548 } | 520 } |
| 549 | 521 |
| 550 void ThreadHeap::visitPersistentRoots(Visitor* visitor) { | 522 void ThreadHeap::visitPersistentRoots(Visitor* visitor) { |
| 551 ASSERT(ThreadState::current()->isInGC()); | 523 ASSERT(ThreadState::current()->isInGC()); |
| 552 TRACE_EVENT0("blink_gc", "ThreadHeap::visitPersistentRoots"); | 524 TRACE_EVENT0("blink_gc", "ThreadHeap::visitPersistentRoots"); |
| 553 ProcessHeap::crossThreadPersistentRegion().tracePersistentNodes(visitor); | 525 ProcessHeap::crossThreadPersistentRegion().tracePersistentNodes(visitor); |
| 554 | 526 |
| 555 for (ThreadState* state : m_threads) | 527 m_threadState->visitPersistents(visitor); |
| 556 state->visitPersistents(visitor); | |
| 557 } | 528 } |
| 558 | 529 |
| 559 void ThreadHeap::visitStackRoots(Visitor* visitor) { | 530 void ThreadHeap::visitStackRoots(Visitor* visitor) { |
| 560 ASSERT(ThreadState::current()->isInGC()); | 531 ASSERT(ThreadState::current()->isInGC()); |
| 561 TRACE_EVENT0("blink_gc", "ThreadHeap::visitStackRoots"); | 532 TRACE_EVENT0("blink_gc", "ThreadHeap::visitStackRoots"); |
| 562 for (ThreadState* state : m_threads) | 533 m_threadState->visitStack(visitor); |
| 563 state->visitStack(visitor); | |
| 564 } | 534 } |
| 565 | 535 |
| 566 void ThreadHeap::enterSafePoint(ThreadState* threadState) { | 536 void ThreadHeap::enterSafePoint(ThreadState* threadState) { |
| 567 m_safePointBarrier->enterSafePoint(threadState); | 537 m_safePointBarrier->enterSafePoint(threadState); |
| 568 } | 538 } |
| 569 | 539 |
| 570 void ThreadHeap::leaveSafePoint() { | 540 void ThreadHeap::leaveSafePoint() { |
| 571 m_safePointBarrier->leaveSafePoint(); | 541 m_safePointBarrier->leaveSafePoint(); |
| 572 } | 542 } |
| 573 | 543 |
| 574 BasePage* ThreadHeap::lookupPageForAddress(Address address) { | 544 BasePage* ThreadHeap::lookupPageForAddress(Address address) { |
| 575 ASSERT(ThreadState::current()->isInGC()); | 545 ASSERT(ThreadState::current()->isInGC()); |
| 576 if (PageMemoryRegion* region = m_regionTree->lookup(address)) { | 546 if (PageMemoryRegion* region = m_regionTree->lookup(address)) { |
| 577 return region->pageFromAddress(address); | 547 return region->pageFromAddress(address); |
| 578 } | 548 } |
| 579 return nullptr; | 549 return nullptr; |
| 580 } | 550 } |
| 581 | 551 |
| 582 void ThreadHeap::resetHeapCounters() { | 552 void ThreadHeap::resetHeapCounters() { |
| 583 ASSERT(ThreadState::current()->isInGC()); | 553 ASSERT(ThreadState::current()->isInGC()); |
| 584 | 554 |
| 585 ThreadHeap::reportMemoryUsageForTracing(); | 555 ThreadHeap::reportMemoryUsageForTracing(); |
| 586 | 556 |
| 587 ProcessHeap::decreaseTotalAllocatedObjectSize(m_stats.allocatedObjectSize()); | 557 ProcessHeap::decreaseTotalAllocatedObjectSize(m_stats.allocatedObjectSize()); |
| 588 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); | 558 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); |
| 589 | 559 |
| 590 m_stats.reset(); | 560 m_stats.reset(); |
| 591 for (ThreadState* state : m_threads) | 561 m_threadState->resetHeapCounters(); |
| 592 state->resetHeapCounters(); | |
| 593 } | 562 } |
| 594 | 563 |
| 595 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; | 564 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; |
| 596 | 565 |
| 597 } // namespace blink | 566 } // namespace blink |
| OLD | NEW |