| 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 |