Index: third_party/WebKit/Source/wtf/StackUtil.cpp |
diff --git a/third_party/WebKit/Source/platform/heap/StackFrameDepth.cpp b/third_party/WebKit/Source/wtf/StackUtil.cpp |
similarity index 64% |
copy from third_party/WebKit/Source/platform/heap/StackFrameDepth.cpp |
copy to third_party/WebKit/Source/wtf/StackUtil.cpp |
index 1d164f510a36de4ecb3328e6c80065f4913eca5d..f9e51b866b60fe64317289f43ee7783a86412b8f 100644 |
--- a/third_party/WebKit/Source/platform/heap/StackFrameDepth.cpp |
+++ b/third_party/WebKit/Source/wtf/StackUtil.cpp |
@@ -1,10 +1,12 @@ |
-// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Copyright 2017 The Chromium Authors. All rights reserved. |
// Use of this source code is governed by a BSD-style license that can be |
// found in the LICENSE file. |
-#include "platform/heap/StackFrameDepth.h" |
+#include "wtf/StackUtil.h" |
-#include "public/platform/Platform.h" |
+#include "wtf/Assertions.h" |
+#include "wtf/Threading.h" |
+#include "wtf/WTFThreadData.h" |
#if OS(WIN) |
#include <stddef.h> |
@@ -14,51 +16,9 @@ |
extern "C" void* __libc_stack_end; // NOLINT |
#endif |
-namespace blink { |
+namespace WTF { |
-static const char* s_avoidOptimization = nullptr; |
- |
-// NEVER_INLINE ensures that |dummy| array on configureLimit() is not optimized |
-// away, and the stack frame base register is adjusted |kSafeStackFrameSize|. |
-NEVER_INLINE static uintptr_t currentStackFrameBaseOnCallee(const char* dummy) { |
- s_avoidOptimization = dummy; |
- return StackFrameDepth::currentStackFrame(); |
-} |
- |
-uintptr_t StackFrameDepth::getFallbackStackLimit() { |
- // Allocate an |kSafeStackFrameSize|-sized object on stack and query |
- // stack frame base after it. |
- char dummy[kSafeStackFrameSize]; |
- |
- // Check that the stack frame can be used. |
- dummy[sizeof(dummy) - 1] = 0; |
- return currentStackFrameBaseOnCallee(dummy); |
-} |
- |
-void StackFrameDepth::enableStackLimit() { |
- // All supported platforms will currently return a non-zero estimate, |
- // except if ASan is enabled. |
- size_t stackSize = getUnderestimatedStackSize(); |
- if (!stackSize) { |
- m_stackFrameLimit = getFallbackStackLimit(); |
- return; |
- } |
- |
- static const int kStackRoomSize = 1024; |
- |
- Address stackBase = reinterpret_cast<Address>(getStackStart()); |
- RELEASE_ASSERT(stackSize > static_cast<const size_t>(kStackRoomSize)); |
- size_t stackRoom = stackSize - kStackRoomSize; |
- RELEASE_ASSERT(stackBase > reinterpret_cast<Address>(stackRoom)); |
- m_stackFrameLimit = reinterpret_cast<uintptr_t>(stackBase - stackRoom); |
- |
- // If current stack use is already exceeding estimated limit, mark as |
- // disabled. |
- if (!isSafeToRecurse()) |
- disableStackLimit(); |
-} |
- |
-size_t StackFrameDepth::getUnderestimatedStackSize() { |
+size_t getUnderestimatedStackSize() { |
// FIXME: ASAN bot uses a fake stack as a thread stack frame, |
// and its size is different from the value which APIs tells us. |
#if defined(ADDRESS_SANITIZER) |
@@ -127,14 +87,14 @@ size_t StackFrameDepth::getUnderestimatedStackSize() { |
} |
return pthread_get_stacksize_np(pthread_self()); |
#elif OS(WIN) && COMPILER(MSVC) |
- return ThreadState::current()->threadStackSize(); |
+ return WTFThreadData::threadStackSize(); |
#else |
#error "Stack frame size estimation not supported on this platform." |
return 0; |
#endif |
} |
-void* StackFrameDepth::getStackStart() { |
+void* getStackStart() { |
#if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD) |
pthread_attr_t attr; |
int error; |
@@ -162,7 +122,7 @@ void* StackFrameDepth::getStackStart() { |
// See https://code.google.com/p/nativeclient/issues/detail?id=3431. |
return __libc_stack_end; |
#else |
- ASSERT_NOT_REACHED(); |
+ NOTREACHED(); |
return nullptr; |
#endif |
#elif OS(MACOSX) |
@@ -181,4 +141,49 @@ void* StackFrameDepth::getStackStart() { |
#endif |
} |
-} // namespace blink |
+namespace internal { |
+ |
+uintptr_t mainThreadUnderestimatedStackSize() { |
+ size_t underestimatedStackSize = getUnderestimatedStackSize(); |
+ // See comment in mayNotBeMainThread as to why we subtract here. |
+ if (underestimatedStackSize > sizeof(void*)) { |
+ underestimatedStackSize = underestimatedStackSize - sizeof(void*); |
+ } |
+ return underestimatedStackSize; |
+} |
+ |
+#if OS(WIN) && COMPILER(MSVC) |
+size_t threadStackSize() { |
+ // Notice that we cannot use the TIB's StackLimit for the stack end, as i |
+ // 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); |
+ size_t s_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(s_threadStackSize > 4 * 0x1000); |
+ s_threadStackSize -= 4 * 0x1000; |
+ return s_threadStackSize; |
+} |
+#endif |
+ |
+} // namespace internal |
+ |
+} // namespace WTF |