Fixing bug 412698. Make XPConnect cache the per thread data for the main thread and use the cache when running on the main thread to save on time getting at the per thread data. r=dbradley@gmail.com, sr=brendan@mozilla.org

This commit is contained in:
jst@mozilla.org 2008-01-20 20:51:55 -08:00
parent 67747c0779
commit e3b9c872ac
8 changed files with 60 additions and 22 deletions

View File

@ -1613,7 +1613,7 @@ nsXPConnect::GetCurrentNativeCallContext(nsAXPCNativeCallContext * *aCurrentNati
{
NS_ASSERTION(aCurrentNativeCallContext, "bad param");
XPCPerThreadData* data = XPCPerThreadData::GetData();
XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
if(data)
{
*aCurrentNativeCallContext = data->GetCallContext();
@ -1630,7 +1630,7 @@ nsXPConnect::GetPendingException(nsIException * *aPendingException)
{
NS_ASSERTION(aPendingException, "bad param");
XPCPerThreadData* data = XPCPerThreadData::GetData();
XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
if(!data)
{
*aPendingException = nsnull;
@ -1643,7 +1643,7 @@ nsXPConnect::GetPendingException(nsIException * *aPendingException)
NS_IMETHODIMP
nsXPConnect::SetPendingException(nsIException * aPendingException)
{
XPCPerThreadData* data = XPCPerThreadData::GetData();
XPCPerThreadData* data = XPCPerThreadData::GetData(nsnull);
if(!data)
return UnexpectedFailure(NS_ERROR_FAILURE);
@ -1993,7 +1993,7 @@ NS_IMETHODIMP
nsXPConnect::ReleaseJSContext(JSContext * aJSContext, PRBool noGC)
{
NS_ASSERTION(aJSContext, "bad param");
XPCPerThreadData* tls = XPCPerThreadData::GetData();
XPCPerThreadData* tls = XPCPerThreadData::GetData(aJSContext);
if(tls)
{
XPCCallContext* ccx = nsnull;

View File

@ -77,7 +77,9 @@ XPCCallContext::XPCCallContext(XPCContext::LangType callerLanguage,
NS_ADDREF(mXPC);
if(!(mThreadData = XPCPerThreadData::GetData()))
mThreadData = XPCPerThreadData::GetData(mJSContext);
if(!mThreadData)
return;
XPCJSContextStack* stack = mThreadData->GetJSContextStack();
@ -357,7 +359,7 @@ XPCCallContext::~XPCCallContext()
// Don't clear newborns if JS frames (compilation or execution)
// are active! Doing so violates ancient invariants in the JS
// engine, and it's not necessary to fix JS component leaks.
if (!mJSContext->fp)
if(!mJSContext->fp)
JS_ClearNewbornRoots(mJSContext);
}
}
@ -389,7 +391,8 @@ XPCCallContext::NewStringWrapper(PRUnichar *str, PRUint32 len)
{
StringWrapperEntry& ent = se[i];
if (!ent.mInUse) {
if(!ent.mInUse)
{
ent.mInUse = PR_TRUE;
// Construct the string using placement new.
@ -413,7 +416,7 @@ XPCCallContext::DeleteString(nsAString *string)
for(i = 0; i < XPCCCX_STRING_CACHE_SIZE; ++i)
{
StringWrapperEntry& ent = se[i];
if (string == &ent.mString)
if(string == &ent.mString)
{
// One of our internal strings is no longer in use, mark
// it as such and destroy the string.

View File

@ -3506,7 +3506,7 @@ xpc_EvalInSandbox(JSContext *cx, JSObject *sandbox, const nsAString& source,
return NS_ERROR_OUT_OF_MEMORY;
}
XPCPerThreadData *data = XPCPerThreadData::GetData();
XPCPerThreadData *data = XPCPerThreadData::GetData(cx);
XPCJSContextStack *stack = nsnull;
if (data && (stack = data->GetJSContextStack())) {
if (NS_FAILED(stack->Push(sandcx->GetJSContext()))) {

View File

@ -238,7 +238,7 @@ ContextCallback(JSContext *cx, uintN operation)
{
if (operation == JSCONTEXT_NEW)
{
XPCPerThreadData* tls = XPCPerThreadData::GetData();
XPCPerThreadData* tls = XPCPerThreadData::GetData(cx);
if(tls)
{
JS_SetThreadStackLimit(cx, tls->GetStackLimit());
@ -1201,7 +1201,7 @@ XPCJSRuntime::SyncXPCContextList(JSContext* cx /* = nsnull */)
// get rid of any XPCContexts that represent dead JSContexts
mContextMap->Enumerate(SweepContextsCB, 0);
XPCPerThreadData* tls = XPCPerThreadData::GetData();
XPCPerThreadData* tls = XPCPerThreadData::GetData(cx);
if(tls)
{
if(found)

View File

@ -3041,7 +3041,19 @@ class XPCPerThreadData
{
public:
// Get the instance of this object for the current thread
static XPCPerThreadData* GetData();
static inline XPCPerThreadData* GetData(JSContext *cx)
{
if(cx)
{
NS_ASSERTION(cx->thread, "Uh, JS context w/o a thread?");
if(cx->thread == sMainJSThread)
return sMainThreadData;
}
return GetDataImpl(cx);
}
static void CleanupAllThreads();
~XPCPerThreadData();
@ -3143,8 +3155,12 @@ public:
{mWrappedNativeThreadsafetyReportDepth = 0;}
#endif
static void ShutDown()
{sMainJSThread = nsnull; sMainThreadData = nsnull;}
private:
XPCPerThreadData();
static XPCPerThreadData* GetDataImpl(JSContext *cx);
private:
XPCJSContextStack* mJSContextStack;
@ -3171,6 +3187,13 @@ private:
static PRLock* gLock;
static XPCPerThreadData* gThreads;
static PRUintn gTLSIndex;
// Cached value of cx->thread on the main thread.
static void *sMainJSThread;
// Cached per thread data for the main thread. Only safe to access
// if cx->thread == sMainJSThread.
static XPCPerThreadData *sMainThreadData;
};
/**************************************************************/
@ -3199,8 +3222,8 @@ public:
virtual ~nsXPCThreadJSContextStackImpl();
private:
XPCJSContextStack* GetStackForCurrentThread()
{XPCPerThreadData* data = XPCPerThreadData::GetData();
XPCJSContextStack* GetStackForCurrentThread(JSContext *cx = nsnull)
{XPCPerThreadData* data = XPCPerThreadData::GetData(cx);
return data ? data->GetJSContextStack() : nsnull;}
static nsXPCThreadJSContextStackImpl* gXPCThreadJSContextStack;

View File

@ -201,6 +201,8 @@ nsJSRuntimeServiceImpl::~nsJSRuntimeServiceImpl() {
fprintf(stderr, "nJRSI: destroyed runtime %p\n", (void *)mRuntime);
#endif
}
XPCPerThreadData::ShutDown();
}
NS_IMPL_THREADSAFE_ISUPPORTS2(nsJSRuntimeServiceImpl,
@ -257,7 +259,7 @@ nsJSRuntimeServiceImpl::GetRuntime(JSRuntime **runtime)
//
// We rely on the implementation of NSPR that calls destructors at
// the same order of calling PR_NewThreadPrivateIndex.
XPCPerThreadData::GetData();
XPCPerThreadData::GetData(nsnull);
mRuntime = JS_NewRuntime(gGCSize);
if(!mRuntime)

View File

@ -384,7 +384,7 @@ nsXPCThreadJSContextStackImpl::Pop(JSContext * *_retval)
NS_IMETHODIMP
nsXPCThreadJSContextStackImpl::Push(JSContext * cx)
{
XPCJSContextStack* myStack = GetStackForCurrentThread();
XPCJSContextStack* myStack = GetStackForCurrentThread(cx);
if(!myStack)
return NS_ERROR_FAILURE;
@ -413,7 +413,7 @@ nsXPCThreadJSContextStackImpl::GetSafeJSContext(JSContext * *aSafeJSContext)
NS_IMETHODIMP
nsXPCThreadJSContextStackImpl::SetSafeJSContext(JSContext * aSafeJSContext)
{
XPCJSContextStack* myStack = GetStackForCurrentThread();
XPCJSContextStack* myStack = GetStackForCurrentThread(aSafeJSContext);
if(!myStack)
return NS_ERROR_FAILURE;
@ -423,9 +423,11 @@ nsXPCThreadJSContextStackImpl::SetSafeJSContext(JSContext * aSafeJSContext)
/***************************************************************************/
PRUintn XPCPerThreadData::gTLSIndex = BAD_TLS_INDEX;
PRLock* XPCPerThreadData::gLock = nsnull;
XPCPerThreadData* XPCPerThreadData::gThreads = nsnull;
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()
@ -559,7 +561,7 @@ void XPCPerThreadData::MarkAutoRootsAfterJSFinalize()
// static
XPCPerThreadData*
XPCPerThreadData::GetData()
XPCPerThreadData::GetDataImpl(JSContext *cx)
{
XPCPerThreadData* data;
@ -604,6 +606,14 @@ XPCPerThreadData::GetData()
return nsnull;
}
}
if(cx && !sMainJSThread && NS_IsMainThread())
{
sMainJSThread = cx->thread;
sMainThreadData = data;
}
return data;
}

View File

@ -229,7 +229,7 @@ XPCThrower::BuildAndThrowException(JSContext* cx, nsresult rv, const char* sz)
nsCOMPtr<nsIException> finalException;
nsCOMPtr<nsIException> defaultException;
nsXPCException::NewException(sz, rv, nsnull, nsnull, getter_AddRefs(defaultException));
XPCPerThreadData* tls = XPCPerThreadData::GetData();
XPCPerThreadData* tls = XPCPerThreadData::GetData(cx);
if(tls)
{
nsIExceptionManager * exceptionManager = tls->GetExceptionManager();