Bug 342854: Using JSContext callback to ensure that C stack limit is always set. r=brendan,mrbkap,sr=jst
git-svn-id: svn://10.0.0.236/trunk@205904 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -880,37 +880,6 @@ nsJSContext::JSOptionChangedCallback(const char *pref, void *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static jsuword
|
||||
GetThreadStackLimit()
|
||||
{
|
||||
// Store the thread stack limit in a static local to ensure that all
|
||||
// contexts get the same stack limit (they're all on the same thread
|
||||
// anyways), and this also helps prevent returning a stack limit
|
||||
// that is beyond the end of the stack if this method is called way
|
||||
// deep on the stack.
|
||||
|
||||
static jsuword sThreadStackLimit;
|
||||
|
||||
if (sThreadStackLimit == 0) {
|
||||
int stackDummy;
|
||||
jsuword currentStackAddr = (jsuword)&stackDummy;
|
||||
|
||||
const jsuword kStackSize = 0x80000; // 512k
|
||||
|
||||
#if JS_STACK_GROWTH_DIRECTION < 0
|
||||
sThreadStackLimit = (currentStackAddr > kStackSize)
|
||||
? currentStackAddr - kStackSize
|
||||
: 0;
|
||||
#else
|
||||
sThreadStackLimit = (currentStackAddr + kStackSize > currentStackAddr)
|
||||
? currentStackAddr + kStackSize
|
||||
: (jsuword) -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
return sThreadStackLimit;
|
||||
}
|
||||
|
||||
nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE)
|
||||
{
|
||||
|
||||
@@ -932,8 +901,6 @@ nsJSContext::nsJSContext(JSRuntime *aRuntime) : mGCOnDestruction(PR_TRUE)
|
||||
if (mContext) {
|
||||
::JS_SetContextPrivate(mContext, NS_STATIC_CAST(nsIScriptContext *, this));
|
||||
|
||||
::JS_SetThreadStackLimit(mContext, GetThreadStackLimit());
|
||||
|
||||
// Make sure the new context gets the default context options
|
||||
::JS_SetOptions(mContext, mDefaultJSOptions);
|
||||
|
||||
|
||||
@@ -68,6 +68,9 @@ const char* XPCJSRuntime::mStrings[] = {
|
||||
|
||||
/***************************************************************************/
|
||||
|
||||
// ContextCallback calls are chained
|
||||
static JSContextCallback gOldJSContextCallback;
|
||||
|
||||
// GCCallback calls are chained
|
||||
static JSGCCallback gOldJSGCCallback;
|
||||
|
||||
@@ -224,6 +227,28 @@ DetachedWrappedNativeProtoMarker(JSDHashTable *table, JSDHashEntryHdr *hdr,
|
||||
return JS_DHASH_NEXT;
|
||||
}
|
||||
|
||||
// GCCallback calls are chained
|
||||
JS_STATIC_DLL_CALLBACK(JSBool)
|
||||
ContextCallback(JSContext *cx, uintN operation)
|
||||
{
|
||||
XPCJSRuntime* self = nsXPConnect::GetRuntime();
|
||||
if (self)
|
||||
{
|
||||
if (operation == JSCONTEXT_NEW)
|
||||
{
|
||||
XPCPerThreadData* tls = XPCPerThreadData::GetData();
|
||||
if(tls)
|
||||
{
|
||||
JS_SetThreadStackLimit(cx, tls->GetStackLimit());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return gOldJSContextCallback
|
||||
? gOldJSContextCallback(cx, operation)
|
||||
: JS_TRUE;
|
||||
}
|
||||
|
||||
// static
|
||||
JSBool XPCJSRuntime::GCCallback(JSContext *cx, JSGCStatus status)
|
||||
{
|
||||
@@ -768,6 +793,7 @@ XPCJSRuntime::~XPCJSRuntime()
|
||||
XPCConvert::RemoveXPCOMUCStringFinalizer();
|
||||
|
||||
gOldJSGCCallback = NULL;
|
||||
gOldJSContextCallback = NULL;
|
||||
}
|
||||
|
||||
XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
|
||||
@@ -811,7 +837,11 @@ XPCJSRuntime::XPCJSRuntime(nsXPConnect* aXPConnect,
|
||||
|
||||
NS_ASSERTION(!gOldJSGCCallback, "XPCJSRuntime created more than once");
|
||||
if(mJSRuntime)
|
||||
{
|
||||
gOldJSContextCallback = JS_SetContextCallback(mJSRuntime,
|
||||
ContextCallback);
|
||||
gOldJSGCCallback = JS_SetGCCallbackRT(mJSRuntime, GCCallback);
|
||||
}
|
||||
|
||||
// Install a JavaScript 'debugger' keyword handler in debug builds only
|
||||
#ifdef DEBUG
|
||||
|
||||
@@ -2893,6 +2893,8 @@ public:
|
||||
void MarkAutoRootsBeforeJSFinalize(JSContext* cx);
|
||||
void MarkAutoRootsAfterJSFinalize();
|
||||
|
||||
jsuword GetStackLimit() const { return mStackLimit; }
|
||||
|
||||
static void InitStatics()
|
||||
{ gLock = nsnull; gThreads = nsnull; gTLSIndex = BAD_TLS_INDEX; }
|
||||
|
||||
@@ -2921,6 +2923,8 @@ private:
|
||||
JSBool mExceptionManagerNotAvailable;
|
||||
AutoMarkingPtr* mAutoRoots;
|
||||
|
||||
jsuword mStackLimit;
|
||||
|
||||
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
|
||||
JSUint32 mWrappedNativeThreadsafetyReportDepth;
|
||||
#endif
|
||||
|
||||
@@ -404,6 +404,27 @@ PRUintn XPCPerThreadData::gTLSIndex = BAD_TLS_INDEX;
|
||||
PRLock* XPCPerThreadData::gLock = nsnull;
|
||||
XPCPerThreadData* XPCPerThreadData::gThreads = 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),
|
||||
@@ -415,7 +436,8 @@ XPCPerThreadData::XPCPerThreadData()
|
||||
mExceptionManager(nsnull),
|
||||
mException(nsnull),
|
||||
mExceptionManagerNotAvailable(JS_FALSE),
|
||||
mAutoRoots(nsnull)
|
||||
mAutoRoots(nsnull),
|
||||
mStackLimit(GetThreadStackLimit())
|
||||
#ifdef XPC_CHECK_WRAPPER_THREADSAFETY
|
||||
, mWrappedNativeThreadsafetyReportDepth(0)
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user