| 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 336 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 347 // C++ objects can contain pointers to objects outside of the heap and | 347 // C++ objects can contain pointers to objects outside of the heap and |
| 348 // should therefore be part of the LSan root set. | 348 // should therefore be part of the LSan root set. |
| 349 __lsan_register_root_region(m_writable.base(), m_writable.size()); | 349 __lsan_register_root_region(m_writable.base(), m_writable.size()); |
| 350 } | 350 } |
| 351 | 351 |
| 352 | 352 |
| 353 PageMemoryRegion* m_reserved; | 353 PageMemoryRegion* m_reserved; |
| 354 MemoryRegion m_writable; | 354 MemoryRegion m_writable; |
| 355 }; | 355 }; |
| 356 | 356 |
| 357 class GCScope { | |
| 358 public: | |
| 359 explicit GCScope(ThreadState::StackState stackState) | |
| 360 : m_state(ThreadState::current()) | |
| 361 , m_safePointScope(stackState) | |
| 362 , m_parkedAllThreads(false) | |
| 363 { | |
| 364 TRACE_EVENT0("blink_gc", "Heap::GCScope"); | |
| 365 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); | |
| 366 if (m_state->isMainThread()) | |
| 367 TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting"); | |
| 368 | |
| 369 m_state->checkThread(); | |
| 370 | |
| 371 // FIXME: in an unlikely coincidence that two threads decide | |
| 372 // to collect garbage at the same time, avoid doing two GCs in | |
| 373 // a row. | |
| 374 RELEASE_ASSERT(!m_state->isInGC()); | |
| 375 RELEASE_ASSERT(!m_state->isSweepInProgress()); | |
| 376 if (LIKELY(ThreadState::stopThreads())) { | |
| 377 m_parkedAllThreads = true; | |
| 378 m_state->enterGC(); | |
| 379 } | |
| 380 if (m_state->isMainThread()) | |
| 381 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); | |
| 382 } | |
| 383 | |
| 384 bool allThreadsParked() { return m_parkedAllThreads; } | |
| 385 | |
| 386 ~GCScope() | |
| 387 { | |
| 388 // Only cleanup if we parked all threads in which case the GC happened | |
| 389 // and we need to resume the other threads. | |
| 390 if (LIKELY(m_parkedAllThreads)) { | |
| 391 m_state->leaveGC(); | |
| 392 ASSERT(!m_state->isInGC()); | |
| 393 ThreadState::resumeThreads(); | |
| 394 } | |
| 395 } | |
| 396 | |
| 397 private: | |
| 398 ThreadState* m_state; | |
| 399 ThreadState::SafePointScope m_safePointScope; | |
| 400 bool m_parkedAllThreads; // False if we fail to park all threads | |
| 401 }; | |
| 402 | |
| 403 NO_SANITIZE_ADDRESS | 357 NO_SANITIZE_ADDRESS |
| 404 bool HeapObjectHeader::isMarked() const | 358 bool HeapObjectHeader::isMarked() const |
| 405 { | 359 { |
| 406 checkHeader(); | 360 checkHeader(); |
| 407 unsigned size = acquireLoad(&m_size); | 361 unsigned size = acquireLoad(&m_size); |
| 408 return size & markBitMask; | 362 return size & markBitMask; |
| 409 } | 363 } |
| 410 | 364 |
| 411 NO_SANITIZE_ADDRESS | 365 NO_SANITIZE_ADDRESS |
| 412 void HeapObjectHeader::unmark() | 366 void HeapObjectHeader::unmark() |
| (...skipping 1788 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2201 protected: | 2155 protected: |
| 2202 virtual void registerWeakCell(void** cell, WeakPointerCallback callback) ove
rride | 2156 virtual void registerWeakCell(void** cell, WeakPointerCallback callback) ove
rride |
| 2203 { | 2157 { |
| 2204 Heap::pushWeakCellPointerCallback(cell, callback); | 2158 Heap::pushWeakCellPointerCallback(cell, callback); |
| 2205 } | 2159 } |
| 2206 | 2160 |
| 2207 private: | 2161 private: |
| 2208 CallbackStack** m_markingStack; | 2162 CallbackStack** m_markingStack; |
| 2209 }; | 2163 }; |
| 2210 | 2164 |
| 2211 void Heap::init() | |
| 2212 { | |
| 2213 ThreadState::init(); | |
| 2214 CallbackStack::init(&s_markingStack); | |
| 2215 CallbackStack::init(&s_postMarkingCallbackStack); | |
| 2216 CallbackStack::init(&s_weakCallbackStack); | |
| 2217 CallbackStack::init(&s_ephemeronStack); | |
| 2218 s_heapDoesNotContainCache = new HeapDoesNotContainCache(); | |
| 2219 s_markingVisitor = new MarkingVisitor(&s_markingStack); | |
| 2220 s_freePagePool = new FreePagePool(); | |
| 2221 s_orphanedPagePool = new OrphanedPagePool(); | |
| 2222 s_markingThreads = new Vector<OwnPtr<blink::WebThread> >(); | |
| 2223 } | |
| 2224 | |
| 2225 void Heap::shutdown() | |
| 2226 { | |
| 2227 s_shutdownCalled = true; | |
| 2228 ThreadState::shutdownHeapIfNecessary(); | |
| 2229 } | |
| 2230 | |
| 2231 void Heap::doShutdown() | |
| 2232 { | |
| 2233 // We don't want to call doShutdown() twice. | |
| 2234 if (!s_markingVisitor) | |
| 2235 return; | |
| 2236 | |
| 2237 ASSERT(!ThreadState::isAnyThreadInGC()); | |
| 2238 ASSERT(!ThreadState::attachedThreads().size()); | |
| 2239 delete s_markingThreads; | |
| 2240 s_markingThreads = 0; | |
| 2241 delete s_markingVisitor; | |
| 2242 s_markingVisitor = 0; | |
| 2243 delete s_heapDoesNotContainCache; | |
| 2244 s_heapDoesNotContainCache = 0; | |
| 2245 delete s_freePagePool; | |
| 2246 s_freePagePool = 0; | |
| 2247 delete s_orphanedPagePool; | |
| 2248 s_orphanedPagePool = 0; | |
| 2249 CallbackStack::shutdown(&s_weakCallbackStack); | |
| 2250 CallbackStack::shutdown(&s_postMarkingCallbackStack); | |
| 2251 CallbackStack::shutdown(&s_markingStack); | |
| 2252 CallbackStack::shutdown(&s_ephemeronStack); | |
| 2253 ThreadState::shutdown(); | |
| 2254 } | |
| 2255 | |
| 2256 BaseHeapPage* Heap::contains(Address address) | 2165 BaseHeapPage* Heap::contains(Address address) |
| 2257 { | 2166 { |
| 2258 ASSERT(ThreadState::isAnyThreadInGC()); | 2167 ASSERT(ThreadState::isAnyThreadInGC()); |
| 2259 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); | 2168 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); |
| 2260 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { | 2169 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) { |
| 2261 BaseHeapPage* page = (*it)->contains(address); | 2170 BaseHeapPage* page = (*it)->contains(address); |
| 2262 if (page) | 2171 if (page) |
| 2263 return page; | 2172 return page; |
| 2264 } | 2173 } |
| 2265 return 0; | 2174 return 0; |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2433 void Heap::prepareForGC() | 2342 void Heap::prepareForGC() |
| 2434 { | 2343 { |
| 2435 ASSERT(ThreadState::isAnyThreadInGC()); | 2344 ASSERT(ThreadState::isAnyThreadInGC()); |
| 2436 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); | 2345 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads(
); |
| 2437 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) | 2346 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end
= threads.end(); it != end; ++it) |
| 2438 (*it)->prepareForGC(); | 2347 (*it)->prepareForGC(); |
| 2439 } | 2348 } |
| 2440 | 2349 |
| 2441 void Heap::collectGarbage(ThreadState::StackState stackState) | 2350 void Heap::collectGarbage(ThreadState::StackState stackState) |
| 2442 { | 2351 { |
| 2443 ThreadState* state = ThreadState::current(); | |
| 2444 state->clearGCRequested(); | |
| 2445 | |
| 2446 GCScope gcScope(stackState); | |
| 2447 // Check if we successfully parked the other threads. If not we bail out of
the GC. | |
| 2448 if (!gcScope.allThreadsParked()) { | |
| 2449 ThreadState::current()->setGCRequested(); | |
| 2450 return; | |
| 2451 } | |
| 2452 | |
| 2453 if (state->isMainThread()) | |
| 2454 ScriptForbiddenScope::enter(); | |
| 2455 | |
| 2456 s_lastGCWasConservative = false; | |
| 2457 | |
| 2458 TRACE_EVENT0("blink_gc", "Heap::collectGarbage"); | |
| 2459 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); | |
| 2460 double timeStamp = WTF::currentTimeMS(); | |
| 2461 #if ENABLE(GC_PROFILE_MARKING) | |
| 2462 static_cast<MarkingVisitor*>(s_markingVisitor)->objectGraph().clear(); | |
| 2463 #endif | |
| 2464 | |
| 2465 // Disallow allocation during garbage collection (but not | |
| 2466 // during the finalization that happens when the gcScope is | |
| 2467 // torn down). | |
| 2468 NoAllocationScope<AnyThread> noAllocationScope; | |
| 2469 | |
| 2470 prepareForGC(); | |
| 2471 | |
| 2472 // 1. trace persistent roots. | |
| 2473 ThreadState::visitPersistentRoots(s_markingVisitor); | |
| 2474 | |
| 2475 // 2. trace objects reachable from the persistent roots including ephemerons
. | |
| 2476 processMarkingStackInParallel(); | |
| 2477 | |
| 2478 // 3. trace objects reachable from the stack. We do this independent of the | |
| 2479 // given stackState since other threads might have a different stack state. | |
| 2480 ThreadState::visitStackRoots(s_markingVisitor); | |
| 2481 | |
| 2482 // 4. trace objects reachable from the stack "roots" including ephemerons. | |
| 2483 // Only do the processing if we found a pointer to an object on one of the | |
| 2484 // thread stacks. | |
| 2485 if (lastGCWasConservative()) | |
| 2486 processMarkingStackInParallel(); | |
| 2487 | |
| 2488 postMarkingProcessing(); | |
| 2489 globalWeakProcessing(); | |
| 2490 | |
| 2491 // After a global marking we know that any orphaned page that was not reache
d | |
| 2492 // cannot be reached in a subsequent GC. This is due to a thread either havi
ng | |
| 2493 // swept its heap or having done a "poor mans sweep" in prepareForGC which m
arks | |
| 2494 // objects that are dead, but not swept in the previous GC as dead. In this
GC's | |
| 2495 // marking we check that any object marked as dead is not traced. E.g. via a | |
| 2496 // conservatively found pointer or a programming error with an object contai
ning | |
| 2497 // a dangling pointer. | |
| 2498 orphanedPagePool()->decommitOrphanedPages(); | |
| 2499 | |
| 2500 #if ENABLE(GC_PROFILE_MARKING) | |
| 2501 static_cast<MarkingVisitor*>(s_markingVisitor)->reportStats(); | |
| 2502 #endif | |
| 2503 | |
| 2504 if (blink::Platform::current()) { | |
| 2505 uint64_t objectSpaceSize; | |
| 2506 uint64_t allocatedSpaceSize; | |
| 2507 getHeapSpaceSize(&objectSpaceSize, &allocatedSpaceSize); | |
| 2508 blink::Platform::current()->histogramCustomCounts("BlinkGC.CollectGarbag
e", WTF::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); | |
| 2509 blink::Platform::current()->histogramCustomCounts("BlinkGC.TotalObjectSp
ace", objectSpaceSize / 1024, 0, 4 * 1024 * 1024, 50); | |
| 2510 blink::Platform::current()->histogramCustomCounts("BlinkGC.TotalAllocate
dSpace", allocatedSpaceSize / 1024, 0, 4 * 1024 * 1024, 50); | |
| 2511 } | |
| 2512 | |
| 2513 if (state->isMainThread()) | |
| 2514 ScriptForbiddenScope::exit(); | |
| 2515 } | 2352 } |
| 2516 | 2353 |
| 2517 void Heap::collectGarbageForTerminatingThread(ThreadState* state) | 2354 void Heap::collectGarbageForTerminatingThread(ThreadState* state) |
| 2518 { | 2355 { |
| 2519 // We explicitly do not enter a safepoint while doing thread specific | |
| 2520 // garbage collection since we don't want to allow a global GC at the | |
| 2521 // same time as a thread local GC. | |
| 2522 | |
| 2523 { | |
| 2524 NoAllocationScope<AnyThread> noAllocationScope; | |
| 2525 | |
| 2526 state->enterGC(); | |
| 2527 state->prepareForGC(); | |
| 2528 | |
| 2529 // 1. trace the thread local persistent roots. For thread local GCs we | |
| 2530 // don't trace the stack (ie. no conservative scanning) since this is | |
| 2531 // only called during thread shutdown where there should be no objects | |
| 2532 // on the stack. | |
| 2533 // We also assume that orphaned pages have no objects reachable from | |
| 2534 // persistent handles on other threads or CrossThreadPersistents. The | |
| 2535 // only cases where this could happen is if a subsequent conservative | |
| 2536 // global GC finds a "pointer" on the stack or due to a programming | |
| 2537 // error where an object has a dangling cross-thread pointer to an | |
| 2538 // object on this heap. | |
| 2539 state->visitPersistents(s_markingVisitor); | |
| 2540 | |
| 2541 // 2. trace objects reachable from the thread's persistent roots | |
| 2542 // including ephemerons. | |
| 2543 processMarkingStack<ThreadLocalMarking>(); | |
| 2544 | |
| 2545 postMarkingProcessing(); | |
| 2546 globalWeakProcessing(); | |
| 2547 | |
| 2548 state->leaveGC(); | |
| 2549 } | |
| 2550 state->performPendingSweep(); | |
| 2551 } | 2356 } |
| 2552 | 2357 |
| 2553 void Heap::processMarkingStackEntries(int* runningMarkingThreads) | 2358 void Heap::processMarkingStackEntries(int* runningMarkingThreads) |
| 2554 { | 2359 { |
| 2555 CallbackStack* stack = 0; | 2360 CallbackStack* stack = 0; |
| 2556 MarkingVisitor visitor(&stack); | 2361 MarkingVisitor visitor(&stack); |
| 2557 { | 2362 { |
| 2558 MutexLocker locker(markingMutex()); | 2363 MutexLocker locker(markingMutex()); |
| 2559 stack = s_markingStack->takeCallbacks(&s_markingStack); | 2364 stack = s_markingStack->takeCallbacks(&s_markingStack); |
| 2560 } | 2365 } |
| (...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2811 CallbackStack* Heap::s_markingStack; | 2616 CallbackStack* Heap::s_markingStack; |
| 2812 CallbackStack* Heap::s_postMarkingCallbackStack; | 2617 CallbackStack* Heap::s_postMarkingCallbackStack; |
| 2813 CallbackStack* Heap::s_weakCallbackStack; | 2618 CallbackStack* Heap::s_weakCallbackStack; |
| 2814 CallbackStack* Heap::s_ephemeronStack; | 2619 CallbackStack* Heap::s_ephemeronStack; |
| 2815 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; | 2620 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; |
| 2816 bool Heap::s_shutdownCalled = false; | 2621 bool Heap::s_shutdownCalled = false; |
| 2817 bool Heap::s_lastGCWasConservative = false; | 2622 bool Heap::s_lastGCWasConservative = false; |
| 2818 FreePagePool* Heap::s_freePagePool; | 2623 FreePagePool* Heap::s_freePagePool; |
| 2819 OrphanedPagePool* Heap::s_orphanedPagePool; | 2624 OrphanedPagePool* Heap::s_orphanedPagePool; |
| 2820 } | 2625 } |
| OLD | NEW |