Commit 82395900 authored by barraclough@apple.com's avatar barraclough@apple.com
Browse files

Bug 26276 - Need a mechanism to determine stack extent

Reviewed by Oliver Hunt.

JavaScriptCore: 

This patch adds a class 'StackBounds', to hold information about the machine stack.
The implementation of this class broadly adheres to the current implmentation of
stack limit checking, and as such does not solve the problem of determining stack
extent, but gives us a common place to do so.

Currently two mechanism are provided to determine the stack origin (the point the
stack is growing away from). currentThreadStackBase() in Collector provides a
more accurate determination of the stack origin, so use this to calculate
StackBounds::m_origin; WTFThreadData::approximatedStackStart is less accurate, and
as such can be removed.  Cache the StackBounds on WTFThreadData such that they
need only be determined once per thread, and for non-API contexts cache this
information in JSGlobalData, to save a thread-specific access.

For the time being retain the estimate of stack size used by JSC's parser
(128 * sizeof(vo...
parent b046b35d
......@@ -165,6 +165,7 @@ LOCAL_SRC_FILES := \
wtf/PageBlock.cpp\
wtf/RandomNumber.cpp \
wtf/RefCountedLeakCounter.cpp \
wtf/StackBounds.cpp \
wtf/TCSystemAlloc.cpp \
wtf/ThreadIdentifierDataPthreads.cpp \
wtf/Threading.cpp \
......
......@@ -42,6 +42,7 @@ LOCAL_SRC_FILES := \
wtf/MainThread.cpp \
wtf/RandomNumber.cpp \
wtf/RefCountedLeakCounter.cpp \
wtf/StackBounds.cpp \
wtf/TCSystemAlloc.cpp \
wtf/ThreadIdentifierDataPthreads.cpp \
wtf/Threading.cpp \
......
2010-12-18 Gavin Barraclough <barraclough@apple.com>
Reviewed by Oliver Hunt.
Bug 26276 - Need a mechanism to determine stack extent
This patch adds a class 'StackBounds', to hold information about the machine stack.
The implementation of this class broadly adheres to the current implmentation of
stack limit checking, and as such does not solve the problem of determining stack
extent, but gives us a common place to do so.
Currently two mechanism are provided to determine the stack origin (the point the
stack is growing away from). currentThreadStackBase() in Collector provides a
more accurate determination of the stack origin, so use this to calculate
StackBounds::m_origin; WTFThreadData::approximatedStackStart is less accurate, and
as such can be removed. Cache the StackBounds on WTFThreadData such that they
need only be determined once per thread, and for non-API contexts cache this
information in JSGlobalData, to save a thread-specific access.
For the time being retain the estimate of stack size used by JSC's parser
(128 * sizeof(void*) * 1024), with a view to replacing this with something more
accurate in the near future.
* parser/JSParser.cpp:
(JSC::JSParser::canRecurse):
(JSC::JSParser::JSParser):
Change to use StackBounds.
* runtime/Collector.cpp:
(JSC::Heap::registerThread):
(JSC::Heap::markCurrentThreadConservativelyInternal):
Change to use StackBounds, cached on JSGlobalData.
* runtime/JSGlobalData.cpp:
(JSC::JSGlobalData::JSGlobalData):
* runtime/JSGlobalData.h:
(JSC::JSGlobalData::stack):
Add a cached copy of StackBounds.
* wtf/StackBounds.cpp: Copied from JavaScriptCore/runtime/Collector.cpp.
(WTF::estimateStackBound):
(WTF::StackBounds::initialize):
(WTF::getStackMax):
Copy code from Collector.cpp to determine stack origin.
* wtf/StackBounds.h: Added.
(WTF::StackBounds::StackBounds):
No argument constructor; returns a null StackBounds.
(WTF::StackBounds::currentThreadStackBounds):
Returns a StackBounds object representing the stack limits
of the current thread.
(WTF::StackBounds::origin):
Returns to stack origin (the point the stack is growing away
from; the highest extent of the stack on machines where the
stack grows downwards.
(WTF::StackBounds::recursionLimit):
Returns a limit value that is 'a comfortable distance from
the end of the stack'. Our concept of this is currently 1 page
away from the end, however the default value may be tuned in
the future, and clients may override passing a larger delta;
should only be called on StackBounds object representing the
stack of the thread this method is called on (checked by
checkConsistency).
(WTF::StackBounds::recursionCheck):
Checks whether we are currently 'a comfortable distance from
the end of the stack'. Our concept of this is currently 1 page
away from the end, however the default value may be tuned in
the future, and clients may override passing a larger delta
to apply when checking, if they wish to do so. This method
should only be called on StackBounds object representing the
stack of the thread this method is called on (checked by
checkConsistency).
(WTF::StackBounds::current):
Approximate current stack position. On machines where the stack
is growing downwards this is the lowest address that might need
conservative collection.
(WTF::StackBounds::isGrowingDownward):
True for all platforms other than WINCE, which has to check.
(WTF::StackBounds::checkConsistency):
This is called in methods that shoulds only be operating on a
valid set of bounds; as such we expect m_origin != m_bounds
(i.e. stack size != zero) - we're really testing that this
object is not null (the constructor initializes both fields
to zero). Also checks that current() is within the stack's
bounds.
* wtf/WTFThreadData.cpp:
(WTF::WTFThreadData::WTFThreadData):
* wtf/WTFThreadData.h:
(WTF::WTFThreadData::stack):
Add the StackBounds member variable.
2010-12-17 Geoffrey Garen <ggaren@apple.com>
 
Reviewed by Sam Weinig.
......
......@@ -494,6 +494,8 @@ javascriptcore_sources += \
JavaScriptCore/wtf/RefPtrHashMap.h \
JavaScriptCore/wtf/RetainPtr.h \
JavaScriptCore/wtf/SegmentedVector.h \
JavaScriptCore/wtf/StackBounds.cpp \
JavaScriptCore/wtf/StackBounds.h \
JavaScriptCore/wtf/StaticConstructors.h \
JavaScriptCore/wtf/StdLibExtras.h \
JavaScriptCore/wtf/StringExtras.h \
......
......@@ -424,6 +424,8 @@
'wtf/RetainPtr.h',
'wtf/SegmentedVector.h',
'wtf/SizeLimits.cpp',
'wtf/StackBounds.cpp',
'wtf/StackBounds.h',
'wtf/StaticConstructors.h',
'wtf/StdLibExtras.h',
'wtf/StringExtras.h',
......
......@@ -776,6 +776,14 @@
RelativePath="..\..\wtf\SizeLimits.cpp"
>
</File>
<File
RelativePath="..\..\wtf\StackBounds.cpp"
>
</File>
<File
RelativePath="..\..\wtf\StackBounds.h"
>
</File>
<File
RelativePath="..\..\wtf\StaticConstructors.h"
>
......
......@@ -252,6 +252,8 @@
86D3B2C610156BDE002865E7 /* MacroAssemblerARM.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */; };
86D3B3C310159D7F002865E7 /* LinkBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C110159D7F002865E7 /* LinkBuffer.h */; };
86D3B3C410159D7F002865E7 /* RepatchBuffer.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D3B3C210159D7F002865E7 /* RepatchBuffer.h */; };
86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86D87DA512BC4B14008E73A1 /* StackBounds.cpp */; };
86D87DDB12BCAF94008E73A1 /* StackBounds.h in Headers */ = {isa = PBXBuildFile; fileRef = 86D87DA612BC4B14008E73A1 /* StackBounds.h */; settings = {ATTRIBUTES = (Private, ); }; };
86DB64640F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */; };
86E116B10FE75AC800B512BC /* CodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E116B00FE75AC800B512BC /* CodeLocation.h */; };
86E85539111B9968001AF51E /* JSStringBuilder.h in Headers */ = {isa = PBXBuildFile; fileRef = 86E85538111B9968001AF51E /* JSStringBuilder.h */; };
......@@ -869,6 +871,8 @@
86D3B2C210156BDE002865E7 /* MacroAssemblerARM.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MacroAssemblerARM.h; sourceTree = "<group>"; };
86D3B3C110159D7F002865E7 /* LinkBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinkBuffer.h; sourceTree = "<group>"; };
86D3B3C210159D7F002865E7 /* RepatchBuffer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RepatchBuffer.h; sourceTree = "<group>"; };
86D87DA512BC4B14008E73A1 /* StackBounds.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackBounds.cpp; sourceTree = "<group>"; };
86D87DA612BC4B14008E73A1 /* StackBounds.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackBounds.h; sourceTree = "<group>"; };
86DB64630F95C6FC00D7D921 /* ExecutableAllocatorFixedVMPool.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ExecutableAllocatorFixedVMPool.cpp; sourceTree = "<group>"; };
86E116B00FE75AC800B512BC /* CodeLocation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodeLocation.h; sourceTree = "<group>"; };
86E85538111B9968001AF51E /* JSStringBuilder.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSStringBuilder.h; sourceTree = "<group>"; };
......@@ -1558,6 +1562,8 @@
51F648D60BB4E2CA0033D760 /* RetainPtr.h */,
969A07290ED1CE6900F1F681 /* SegmentedVector.h */,
0BF28A2811A33DC300638F84 /* SizeLimits.cpp */,
86D87DA512BC4B14008E73A1 /* StackBounds.cpp */,
86D87DA612BC4B14008E73A1 /* StackBounds.h */,
868BFA5F117D048200B908B1 /* StaticConstructors.h */,
FE1B44790ECCD73B004F4DD1 /* StdLibExtras.h */,
E11D51750B2E798D0056C188 /* StringExtras.h */,
......@@ -2295,6 +2301,7 @@
BC18C4640E16F5CD00B34460 /* SourceCode.h in Headers */,
BC18C4630E16F5CD00B34460 /* SourceProvider.h in Headers */,
A7386554118697B400540279 /* SpecializedThunkJIT.h in Headers */,
86D87DDB12BCAF94008E73A1 /* StackBounds.h in Headers */,
868BFA60117D048200B908B1 /* StaticConstructors.h in Headers */,
FE1B447A0ECCD73B004F4DD1 /* StdLibExtras.h in Headers */,
86B99AE3117E578100DF5A90 /* StringBuffer.h in Headers */,
......@@ -2797,6 +2804,7 @@
14469DEA107EC7E700650446 /* ScopeChain.cpp in Sources */,
0BF28A2911A33DC300638F84 /* SizeLimits.cpp in Sources */,
9330402C0E6A764000786E6A /* SmallStrings.cpp in Sources */,
86D87DAE12BCA7D1008E73A1 /* StackBounds.cpp in Sources */,
14469DEB107EC7E700650446 /* StringConstructor.cpp in Sources */,
868BFA0E117CEFD100B908B1 /* StringImpl.cpp in Sources */,
14469DEC107EC7E700650446 /* StringObject.cpp in Sources */,
......
......@@ -65,9 +65,6 @@ namespace JSC {
COMPILE_ASSERT(LastUntaggedToken < 64, LessThan64UntaggedTokens);
// This matches v8
static const ptrdiff_t kMaxParserStackUsage = 128 * sizeof(void*) * 1024;
class JSParser {
public:
JSParser(Lexer*, JSGlobalData*, FunctionParameters*, bool isStrictContext, bool isFunction, SourceProvider*);
......@@ -193,9 +190,7 @@ private:
bool canRecurse()
{
char sample = 0;
ASSERT(m_endAddress);
return &sample > m_endAddress;
return m_stack.recursionCheck();
}
int lastTokenEnd() const
......@@ -205,7 +200,7 @@ private:
ParserArena m_arena;
Lexer* m_lexer;
char* m_endAddress;
StackBounds m_stack;
bool m_error;
JSGlobalData* m_globalData;
JSToken m_token;
......@@ -491,7 +486,7 @@ int jsParse(JSGlobalObject* lexicalGlobalObject, FunctionParameters* parameters,
JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* parameters, bool inStrictContext, bool isFunction, SourceProvider* provider)
: m_lexer(lexer)
, m_endAddress(0)
, m_stack(globalData->stack())
, m_error(false)
, m_globalData(globalData)
, m_allowsIn(true)
......@@ -505,7 +500,6 @@ JSParser::JSParser(Lexer* lexer, JSGlobalData* globalData, FunctionParameters* p
, m_nonTrivialExpressionCount(0)
, m_lastIdentifier(0)
{
m_endAddress = wtfThreadData().approximatedStackStart() - kMaxParserStackUsage;
ScopeRef scope = pushScope();
if (isFunction)
scope->setIsFunction();
......
......@@ -389,175 +389,6 @@ void Heap::shrinkBlocks(size_t neededBlocks)
m_heap.collectorBlock(i)->marked.set(HeapConstants::cellsPerBlock - 1);
}
#if OS(WINCE)
JS_EXPORTDATA void* g_stackBase = 0;
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 void* getStackBase(void* previousFrame)
{
// find the address of this stack frame by taking the address of a local variable
bool isGrowingDownward;
void* thisFrame = (void*)(&isGrowingDownward);
isGrowingDownward = previousFrame < &thisFrame;
static DWORD pageSize = 0;
if (!pageSize) {
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
pageSize = systemInfo.dwPageSize;
}
// scan all of memory starting from this frame, and return the last writeable page found
register char* currentPage = (char*)((DWORD)thisFrame & ~(pageSize - 1));
if (isGrowingDownward) {
while (currentPage > 0) {
// check for underflow
if (currentPage >= (char*)pageSize)
currentPage -= pageSize;
else
currentPage = 0;
if (!isPageWritable(currentPage))
return currentPage + pageSize;
}
return 0;
} else {
while (true) {
// guaranteed to complete because isPageWritable returns false at end of memory
currentPage += pageSize;
if (!isPageWritable(currentPage))
return currentPage;
}
}
}
#endif
#if OS(QNX)
static inline void *currentThreadStackBaseQNX()
{
static void* stackBase = 0;
static size_t stackSize = 0;
static pthread_t stackThread;
pthread_t thread = pthread_self();
if (stackBase == 0 || thread != stackThread) {
struct _debug_thread_info threadInfo;
memset(&threadInfo, 0, sizeof(threadInfo));
threadInfo.tid = pthread_self();
int fd = open("/proc/self", O_RDONLY);
if (fd == -1) {
LOG_ERROR("Unable to open /proc/self (errno: %d)", errno);
return 0;
}
devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0);
close(fd);
stackBase = reinterpret_cast<void*>(threadInfo.stkbase);
stackSize = threadInfo.stksize;
ASSERT(stackBase);
stackThread = thread;
}
return static_cast<char*>(stackBase) + stackSize;
}
#endif
static inline void* currentThreadStackBase()
{
#if OS(DARWIN)
pthread_t thread = pthread_self();
return pthread_get_stackaddr_np(thread);
#elif OS(WINDOWS) && 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
}
return static_cast<void*>(pTib->StackBase);
#elif OS(WINDOWS) && 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)
);
return static_cast<void*>(pTib->StackBase);
#elif OS(WINDOWS) && CPU(X86_64)
PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
return reinterpret_cast<void*>(pTib->StackBase);
#elif OS(QNX)
AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
MutexLocker locker(mutex);
return currentThreadStackBaseQNX();
#elif OS(SOLARIS)
stack_t s;
thr_stksegment(&s);
return s.ss_sp;
#elif OS(OPENBSD)
pthread_t thread = pthread_self();
stack_t stack;
pthread_stackseg_np(thread, &stack);
return stack.ss_sp;
#elif OS(SYMBIAN)
TThreadStackInfo info;
RThread thread;
thread.StackInfo(info);
return (void*)info.iBase;
#elif OS(HAIKU)
thread_info threadInfo;
get_thread_info(find_thread(NULL), &threadInfo);
return threadInfo.stack_end;
#elif OS(UNIX)
AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
MutexLocker locker(mutex);
static void* stackBase = 0;
static size_t stackSize = 0;
static pthread_t stackThread;
pthread_t thread = pthread_self();
if (stackBase == 0 || thread != stackThread) {
pthread_attr_t sattr;
pthread_attr_init(&sattr);
#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
// e.g. on FreeBSD 5.4, neundorf@kde.org
pthread_attr_get_np(thread, &sattr);
#else
// FIXME: this function is non-portable; other POSIX systems may have different np alternatives
pthread_getattr_np(thread, &sattr);
#endif
int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
(void)rc; // FIXME: Deal with error code somehow? Seems fatal.
ASSERT(stackBase);
pthread_attr_destroy(&sattr);
stackThread = thread;
}
return static_cast<char*>(stackBase) + stackSize;
#elif OS(WINCE)
AtomicallyInitializedStatic(Mutex&, mutex = *new Mutex);
MutexLocker locker(mutex);
if (g_stackBase)
return g_stackBase;
else {
int dummy;
return getStackBase(&dummy);
}
#else
#error Need a way to get the stack base on this platform
#endif
}
#if ENABLE(JSC_MULTIPLE_THREADS)
static inline PlatformThread getCurrentPlatformThread()
......@@ -587,7 +418,7 @@ void Heap::registerThread()
return;
pthread_setspecific(m_currentThreadRegistrar, this);
Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), currentThreadStackBase());
Heap::Thread* thread = new Heap::Thread(pthread_self(), getCurrentPlatformThread(), m_globalData->stack().origin());
MutexLocker lock(m_registeredThreadsMutex);
......@@ -654,11 +485,15 @@ static inline bool isPossibleCell(void* p)
void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
{
#if OS(WINCE)
if (start > end) {
void* tmp = start;
start = end;
end = tmp;
}
#else
ASSERT(start <= end);
#endif
ASSERT((static_cast<char*>(end) - static_cast<char*>(start)) < 0x1000000);
ASSERT(isPointerAligned(start));
......@@ -692,10 +527,7 @@ void Heap::markConservatively(MarkStack& markStack, void* start, void* end)
void NEVER_INLINE Heap::markCurrentThreadConservativelyInternal(MarkStack& markStack)
{
void* dummy;
void* stackPointer = &dummy;
void* stackBase = currentThreadStackBase();
markConservatively(markStack, stackPointer, stackBase);
markConservatively(markStack, m_globalData->stack().current(), m_globalData->stack().origin());
markStack.drain();
}
......
......@@ -153,6 +153,9 @@ JSGlobalData::JSGlobalData(GlobalDataType globalDataType, ThreadStackType thread
, exclusiveThread(0)
#endif
{
if (globalDataType == Default)
m_stack = wtfThreadData().stack();
#if PLATFORM(MAC)
startProfilerServerIfNeeded();
#endif
......
......@@ -46,6 +46,7 @@
#include <wtf/HashMap.h>
#include <wtf/RefCounted.h>
#include <wtf/ThreadSpecific.h>
#include <wtf/WTFThreadData.h>
#if ENABLE(REGEXP_TRACING)
#include <wtf/ListHashSet.h>
#endif
......@@ -178,6 +179,14 @@ namespace JSC {
#else
bool canUseJIT() { return m_canUseJIT; }
#endif
const StackBounds& stack()
{
return (globalDataType == Default)
? m_stack
: wtfThreadData().stack();
}
Lexer* lexer;
Parser* parser;
Interpreter* interpreter;
......@@ -250,6 +259,7 @@ namespace JSC {
#if ENABLE(JIT) && ENABLE(INTERPRETER)
bool m_canUseJIT;
#endif
StackBounds m_stack;
};
} // namespace JSC
......
......@@ -9,6 +9,7 @@ SET(WTF_SOURCES
MD5.cpp
RandomNumber.cpp
RefCountedLeakCounter.cpp
StackBounds.cpp
StringExtras.cpp
Threading.cpp
TypeTraits.cpp
......
/*
* Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
* Copyright (C) 2007 Eric Seidel <eric@webkit.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
*/
#include "config.h"
#include "StackBounds.h"
#if OS(DARWIN)
#include <mach/task.h>
#include <mach/thread_act.h>
#elif OS(WINDOWS)
#include <windows.h>
#elif OS(HAIKU)
#include <OS.h>
#elif OS(SOLARIS)
#include <thread.h>
#elif OS(QNX)
#include <fcntl.h>
#include <sys/procfs.h>
#include <stdio.h>
#include <errno.h>
#elif OS(UNIX)
#include <pthread.h>
#if HAVE(PTHREAD_NP_H)
#include <pthread_np.h>
#endif
#endif
namespace WTF {
// 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.
static void* estimateStackBound(void* origin)
{
return static_cast<char*>(origin) - estimatedStackSize;
}
#if OS(DARWIN)
void StackBounds::initialize()
{
pthread_t thread = pthread_self();
m_origin = pthread_get_stackaddr_np(thread);
m_bound = estimateStackBound(m_origin);
}
#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 OS(WINDOWS) && 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 OS(WINDOWS) && CPU(X86_64)
PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
m_origin = reinterpret_cast<void*>(pTib->StackBase);
#else
#error Need a way to get the stack bounds on this platform (Windows)
#endif
m_bound = estimateStackBound(m_origin);
}
#elif OS(QNX)
void StackBounds::initialize()
{
void* stackBase = 0;
size_t stackSize = 0;
pthread_t thread = pthread_self();