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:
igor.bukanov%gmail.com
2006-07-29 08:39:04 +00:00
parent 8980741eea
commit f96eaa3597
4 changed files with 57 additions and 34 deletions

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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