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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
45 #include "platform/instrumentation/tracing/TraceEvent.h" | 45 #include "platform/instrumentation/tracing/TraceEvent.h" |
46 #include "platform/instrumentation/tracing/web_memory_allocator_dump.h" | 46 #include "platform/instrumentation/tracing/web_memory_allocator_dump.h" |
47 #include "platform/instrumentation/tracing/web_process_memory_dump.h" | 47 #include "platform/instrumentation/tracing/web_process_memory_dump.h" |
48 #include "public/platform/Platform.h" | 48 #include "public/platform/Platform.h" |
49 #include "public/platform/WebScheduler.h" | 49 #include "public/platform/WebScheduler.h" |
50 #include "public/platform/WebThread.h" | 50 #include "public/platform/WebThread.h" |
51 #include "public/platform/WebTraceLocation.h" | 51 #include "public/platform/WebTraceLocation.h" |
52 #include "wtf/CurrentTime.h" | 52 #include "wtf/CurrentTime.h" |
53 #include "wtf/DataLog.h" | 53 #include "wtf/DataLog.h" |
54 #include "wtf/PtrUtil.h" | 54 #include "wtf/PtrUtil.h" |
| 55 #include "wtf/StackUtil.h" |
55 #include "wtf/ThreadingPrimitives.h" | 56 #include "wtf/ThreadingPrimitives.h" |
56 #include "wtf/allocator/Partitions.h" | 57 #include "wtf/allocator/Partitions.h" |
57 #include <memory> | 58 #include <memory> |
58 #include <v8.h> | 59 #include <v8.h> |
59 | 60 |
60 #if OS(WIN) | 61 #if OS(WIN) |
61 #include <stddef.h> | 62 #include <stddef.h> |
62 #include <windows.h> | 63 #include <windows.h> |
63 #include <winnt.h> | 64 #include <winnt.h> |
64 #endif | 65 #endif |
65 | 66 |
66 #if defined(MEMORY_SANITIZER) | 67 #if defined(MEMORY_SANITIZER) |
67 #include <sanitizer/msan_interface.h> | 68 #include <sanitizer/msan_interface.h> |
68 #endif | 69 #endif |
69 | 70 |
70 #if OS(FREEBSD) | 71 #if OS(FREEBSD) |
71 #include <pthread_np.h> | 72 #include <pthread_np.h> |
72 #endif | 73 #endif |
73 | 74 |
74 namespace blink { | 75 namespace blink { |
75 | 76 |
76 WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = nullptr; | 77 WTF::ThreadSpecific<ThreadState*>* ThreadState::s_threadSpecific = nullptr; |
77 uintptr_t ThreadState::s_mainThreadStackStart = 0; | |
78 uintptr_t ThreadState::s_mainThreadUnderestimatedStackSize = 0; | |
79 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; | 78 uint8_t ThreadState::s_mainThreadStateStorage[sizeof(ThreadState)]; |
80 | 79 |
81 const size_t defaultAllocatedObjectSizeThreshold = 100 * 1024; | 80 const size_t defaultAllocatedObjectSizeThreshold = 100 * 1024; |
82 | 81 |
83 const char* ThreadState::gcReasonString(BlinkGC::GCReason reason) { | 82 const char* ThreadState::gcReasonString(BlinkGC::GCReason reason) { |
84 switch (reason) { | 83 switch (reason) { |
85 case BlinkGC::IdleGC: | 84 case BlinkGC::IdleGC: |
86 return "IdleGC"; | 85 return "IdleGC"; |
87 case BlinkGC::PreciseGC: | 86 case BlinkGC::PreciseGC: |
88 return "PreciseGC"; | 87 return "PreciseGC"; |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
135 } | 134 } |
136 | 135 |
137 private: | 136 private: |
138 ThreadState* m_state; | 137 ThreadState* m_state; |
139 bool m_shouldResumeThreads; | 138 bool m_shouldResumeThreads; |
140 }; | 139 }; |
141 | 140 |
142 ThreadState::ThreadState() | 141 ThreadState::ThreadState() |
143 : m_thread(currentThread()), | 142 : m_thread(currentThread()), |
144 m_persistentRegion(WTF::makeUnique<PersistentRegion>()), | 143 m_persistentRegion(WTF::makeUnique<PersistentRegion>()), |
145 #if OS(WIN) && COMPILER(MSVC) | 144 m_startOfStack(reinterpret_cast<intptr_t*>(WTF::getStackStart())), |
146 m_threadStackSize(0), | 145 m_endOfStack(reinterpret_cast<intptr_t*>(WTF::getStackStart())), |
147 #endif | |
148 m_startOfStack( | |
149 reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart())), | |
150 m_endOfStack( | |
151 reinterpret_cast<intptr_t*>(StackFrameDepth::getStackStart())), | |
152 m_safePointScopeMarker(nullptr), | 146 m_safePointScopeMarker(nullptr), |
153 m_atSafePoint(false), | 147 m_atSafePoint(false), |
154 m_interruptors(), | 148 m_interruptors(), |
155 m_sweepForbidden(false), | 149 m_sweepForbidden(false), |
156 m_noAllocationCount(0), | 150 m_noAllocationCount(0), |
157 m_gcForbiddenCount(0), | 151 m_gcForbiddenCount(0), |
158 m_mixinsBeingConstructedCount(0), | 152 m_mixinsBeingConstructedCount(0), |
159 m_accumulatedSweepingTime(0), | 153 m_accumulatedSweepingTime(0), |
160 m_vectorBackingArenaIndex(BlinkGC::Vector1ArenaIndex), | 154 m_vectorBackingArenaIndex(BlinkGC::Vector1ArenaIndex), |
161 m_currentArenaAges(0), | 155 m_currentArenaAges(0), |
(...skipping 11 matching lines...) Expand all Loading... |
173 #if defined(LEAK_SANITIZER) | 167 #if defined(LEAK_SANITIZER) |
174 m_disabledStaticPersistentsRegistration(0), | 168 m_disabledStaticPersistentsRegistration(0), |
175 #endif | 169 #endif |
176 m_allocatedObjectSize(0), | 170 m_allocatedObjectSize(0), |
177 m_markedObjectSize(0), | 171 m_markedObjectSize(0), |
178 m_reportedMemoryToV8(0) { | 172 m_reportedMemoryToV8(0) { |
179 ASSERT(checkThread()); | 173 ASSERT(checkThread()); |
180 ASSERT(!**s_threadSpecific); | 174 ASSERT(!**s_threadSpecific); |
181 **s_threadSpecific = this; | 175 **s_threadSpecific = this; |
182 | 176 |
183 if (isMainThread()) { | |
184 s_mainThreadStackStart = | |
185 reinterpret_cast<uintptr_t>(m_startOfStack) - sizeof(void*); | |
186 size_t underestimatedStackSize = | |
187 StackFrameDepth::getUnderestimatedStackSize(); | |
188 if (underestimatedStackSize > sizeof(void*)) { | |
189 s_mainThreadUnderestimatedStackSize = | |
190 underestimatedStackSize - sizeof(void*); | |
191 } | |
192 } | |
193 m_heap = new ThreadHeap(); | 177 m_heap = new ThreadHeap(); |
194 ASSERT(m_heap); | 178 ASSERT(m_heap); |
195 m_heap->attach(this); | 179 m_heap->attach(this); |
196 | 180 |
197 for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex; | 181 for (int arenaIndex = 0; arenaIndex < BlinkGC::LargeObjectArenaIndex; |
198 arenaIndex++) | 182 arenaIndex++) |
199 m_arenas[arenaIndex] = new NormalPageArena(this, arenaIndex); | 183 m_arenas[arenaIndex] = new NormalPageArena(this, arenaIndex); |
200 m_arenas[BlinkGC::LargeObjectArenaIndex] = | 184 m_arenas[BlinkGC::LargeObjectArenaIndex] = |
201 new LargeObjectArena(this, BlinkGC::LargeObjectArenaIndex); | 185 new LargeObjectArena(this, BlinkGC::LargeObjectArenaIndex); |
202 | 186 |
203 m_likelyToBePromptlyFreed = | 187 m_likelyToBePromptlyFreed = |
204 wrapArrayUnique(new int[likelyToBePromptlyFreedArraySize]); | 188 wrapArrayUnique(new int[likelyToBePromptlyFreedArraySize]); |
205 clearArenaAges(); | 189 clearArenaAges(); |
206 } | 190 } |
207 | 191 |
208 ThreadState::~ThreadState() { | 192 ThreadState::~ThreadState() { |
209 ASSERT(checkThread()); | 193 ASSERT(checkThread()); |
210 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) | 194 for (int i = 0; i < BlinkGC::NumberOfArenas; ++i) |
211 delete m_arenas[i]; | 195 delete m_arenas[i]; |
212 | 196 |
213 **s_threadSpecific = nullptr; | 197 **s_threadSpecific = nullptr; |
214 if (isMainThread()) { | |
215 s_mainThreadStackStart = 0; | |
216 s_mainThreadUnderestimatedStackSize = 0; | |
217 } | |
218 } | 198 } |
219 | 199 |
220 #if OS(WIN) && COMPILER(MSVC) | |
221 size_t ThreadState::threadStackSize() { | |
222 if (m_threadStackSize) | |
223 return m_threadStackSize; | |
224 | |
225 // Notice that we cannot use the TIB's StackLimit for the stack end, as it | |
226 // tracks the end of the committed range. We're after the end of the reserved | |
227 // stack area (most of which will be uncommitted, most times.) | |
228 MEMORY_BASIC_INFORMATION stackInfo; | |
229 memset(&stackInfo, 0, sizeof(MEMORY_BASIC_INFORMATION)); | |
230 size_t resultSize = | |
231 VirtualQuery(&stackInfo, &stackInfo, sizeof(MEMORY_BASIC_INFORMATION)); | |
232 DCHECK_GE(resultSize, sizeof(MEMORY_BASIC_INFORMATION)); | |
233 Address stackEnd = reinterpret_cast<Address>(stackInfo.AllocationBase); | |
234 | |
235 Address stackStart = | |
236 reinterpret_cast<Address>(StackFrameDepth::getStackStart()); | |
237 RELEASE_ASSERT(stackStart && stackStart > stackEnd); | |
238 m_threadStackSize = static_cast<size_t>(stackStart - stackEnd); | |
239 // When the third last page of the reserved stack is accessed as a | |
240 // guard page, the second last page will be committed (along with removing | |
241 // the guard bit on the third last) _and_ a stack overflow exception | |
242 // is raised. | |
243 // | |
244 // We have zero interest in running into stack overflow exceptions while | |
245 // marking objects, so simply consider the last three pages + one above | |
246 // as off-limits and adjust the reported stack size accordingly. | |
247 // | |
248 // http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-man
agement.aspx | |
249 // explains the details. | |
250 RELEASE_ASSERT(m_threadStackSize > 4 * 0x1000); | |
251 m_threadStackSize -= 4 * 0x1000; | |
252 return m_threadStackSize; | |
253 } | |
254 #endif | |
255 | |
256 void ThreadState::attachMainThread() { | 200 void ThreadState::attachMainThread() { |
257 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete); | 201 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete); |
258 s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>(); | 202 s_threadSpecific = new WTF::ThreadSpecific<ThreadState*>(); |
259 new (s_mainThreadStateStorage) ThreadState(); | 203 new (s_mainThreadStateStorage) ThreadState(); |
260 } | 204 } |
261 | 205 |
262 void ThreadState::attachCurrentThread() { | 206 void ThreadState::attachCurrentThread() { |
263 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete); | 207 RELEASE_ASSERT(!ProcessHeap::s_shutdownComplete); |
264 new ThreadState(); | 208 new ThreadState(); |
265 } | 209 } |
(...skipping 1064 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1330 | 1274 |
1331 #ifdef ADDRESS_SANITIZER | 1275 #ifdef ADDRESS_SANITIZER |
1332 // When we are running under AddressSanitizer with | 1276 // When we are running under AddressSanitizer with |
1333 // detect_stack_use_after_return=1 then stack marker obtained from | 1277 // detect_stack_use_after_return=1 then stack marker obtained from |
1334 // SafePointScope will point into a fake stack. Detect this case by checking if | 1278 // SafePointScope will point into a fake stack. Detect this case by checking if |
1335 // it falls in between current stack frame and stack start and use an arbitrary | 1279 // it falls in between current stack frame and stack start and use an arbitrary |
1336 // high enough value for it. Don't adjust stack marker in any other case to | 1280 // high enough value for it. Don't adjust stack marker in any other case to |
1337 // match behavior of code running without AddressSanitizer. | 1281 // match behavior of code running without AddressSanitizer. |
1338 NO_SANITIZE_ADDRESS static void* adjustScopeMarkerForAdressSanitizer( | 1282 NO_SANITIZE_ADDRESS static void* adjustScopeMarkerForAdressSanitizer( |
1339 void* scopeMarker) { | 1283 void* scopeMarker) { |
1340 Address start = reinterpret_cast<Address>(StackFrameDepth::getStackStart()); | 1284 Address start = reinterpret_cast<Address>(WTF::getStackStart()); |
1341 Address end = reinterpret_cast<Address>(&start); | 1285 Address end = reinterpret_cast<Address>(&start); |
1342 RELEASE_ASSERT(end < start); | 1286 RELEASE_ASSERT(end < start); |
1343 | 1287 |
1344 if (end <= scopeMarker && scopeMarker < start) | 1288 if (end <= scopeMarker && scopeMarker < start) |
1345 return scopeMarker; | 1289 return scopeMarker; |
1346 | 1290 |
1347 // 256 is as good an approximation as any else. | 1291 // 256 is as good an approximation as any else. |
1348 const size_t bytesToCopy = sizeof(Address) * 256; | 1292 const size_t bytesToCopy = sizeof(Address) * 256; |
1349 if (static_cast<size_t>(start - end) < bytesToCopy) | 1293 if (static_cast<size_t>(start - end) < bytesToCopy) |
1350 return start; | 1294 return start; |
(...skipping 489 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1840 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, | 1784 collectGarbage(BlinkGC::NoHeapPointersOnStack, BlinkGC::GCWithSweep, |
1841 BlinkGC::ForcedGC); | 1785 BlinkGC::ForcedGC); |
1842 size_t liveObjects = heap().heapStats().markedObjectSize(); | 1786 size_t liveObjects = heap().heapStats().markedObjectSize(); |
1843 if (liveObjects == previousLiveObjects) | 1787 if (liveObjects == previousLiveObjects) |
1844 break; | 1788 break; |
1845 previousLiveObjects = liveObjects; | 1789 previousLiveObjects = liveObjects; |
1846 } | 1790 } |
1847 } | 1791 } |
1848 | 1792 |
1849 } // namespace blink | 1793 } // namespace blink |
OLD | NEW |