Chromium Code Reviews| 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 |