Index: third_party/WebKit/Source/wtf/WTFThreadData.cpp |
diff --git a/third_party/WebKit/Source/wtf/WTFThreadData.cpp b/third_party/WebKit/Source/wtf/WTFThreadData.cpp |
index 33abb350ad6961e7e70fada3cb27683297d177f4..802c761d90190f156b7ec023bdc0290112ddc8de 100644 |
--- a/third_party/WebKit/Source/wtf/WTFThreadData.cpp |
+++ b/third_party/WebKit/Source/wtf/WTFThreadData.cpp |
@@ -26,18 +26,112 @@ |
#include "wtf/WTFThreadData.h" |
+#include "wtf/PtrUtil.h" |
+#include "wtf/StackUtil.h" |
#include "wtf/text/AtomicStringTable.h" |
#include "wtf/text/TextCodecICU.h" |
namespace WTF { |
+uintptr_t WTFThreadData::s_mainThreadStackStart = 0; |
+uintptr_t WTFThreadData::s_mainThreadUnderestimatedStackSize = 0; |
+uint8_t WTFThreadData::s_mainThreadDataStorage[sizeof(WTFThreadData)]; |
+ |
ThreadSpecific<WTFThreadData>* WTFThreadData::staticData; |
-WTFThreadData::WTFThreadData() |
- : m_atomicStringTable(new AtomicStringTable), |
- m_cachedConverterICU(new ICUConverterWrapper), |
- m_threadId(internal::currentThreadSyscall()) {} |
+WTFThreadData::WTFThreadData(ThreadType type) |
+ : m_threadId(internal::currentThreadSyscall()) { |
+ // Static globals must be initialized before the AtomicStringTable, but after |
+ // |this| is initialized. Note that we call threadStackSize() from |
+ // getUnderestimatedStackSize() on MSVC. |
+ if (type == MainThread) { |
+ s_mainThreadStackStart = |
+ reinterpret_cast<uintptr_t>(WTF::getStackStart()) - sizeof(void*); |
+ size_t underestimatedStackSize = getUnderestimatedStackSize(); |
+ if (underestimatedStackSize > sizeof(void*)) { |
+ s_mainThreadUnderestimatedStackSize = |
+ underestimatedStackSize - sizeof(void*); |
+ } |
haraken
2017/01/16 04:42:30
Can we do this initialization in WTFThreadData::in
Charlie Harrison
2017/01/18 01:49:48
This is all gone.
|
+ } |
+ m_atomicStringTable = makeUnique<AtomicStringTable>(); |
+ m_cachedConverterICU = makeUnique<ICUConverterWrapper>(); |
+} |
WTFThreadData::~WTFThreadData() {} |
+#if OS(WIN) && COMPILER(MSVC) |
+size_t WTFThreadData::threadStackSize() { |
haraken
2017/01/16 04:42:30
I want to put this method in the same file as getU
Charlie Harrison
2017/01/18 01:49:48
Done.
|
+ if (m_threadStackSize) |
+ return m_threadStackSize; |
+ |
+ // Notice that we cannot use the TIB's StackLimit for the stack end, as it |
+ // tracks the end of the committed range. We're after the end of the reserved |
+ // stack area (most of which will be uncommitted, most times.) |
+ MEMORY_BASIC_INFORMATION stackInfo; |
+ memset(&stackInfo, 0, sizeof(MEMORY_BASIC_INFORMATION)); |
+ size_t resultSize = |
+ VirtualQuery(&stackInfo, &stackInfo, sizeof(MEMORY_BASIC_INFORMATION)); |
+ DCHECK_GE(resultSize, sizeof(MEMORY_BASIC_INFORMATION)); |
+ uint8_t* stackEnd = reinterpret_cast<uint8_t*>(stackInfo.AllocationBase); |
+ |
+ uint8_t* stackStart = reinterpret_cast<uint8_t*>(WTF::getStackStart()); |
+ RELEASE_ASSERT(stackStart && stackStart > stackEnd); |
+ m_threadStackSize = static_cast<size_t>(stackStart - stackEnd); |
+ // When the third last page of the reserved stack is accessed as a |
+ // guard page, the second last page will be committed (along with removing |
+ // the guard bit on the third last) _and_ a stack overflow exception |
+ // is raised. |
+ // |
+ // We have zero interest in running into stack overflow exceptions while |
+ // marking objects, so simply consider the last three pages + one above |
+ // as off-limits and adjust the reported stack size accordingly. |
+ // |
+ // http://blogs.msdn.com/b/satyem/archive/2012/08/13/thread-s-stack-memory-management.aspx |
+ // explains the details. |
+ RELEASE_ASSERT(m_threadStackSize > 4 * 0x1000); |
+ m_threadStackSize -= 4 * 0x1000; |
+ return m_threadStackSize; |
+} |
+#endif |
+ |
+void WTFThreadData::initialize() { |
+ DCHECK(!WTFThreadData::staticData); |
+ WTFThreadData::staticData = new ThreadSpecific<WTFThreadData>; |
+ new (s_mainThreadDataStorage) WTFThreadData(MainThread); |
+} |
+ |
+WTFThreadData& WTFThreadData::current() { |
+#if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) |
+ return **WTFThreadData::staticData; |
+#else |
+ // TLS lookup is slow. |
+ if (LIKELY(stackBasedIsMainThread())) |
+ return mainThreadData(); |
+ return **WTFThreadData::staticData; |
+#endif |
+} |
+ |
+bool WTFThreadData::isMainThread() { |
+ return current() == mainThreadData(); |
+} |
+ |
+WTFThreadData& WTFThreadData::mainThreadData() { |
+ return *(reinterpret_cast<WTFThreadData*>(s_mainThreadDataStorage)); |
+} |
+ |
+bool WTFThreadData::stackBasedIsMainThread() { |
+ uintptr_t dummy; |
+ uintptr_t addressDiff = |
+ s_mainThreadStackStart - reinterpret_cast<uintptr_t>(&dummy); |
+ // This is a fast way to judge if we are in the main thread. |
+ // If |&dummy| is within |s_mainThreadUnderestimatedStackSize| byte from |
+ // the stack start of the main thread, we judge that we are in |
+ // the main thread. |
+ return addressDiff < s_mainThreadUnderestimatedStackSize; |
+} |
+ |
+bool operator==(const WTFThreadData& data1, const WTFThreadData& data2) { |
+ return data1.threadId() == data2.threadId(); |
+} |
+ |
} // namespace WTF |