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-21 04:51:55 +00:00
Родитель 26a66a2208
Коммит 0e7f93e216
8 изменённых файлов: 60 добавлений и 22 удалений

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

@ -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()))) {

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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

Просмотреть файл

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