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 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
138 void ThreadHeapStats::increaseAllocatedSpace(size_t delta) { | 138 void ThreadHeapStats::increaseAllocatedSpace(size_t delta) { |
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(ThreadState* threadState) |
149 : m_regionTree(WTF::makeUnique<RegionTree>()), | 149 : m_threadState(threadState), |
| 150 m_regionTree(WTF::makeUnique<RegionTree>()), |
150 m_heapDoesNotContainCache(WTF::wrapUnique(new HeapDoesNotContainCache)), | 151 m_heapDoesNotContainCache(WTF::wrapUnique(new HeapDoesNotContainCache)), |
151 m_freePagePool(WTF::wrapUnique(new PagePool)), | 152 m_freePagePool(WTF::wrapUnique(new PagePool)), |
152 m_markingStack(CallbackStack::create()), | 153 m_markingStack(CallbackStack::create()), |
153 m_postMarkingCallbackStack(CallbackStack::create()), | 154 m_postMarkingCallbackStack(CallbackStack::create()), |
154 m_globalWeakCallbackStack(CallbackStack::create()), | 155 m_globalWeakCallbackStack(CallbackStack::create()), |
155 m_ephemeronStack(CallbackStack::create()) { | 156 m_ephemeronStack(CallbackStack::create()) { |
156 if (ThreadState::current()->isMainThread()) | 157 if (ThreadState::current()->isMainThread()) |
157 s_mainThreadHeap = this; | 158 s_mainThreadHeap = this; |
158 } | 159 } |
159 | 160 |
160 ThreadHeap::~ThreadHeap() { | 161 ThreadHeap::~ThreadHeap() { |
161 } | 162 } |
162 | 163 |
163 void ThreadHeap::attach(ThreadState* thread) { | |
164 MutexLocker locker(m_threadAttachMutex); | |
165 m_threads.insert(thread); | |
166 } | |
167 | |
168 void ThreadHeap::detach(ThreadState* thread) { | |
169 ASSERT(ThreadState::current() == thread); | |
170 bool isLastThread = false; | |
171 { | |
172 // Grab the threadAttachMutex to ensure only one thread can shutdown at | |
173 // a time and that no other thread can do a global GC. It also allows | |
174 // safe iteration of the m_threads set which happens as part of | |
175 // thread local GC asserts. We enter a safepoint while waiting for the | |
176 // lock to avoid a dead-lock where another thread has already requested | |
177 // GC. | |
178 MutexLocker locker(m_threadAttachMutex); | |
179 thread->runTerminationGC(); | |
180 ASSERT(m_threads.contains(thread)); | |
181 m_threads.erase(thread); | |
182 isLastThread = m_threads.isEmpty(); | |
183 } | |
184 if (thread->isMainThread()) | |
185 DCHECK_EQ(heapStats().allocatedSpace(), 0u); | |
186 if (isLastThread) | |
187 delete this; | |
188 } | |
189 | |
190 #if DCHECK_IS_ON() | 164 #if DCHECK_IS_ON() |
191 BasePage* ThreadHeap::findPageFromAddress(Address address) { | 165 BasePage* ThreadHeap::findPageFromAddress(Address address) { |
192 MutexLocker locker(m_threadAttachMutex); | 166 return m_threadState->findPageFromAddress(address); |
193 for (ThreadState* state : m_threads) { | |
194 if (BasePage* page = state->findPageFromAddress(address)) | |
195 return page; | |
196 } | |
197 return nullptr; | |
198 } | 167 } |
199 #endif | 168 #endif |
200 | 169 |
201 Address ThreadHeap::checkAndMarkPointer(Visitor* visitor, Address address) { | 170 Address ThreadHeap::checkAndMarkPointer(Visitor* visitor, Address address) { |
202 ASSERT(ThreadState::current()->isInGC()); | 171 ASSERT(ThreadState::current()->isInGC()); |
203 | 172 |
204 #if !DCHECK_IS_ON() | 173 #if !DCHECK_IS_ON() |
205 if (m_heapDoesNotContainCache->lookup(address)) | 174 if (m_heapDoesNotContainCache->lookup(address)) |
206 return nullptr; | 175 return nullptr; |
207 #endif | 176 #endif |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
339 | 308 |
340 void ThreadHeap::decommitCallbackStacks() { | 309 void ThreadHeap::decommitCallbackStacks() { |
341 m_markingStack->decommit(); | 310 m_markingStack->decommit(); |
342 m_postMarkingCallbackStack->decommit(); | 311 m_postMarkingCallbackStack->decommit(); |
343 m_globalWeakCallbackStack->decommit(); | 312 m_globalWeakCallbackStack->decommit(); |
344 m_ephemeronStack->decommit(); | 313 m_ephemeronStack->decommit(); |
345 } | 314 } |
346 | 315 |
347 void ThreadHeap::preGC() { | 316 void ThreadHeap::preGC() { |
348 ASSERT(!ThreadState::current()->isInGC()); | 317 ASSERT(!ThreadState::current()->isInGC()); |
349 for (ThreadState* state : m_threads) | 318 m_threadState->preGC(); |
350 state->preGC(); | |
351 } | 319 } |
352 | 320 |
353 void ThreadHeap::postGC(BlinkGC::GCType gcType) { | 321 void ThreadHeap::postGC(BlinkGC::GCType gcType) { |
354 ASSERT(ThreadState::current()->isInGC()); | 322 ASSERT(ThreadState::current()->isInGC()); |
355 for (ThreadState* state : m_threads) | 323 m_threadState->postGC(gcType); |
356 state->postGC(gcType); | |
357 } | 324 } |
358 | 325 |
359 void ThreadHeap::preSweep(BlinkGC::GCType gcType) { | 326 void ThreadHeap::preSweep(BlinkGC::GCType gcType) { |
360 for (ThreadState* state : m_threads) | 327 m_threadState->preSweep(gcType); |
361 state->preSweep(gcType); | |
362 } | 328 } |
363 | 329 |
364 void ThreadHeap::processMarkingStack(Visitor* visitor) { | 330 void ThreadHeap::processMarkingStack(Visitor* visitor) { |
365 // Ephemeron fixed point loop. | 331 // Ephemeron fixed point loop. |
366 do { | 332 do { |
367 { | 333 { |
368 // Iteratively mark all objects that are reachable from the objects | 334 // Iteratively mark all objects that are reachable from the objects |
369 // currently pushed onto the marking stack. | 335 // currently pushed onto the marking stack. |
370 TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThreaded"); | 336 TRACE_EVENT0("blink_gc", "ThreadHeap::processMarkingStackSingleThreaded"); |
371 while (popAndInvokeTraceCallback(visitor)) { | 337 while (popAndInvokeTraceCallback(visitor)) { |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 "ThreadHeap::partitionAllocSizeAtLastGCKB", | 469 "ThreadHeap::partitionAllocSizeAtLastGCKB", |
504 std::min(heap.heapStats().partitionAllocSizeAtLastGC() / 1024, | 470 std::min(heap.heapStats().partitionAllocSizeAtLastGC() / 1024, |
505 static_cast<size_t>(INT_MAX))); | 471 static_cast<size_t>(INT_MAX))); |
506 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), | 472 TRACE_COUNTER1(TRACE_DISABLED_BY_DEFAULT("blink_gc"), |
507 "Partitions::totalSizeOfCommittedPagesKB", | 473 "Partitions::totalSizeOfCommittedPagesKB", |
508 std::min(WTF::Partitions::totalSizeOfCommittedPages() / 1024, | 474 std::min(WTF::Partitions::totalSizeOfCommittedPages() / 1024, |
509 static_cast<size_t>(INT_MAX))); | 475 static_cast<size_t>(INT_MAX))); |
510 } | 476 } |
511 | 477 |
512 size_t ThreadHeap::objectPayloadSizeForTesting() { | 478 size_t ThreadHeap::objectPayloadSizeForTesting() { |
513 // MEMO: is threadAttachMutex locked? | |
514 size_t objectPayloadSize = 0; | 479 size_t objectPayloadSize = 0; |
515 for (ThreadState* state : m_threads) { | 480 m_threadState->setGCState(ThreadState::GCRunning); |
516 state->setGCState(ThreadState::GCRunning); | 481 m_threadState->makeConsistentForGC(); |
517 state->makeConsistentForGC(); | 482 objectPayloadSize += m_threadState->objectPayloadSizeForTesting(); |
518 objectPayloadSize += state->objectPayloadSizeForTesting(); | 483 m_threadState->setGCState(ThreadState::Sweeping); |
519 state->setGCState(ThreadState::Sweeping); | 484 m_threadState->setGCState(ThreadState::NoGCScheduled); |
520 state->setGCState(ThreadState::NoGCScheduled); | |
521 } | |
522 return objectPayloadSize; | 485 return objectPayloadSize; |
523 } | 486 } |
524 | 487 |
525 void ThreadHeap::visitPersistentRoots(Visitor* visitor) { | 488 void ThreadHeap::visitPersistentRoots(Visitor* visitor) { |
526 ASSERT(ThreadState::current()->isInGC()); | 489 ASSERT(ThreadState::current()->isInGC()); |
527 TRACE_EVENT0("blink_gc", "ThreadHeap::visitPersistentRoots"); | 490 TRACE_EVENT0("blink_gc", "ThreadHeap::visitPersistentRoots"); |
528 ProcessHeap::crossThreadPersistentRegion().tracePersistentNodes(visitor); | 491 ProcessHeap::crossThreadPersistentRegion().tracePersistentNodes(visitor); |
529 | 492 |
530 for (ThreadState* state : m_threads) | 493 m_threadState->visitPersistents(visitor); |
531 state->visitPersistents(visitor); | |
532 } | 494 } |
533 | 495 |
534 void ThreadHeap::visitStackRoots(Visitor* visitor) { | 496 void ThreadHeap::visitStackRoots(Visitor* visitor) { |
535 ASSERT(ThreadState::current()->isInGC()); | 497 ASSERT(ThreadState::current()->isInGC()); |
536 TRACE_EVENT0("blink_gc", "ThreadHeap::visitStackRoots"); | 498 TRACE_EVENT0("blink_gc", "ThreadHeap::visitStackRoots"); |
537 for (ThreadState* state : m_threads) | 499 m_threadState->visitStack(visitor); |
538 state->visitStack(visitor); | |
539 } | 500 } |
540 | 501 |
541 BasePage* ThreadHeap::lookupPageForAddress(Address address) { | 502 BasePage* ThreadHeap::lookupPageForAddress(Address address) { |
542 ASSERT(ThreadState::current()->isInGC()); | 503 ASSERT(ThreadState::current()->isInGC()); |
543 if (PageMemoryRegion* region = m_regionTree->lookup(address)) { | 504 if (PageMemoryRegion* region = m_regionTree->lookup(address)) { |
544 return region->pageFromAddress(address); | 505 return region->pageFromAddress(address); |
545 } | 506 } |
546 return nullptr; | 507 return nullptr; |
547 } | 508 } |
548 | 509 |
549 void ThreadHeap::resetHeapCounters() { | 510 void ThreadHeap::resetHeapCounters() { |
550 ASSERT(ThreadState::current()->isInGC()); | 511 ASSERT(ThreadState::current()->isInGC()); |
551 | 512 |
552 ThreadHeap::reportMemoryUsageForTracing(); | 513 ThreadHeap::reportMemoryUsageForTracing(); |
553 | 514 |
554 ProcessHeap::decreaseTotalAllocatedObjectSize(m_stats.allocatedObjectSize()); | 515 ProcessHeap::decreaseTotalAllocatedObjectSize(m_stats.allocatedObjectSize()); |
555 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); | 516 ProcessHeap::decreaseTotalMarkedObjectSize(m_stats.markedObjectSize()); |
556 | 517 |
557 m_stats.reset(); | 518 m_stats.reset(); |
558 for (ThreadState* state : m_threads) | 519 m_threadState->resetHeapCounters(); |
559 state->resetHeapCounters(); | |
560 } | 520 } |
561 | 521 |
562 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; | 522 ThreadHeap* ThreadHeap::s_mainThreadHeap = nullptr; |
563 | 523 |
564 } // namespace blink | 524 } // namespace blink |
OLD | NEW |