| 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 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 102 | 102 |
| 103 #if ENABLE(GC_PROFILING) | 103 #if ENABLE(GC_PROFILING) |
| 104 static String classOf(const void* object) | 104 static String classOf(const void* object) |
| 105 { | 105 { |
| 106 if (const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_
cast<void*>(object)))) | 106 if (const GCInfo* gcInfo = Heap::findGCInfo(reinterpret_cast<Address>(const_
cast<void*>(object)))) |
| 107 return gcInfo->m_className; | 107 return gcInfo->m_className; |
| 108 return "unknown"; | 108 return "unknown"; |
| 109 } | 109 } |
| 110 #endif | 110 #endif |
| 111 | 111 |
| 112 class GCForbiddenScope final { |
| 113 public: |
| 114 explicit GCForbiddenScope(ThreadState* state) |
| 115 : m_state(state) |
| 116 { |
| 117 // Prevent nested collectGarbage() invocations. |
| 118 m_state->enterGCForbiddenScope(); |
| 119 } |
| 120 |
| 121 ~GCForbiddenScope() |
| 122 { |
| 123 m_state->leaveGCForbiddenScope(); |
| 124 } |
| 125 |
| 126 private: |
| 127 ThreadState* m_state; |
| 128 }; |
| 129 |
| 112 class GCScope final { | 130 class GCScope final { |
| 113 public: | 131 public: |
| 114 GCScope(ThreadState::StackState stackState, ThreadState::GCType gcType) | 132 GCScope(ThreadState* state, ThreadState::StackState stackState, ThreadState:
:GCType gcType) |
| 115 : m_state(ThreadState::current()) | 133 : m_state(state) |
| 134 , m_gcForbiddenScope(state) |
| 135 // See collectGarbageForTerminatingThread() comment on why a |
| 136 // safepoint scope isn't entered for its GCScope. |
| 137 , m_safePointScope(stackState, gcType != ThreadState::ThreadTerminationG
C ? state : nullptr) |
| 116 , m_gcType(gcType) | 138 , m_gcType(gcType) |
| 117 , m_parkedAllThreads(false) | 139 , m_parkedAllThreads(false) |
| 118 { | 140 { |
| 119 TRACE_EVENT0("blink_gc", "Heap::GCScope"); | 141 TRACE_EVENT0("blink_gc", "Heap::GCScope"); |
| 120 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); | 142 const char* samplingState = TRACE_EVENT_GET_SAMPLING_STATE(); |
| 121 if (m_state->isMainThread()) | 143 if (m_state->isMainThread()) |
| 122 TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting"); | 144 TRACE_EVENT_SET_SAMPLING_STATE("blink_gc", "BlinkGCWaiting"); |
| 123 | 145 |
| 124 m_state->checkThread(); | 146 m_state->checkThread(); |
| 125 | 147 |
| 126 // We explicitly do not enter a safepoint while doing thread specific | 148 // TODO(haraken): In an unlikely coincidence that two threads decide |
| 127 // garbage collection since we don't want to allow a global GC at the | 149 // to collect garbage at the same time, avoid doing two GCs in |
| 128 // same time as a thread local GC. | 150 // a row. |
| 129 if (gcType != ThreadState::ThreadTerminationGC) { | 151 if (LIKELY(gcType != ThreadState::ThreadTerminationGC && ThreadState::st
opThreads())) |
| 130 RELEASE_ASSERT(!ThreadState::current()->isAtSafePoint()); | 152 m_parkedAllThreads = true; |
| 131 m_state->enterSafePoint(stackState, this); | |
| 132 | |
| 133 // TODO(haraken): In an unlikely coincidence that two threads decide | |
| 134 // to collect garbage at the same time, avoid doing two GCs in | |
| 135 // a row. | |
| 136 if (LIKELY(ThreadState::stopThreads())) { | |
| 137 m_parkedAllThreads = true; | |
| 138 } | |
| 139 } | |
| 140 | 153 |
| 141 if (m_state->isMainThread()) | 154 if (m_state->isMainThread()) |
| 142 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); | 155 TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(samplingState); |
| 143 } | 156 } |
| 144 | 157 |
| 145 bool allThreadsParked() { return m_parkedAllThreads; } | 158 bool allThreadsParked() { return m_parkedAllThreads; } |
| 146 | 159 |
| 147 ~GCScope() | 160 ~GCScope() |
| 148 { | 161 { |
| 149 if (m_gcType != ThreadState::ThreadTerminationGC) { | 162 // Only cleanup if we parked all threads in which case the GC happened |
| 150 // Only cleanup if we parked all threads in which case the GC happen
ed | 163 // and we need to resume the other threads. |
| 151 // and we need to resume the other threads. | 164 if (LIKELY(m_gcType != ThreadState::ThreadTerminationGC && m_parkedAllTh
reads)) |
| 152 if (LIKELY(m_parkedAllThreads)) { | 165 ThreadState::resumeThreads(); |
| 153 ThreadState::resumeThreads(); | |
| 154 } | |
| 155 | |
| 156 m_state->leaveSafePoint(); | |
| 157 } | |
| 158 } | 166 } |
| 159 | 167 |
| 160 private: | 168 private: |
| 161 ThreadState* m_state; | 169 ThreadState* m_state; |
| 170 // The ordering of the two scope objects matters: GCs must first be forbidde
n |
| 171 // before entering the safe point scope. Prior to reaching the safe point, |
| 172 // ThreadState::runScheduledGC() is called. See its comment why we need |
| 173 // to be in a GC forbidden scope when doing so. |
| 174 GCForbiddenScope m_gcForbiddenScope; |
| 175 SafePointScope m_safePointScope; |
| 162 ThreadState::GCType m_gcType; | 176 ThreadState::GCType m_gcType; |
| 163 bool m_parkedAllThreads; // False if we fail to park all threads | 177 bool m_parkedAllThreads; // False if we fail to park all threads |
| 164 }; | 178 }; |
| 165 | 179 |
| 166 #if ENABLE(ASSERT) | 180 #if ENABLE(ASSERT) |
| 167 NO_SANITIZE_ADDRESS | 181 NO_SANITIZE_ADDRESS |
| 168 void HeapObjectHeader::zapMagic() | 182 void HeapObjectHeader::zapMagic() |
| 169 { | 183 { |
| 170 checkHeader(); | 184 checkHeader(); |
| 171 m_magic = zappedMagic; | 185 m_magic = zappedMagic; |
| (...skipping 1716 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1888 STRINGIFY_REASON(ForcedGC); | 1902 STRINGIFY_REASON(ForcedGC); |
| 1889 #undef STRINGIFY_REASON | 1903 #undef STRINGIFY_REASON |
| 1890 case NumberOfGCReason: ASSERT_NOT_REACHED(); | 1904 case NumberOfGCReason: ASSERT_NOT_REACHED(); |
| 1891 } | 1905 } |
| 1892 return "<Unknown>"; | 1906 return "<Unknown>"; |
| 1893 } | 1907 } |
| 1894 | 1908 |
| 1895 void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCTyp
e gcType, GCReason reason) | 1909 void Heap::collectGarbage(ThreadState::StackState stackState, ThreadState::GCTyp
e gcType, GCReason reason) |
| 1896 { | 1910 { |
| 1897 ThreadState* state = ThreadState::current(); | 1911 ThreadState* state = ThreadState::current(); |
| 1898 RELEASE_ASSERT(!state->isInGC()); | 1912 // Nested collectGarbage() invocations aren't supported. |
| 1913 RELEASE_ASSERT(!state->isGCForbidden()); |
| 1899 state->completeSweep(); | 1914 state->completeSweep(); |
| 1900 ThreadState::GCState originalGCState = state->gcState(); | |
| 1901 state->setGCState(ThreadState::StoppingOtherThreads); | |
| 1902 | 1915 |
| 1903 GCScope gcScope(stackState, gcType); | 1916 GCScope gcScope(state, stackState, gcType); |
| 1904 // Check if we successfully parked the other threads. If not we bail out of | 1917 // Check if we successfully parked the other threads. If not we bail out of |
| 1905 // the GC. | 1918 // the GC. |
| 1906 if (!gcScope.allThreadsParked()) { | 1919 if (!gcScope.allThreadsParked()) |
| 1907 // Restore the original GCState. | |
| 1908 if (LIKELY(state->gcState() == ThreadState::StoppingOtherThreads)) | |
| 1909 state->setGCState(originalGCState); | |
| 1910 return; | 1920 return; |
| 1911 } | |
| 1912 | 1921 |
| 1913 if (state->isMainThread()) | 1922 if (state->isMainThread()) |
| 1914 ScriptForbiddenScope::enter(); | 1923 ScriptForbiddenScope::enter(); |
| 1915 | 1924 |
| 1916 s_lastGCWasConservative = false; | 1925 s_lastGCWasConservative = false; |
| 1917 | 1926 |
| 1918 TRACE_EVENT2("blink_gc", "Heap::collectGarbage", | 1927 TRACE_EVENT2("blink_gc", "Heap::collectGarbage", |
| 1919 "lazySweeping", gcType == ThreadState::GCWithoutSweep, | 1928 "lazySweeping", gcType == ThreadState::GCWithoutSweep, |
| 1920 "gcReason", gcReasonString(reason)); | 1929 "gcReason", gcReasonString(reason)); |
| 1921 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); | 1930 TRACE_EVENT_SCOPED_SAMPLING_STATE("blink_gc", "BlinkGC"); |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1976 Heap::reportMemoryUsageHistogram(); | 1985 Heap::reportMemoryUsageHistogram(); |
| 1977 WTF::Partitions::reportMemoryUsageHistogram(); | 1986 WTF::Partitions::reportMemoryUsageHistogram(); |
| 1978 | 1987 |
| 1979 if (state->isMainThread()) | 1988 if (state->isMainThread()) |
| 1980 ScriptForbiddenScope::exit(); | 1989 ScriptForbiddenScope::exit(); |
| 1981 } | 1990 } |
| 1982 | 1991 |
| 1983 void Heap::collectGarbageForTerminatingThread(ThreadState* state) | 1992 void Heap::collectGarbageForTerminatingThread(ThreadState* state) |
| 1984 { | 1993 { |
| 1985 { | 1994 { |
| 1986 GCScope gcScope(ThreadState::NoHeapPointersOnStack, ThreadState::ThreadT
erminationGC); | 1995 // A thread-specific termination GC must not allow other global GCs to g
o |
| 1996 // ahead while it is running, hence the termination GC does not enter a |
| 1997 // safepoint. GCScope will not enter also a safepoint scope for |
| 1998 // ThreadTerminationGC. |
| 1999 GCScope gcScope(state, ThreadState::NoHeapPointersOnStack, ThreadState::
ThreadTerminationGC); |
| 1987 | 2000 |
| 1988 MarkingVisitor<Visitor::ThreadLocalMarking> markingVisitor; | 2001 MarkingVisitor<Visitor::ThreadLocalMarking> markingVisitor; |
| 1989 ThreadState::NoAllocationScope noAllocationScope(state); | 2002 ThreadState::NoAllocationScope noAllocationScope(state); |
| 1990 | 2003 |
| 1991 state->preGC(); | 2004 state->preGC(); |
| 1992 StackFrameDepthScope stackDepthScope; | 2005 StackFrameDepthScope stackDepthScope; |
| 1993 | 2006 |
| 1994 // 1. Trace the thread local persistent roots. For thread local GCs we | 2007 // 1. Trace the thread local persistent roots. For thread local GCs we |
| 1995 // don't trace the stack (ie. no conservative scanning) since this is | 2008 // don't trace the stack (ie. no conservative scanning) since this is |
| 1996 // only called during thread shutdown where there should be no objects | 2009 // only called during thread shutdown where there should be no objects |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2246 size_t Heap::s_allocatedObjectSize = 0; | 2259 size_t Heap::s_allocatedObjectSize = 0; |
| 2247 size_t Heap::s_allocatedSpace = 0; | 2260 size_t Heap::s_allocatedSpace = 0; |
| 2248 size_t Heap::s_markedObjectSize = 0; | 2261 size_t Heap::s_markedObjectSize = 0; |
| 2249 // We don't want to use 0 KB for the initial value because it may end up | 2262 // We don't want to use 0 KB for the initial value because it may end up |
| 2250 // triggering the first GC of some thread too prematurely. | 2263 // triggering the first GC of some thread too prematurely. |
| 2251 size_t Heap::s_estimatedLiveObjectSize = 512 * 1024; | 2264 size_t Heap::s_estimatedLiveObjectSize = 512 * 1024; |
| 2252 size_t Heap::s_externalObjectSizeAtLastGC = 0; | 2265 size_t Heap::s_externalObjectSizeAtLastGC = 0; |
| 2253 double Heap::s_estimatedMarkingTimePerByte = 0.0; | 2266 double Heap::s_estimatedMarkingTimePerByte = 0.0; |
| 2254 | 2267 |
| 2255 } // namespace blink | 2268 } // namespace blink |
| OLD | NEW |