bug 237006 - automatic detection of the native thread stack base. The patch is based on the initial patches for bug 516832 by gal and gregor. r=gregor
authorIgor Bukanov <igor@mir2.org>
Wed, 19 May 2010 10:29:05 +0200
changeset 42740 a01307d7ba0e9616e76b7495780102b14dc80f8c
parent 42739 cccfe5cd7b390f33759985ab5c33ddd28407ee42
child 42741 67e1c38f60fd5e85d29b4668c0bf09c20f2693ef
push id13436
push userrsayre@mozilla.com
push dateMon, 24 May 2010 23:31:12 +0000
treeherdermozilla-central@23b20b0eb9f3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgregor
bugs237006, 516832
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
bug 237006 - automatic detection of the native thread stack base. The patch is based on the initial patches for bug 516832 by gal and gregor. r=gregor
dom/src/threads/nsDOMThreadService.cpp
js/src/Makefile.in
js/src/jsapi.cpp
js/src/jsapi.h
js/src/jscntxt.cpp
js/src/jscntxt.h
js/src/jsnativestack.cpp
js/src/jsnativestack.h
js/src/shell/js.cpp
js/src/shell/jsworkers.cpp
js/src/xpconnect/loader/mozJSComponentLoader.cpp
js/src/xpconnect/src/xpcjsruntime.cpp
js/src/xpconnect/src/xpcprivate.h
js/src/xpconnect/src/xpcthreadcontext.cpp
--- a/dom/src/threads/nsDOMThreadService.cpp
+++ b/dom/src/threads/nsDOMThreadService.cpp
@@ -1014,33 +1014,17 @@ nsDOMThreadService::CreateJSContext()
   JS_SetContextSecurityCallbacks(cx, &securityCallbacks);
 
   JS_ClearContextDebugHooks(cx);
 
   nsresult rv = nsContentUtils::XPConnect()->
     SetSecurityManagerForJSContext(cx, gWorkerSecurityManager, 0);
   NS_ENSURE_SUCCESS(rv, nsnull);
 
-  PRUint32 stackDummy;
-  jsuword stackLimit, currentStackAddr = (jsuword)&stackDummy;
-
-  // 256k stack space.
-  const jsuword kStackSize = 0x40000;
-
-#if JS_STACK_GROWTH_DIRECTION < 0
-  stackLimit = (currentStackAddr > kStackSize) ?
-               currentStackAddr - kStackSize :
-               0;
-#else
-  stackLimit = (currentStackAddr + kStackSize > currentStackAddr) ?
-               currentStackAddr + kStackSize :
-               (jsuword) -1;
-#endif
-
-  JS_SetThreadStackLimit(cx, stackLimit);
+  JS_SetNativeStackQuota(cx, 256*1024);
   JS_SetScriptStackQuota(cx, 100*1024*1024);
 
   JS_SetOptions(cx, JS_GetOptions(cx) | JSOPTION_JIT | JSOPTION_ANONFUNFIX);
   JS_SetGCParameterForThread(cx, JSGC_MAX_CODE_CACHE_BYTES, 1 * 1024 * 1024);
 
   return cx.forget();
 }
 
--- a/js/src/Makefile.in
+++ b/js/src/Makefile.in
@@ -142,16 +142,17 @@ CPPSRCS		= \
 		jsgcchunk.cpp \
 		jshash.cpp \
 		jsinterp.cpp \
 		jsinvoke.cpp \
 		jsiter.cpp \
 		jslock.cpp \
 		jslog2.cpp \
 		jsmath.cpp \
+		jsnativestack.cpp \
 		jsnum.cpp \
 		jsobj.cpp \
 		json.cpp \
 		jsopcode.cpp \
 		jsparse.cpp \
 		jsproxy.cpp \
 		jsprf.cpp \
 		jspropertycache.cpp \
--- a/js/src/jsapi.cpp
+++ b/js/src/jsapi.cpp
@@ -2508,22 +2508,50 @@ JS_GetExternalStringGCType(JSRuntime *rt
     return js_GetExternalStringGCType(str);
 }
 
 JS_PUBLIC_API(void)
 JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr)
 {
 #if JS_STACK_GROWTH_DIRECTION > 0
     if (limitAddr == 0)
-        limitAddr = (jsuword)-1;
+        limitAddr = jsuword(-1);
 #endif
     cx->stackLimit = limitAddr;
 }
 
 JS_PUBLIC_API(void)
+JS_SetNativeStackQuota(JSContext *cx, size_t stackSize)
+{
+#ifdef JS_THREADSAFE
+    JS_ASSERT(cx->thread);
+#endif
+
+#if JS_STACK_GROWTH_DIRECTION > 0
+    if (stackSize == 0) {
+        cx->stackLimit = jsuword(-1);
+    } else {
+        jsuword stackBase = reinterpret_cast<jsuword>(JS_THREAD_DATA(cx)->
+                                                      nativeStackBase);
+        JS_ASSERT(stackBase <= size_t(-1) - stackSize);
+        cx->stackLimit = stackBase + stackSize - 1;
+    }
+#else
+    if (stackSize == 0) {
+        cx->stackLimit = 0;
+    } else {
+        jsuword stackBase = reinterpret_cast<jsuword>(JS_THREAD_DATA(cx)->
+                                                      nativeStackBase);
+        JS_ASSERT(stackBase >= stackSize);
+        cx->stackLimit = stackBase - (stackSize - 1);
+    }
+#endif
+}
+
+JS_PUBLIC_API(void)
 JS_SetScriptStackQuota(JSContext *cx, size_t quota)
 {
     cx->scriptStackQuota = quota;
 }
 
 /************************************************************************/
 
 JS_PUBLIC_API(void)
--- a/js/src/jsapi.h
+++ b/js/src/jsapi.h
@@ -1392,24 +1392,30 @@ JS_NewExternalString(JSContext *cx, jsch
 /*
  * Returns the external-string finalizer index for this string, or -1 if it is
  * an "internal" (native to JS engine) string.
  */
 extern JS_PUBLIC_API(intN)
 JS_GetExternalStringGCType(JSRuntime *rt, JSString *str);
 
 /*
- * Sets maximum (if stack grows upward) or minimum (downward) legal stack byte
- * address in limitAddr for the thread or process stack used by cx.  To disable
- * stack size checking, pass 0 for limitAddr.
+ * Deprecated. Use JS_SetNativeStackQuoata instead.
  */
 extern JS_PUBLIC_API(void)
 JS_SetThreadStackLimit(JSContext *cx, jsuword limitAddr);
 
 /*
+ * Set the size of the native stack that should not be exceed. To disable
+ * stack size checking pass 0.
+ */
+extern JS_PUBLIC_API(void)
+JS_SetNativeStackQuota(JSContext *cx, size_t stackSize);
+
+
+/*
  * Set the quota on the number of bytes that stack-like data structures can
  * use when the runtime compiles and executes scripts. These structures
  * consume heap space, so JS_SetThreadStackLimit does not bound their size.
  * The default quota is 32MB which is quite generous.
  *
  * The function must be called before any script compilation or execution API
  * calls, i.e. either immediately after JS_NewContext or from JSCONTEXT_NEW
  * context callback.
--- a/js/src/jscntxt.cpp
+++ b/js/src/jscntxt.cpp
@@ -66,16 +66,17 @@
 #include "jsopcode.h"
 #include "jspubtd.h"
 #include "jsscan.h"
 #include "jsscope.h"
 #include "jsscript.h"
 #include "jsstaticcheck.h"
 #include "jsstr.h"
 #include "jstracer.h"
+#include "jsnativestack.h"
 
 #include "jscntxtinlines.h"
 
 #ifdef XP_WIN
 # include <windows.h>
 #else
 # include <unistd.h>
 # include <sys/mman.h>
@@ -504,16 +505,17 @@ JSThreadData::init()
 #ifdef JS_TRACER
     InitJIT(&traceMonitor);
 #endif
     dtoaState = js_NewDtoaState();
     if (!dtoaState) {
         finish();
         return false;
     }
+    nativeStackBase = GetNativeStackBase();
     return true;
 }
 
 void
 JSThreadData::finish()
 {
 #ifdef DEBUG
     /* All GC-related things must be already removed at this point. */
--- a/js/src/jscntxt.h
+++ b/js/src/jscntxt.h
@@ -1022,17 +1022,20 @@ struct JSThreadData {
      */
     struct {
         jsdouble d;
         jsint    base;
         JSString *s;        // if s==NULL, d and base are not valid
     } dtoaCache;
 
     /* Cached native iterators. */
-    JSObject *cachedNativeIterators[NATIVE_ITER_CACHE_SIZE];
+    JSObject            *cachedNativeIterators[NATIVE_ITER_CACHE_SIZE];
+
+    /* Base address of the native stack for the current thread. */
+    jsuword             *nativeStackBase;
 
     bool init();
     void finish();
     void mark(JSTracer *trc);
     void purge(JSContext *cx);
     void purgeGCFreeLists();
 };
 
new file mode 100644
--- /dev/null
+++ b/js/src/jsnativestack.cpp
@@ -0,0 +1,181 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 et sw=4 tw=80:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include <stdlib.h>
+#include "jstypes.h"
+#include "jsnativestack.h"
+
+#ifdef XP_WIN
+# include <windows.h>
+
+#elif defined(XP_MACOSX) || defined(DARWIN) || defined(XP_UNIX)
+# include <pthread.h>
+
+#else
+# error "Unsupported platform"
+
+#endif
+
+namespace js {
+
+#if defined(XP_WIN) && defined(WINCE)
+
+inline bool
+isPageWritable(void *page)
+{
+    MEMORY_BASIC_INFORMATION memoryInformation;
+    jsuword result = VirtualQuery(page, &memoryInformation, sizeof(memoryInformation));
+
+    /* return false on error, including ptr outside memory */
+    if (result != sizeof(memoryInformation))
+        return false;
+
+    jsuword protect = memoryInformation.Protect & ~(PAGE_GUARD | PAGE_NOCACHE);
+    return protect == PAGE_READWRITE ||
+           protect == PAGE_WRITECOPY ||
+           protect == PAGE_EXECUTE_READWRITE ||
+           protect == PAGE_EXECUTE_WRITECOPY;
+}
+
+void *
+GetNativeStackBase()
+{
+    /* find the address of this stack frame by taking the address of a local variable */
+    bool isGrowingDownward = JS_STACK_GROWTH_DIRECTION < 0;
+    void *thisFrame = (void *)(&isGrowingDownward);
+
+    static jsuword 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 *)((jsuword)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;
+        }
+    }
+}
+
+#elif defined(XP_WIN)
+
+void *
+GetNativeStackBaseImpl()
+{
+# if defined(_WIN32) && defined(_MSC_VER)
+    /*
+     * 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 defined(_WIN64) && defined(_MSC_VER)
+    PNT_TIB64 pTib = reinterpret_cast<PNT_TIB64>(NtCurrentTeb());
+    return reinterpret_cast<void*>(pTib->StackBase);
+
+# elif defined(_WIN32) && defined(__GNUC__)
+    NT_TIB* pTib;
+    asm ("movl %%fs:0x18, %0\n" : "=r" (pTib));
+    return static_cast<void*>(pTib->StackBase);
+
+# endif
+}
+
+#else /* !XP_WIN */
+
+void *
+GetNativeStackBaseImpl()
+{
+    pthread_t thread = pthread_self();
+# if defined(XP_MACOSX) || defined(DARWIN)
+    return pthread_get_stackaddr_np(thread);
+
+# else
+    pthread_attr_t sattr;
+    pthread_attr_init(&sattr);
+#  if defined(PTHREAD_NP_H) || defined(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
+
+    void *stackBase = 0;
+    size_t stackSize = 0;
+    int rc = pthread_attr_getstack(&sattr, &stackBase, &stackSize);
+    JS_ASSERT(!rc);
+    JS_ASSERT(stackBase);
+    pthread_attr_destroy(&sattr);
+
+#  if JS_STACK_GROWTH_DIRECTION > 0
+    return stackBase;
+#  else
+    return static_cast<char*>(stackBase) + stackSize;
+#  endif
+# endif
+}
+
+#endif /* !XP_WIN */
+
+} /* namespace js */
new file mode 100644
--- /dev/null
+++ b/js/src/jsnativestack.h
@@ -0,0 +1,60 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * vim: set ts=8 et sw=4 tw=80:
+ */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Mozilla code.
+ *
+ * The Initial Developer of the Original Code is the Mozilla Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2009
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of the GNU General Public License Version 2 or later (the "GPL"),
+ * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef jsnativestack_h__
+#define jsnativestack_h__
+
+#include "jspubtd.h"
+#include "jsutil.h"
+
+namespace js {
+
+extern void *
+GetNativeStackBaseImpl();
+
+inline jsuword *
+GetNativeStackBase()
+{
+    void *stackBase = GetNativeStackBaseImpl();
+    JS_ASSERT(reinterpret_cast<jsuword>(stackBase) % sizeof(void *) == 0);
+    return static_cast<jsuword *>(stackBase);
+}
+
+} /* namespace js */
+
+#endif /* jsnativestack_h__ */
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -113,19 +113,19 @@ typedef enum JSShellExitCode {
 } JSShellExitCode;
 
 size_t gStackChunkSize = 8192;
 
 /* Assume that we can not use more than 5e5 bytes of C stack by default. */
 #if defined(DEBUG) && defined(__SUNPRO_CC)
 /* Sun compiler uses larger stack space for js_Interpret() with debug
    Use a bigger gMaxStackSize to make "make check" happy. */
-static size_t gMaxStackSize = 5000000;
+size_t gMaxStackSize = 5000000;
 #else
-static size_t gMaxStackSize = 500000;
+size_t gMaxStackSize = 500000;
 #endif
 
 
 #ifdef JS_THREADSAFE
 static PRUintn gStackBaseThreadIndex;
 #else
 static jsuword gStackBase;
 #endif
@@ -346,50 +346,19 @@ ShellOperationCallback(JSContext *cx)
     if (!gCanceled)
         return JS_TRUE;
 
     JS_ClearPendingException(cx);
     return JS_FALSE;
 }
 
 static void
-SetThreadStackLimit(JSContext *cx)
-{
-    jsuword stackLimit;
-
-    if (gMaxStackSize == 0) {
-        /*
-         * Disable checking for stack overflow if limit is zero.
-         */
-        stackLimit = 0;
-    } else {
-        jsuword stackBase;
-#ifdef JS_THREADSAFE
-        stackBase = (jsuword) PR_GetThreadPrivate(gStackBaseThreadIndex);
-#else
-        stackBase = gStackBase;
-#endif
-        if (stackBase) {
-#if JS_STACK_GROWTH_DIRECTION > 0
-            stackLimit = stackBase + gMaxStackSize;
-#else
-            stackLimit = stackBase - gMaxStackSize;
-#endif
-        } else {
-            stackLimit = 0;
-        }
-    }
-    JS_SetThreadStackLimit(cx, stackLimit);
-
-}
-
-static void
 SetContextOptions(JSContext *cx)
 {
-    SetThreadStackLimit(cx);
+    JS_SetNativeStackQuota(cx, gMaxStackSize);
     JS_SetScriptStackQuota(cx, gScriptStackQuota);
     JS_SetOperationCallback(cx, ShellOperationCallback);
 }
 
 #ifdef WINCE
 int errno;
 #endif
 
@@ -3225,17 +3194,17 @@ RunScatterThread(void *arg)
         PR_WaitCondVar(td->shared->cvar, PR_INTERVAL_NO_TIMEOUT);
     PR_Unlock(td->shared->lock);
 
     if (st == SCATTER_CANCEL)
         return;
 
     /* We are good to go. */
     JS_SetContextThread(cx);
-    SetThreadStackLimit(cx);
+    JS_SetNativeStackQuota(cx, gMaxStackSize);
     JS_BeginRequest(cx);
     DoScatteredWork(cx, td);
     JS_EndRequest(cx);
     JS_ClearContextThread(cx);
 }
 
 /*
  * scatter(fnArray) - Call each function in `fnArray` without arguments, each
--- a/js/src/shell/jsworkers.cpp
+++ b/js/src/shell/jsworkers.cpp
@@ -48,16 +48,18 @@
 #include "jsapi.h"
 #include "jscntxt.h"
 #include "jshashtable.h"
 #include "jsstdint.h"
 #include "jslock.h"
 #include "jsvector.h"
 #include "jsworkers.h"
 
+extern size_t gMaxStackSize;
+
 /*
  * JavaScript shell workers.
  *
  * == Object lifetime rules ==
  *
  *   - The ThreadPool lasts from init() to finish().
  *
  *   - The ThreadPool owns the MainQueue and the WorkerQueue. Those live from
@@ -1073,17 +1075,17 @@ Worker::processOneEvent()
         AutoLock hold1(lock);
         if (lockedCheckTermination() || events.empty())
             return;
 
         event = current = events.pop();
     }
 
     JS_SetContextThread(context);
-    JS_SetThreadStackLimit(context, 0);
+    JS_SetNativeStackQuota(context, gMaxStackSize);
 
     Event::Result result;
     {
         JSAutoRequest req(context);
         result = event->process(context);
     }
 
     // Note: we have to leave the above request before calling parent->post or
--- a/js/src/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/src/xpconnect/loader/mozJSComponentLoader.cpp
@@ -603,31 +603,17 @@ mozJSComponentLoader::ReallyInit()
 
     uint32 options = JS_GetOptions(mContext);
     JS_SetOptions(mContext, options | JSOPTION_XML);
 
     // Always use the latest js version
     JS_SetVersion(mContext, JSVERSION_LATEST);
 
     // Limit C stack consumption to a reasonable 512K
-    int stackDummy;
-    const jsuword kStackSize = 0x80000;
-    jsuword stackLimit, currentStackAddr = (jsuword)&stackDummy;
-
-#if JS_STACK_GROWTH_DIRECTION < 0
-    stackLimit = (currentStackAddr > kStackSize)
-                 ? currentStackAddr - kStackSize
-                 : 0;
-#else
-    stackLimit = (currentStackAddr + kStackSize > currentStackAddr)
-                 ? currentStackAddr + kStackSize
-                 : (jsuword) -1;
-#endif
-    
-    JS_SetThreadStackLimit(mContext, stackLimit);
+    JS_SetNativeStackQuota(mContext, 512 * 1024);
 
 #ifndef XPCONNECT_STANDALONE
     nsCOMPtr<nsIScriptSecurityManager> secman = 
         do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID);
     if (!secman)
         return NS_ERROR_FAILURE;
 
     rv = secman->GetSystemPrincipal(getter_AddRefs(mSystemPrincipal));
--- a/js/src/xpconnect/src/xpcjsruntime.cpp
+++ b/js/src/xpconnect/src/xpcjsruntime.cpp
@@ -1163,18 +1163,18 @@ XPCJSRuntime::OnJSContextNew(JSContext *
     XPCPerThreadData* tls = XPCPerThreadData::GetData(cx);
     if(!tls)
         return JS_FALSE;
 
     XPCContext* xpc = new XPCContext(this, cx);
     if (!xpc)
         return JS_FALSE;
 
-    JS_SetThreadStackLimit(cx, tls->GetStackLimit());
-    JS_SetScriptStackQuota(cx, 100*1024*1024);
+    JS_SetNativeStackQuota(cx, 512 * 1024);
+    JS_SetScriptStackQuota(cx, 100 * 1024 * 1024);
     return JS_TRUE;
 }
 
 JSBool
 XPCJSRuntime::DeferredRelease(nsISupports* obj)
 {
     NS_ASSERTION(obj, "bad param");
 
--- a/js/src/xpconnect/src/xpcprivate.h
+++ b/js/src/xpconnect/src/xpcprivate.h
@@ -3541,18 +3541,16 @@ public:
     // Must be called with the threads locked.
     static XPCPerThreadData* IterateThreads(XPCPerThreadData** iteratorp);
 
     AutoMarkingPtr**  GetAutoRootsAdr() {return &mAutoRoots;}
 
     void TraceJS(JSTracer* trc);
     void MarkAutoRootsAfterJSFinalize();
 
-    jsuword GetStackLimit() const { return mStackLimit; }
-
     static void InitStatics()
         { gLock = nsnull; gThreads = nsnull; gTLSIndex = BAD_TLS_INDEX; }
 
 #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
     JSUint32  IncrementWrappedNativeThreadsafetyReportDepth()
         {return ++mWrappedNativeThreadsafetyReportDepth;}
     void      ClearWrappedNativeThreadsafetyReportDepth()
         {mWrappedNativeThreadsafetyReportDepth = 0;}
@@ -3575,18 +3573,16 @@ private:
     jsval                mResolveName;
     XPCWrappedNative*    mResolvingWrapper;
 
     nsIExceptionManager* mExceptionManager;
     nsIException*        mException;
     JSBool               mExceptionManagerNotAvailable;
     AutoMarkingPtr*      mAutoRoots;
 
-    jsuword              mStackLimit;
-
 #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
     JSUint32             mWrappedNativeThreadsafetyReportDepth;
 #endif
     PRThread*            mThread;
 
     static PRLock*           gLock;
     static XPCPerThreadData* gThreads;
     static PRUintn           gTLSIndex;
--- a/js/src/xpconnect/src/xpcthreadcontext.cpp
+++ b/js/src/xpconnect/src/xpcthreadcontext.cpp
@@ -323,48 +323,26 @@ XPCJSContextStack::SetSafeJSContext(JSCo
 /***************************************************************************/
 
 PRUintn           XPCPerThreadData::gTLSIndex       = BAD_TLS_INDEX;
 PRLock*           XPCPerThreadData::gLock           = nsnull;
 XPCPerThreadData* XPCPerThreadData::gThreads        = nsnull;
 XPCPerThreadData *XPCPerThreadData::sMainThreadData = nsnull;
 void *            XPCPerThreadData::sMainJSThread   = nsnull;
 
-static jsuword
-GetThreadStackLimit()
-{
-    int stackDummy;
-    jsuword stackLimit, currentStackAddr = (jsuword)&stackDummy;
-
-    const jsuword kStackSize = 0x80000;   // 512k
-
-#if JS_STACK_GROWTH_DIRECTION < 0
-    stackLimit = (currentStackAddr > kStackSize)
-                 ? currentStackAddr - kStackSize
-                 : 0;
-#else
-    stackLimit = (currentStackAddr + kStackSize > currentStackAddr)
-                 ? currentStackAddr + kStackSize
-                 : (jsuword) -1;
-#endif
-
-  return stackLimit;
-}
-
 XPCPerThreadData::XPCPerThreadData()
     :   mJSContextStack(new XPCJSContextStack()),
         mNextThread(nsnull),
         mCallContext(nsnull),
         mResolveName(0),
         mResolvingWrapper(nsnull),
         mExceptionManager(nsnull),
         mException(nsnull),
         mExceptionManagerNotAvailable(JS_FALSE),
-        mAutoRoots(nsnull),
-        mStackLimit(GetThreadStackLimit())
+        mAutoRoots(nsnull)
 #ifdef XPC_CHECK_WRAPPER_THREADSAFETY
       , mWrappedNativeThreadsafetyReportDepth(0)
 #endif
 {
     MOZ_COUNT_CTOR(xpcPerThreadData);
     if(gLock)
     {
         nsAutoLock lock(gLock);