1f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch/*
2f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
3f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  Copyright (C) 2007 Eric Seidel <eric@webkit.org>
4f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *
5f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  This library is free software; you can redistribute it and/or
6f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  modify it under the terms of the GNU Lesser General Public
7f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  License as published by the Free Software Foundation; either
8f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  version 2 of the License, or (at your option) any later version.
9f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *
10f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  This library is distributed in the hope that it will be useful,
11f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  Lesser General Public License for more details.
14f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *
15f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  You should have received a copy of the GNU Lesser General Public
16f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  License along with this library; if not, write to the Free Software
17f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
18f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch *
19f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch */
20f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
21f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "config.h"
22f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "StackBounds.h"
23f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
24f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if OS(DARWIN)
25f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
26f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <mach/task.h>
27f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <mach/thread_act.h>
28f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <pthread.h>
29f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
30f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(WINDOWS)
31f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
32f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <windows.h>
33f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
34f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(HAIKU)
35f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
36f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <OS.h>
37f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
38f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(SOLARIS)
39f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
40f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <thread.h>
41f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
42f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(QNX)
43f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
44f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <fcntl.h>
45f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <sys/procfs.h>
46f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <stdio.h>
47f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <errno.h>
48f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
49f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(UNIX)
50f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
51f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <pthread.h>
52f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if HAVE(PTHREAD_NP_H)
53f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include <pthread_np.h>
54f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
55f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
56f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
57f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
58f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochnamespace WTF {
59f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
60f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// Bug 26276 - Need a mechanism to determine stack extent
61f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch//
62f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// These platforms should now be working correctly:
63ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch//     DARWIN, QNX, UNIX, SYMBIAN
64f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// These platforms are not:
65ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch//     WINDOWS, SOLARIS, OPENBSD, HAIKU, WINCE
66f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch//
67f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// FIXME: remove this! - this code unsafely guesses at stack sizes!
68ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#if OS(WINDOWS) || OS(SOLARIS) || OS(OPENBSD) || OS(HAIKU)
69f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// Based on the current limit used by the JSC parser, guess the stack size.
70f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic const ptrdiff_t estimatedStackSize = 128 * sizeof(void*) * 1024;
71f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch// This method assumes the stack is growing downwards.
72f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochstatic void* estimateStackBound(void* origin)
73f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
74f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return static_cast<char*>(origin) - estimatedStackSize;
75f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
76f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
77f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
78f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if OS(DARWIN)
79f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
80f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid StackBounds::initialize()
81f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
82f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_t thread = pthread_self();
83f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_origin = pthread_get_stackaddr_np(thread);
84f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_bound = static_cast<char*>(m_origin) - pthread_get_stacksize_np(thread);
85f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
86f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
87f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(QNX)
88f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
89f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid StackBounds::initialize()
90f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
91f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    void* stackBase = 0;
92f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    size_t stackSize = 0;
93f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_t thread = pthread_self();
94f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
95f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    struct _debug_thread_info threadInfo;
96f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    memset(&threadInfo, 0, sizeof(threadInfo));
97f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    threadInfo.tid = pthread_self();
98f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    int fd = open("/proc/self", O_RDONLY);
99f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (fd == -1) {
100f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        LOG_ERROR("Unable to open /proc/self (errno: %d)", errno);
101f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        CRASH();
102f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    }
103f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    devctl(fd, DCMD_PROC_TIDSTATUS, &threadInfo, sizeof(threadInfo), 0);
104f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    close(fd);
105f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    stackBase = reinterpret_cast<void*>(threadInfo.stkbase);
106f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    stackSize = threadInfo.stksize;
107f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ASSERT(stackBase);
108f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
109f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_bound = stackBase;
110f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_origin = static_cast<char*>(stackBase) + stackSize;
111f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
112f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
113f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(SOLARIS)
114f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
115f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid StackBounds::initialize()
116f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
117f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    stack_t s;
118f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    thr_stksegment(&s);
119f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_origin = s.ss_sp;
120f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_bound = estimateStackBound(m_origin);
121f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
122f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
123f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(OPENBSD)
124f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
125f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid StackBounds::initialize()
126f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
127f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_t thread = pthread_self();
128f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    stack_t stack;
129f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_stackseg_np(thread, &stack);
130f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_origin = stack.ss_sp;
131f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_bound = estimateStackBound(m_origin);
132f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
133f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
134f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(SYMBIAN)
135f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
136f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid StackBounds::initialize()
137f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
138f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    TThreadStackInfo info;
139f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    RThread thread;
140f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    thread.StackInfo(info);
141f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_origin = (void*)info.iBase;
142ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch    m_bound = (void*)info.iLimit;
143f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
144f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
145f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(HAIKU)
146f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
147f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid StackBounds::initialize()
148f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
149f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    thread_info threadInfo;
150f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    get_thread_info(find_thread(NULL), &threadInfo);
151f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_origin = threadInfo.stack_end;
152f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_bound = estimateStackBound(m_origin);
153f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
154f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
155f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(UNIX)
156f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
157f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid StackBounds::initialize()
158f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
159f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    void* stackBase = 0;
160f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    size_t stackSize = 0;
161f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
162f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_t thread = pthread_self();
163f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_attr_t sattr;
164f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_attr_init(&sattr);
165f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#if HAVE(PTHREAD_NP_H) || OS(NETBSD)
166f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // e.g. on FreeBSD 5.4, neundorf@kde.org
167f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_attr_get_np(thread, &sattr);
168f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#else
169f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // FIXME: this function is non-portable; other POSIX systems may have different np alternatives
170f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_getattr_np(thread, &sattr);
171f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
172f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
173f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    (void)rc; // FIXME: Deal with error code somehow? Seems fatal.
174f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    ASSERT(stackBase);
175f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    pthread_attr_destroy(&sattr);
176f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_bound = stackBase;
177f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_origin = static_cast<char*>(stackBase) + stackSize;
178f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
179f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
180f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#elif OS(WINCE)
181f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
182cad810f21b803229eb11403f9209855525a25d57Steve Blockstatic bool detectGrowingDownward(void* previousFrame)
183cad810f21b803229eb11403f9209855525a25d57Steve Block{
184cad810f21b803229eb11403f9209855525a25d57Steve Block    // Find the address of this stack frame by taking the address of a local variable.
185cad810f21b803229eb11403f9209855525a25d57Steve Block    int thisFrame;
186cad810f21b803229eb11403f9209855525a25d57Steve Block    return previousFrame > &thisFrame;
187cad810f21b803229eb11403f9209855525a25d57Steve Block}
188f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
189cad810f21b803229eb11403f9209855525a25d57Steve Blockstatic inline bool isPageWritable(void* page)
190f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
191f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    MEMORY_BASIC_INFORMATION memoryInformation;
192f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    DWORD result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation));
193f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
194f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // return false on error, including ptr outside memory
195f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    if (result != sizeof(memoryInformation))
196f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        return false;
197f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
198f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    DWORD protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE);
199f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    return protect == PAGE_READWRITE
200f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        || protect == PAGE_WRITECOPY
201f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        || protect == PAGE_EXECUTE_READWRITE
202f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        || protect == PAGE_EXECUTE_WRITECOPY;
203f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
204f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
205cad810f21b803229eb11403f9209855525a25d57Steve Blockstatic inline void* getLowerStackBound(char* currentPage, DWORD pageSize)
206cad810f21b803229eb11403f9209855525a25d57Steve Block{
207cad810f21b803229eb11403f9209855525a25d57Steve Block    while (currentPage > 0) {
208cad810f21b803229eb11403f9209855525a25d57Steve Block        // check for underflow
209cad810f21b803229eb11403f9209855525a25d57Steve Block        if (currentPage >= reinterpret_cast<char*>(pageSize))
210cad810f21b803229eb11403f9209855525a25d57Steve Block            currentPage -= pageSize;
211cad810f21b803229eb11403f9209855525a25d57Steve Block        else
212cad810f21b803229eb11403f9209855525a25d57Steve Block            currentPage = 0;
213cad810f21b803229eb11403f9209855525a25d57Steve Block
214cad810f21b803229eb11403f9209855525a25d57Steve Block        if (!isPageWritable(currentPage))
215cad810f21b803229eb11403f9209855525a25d57Steve Block            return currentPage + pageSize;
216cad810f21b803229eb11403f9209855525a25d57Steve Block    }
217cad810f21b803229eb11403f9209855525a25d57Steve Block
218cad810f21b803229eb11403f9209855525a25d57Steve Block    return 0;
219cad810f21b803229eb11403f9209855525a25d57Steve Block}
220cad810f21b803229eb11403f9209855525a25d57Steve Block
221cad810f21b803229eb11403f9209855525a25d57Steve Blockstatic inline void* getUpperStackBound(char* currentPage, DWORD pageSize)
222cad810f21b803229eb11403f9209855525a25d57Steve Block{
223cad810f21b803229eb11403f9209855525a25d57Steve Block    do {
224cad810f21b803229eb11403f9209855525a25d57Steve Block        // guaranteed to complete because isPageWritable returns false at end of memory
225cad810f21b803229eb11403f9209855525a25d57Steve Block        currentPage += pageSize;
226cad810f21b803229eb11403f9209855525a25d57Steve Block    } while (isPageWritable(currentPage));
227cad810f21b803229eb11403f9209855525a25d57Steve Block
228cad810f21b803229eb11403f9209855525a25d57Steve Block    return currentPage - pageSize;
229cad810f21b803229eb11403f9209855525a25d57Steve Block}
230cad810f21b803229eb11403f9209855525a25d57Steve Block
231cad810f21b803229eb11403f9209855525a25d57Steve Blockvoid StackBounds::initialize()
232f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
233f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // find the address of this stack frame by taking the address of a local variable
234f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    void* thisFrame = &thisFrame;
235cad810f21b803229eb11403f9209855525a25d57Steve Block    bool isGrowingDownward = detectGrowingDownward(thisFrame);
236f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
237f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    SYSTEM_INFO systemInfo;
238f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    GetSystemInfo(&systemInfo);
239f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    DWORD pageSize = systemInfo.dwPageSize;
240f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
241f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    // scan all of memory starting from this frame, and return the last writeable page found
242cad810f21b803229eb11403f9209855525a25d57Steve Block    char* currentPage = reinterpret_cast<char*>(reinterpret_cast<DWORD>(thisFrame) & ~(pageSize - 1));
243cad810f21b803229eb11403f9209855525a25d57Steve Block    void* lowerStackBound = getLowerStackBound(currentPage, pageSize);
244cad810f21b803229eb11403f9209855525a25d57Steve Block    void* upperStackBound = getUpperStackBound(currentPage, pageSize);
245cad810f21b803229eb11403f9209855525a25d57Steve Block
246cad810f21b803229eb11403f9209855525a25d57Steve Block    m_origin = isGrowingDownward ? upperStackBound : lowerStackBound;
247cad810f21b803229eb11403f9209855525a25d57Steve Block    m_bound = isGrowingDownward ? lowerStackBound : upperStackBound;
248f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
249f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
25065f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#elif OS(WINDOWS)
251cad810f21b803229eb11403f9209855525a25d57Steve Block
252f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid StackBounds::initialize()
253f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch{
25465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#if CPU(X86) && COMPILER(MSVC)
25565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // offset 0x18 from the FS segment register gives a pointer to
25665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // the thread information block for the current thread
257cad810f21b803229eb11403f9209855525a25d57Steve Block    NT_TIB* pTib;
258cad810f21b803229eb11403f9209855525a25d57Steve Block    __asm {
259cad810f21b803229eb11403f9209855525a25d57Steve Block        MOV EAX, FS:[18h]
260cad810f21b803229eb11403f9209855525a25d57Steve Block        MOV pTib, EAX
261cad810f21b803229eb11403f9209855525a25d57Steve Block    }
26265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_origin = static_cast<void*>(pTib->StackBase);
26365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#elif CPU(X86) && COMPILER(GCC)
26465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // offset 0x18 from the FS segment register gives a pointer to
26565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // the thread information block for the current thread
26665f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    NT_TIB* pTib;
267cad810f21b803229eb11403f9209855525a25d57Steve Block    asm ( "movl %%fs:0x18, %0\n"
268cad810f21b803229eb11403f9209855525a25d57Steve Block          : "=r" (pTib)
269cad810f21b803229eb11403f9209855525a25d57Steve Block        );
270cad810f21b803229eb11403f9209855525a25d57Steve Block    m_origin = static_cast<void*>(pTib->StackBase);
271cad810f21b803229eb11403f9209855525a25d57Steve Block#elif CPU(X86_64)
272cad810f21b803229eb11403f9209855525a25d57Steve Block    PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
273cad810f21b803229eb11403f9209855525a25d57Steve Block    m_origin = reinterpret_cast<void*>(pTib->StackBase);
27465f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#else
27565f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#error Need a way to get the stack bounds on this platform (Windows)
276cad810f21b803229eb11403f9209855525a25d57Steve Block#endif
27765f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    // Looks like we should be able to get pTib->StackLimit
27865f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch    m_bound = estimateStackBound(m_origin);
279f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch}
280f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
281f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#else
28265f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch#error Need a way to get the stack bounds on this platform
283f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#endif
284f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch
285f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch} // namespace WTF
286