Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(161)

Side by Side Diff: Source/platform/heap/Heap.cpp

Issue 747363005: Oilpan: Introduce a state transition model for Oilpan GC states (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 409 matching lines...) Expand 10 before | Expand all | Expand 10 after
420 TRACE_EVENT0("blink_gc", "Heap::GCScope"); 420 TRACE_EVENT0("blink_gc", "Heap::GCScope");
421 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); 421 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE();
422 if (m_state->isMainThread()) 422 if (m_state->isMainThread())
423 TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting"); 423 TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting");
424 424
425 m_state->checkThread(); 425 m_state->checkThread();
426 426
427 // FIXME: in an unlikely coincidence that two threads decide 427 // FIXME: in an unlikely coincidence that two threads decide
428 // to collect garbage at the same time, avoid doing two GCs in 428 // to collect garbage at the same time, avoid doing two GCs in
429 // a row. 429 // a row.
430 RELEASE_ASSERT(!m_state->isInGC());
431 RELEASE_ASSERT(!m_state->isSweepInProgress());
432 if (LIKELY(ThreadState::stopThreads())) { 430 if (LIKELY(ThreadState::stopThreads())) {
433 m_parkedAllThreads = true; 431 m_parkedAllThreads = true;
434 m_state->enterGC();
435 } 432 }
436 if (m_state->isMainThread()) 433 if (m_state->isMainThread())
437 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); 434 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState);
438 } 435 }
439 436
440 bool allThreadsParked() { return m_parkedAllThreads; } 437 bool allThreadsParked() { return m_parkedAllThreads; }
441 438
442 ~GCScope() 439 ~GCScope()
443 { 440 {
444 // Only cleanup if we parked all threads in which case the GC happened 441 // Only cleanup if we parked all threads in which case the GC happened
445 // and we need to resume the other threads. 442 // and we need to resume the other threads.
446 if (LIKELY(m_parkedAllThreads)) { 443 if (LIKELY(m_parkedAllThreads)) {
447 m_state->leaveGC();
448 ASSERT(!m_state->isInGC());
449 ThreadState::resumeThreads(); 444 ThreadState::resumeThreads();
450 } 445 }
451 } 446 }
452 447
453 private: 448 private:
454 ThreadState* m_state; 449 ThreadState* m_state;
455 ThreadState::SafePointScope m_safePointScope; 450 ThreadState::SafePointScope m_safePointScope;
456 bool m_parkedAllThreads; // False if we fail to park all threads 451 bool m_parkedAllThreads; // False if we fail to park all threads
457 }; 452 };
458 453
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
686 { 681 {
687 ASSERT(allocationSize > remainingAllocationSize()); 682 ASSERT(allocationSize > remainingAllocationSize());
688 if (allocationSize > blinkPageSize / 2) 683 if (allocationSize > blinkPageSize / 2)
689 return allocateLargeObject(allocationSize, gcInfo); 684 return allocateLargeObject(allocationSize, gcInfo);
690 685
691 updateRemainingAllocationSize(); 686 updateRemainingAllocationSize();
692 if (threadState()->shouldGC()) { 687 if (threadState()->shouldGC()) {
693 if (threadState()->shouldForceConservativeGC()) 688 if (threadState()->shouldForceConservativeGC())
694 Heap::collectGarbage(ThreadState::HeapPointersOnStack); 689 Heap::collectGarbage(ThreadState::HeapPointersOnStack);
695 else 690 else
696 threadState()->setGCRequested(); 691 threadState()->setGCState(ThreadState::GCScheduled);
697 } 692 }
698 if (remainingAllocationSize() > 0) { 693 if (remainingAllocationSize() > 0) {
699 m_freeList.addToFreeList(currentAllocationPoint(), remainingAllocationSi ze()); 694 m_freeList.addToFreeList(currentAllocationPoint(), remainingAllocationSi ze());
700 setAllocationPoint(0, 0); 695 setAllocationPoint(0, 0);
701 } 696 }
702 ensureCurrentAllocation(allocationSize, gcInfo); 697 ensureCurrentAllocation(allocationSize, gcInfo);
703 return allocate(payloadSize, gcInfo); 698 return allocate(payloadSize, gcInfo);
704 } 699 }
705 700
706 template<typename Header> 701 template<typename Header>
(...skipping 314 matching lines...) Expand 10 before | Expand all | Expand 10 after
1021 allocationSize += headerPadding<Header>(); 1016 allocationSize += headerPadding<Header>();
1022 1017
1023 // If ASan is supported we add allocationGranularity bytes to the allocated space and 1018 // If ASan is supported we add allocationGranularity bytes to the allocated space and
1024 // poison that to detect overflows 1019 // poison that to detect overflows
1025 #if defined(ADDRESS_SANITIZER) 1020 #if defined(ADDRESS_SANITIZER)
1026 allocationSize += allocationGranularity; 1021 allocationSize += allocationGranularity;
1027 #endif 1022 #endif
1028 1023
1029 updateRemainingAllocationSize(); 1024 updateRemainingAllocationSize();
1030 if (m_threadState->shouldGC()) 1025 if (m_threadState->shouldGC())
1031 m_threadState->setGCRequested(); 1026 m_threadState->setGCState(ThreadState::GCScheduled);
1032 m_threadState->shouldFlushHeapDoesNotContainCache(); 1027 m_threadState->shouldFlushHeapDoesNotContainCache();
1033 PageMemory* pageMemory = PageMemory::allocate(allocationSize); 1028 PageMemory* pageMemory = PageMemory::allocate(allocationSize);
1034 m_threadState->allocatedRegionsSinceLastGC().append(pageMemory->region()); 1029 m_threadState->allocatedRegionsSinceLastGC().append(pageMemory->region());
1035 Address largeObjectAddress = pageMemory->writableStart(); 1030 Address largeObjectAddress = pageMemory->writableStart();
1036 Address headerAddress = largeObjectAddress + sizeof(LargeObject<Header>) + h eaderPadding<Header>(); 1031 Address headerAddress = largeObjectAddress + sizeof(LargeObject<Header>) + h eaderPadding<Header>();
1037 memset(headerAddress, 0, size); 1032 memset(headerAddress, 0, size);
1038 Header* header = new (NotNull, headerAddress) Header(size, gcInfo); 1033 Header* header = new (NotNull, headerAddress) Header(size, gcInfo);
1039 Address result = headerAddress + sizeof(*header); 1034 Address result = headerAddress + sizeof(*header);
1040 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask)); 1035 ASSERT(!(reinterpret_cast<uintptr_t>(result) & allocationMask));
1041 LargeObject<Header>* largeObject = new (largeObjectAddress) LargeObject<Head er>(pageMemory, gcInfo, threadState()); 1036 LargeObject<Header>* largeObject = new (largeObjectAddress) LargeObject<Head er>(pageMemory, gcInfo, threadState());
(...skipping 843 matching lines...) Expand 10 before | Expand all | Expand 10 after
1885 if (json) { 1880 if (json) {
1886 json->setInteger("class", tag); 1881 json->setInteger("class", tag);
1887 json->setInteger("size", header->size()); 1882 json->setInteger("size", header->size());
1888 json->setInteger("isMarked", isMarked()); 1883 json->setInteger("isMarked", isMarked());
1889 } 1884 }
1890 } 1885 }
1891 #endif 1886 #endif
1892 1887
1893 void HeapDoesNotContainCache::flush() 1888 void HeapDoesNotContainCache::flush()
1894 { 1889 {
1895 ASSERT(ThreadState::isAnyThreadInGC()); 1890 ASSERT(Heap::isInGC());
1896 1891
1897 if (m_hasEntries) { 1892 if (m_hasEntries) {
1898 for (int i = 0; i < numberOfEntries; i++) 1893 for (int i = 0; i < numberOfEntries; i++)
1899 m_entries[i] = 0; 1894 m_entries[i] = 0;
1900 m_hasEntries = false; 1895 m_hasEntries = false;
1901 } 1896 }
1902 } 1897 }
1903 1898
1904 size_t HeapDoesNotContainCache::hash(Address address) 1899 size_t HeapDoesNotContainCache::hash(Address address)
1905 { 1900 {
1906 size_t value = (reinterpret_cast<size_t>(address) >> blinkPageSizeLog2); 1901 size_t value = (reinterpret_cast<size_t>(address) >> blinkPageSizeLog2);
1907 value ^= value >> numberOfEntriesLog2; 1902 value ^= value >> numberOfEntriesLog2;
1908 value ^= value >> (numberOfEntriesLog2 * 2); 1903 value ^= value >> (numberOfEntriesLog2 * 2);
1909 value &= numberOfEntries - 1; 1904 value &= numberOfEntries - 1;
1910 return value & ~1; // Returns only even number. 1905 return value & ~1; // Returns only even number.
1911 } 1906 }
1912 1907
1913 bool HeapDoesNotContainCache::lookup(Address address) 1908 bool HeapDoesNotContainCache::lookup(Address address)
1914 { 1909 {
1915 ASSERT(ThreadState::isAnyThreadInGC()); 1910 ASSERT(Heap::isInGC());
1916 1911
1917 size_t index = hash(address); 1912 size_t index = hash(address);
1918 ASSERT(!(index & 1)); 1913 ASSERT(!(index & 1));
1919 Address cachePage = roundToBlinkPageStart(address); 1914 Address cachePage = roundToBlinkPageStart(address);
1920 if (m_entries[index] == cachePage) 1915 if (m_entries[index] == cachePage)
1921 return m_entries[index]; 1916 return m_entries[index];
1922 if (m_entries[index + 1] == cachePage) 1917 if (m_entries[index + 1] == cachePage)
1923 return m_entries[index + 1]; 1918 return m_entries[index + 1];
1924 return 0; 1919 return 0;
1925 } 1920 }
1926 1921
1927 void HeapDoesNotContainCache::addEntry(Address address) 1922 void HeapDoesNotContainCache::addEntry(Address address)
1928 { 1923 {
1929 ASSERT(ThreadState::isAnyThreadInGC()); 1924 ASSERT(Heap::isInGC());
1930 1925
1931 m_hasEntries = true; 1926 m_hasEntries = true;
1932 size_t index = hash(address); 1927 size_t index = hash(address);
1933 ASSERT(!(index & 1)); 1928 ASSERT(!(index & 1));
1934 Address cachePage = roundToBlinkPageStart(address); 1929 Address cachePage = roundToBlinkPageStart(address);
1935 m_entries[index + 1] = m_entries[index]; 1930 m_entries[index + 1] = m_entries[index];
1936 m_entries[index] = cachePage; 1931 m_entries[index] = cachePage;
1937 } 1932 }
1938 1933
1939 void Heap::flushHeapDoesNotContainCache() 1934 void Heap::flushHeapDoesNotContainCache()
(...skipping 21 matching lines...) Expand all
1961 inline void visitHeader(HeapObjectHeader* header, const void* objectPointer, TraceCallback callback) 1956 inline void visitHeader(HeapObjectHeader* header, const void* objectPointer, TraceCallback callback)
1962 { 1957 {
1963 ASSERT(header); 1958 ASSERT(header);
1964 #if ENABLE(ASSERT) 1959 #if ENABLE(ASSERT)
1965 { 1960 {
1966 // Check that we are not marking objects that are outside 1961 // Check that we are not marking objects that are outside
1967 // the heap by calling Heap::contains. However we cannot 1962 // the heap by calling Heap::contains. However we cannot
1968 // call Heap::contains when outside a GC and we call mark 1963 // call Heap::contains when outside a GC and we call mark
1969 // when doing weakness for ephemerons. Hence we only check 1964 // when doing weakness for ephemerons. Hence we only check
1970 // when called within. 1965 // when called within.
1971 ASSERT(!ThreadState::isAnyThreadInGC() || Heap::containedInHeapOrOrp hanedPage(header)); 1966 ASSERT(!Heap::isInGC() || Heap::containedInHeapOrOrphanedPage(header ));
1972 } 1967 }
1973 #endif 1968 #endif
1974 ASSERT(objectPointer); 1969 ASSERT(objectPointer);
1975 if (header->isMarked()) 1970 if (header->isMarked())
1976 return; 1971 return;
1977 header->mark(); 1972 header->mark();
1978 #if ENABLE(GC_PROFILE_MARKING) 1973 #if ENABLE(GC_PROFILE_MARKING)
1979 MutexLocker locker(objectGraphMutex()); 1974 MutexLocker locker(objectGraphMutex());
1980 String className(classOf(objectPointer)); 1975 String className(classOf(objectPointer));
1981 { 1976 {
(...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after
2184 s_shutdownCalled = true; 2179 s_shutdownCalled = true;
2185 ThreadState::shutdownHeapIfNecessary(); 2180 ThreadState::shutdownHeapIfNecessary();
2186 } 2181 }
2187 2182
2188 void Heap::doShutdown() 2183 void Heap::doShutdown()
2189 { 2184 {
2190 // We don't want to call doShutdown() twice. 2185 // We don't want to call doShutdown() twice.
2191 if (!s_markingVisitor) 2186 if (!s_markingVisitor)
2192 return; 2187 return;
2193 2188
2194 ASSERT(!ThreadState::isAnyThreadInGC()); 2189 ASSERT(!Heap::isInGC());
2195 ASSERT(!ThreadState::attachedThreads().size()); 2190 ASSERT(!ThreadState::attachedThreads().size());
2196 delete s_markingVisitor; 2191 delete s_markingVisitor;
2197 s_markingVisitor = 0; 2192 s_markingVisitor = 0;
2198 delete s_heapDoesNotContainCache; 2193 delete s_heapDoesNotContainCache;
2199 s_heapDoesNotContainCache = 0; 2194 s_heapDoesNotContainCache = 0;
2200 delete s_freePagePool; 2195 delete s_freePagePool;
2201 s_freePagePool = 0; 2196 s_freePagePool = 0;
2202 delete s_orphanedPagePool; 2197 delete s_orphanedPagePool;
2203 s_orphanedPagePool = 0; 2198 s_orphanedPagePool = 0;
2204 delete s_weakCallbackStack; 2199 delete s_weakCallbackStack;
2205 s_weakCallbackStack = 0; 2200 s_weakCallbackStack = 0;
2206 delete s_postMarkingCallbackStack; 2201 delete s_postMarkingCallbackStack;
2207 s_postMarkingCallbackStack = 0; 2202 s_postMarkingCallbackStack = 0;
2208 delete s_markingStack; 2203 delete s_markingStack;
2209 s_markingStack = 0; 2204 s_markingStack = 0;
2210 delete s_ephemeronStack; 2205 delete s_ephemeronStack;
2211 s_ephemeronStack = 0; 2206 s_ephemeronStack = 0;
2212 delete s_regionTree; 2207 delete s_regionTree;
2213 s_regionTree = 0; 2208 s_regionTree = 0;
2214 ThreadState::shutdown(); 2209 ThreadState::shutdown();
2215 ASSERT(Heap::allocatedSpace() == 0); 2210 ASSERT(Heap::allocatedSpace() == 0);
2216 } 2211 }
2217 2212
2218 BaseHeapPage* Heap::contains(Address address) 2213 BaseHeapPage* Heap::contains(Address address)
2219 { 2214 {
2220 ASSERT(ThreadState::isAnyThreadInGC()); 2215 ASSERT(Heap::isInGC());
2221 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( ); 2216 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( );
2222 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) { 2217 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) {
2223 BaseHeapPage* page = (*it)->contains(address); 2218 BaseHeapPage* page = (*it)->contains(address);
2224 if (page) 2219 if (page)
2225 return page; 2220 return page;
2226 } 2221 }
2227 return 0; 2222 return 0;
2228 } 2223 }
2229 2224
2230 #if ENABLE(ASSERT) 2225 #if ENABLE(ASSERT)
2231 bool Heap::containedInHeapOrOrphanedPage(void* object) 2226 bool Heap::containedInHeapOrOrphanedPage(void* object)
2232 { 2227 {
2233 return contains(object) || orphanedPagePool()->contains(object); 2228 return contains(object) || orphanedPagePool()->contains(object);
2234 } 2229 }
2235 #endif 2230 #endif
2236 2231
2237 Address Heap::checkAndMarkPointer(Visitor* visitor, Address address) 2232 Address Heap::checkAndMarkPointer(Visitor* visitor, Address address)
2238 { 2233 {
2239 ASSERT(ThreadState::isAnyThreadInGC()); 2234 ASSERT(Heap::isInGC());
2240 2235
2241 #if !ENABLE(ASSERT) 2236 #if !ENABLE(ASSERT)
2242 if (s_heapDoesNotContainCache->lookup(address)) 2237 if (s_heapDoesNotContainCache->lookup(address))
2243 return 0; 2238 return 0;
2244 #endif 2239 #endif
2245 2240
2246 if (BaseHeapPage* page = lookup(address)) { 2241 if (BaseHeapPage* page = lookup(address)) {
2247 ASSERT(page->contains(address)); 2242 ASSERT(page->contains(address));
2248 ASSERT(!page->orphaned()); 2243 ASSERT(!page->orphaned());
2249 ASSERT(!s_heapDoesNotContainCache->lookup(address)); 2244 ASSERT(!s_heapDoesNotContainCache->lookup(address));
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
2420 } 2415 }
2421 2416
2422 #if ENABLE(ASSERT) 2417 #if ENABLE(ASSERT)
2423 bool Heap::weakTableRegistered(const void* table) 2418 bool Heap::weakTableRegistered(const void* table)
2424 { 2419 {
2425 ASSERT(s_ephemeronStack); 2420 ASSERT(s_ephemeronStack);
2426 return s_ephemeronStack->hasCallbackForObject(table); 2421 return s_ephemeronStack->hasCallbackForObject(table);
2427 } 2422 }
2428 #endif 2423 #endif
2429 2424
2430 void Heap::prepareForGC() 2425 void Heap::preGC()
2431 { 2426 {
2432 ASSERT(ThreadState::isAnyThreadInGC());
2433 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( ); 2427 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( );
2434 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it) 2428 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
2435 (*it)->prepareForGC(); 2429 (*it)->preGC();
2430 }
2431
2432 void Heap::postGC()
2433 {
2434 ASSERT(Heap::isInGC());
2435 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( );
2436 for (ThreadState::AttachedThreadStateSet::iterator it = threads.begin(), end = threads.end(); it != end; ++it)
2437 (*it)->postGC();
2436 } 2438 }
2437 2439
2438 void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::Cause OfGC cause) 2440 void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::Cause OfGC cause)
2439 { 2441 {
2440 ThreadState* state = ThreadState::current(); 2442 ThreadState* state = ThreadState::current();
2441 state->clearGCRequested(); 2443 state->setGCState(ThreadState::StoppingOtherThreads);
2442 2444
2443 GCScope gcScope(stackState); 2445 GCScope gcScope(stackState);
2444 // Check if we successfully parked the other threads. If not we bail out of the GC. 2446 // Check if we successfully parked the other threads. If not we bail out of the GC.
2445 if (!gcScope.allThreadsParked()) { 2447 if (!gcScope.allThreadsParked()) {
2446 ThreadState::current()->setGCRequested(); 2448 state->setGCState(ThreadState::GCScheduled);
2447 return; 2449 return;
2448 } 2450 }
2449 2451
2450 if (state->isMainThread()) 2452 if (state->isMainThread())
2451 ScriptForbiddenScope::enter(); 2453 ScriptForbiddenScope::enter();
2452 2454
2453 s_lastGCWasConservative = false; 2455 s_lastGCWasConservative = false;
2454 2456
2455 Heap::resetMarkedObjectSize();
2456 Heap::resetAllocatedObjectSize();
2457
2458 TRACE_EVENT2("blink_gc", "Heap::collectGarbage", 2457 TRACE_EVENT2("blink_gc", "Heap::collectGarbage",
2459 "precise", stackState == ThreadState::NoHeapPointersOnStack, 2458 "precise", stackState == ThreadState::NoHeapPointersOnStack,
2460 "forced", cause == ThreadState::ForcedGC); 2459 "forced", cause == ThreadState::ForcedGC);
2461 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); 2460 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC");
2462 double timeStamp = WTF::currentTimeMS(); 2461 double timeStamp = WTF::currentTimeMS();
2463 #if ENABLE(GC_PROFILE_MARKING) 2462 #if ENABLE(GC_PROFILE_MARKING)
2464 static_cast<MarkingVisitor*>(s_markingVisitor)->objectGraph().clear(); 2463 static_cast<MarkingVisitor*>(s_markingVisitor)->objectGraph().clear();
2465 #endif 2464 #endif
2466 2465
2467 // Disallow allocation during garbage collection (but not 2466 // Disallow allocation during garbage collection (but not
2468 // during the finalization that happens when the gcScope is 2467 // during the finalization that happens when the gcScope is
2469 // torn down). 2468 // torn down).
2470 NoAllocationScope<AnyThread> noAllocationScope; 2469 NoAllocationScope<AnyThread> noAllocationScope;
2471 2470
2472 prepareForGC(); 2471 enterGC();
2472 preGC();
2473
2474 Heap::resetMarkedObjectSize();
2475 Heap::resetAllocatedObjectSize();
2473 2476
2474 // 1. trace persistent roots. 2477 // 1. trace persistent roots.
2475 ThreadState::visitPersistentRoots(s_markingVisitor); 2478 ThreadState::visitPersistentRoots(s_markingVisitor);
2476 2479
2477 // 2. trace objects reachable from the persistent roots including ephemerons . 2480 // 2. trace objects reachable from the persistent roots including ephemerons .
2478 processMarkingStack<GlobalMarking>(); 2481 processMarkingStack<GlobalMarking>();
2479 2482
2480 // 3. trace objects reachable from the stack. We do this independent of the 2483 // 3. trace objects reachable from the stack. We do this independent of the
2481 // given stackState since other threads might have a different stack state. 2484 // given stackState since other threads might have a different stack state.
2482 ThreadState::visitStackRoots(s_markingVisitor); 2485 ThreadState::visitStackRoots(s_markingVisitor);
2483 2486
2484 // 4. trace objects reachable from the stack "roots" including ephemerons. 2487 // 4. trace objects reachable from the stack "roots" including ephemerons.
2485 // Only do the processing if we found a pointer to an object on one of the 2488 // Only do the processing if we found a pointer to an object on one of the
2486 // thread stacks. 2489 // thread stacks.
2487 if (lastGCWasConservative()) { 2490 if (lastGCWasConservative()) {
2488 processMarkingStack<GlobalMarking>(); 2491 processMarkingStack<GlobalMarking>();
2489 } 2492 }
2490 2493
2491 postMarkingProcessing(); 2494 postMarkingProcessing();
2492 globalWeakProcessing(); 2495 globalWeakProcessing();
2493 2496
2494 // Now we can delete all orphaned pages because there are no dangling 2497 // Now we can delete all orphaned pages because there are no dangling
2495 // pointers to the orphaned pages. (If we have such dangling pointers, 2498 // pointers to the orphaned pages. (If we have such dangling pointers,
2496 // we should have crashed during marking before getting here.) 2499 // we should have crashed during marking before getting here.)
2497 orphanedPagePool()->decommitOrphanedPages(); 2500 orphanedPagePool()->decommitOrphanedPages();
2498 2501
2502 postGC();
2503 leaveGC();
2504
2499 #if ENABLE(GC_PROFILE_MARKING) 2505 #if ENABLE(GC_PROFILE_MARKING)
2500 static_cast<MarkingVisitor*>(s_markingVisitor)->reportStats(); 2506 static_cast<MarkingVisitor*>(s_markingVisitor)->reportStats();
2501 #endif 2507 #endif
2502 2508
2503 if (Platform::current()) { 2509 if (Platform::current()) {
2504 Platform::current()->histogramCustomCounts("BlinkGC.CollectGarbage", WTF ::currentTimeMS() - timeStamp, 0, 10 * 1000, 50); 2510 Platform::current()->histogramCustomCounts("BlinkGC.CollectGarbage", WTF ::currentTimeMS() - timeStamp, 0, 10 * 1000, 50);
2505 Platform::current()->histogramCustomCounts("BlinkGC.TotalObjectSpace", H eap::allocatedObjectSize() / 1024, 0, 4 * 1024 * 1024, 50); 2511 Platform::current()->histogramCustomCounts("BlinkGC.TotalObjectSpace", H eap::allocatedObjectSize() / 1024, 0, 4 * 1024 * 1024, 50);
2506 Platform::current()->histogramCustomCounts("BlinkGC.TotalAllocatedSpace" , Heap::allocatedSpace() / 1024, 0, 4 * 1024 * 1024, 50); 2512 Platform::current()->histogramCustomCounts("BlinkGC.TotalAllocatedSpace" , Heap::allocatedSpace() / 1024, 0, 4 * 1024 * 1024, 50);
2507 } 2513 }
2508 2514
2509 if (state->isMainThread()) 2515 if (state->isMainThread())
2510 ScriptForbiddenScope::exit(); 2516 ScriptForbiddenScope::exit();
2511 } 2517 }
2512 2518
2513 void Heap::collectGarbageForTerminatingThread(ThreadState* state) 2519 void Heap::collectGarbageForTerminatingThread(ThreadState* state)
2514 { 2520 {
2515 // We explicitly do not enter a safepoint while doing thread specific 2521 // We explicitly do not enter a safepoint while doing thread specific
2516 // garbage collection since we don't want to allow a global GC at the 2522 // garbage collection since we don't want to allow a global GC at the
2517 // same time as a thread local GC. 2523 // same time as a thread local GC.
2518 2524
2519 { 2525 {
2520 NoAllocationScope<AnyThread> noAllocationScope; 2526 NoAllocationScope<AnyThread> noAllocationScope;
2521 2527
2522 state->enterGC(); 2528 enterGC();
2523 state->prepareForGC(); 2529 state->preGC();
2524 2530
2525 // 1. trace the thread local persistent roots. For thread local GCs we 2531 // 1. trace the thread local persistent roots. For thread local GCs we
2526 // don't trace the stack (ie. no conservative scanning) since this is 2532 // don't trace the stack (ie. no conservative scanning) since this is
2527 // only called during thread shutdown where there should be no objects 2533 // only called during thread shutdown where there should be no objects
2528 // on the stack. 2534 // on the stack.
2529 // We also assume that orphaned pages have no objects reachable from 2535 // We also assume that orphaned pages have no objects reachable from
2530 // persistent handles on other threads or CrossThreadPersistents. The 2536 // persistent handles on other threads or CrossThreadPersistents. The
2531 // only cases where this could happen is if a subsequent conservative 2537 // only cases where this could happen is if a subsequent conservative
2532 // global GC finds a "pointer" on the stack or due to a programming 2538 // global GC finds a "pointer" on the stack or due to a programming
2533 // error where an object has a dangling cross-thread pointer to an 2539 // error where an object has a dangling cross-thread pointer to an
2534 // object on this heap. 2540 // object on this heap.
2535 state->visitPersistents(s_markingVisitor); 2541 state->visitPersistents(s_markingVisitor);
2536 2542
2537 // 2. trace objects reachable from the thread's persistent roots 2543 // 2. trace objects reachable from the thread's persistent roots
2538 // including ephemerons. 2544 // including ephemerons.
2539 processMarkingStack<ThreadLocalMarking>(); 2545 processMarkingStack<ThreadLocalMarking>();
2540 2546
2541 postMarkingProcessing(); 2547 postMarkingProcessing();
2542 globalWeakProcessing(); 2548 globalWeakProcessing();
2543 2549
2544 state->leaveGC(); 2550 state->postGC();
2551 leaveGC();
2545 } 2552 }
2546 state->performPendingSweep(); 2553 state->performPendingSweep();
2547 } 2554 }
2548 2555
2549 template<CallbackInvocationMode Mode> 2556 template<CallbackInvocationMode Mode>
2550 void Heap::processMarkingStack() 2557 void Heap::processMarkingStack()
2551 { 2558 {
2552 // Ephemeron fixed point loop. 2559 // Ephemeron fixed point loop.
2553 do { 2560 do {
2554 { 2561 {
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
2623 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) { 2630 for (HeapPage<Header>* page = m_firstPage; page; page = page->next()) {
2624 page->setTerminating(); 2631 page->setTerminating();
2625 } 2632 }
2626 for (LargeObject<Header>* largeObject = m_firstLargeObject; largeObject; lar geObject = largeObject->next()) { 2633 for (LargeObject<Header>* largeObject = m_firstLargeObject; largeObject; lar geObject = largeObject->next()) {
2627 largeObject->setTerminating(); 2634 largeObject->setTerminating();
2628 } 2635 }
2629 } 2636 }
2630 size_t Heap::objectPayloadSizeForTesting() 2637 size_t Heap::objectPayloadSizeForTesting()
2631 { 2638 {
2632 size_t objectPayloadSize = 0; 2639 size_t objectPayloadSize = 0;
2633 ASSERT(ThreadState::isAnyThreadInGC()); 2640 ASSERT(Heap::isInGC());
2634 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( ); 2641 ThreadState::AttachedThreadStateSet& threads = ThreadState::attachedThreads( );
2635 typedef ThreadState::AttachedThreadStateSet::iterator ThreadStateIterator; 2642 typedef ThreadState::AttachedThreadStateSet::iterator ThreadStateIterator;
2636 for (ThreadStateIterator it = threads.begin(), end = threads.end(); it != en d; ++it) { 2643 for (ThreadStateIterator it = threads.begin(), end = threads.end(); it != en d; ++it) {
2637 (*it)->makeConsistentForSweeping(); 2644 (*it)->makeConsistentForSweeping();
2638 objectPayloadSize += (*it)->objectPayloadSizeForTesting(); 2645 objectPayloadSize += (*it)->objectPayloadSizeForTesting();
2639 } 2646 }
2640 return objectPayloadSize; 2647 return objectPayloadSize;
2641 } 2648 }
2642 2649
2643 template<typename HeapTraits, typename HeapType, typename HeaderType> 2650 template<typename HeapTraits, typename HeapType, typename HeaderType>
2644 void HeapAllocator::backingFree(void* address) 2651 void HeapAllocator::backingFree(void* address)
2645 { 2652 {
2646 if (!address || ThreadState::isAnyThreadInGC()) 2653 if (!address || Heap::isInGC())
2647 return; 2654 return;
2648 2655
2649 ThreadState* state = ThreadState::current(); 2656 ThreadState* state = ThreadState::current();
2650 if (state->isSweepInProgress()) 2657 if (state->isSweepInProgress())
2651 return; 2658 return;
2652 2659
2653 // Don't promptly free large objects because their page is never reused 2660 // Don't promptly free large objects because their page is never reused
2654 // and don't free backings allocated on other threads. 2661 // and don't free backings allocated on other threads.
2655 BaseHeapPage* page = pageFromObject(address); 2662 BaseHeapPage* page = pageFromObject(address);
2656 if (page->isLargeObject() || page->threadState() != state) 2663 if (page->isLargeObject() || page->threadState() != state)
(...skipping 20 matching lines...) Expand all
2677 { 2684 {
2678 typedef HeapIndexTrait<HashTableBackingHeap> HeapTraits; 2685 typedef HeapIndexTrait<HashTableBackingHeap> HeapTraits;
2679 typedef HeapTraits::HeapType HeapType; 2686 typedef HeapTraits::HeapType HeapType;
2680 typedef HeapTraits::HeaderType HeaderType; 2687 typedef HeapTraits::HeaderType HeaderType;
2681 backingFree<HeapTraits, HeapType, HeaderType>(address); 2688 backingFree<HeapTraits, HeapType, HeaderType>(address);
2682 } 2689 }
2683 2690
2684 template<typename HeapTraits, typename HeapType, typename HeaderType> 2691 template<typename HeapTraits, typename HeapType, typename HeaderType>
2685 bool HeapAllocator::backingExpand(void* address, size_t newSize) 2692 bool HeapAllocator::backingExpand(void* address, size_t newSize)
2686 { 2693 {
2687 if (!address || ThreadState::isAnyThreadInGC()) 2694 if (!address || Heap::isInGC())
2688 return false; 2695 return false;
2689 2696
2690 ThreadState* state = ThreadState::current(); 2697 ThreadState* state = ThreadState::current();
2691 if (state->isSweepInProgress()) 2698 if (state->isSweepInProgress())
2692 return false; 2699 return false;
2693 ASSERT(state->isAllocationAllowed()); 2700 ASSERT(state->isAllocationAllowed());
2694 2701
2695 BaseHeapPage* page = pageFromObject(address); 2702 BaseHeapPage* page = pageFromObject(address);
2696 if (page->isLargeObject() || page->threadState() != state) 2703 if (page->isLargeObject() || page->threadState() != state)
2697 return false; 2704 return false;
(...skipping 10 matching lines...) Expand all
2708 bool HeapAllocator::vectorBackingExpand(void* address, size_t newSize) 2715 bool HeapAllocator::vectorBackingExpand(void* address, size_t newSize)
2709 { 2716 {
2710 typedef HeapIndexTrait<VectorBackingHeap> HeapTraits; 2717 typedef HeapIndexTrait<VectorBackingHeap> HeapTraits;
2711 typedef HeapTraits::HeapType HeapType; 2718 typedef HeapTraits::HeapType HeapType;
2712 typedef HeapTraits::HeaderType HeaderType; 2719 typedef HeapTraits::HeaderType HeaderType;
2713 return backingExpand<HeapTraits, HeapType, HeaderType>(address, newSize); 2720 return backingExpand<HeapTraits, HeapType, HeaderType>(address, newSize);
2714 } 2721 }
2715 2722
2716 BaseHeapPage* Heap::lookup(Address address) 2723 BaseHeapPage* Heap::lookup(Address address)
2717 { 2724 {
2718 ASSERT(ThreadState::isAnyThreadInGC()); 2725 ASSERT(Heap::isInGC());
2719 if (!s_regionTree) 2726 if (!s_regionTree)
2720 return 0; 2727 return 0;
2721 if (PageMemoryRegion* region = s_regionTree->lookup(address)) { 2728 if (PageMemoryRegion* region = s_regionTree->lookup(address)) {
2722 BaseHeapPage* page = region->pageFromAddress(address); 2729 BaseHeapPage* page = region->pageFromAddress(address);
2723 return page && !page->orphaned() ? page : 0; 2730 return page && !page->orphaned() ? page : 0;
2724 } 2731 }
2725 return 0; 2732 return 0;
2726 } 2733 }
2727 2734
2728 static Mutex& regionTreeMutex() 2735 static Mutex& regionTreeMutex()
2729 { 2736 {
2730 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex); 2737 AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
2731 return mutex; 2738 return mutex;
2732 } 2739 }
2733 2740
2734 void Heap::removePageMemoryRegion(PageMemoryRegion* region) 2741 void Heap::removePageMemoryRegion(PageMemoryRegion* region)
2735 { 2742 {
2736 // Deletion of large objects (and thus their regions) can happen concurrentl y 2743 // Deletion of large objects (and thus their regions) can happen concurrentl y
2737 // on sweeper threads. Removal can also happen during thread shutdown, but 2744 // on sweeper threads. Removal can also happen during thread shutdown, but
2738 // that case is safe. Regardless, we make all removals mutually exclusive. 2745 // that case is safe. Regardless, we make all removals mutually exclusive.
2739 MutexLocker locker(regionTreeMutex()); 2746 MutexLocker locker(regionTreeMutex());
2740 RegionTree::remove(region, &s_regionTree); 2747 RegionTree::remove(region, &s_regionTree);
2741 } 2748 }
2742 2749
2743 void Heap::addPageMemoryRegion(PageMemoryRegion* region) 2750 void Heap::addPageMemoryRegion(PageMemoryRegion* region)
2744 { 2751 {
2745 ASSERT(ThreadState::isAnyThreadInGC()); 2752 ASSERT(Heap::isInGC());
2746 RegionTree::add(new RegionTree(region), &s_regionTree); 2753 RegionTree::add(new RegionTree(region), &s_regionTree);
2747 } 2754 }
2748 2755
2749 PageMemoryRegion* Heap::RegionTree::lookup(Address address) 2756 PageMemoryRegion* Heap::RegionTree::lookup(Address address)
2750 { 2757 {
2751 RegionTree* current = s_regionTree; 2758 RegionTree* current = s_regionTree;
2752 while (current) { 2759 while (current) {
2753 Address base = current->m_region->base(); 2760 Address base = current->m_region->base();
2754 if (address < base) { 2761 if (address < base) {
2755 current = current->m_left; 2762 current = current->m_left;
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2811 template class ThreadHeap<HeapObjectHeader>; 2818 template class ThreadHeap<HeapObjectHeader>;
2812 2819
2813 Visitor* Heap::s_markingVisitor; 2820 Visitor* Heap::s_markingVisitor;
2814 CallbackStack* Heap::s_markingStack; 2821 CallbackStack* Heap::s_markingStack;
2815 CallbackStack* Heap::s_postMarkingCallbackStack; 2822 CallbackStack* Heap::s_postMarkingCallbackStack;
2816 CallbackStack* Heap::s_weakCallbackStack; 2823 CallbackStack* Heap::s_weakCallbackStack;
2817 CallbackStack* Heap::s_ephemeronStack; 2824 CallbackStack* Heap::s_ephemeronStack;
2818 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache; 2825 HeapDoesNotContainCache* Heap::s_heapDoesNotContainCache;
2819 bool Heap::s_shutdownCalled = false; 2826 bool Heap::s_shutdownCalled = false;
2820 bool Heap::s_lastGCWasConservative = false; 2827 bool Heap::s_lastGCWasConservative = false;
2828 bool Heap::s_inGC = false;
2821 FreePagePool* Heap::s_freePagePool; 2829 FreePagePool* Heap::s_freePagePool;
2822 OrphanedPagePool* Heap::s_orphanedPagePool; 2830 OrphanedPagePool* Heap::s_orphanedPagePool;
2823 Heap::RegionTree* Heap::s_regionTree = 0; 2831 Heap::RegionTree* Heap::s_regionTree = 0;
2824 size_t Heap::s_allocatedObjectSize = 0; 2832 size_t Heap::s_allocatedObjectSize = 0;
2825 size_t Heap::s_allocatedSpace = 0; 2833 size_t Heap::s_allocatedSpace = 0;
2826 size_t Heap::s_markedObjectSize = 0; 2834 size_t Heap::s_markedObjectSize = 0;
2827 2835
2828 } // namespace blink 2836 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698