Changeset 150600 in webkit


Ignore:
Timestamp:
May 23, 2013 11:51:00 AM (11 years ago)
Author:
Patrick Gansterer
Message:

[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):

Location:
trunk/Source/WTF
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r150561 r150600  
     12013-05-23  Patrick Gansterer  <paroga@webkit.org>
     2
     3        [WIN] Implement correct detection of stack size
     4        https://bugs.webkit.org/show_bug.cgi?id=116661
     5
     6        Reviewed by Oliver Hunt.
     7
     8        * wtf/StackBounds.cpp:
     9        (WTF):
     10        (WTF::StackBounds::initialize):
     11
    1122013-05-22  Dean Jackson  <dino@apple.com>
    213
  • trunk/Source/WTF/wtf/StackBounds.cpp

    r149150 r150600  
    5959//
    6060// These platforms should now be working correctly:
    61 //     DARWIN, QNX, UNIX
     61//     DARWIN, QNX, UNIX, WINDOWS
    6262// These platforms are not:
    63 //     WINDOWS, SOLARIS, OPENBSD, WINCE
     63//     SOLARIS, OPENBSD
    6464//
    6565// FIXME: remove this! - this code unsafely guesses at stack sizes!
    66 #if OS(WINDOWS) || OS(SOLARIS) || OS(OPENBSD)
     66#if OS(SOLARIS) || OS(OPENBSD)
    6767// Based on the current limit used by the JSC parser, guess the stack size.
    6868static const ptrdiff_t estimatedStackSize = 128 * sizeof(void*) * 1024;
     
    164164}
    165165
    166 #elif OS(WINCE)
    167 
    168 static bool detectGrowingDownward(void* previousFrame)
    169 {
    170     // Find the address of this stack frame by taking the address of a local variable.
    171     int thisFrame;
    172     return previousFrame > &thisFrame;
    173 }
    174 
    175 static inline bool isPageWritable(void* page)
    176 {
    177     MEMORY_BASIC_INFORMATION memoryInformation;
    178     DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation));
    179 
    180     // return false on error, including ptr outside memory
    181     if (result != sizeof(memoryInformation))
    182         return false;
    183 
    184     DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE);
    185     return protect == PAGE_READWRITE
    186         || protect == PAGE_WRITECOPY
    187         || protect == PAGE_EXECUTE_READWRITE
    188         || protect == PAGE_EXECUTE_WRITECOPY;
    189 }
    190 
    191 static inline void* getLowerStackBound(char* currentPage, DWORD pageSize)
    192 {
    193     while (currentPage > 0) {
    194         // check for underflow
    195         if (currentPage >= reinterpret_cast<char*>(pageSize))
    196             currentPage -= pageSize;
    197         else
    198             currentPage = 0;
    199 
    200         if (!isPageWritable(currentPage))
    201             return currentPage + pageSize;
    202     }
    203 
    204     return 0;
    205 }
    206 
    207 static inline void* getUpperStackBound(char* currentPage, DWORD pageSize)
    208 {
    209     do {
    210         // guaranteed to complete because isPageWritable returns false at end of memory
    211         currentPage += pageSize;
    212     } while (isPageWritable(currentPage));
    213 
    214     return currentPage - pageSize;
    215 }
    216 
    217 void StackBounds::initialize()
    218 {
    219     // find the address of this stack frame by taking the address of a local variable
    220     void* thisFrame = &thisFrame;
    221     bool isGrowingDownward = detectGrowingDownward(thisFrame);
    222 
     166#elif OS(WINDOWS)
     167
     168void StackBounds::initialize()
     169{
    223170    SYSTEM_INFO systemInfo;
    224171    GetSystemInfo(&systemInfo);
    225172    DWORD pageSize = systemInfo.dwPageSize;
    226173
    227     // scan all of memory starting from this frame, and return the last writeable page found
    228     char* currentPage = reinterpret_cast<char*>(reinterpret_cast<DWORD>(thisFrame) & ~(pageSize - 1));
    229     void* lowerStackBound = getLowerStackBound(currentPage, pageSize);
    230     void* upperStackBound = getUpperStackBound(currentPage, pageSize);
    231 
    232     m_origin = isGrowingDownward ? upperStackBound : lowerStackBound;
    233     m_bound = isGrowingDownward ? lowerStackBound : upperStackBound;
    234 }
    235 
    236 #elif OS(WINDOWS)
    237 
    238 void StackBounds::initialize()
    239 {
    240 #if CPU(X86) && COMPILER(MSVC)
    241     // offset 0x18 from the FS segment register gives a pointer to
    242     // the thread information block for the current thread
    243     NT_TIB* pTib;
    244     __asm {
    245         MOV EAX, FS:[18h]
    246         MOV pTib, EAX
    247     }
    248     m_origin = static_cast<void*>(pTib->StackBase);
    249 #elif CPU(X86) && COMPILER(GCC)
    250     // offset 0x18 from the FS segment register gives a pointer to
    251     // the thread information block for the current thread
    252     NT_TIB* pTib;
    253     asm ( "movl %%fs:0x18, %0\n"
    254           : "=r" (pTib)
    255         );
    256     m_origin = static_cast<void*>(pTib->StackBase);
    257 #elif CPU(X86_64)
    258     PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
    259     m_origin = reinterpret_cast<void*>(pTib->StackBase);
     174    MEMORY_BASIC_INFORMATION stackOrigin;
     175    VirtualQuery(&stackOrigin, &stackOrigin, sizeof(stackOrigin));
     176    // stackOrigin.AllocationBase points to the reserved stack memory base address.
     177
     178    m_origin = static_cast<char*>(stackOrigin.BaseAddress) + stackOrigin.RegionSize;
     179#if OS(WINCE)
     180    MEMORY_BASIC_INFORMATION stackMemory;
     181    VirtualQuery(m_origin, &stackMemory, sizeof(stackMemory));
     182
     183    m_bound = static_cast<char*>(m_origin) - stackMemory.RegionSize + pageSize;
    260184#else
    261 #error Need a way to get the stack bounds on this platform (Windows)
    262 #endif
    263     // Looks like we should be able to get pTib->StackLimit
    264     m_bound = estimateStackBound(m_origin);
     185    // The stack on Windows consists out of three parts (reserved memory, a guard page and initially committed memory),
     186    // which need to me queried seperately to get the full size of the stack.
     187    // See http://msdn.microsoft.com/en-us/library/ms686774%28VS.85%29.aspx for more information.
     188
     189    MEMORY_BASIC_INFORMATION reservedMemory;
     190    VirtualQuery(stackOrigin.AllocationBase, &reservedMemory, sizeof(reservedMemory));
     191    ASSERT(reservedMemory.State == MEM_RESERVE);
     192    // reservedMemory.BaseAddress and reservedMemory.RegionSize describe reserved (uncommitted) portion of the stack.
     193
     194    MEMORY_BASIC_INFORMATION guardPage;
     195    VirtualQuery(static_cast<char*>(reservedMemory.BaseAddress) + reservedMemory.RegionSize, &guardPage, sizeof(guardPage));
     196    ASSERT(guardPage.Protect & PAGE_GUARD);
     197    // guardPage.BaseAddress and guardPage.RegionSize describe the guard page.
     198
     199    MEMORY_BASIC_INFORMATION committedMemory;
     200    VirtualQuery(static_cast<char*>(guardPage.BaseAddress) + guardPage.RegionSize, &committedMemory, sizeof(committedMemory));
     201    ASSERT(committedMemory.State == MEM_COMMIT);
     202    // committedMemory.BaseAddress, committedMemory.RegionSize describe the committed (i.e. accessed) portion of the stack.
     203
     204    m_bound = static_cast<char*>(m_origin) - (reservedMemory.RegionSize - guardPage.RegionSize + committedMemory.RegionSize) + pageSize;
     205#endif
    265206}
    266207
Note: See TracChangeset for help on using the changeset viewer.