Changeset 150600 in webkit
- Timestamp:
- May 23, 2013 11:51:00 AM (11 years ago)
- Location:
- trunk/Source/WTF
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WTF/ChangeLog
r150561 r150600 1 2013-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 1 12 2013-05-22 Dean Jackson <dino@apple.com> 2 13 -
trunk/Source/WTF/wtf/StackBounds.cpp
r149150 r150600 59 59 // 60 60 // These platforms should now be working correctly: 61 // DARWIN, QNX, UNIX 61 // DARWIN, QNX, UNIX, WINDOWS 62 62 // These platforms are not: 63 // WINDOWS, SOLARIS, OPENBSD, WINCE63 // SOLARIS, OPENBSD 64 64 // 65 65 // FIXME: remove this! - this code unsafely guesses at stack sizes! 66 #if OS( WINDOWS) || OS(SOLARIS) || OS(OPENBSD)66 #if OS(SOLARIS) || OS(OPENBSD) 67 67 // Based on the current limit used by the JSC parser, guess the stack size. 68 68 static const ptrdiff_t estimatedStackSize = 128 * sizeof(void*) * 1024; … … 164 164 } 165 165 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 168 void StackBounds::initialize() 169 { 223 170 SYSTEM_INFO systemInfo; 224 171 GetSystemInfo(&systemInfo); 225 172 DWORD pageSize = systemInfo.dwPageSize; 226 173 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; 260 184 #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 265 206 } 266 207
Note: See TracChangeset
for help on using the changeset viewer.