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 |