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

Side by Side Diff: third_party/WebKit/Source/platform/heap/ThreadState.cpp

Issue 2623273007: Fast path for ThreadSpecific for main thread on TLS-slow platforms (Closed)
Patch Set: haraken revieqw Created 3 years, 11 months 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
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 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/heap/ThreadState.h ('k') | third_party/WebKit/Source/wtf/BUILD.gn » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698