Modified: trunk/Source/WTF/ChangeLog (150599 => 150600)
--- trunk/Source/WTF/ChangeLog 2013-05-23 18:49:57 UTC (rev 150599)
+++ trunk/Source/WTF/ChangeLog 2013-05-23 18:51:00 UTC (rev 150600)
@@ -1,3 +1,14 @@
+2013-05-23 Patrick Gansterer <par...@webkit.org>
+
+ [WIN] Implement correct detection of stack size
+ https://bugs.webkit.org/show_bug.cgi?id=116661
+
+ Reviewed by Oliver Hunt.
+
+ * wtf/StackBounds.cpp:
+ (WTF):
+ (WTF::StackBounds::initialize):
+
2013-05-22 Dean Jackson <d...@apple.com>
Rolling out r150555. It borked about 30 media tests.
Modified: trunk/Source/WTF/wtf/StackBounds.cpp (150599 => 150600)
--- trunk/Source/WTF/wtf/StackBounds.cpp 2013-05-23 18:49:57 UTC (rev 150599)
+++ trunk/Source/WTF/wtf/StackBounds.cpp 2013-05-23 18:51:00 UTC (rev 150600)
@@ -58,12 +58,12 @@
// Bug 26276 - Need a mechanism to determine stack extent
//
// These platforms should now be working correctly:
-// DARWIN, QNX, UNIX
+// DARWIN, QNX, UNIX, WINDOWS
// These platforms are not:
-// WINDOWS, SOLARIS, OPENBSD, WINCE
+// SOLARIS, OPENBSD
//
// FIXME: remove this! - this code unsafely guesses at stack sizes!
-#if OS(WINDOWS) || OS(SOLARIS) || OS(OPENBSD)
+#if OS(SOLARIS) || OS(OPENBSD)
// Based on the current limit used by the JSC parser, guess the stack size.
static const ptrdiff_t estimatedStackSize = 128 * sizeof(void*) * 1024;
// This method assumes the stack is growing downwards.
@@ -163,105 +163,46 @@
m_origin = static_cast<char*>(stackBase) + stackSize;
}
-#elif OS(WINCE)
+#elif OS(WINDOWS)
-static bool detectGrowingDownward(void* previousFrame)
-{
- // Find the address of this stack frame by taking the address of a local variable.
- int thisFrame;
- return previousFrame > &thisFrame;
-}
-
-static inline bool isPageWritable(void* page)
-{
- MEMORY_BASIC_INFORMATION memoryInformation;
- DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation));
-
- // return false on error, including ptr outside memory
- if (result != sizeof(memoryInformation))
- return false;
-
- DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE);
- return protect == PAGE_READWRITE
- || protect == PAGE_WRITECOPY
- || protect == PAGE_EXECUTE_READWRITE
- || protect == PAGE_EXECUTE_WRITECOPY;
-}
-
-static inline void* getLowerStackBound(char* currentPage, DWORD pageSize)
-{
- while (currentPage > 0) {
- // check for underflow
- if (currentPage >= reinterpret_cast<char*>(pageSize))
- currentPage -= pageSize;
- else
- currentPage = 0;
-
- if (!isPageWritable(currentPage))
- return currentPage + pageSize;
- }
-
- return 0;
-}
-
-static inline void* getUpperStackBound(char* currentPage, DWORD pageSize)
-{
- do {
- // guaranteed to complete because isPageWritable returns false at end of memory
- currentPage += pageSize;
- } while (isPageWritable(currentPage));
-
- return currentPage - pageSize;
-}
-
void StackBounds::initialize()
{
- // find the address of this stack frame by taking the address of a local variable
- void* thisFrame = &thisFrame;
- bool isGrowingDownward = detectGrowingDownward(thisFrame);
-
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
DWORD pageSize = systemInfo.dwPageSize;
- // scan all of memory starting from this frame, and return the last writeable page found
- char* currentPage = reinterpret_cast<char*>(reinterpret_cast<DWORD>(thisFrame) & ~(pageSize - 1));
- void* lowerStackBound = getLowerStackBound(currentPage, pageSize);
- void* upperStackBound = getUpperStackBound(currentPage, pageSize);
+ MEMORY_BASIC_INFORMATION stackOrigin;
+ VirtualQuery(&stackOrigin, &stackOrigin, sizeof(stackOrigin));
+ // stackOrigin.AllocationBase points to the reserved stack memory base address.
- m_origin = isGrowingDownward ? upperStackBound : lowerStackBound;
- m_bound = isGrowingDownward ? lowerStackBound : upperStackBound;
-}
+ m_origin = static_cast<char*>(stackOrigin.BaseAddress) + stackOrigin.RegionSize;
+#if OS(WINCE)
+ MEMORY_BASIC_INFORMATION stackMemory;
+ VirtualQuery(m_origin, &stackMemory, sizeof(stackMemory));
-#elif OS(WINDOWS)
-
-void StackBounds::initialize()
-{
-#if CPU(X86) && COMPILER(MSVC)
- // offset 0x18 from the FS segment register gives a pointer to
- // the thread information block for the current thread
- NT_TIB* pTib;
- __asm {
- MOV EAX, FS:[18h]
- MOV pTib, EAX
- }
- m_origin = static_cast<void*>(pTib->StackBase);
-#elif CPU(X86) && COMPILER(GCC)
- // offset 0x18 from the FS segment register gives a pointer to
- // the thread information block for the current thread
- NT_TIB* pTib;
- asm ( "movl %%fs:0x18, %0\n"
- : "=r" (pTib)
- );
- m_origin = static_cast<void*>(pTib->StackBase);
-#elif CPU(X86_64)
- PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
- m_origin = reinterpret_cast<void*>(pTib->StackBase);
+ m_bound = static_cast<char*>(m_origin) - stackMemory.RegionSize + pageSize;
#else
-#error Need a way to get the stack bounds on this platform (Windows)
+ // The stack on Windows consists out of three parts (reserved memory, a guard page and initially committed memory),
+ // which need to me queried seperately to get the full size of the stack.
+ // See http://msdn.microsoft.com/en-us/library/ms686774%28VS.85%29.aspx for more information.
+
+ MEMORY_BASIC_INFORMATION reservedMemory;
+ VirtualQuery(stackOrigin.AllocationBase, &reservedMemory, sizeof(reservedMemory));
+ ASSERT(reservedMemory.State == MEM_RESERVE);
+ // reservedMemory.BaseAddress and reservedMemory.RegionSize describe reserved (uncommitted) portion of the stack.
+
+ MEMORY_BASIC_INFORMATION guardPage;
+ VirtualQuery(static_cast<char*>(reservedMemory.BaseAddress) + reservedMemory.RegionSize, &guardPage, sizeof(guardPage));
+ ASSERT(guardPage.Protect & PAGE_GUARD);
+ // guardPage.BaseAddress and guardPage.RegionSize describe the guard page.
+
+ MEMORY_BASIC_INFORMATION committedMemory;
+ VirtualQuery(static_cast<char*>(guardPage.BaseAddress) + guardPage.RegionSize, &committedMemory, sizeof(committedMemory));
+ ASSERT(committedMemory.State == MEM_COMMIT);
+ // committedMemory.BaseAddress, committedMemory.RegionSize describe the committed (i.e. accessed) portion of the stack.
+
+ m_bound = static_cast<char*>(m_origin) - (reservedMemory.RegionSize - guardPage.RegionSize + committedMemory.RegionSize) + pageSize;
#endif
- // Looks like we should be able to get pTib->StackLimit
- m_bound = estimateStackBound(m_origin);
}
#else