mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 23:31:56 +00:00
Bug 916255 - Allow multiple in flight off thread parses at once for each script loader, r=bz.
This commit is contained in:
parent
c965ffbdef
commit
fbf409cb2a
@ -697,62 +697,64 @@ namespace {
|
||||
|
||||
class NotifyOffThreadScriptLoadCompletedRunnable : public nsRunnable
|
||||
{
|
||||
nsRefPtr<nsScriptLoader> mLoader;
|
||||
void *mToken;
|
||||
nsRefPtr<nsScriptLoadRequest> mRequest;
|
||||
nsRefPtr<nsScriptLoader> mLoader;
|
||||
void *mToken;
|
||||
|
||||
public:
|
||||
NotifyOffThreadScriptLoadCompletedRunnable(already_AddRefed<nsScriptLoader> aLoader,
|
||||
void *aToken)
|
||||
: mLoader(aLoader), mToken(aToken)
|
||||
{}
|
||||
NotifyOffThreadScriptLoadCompletedRunnable(nsScriptLoadRequest* aRequest,
|
||||
nsScriptLoader* aLoader)
|
||||
: mRequest(aRequest), mLoader(aLoader), mToken(NULL)
|
||||
{}
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
void SetToken(void* aToken) {
|
||||
MOZ_ASSERT(aToken && !mToken);
|
||||
mToken = aToken;
|
||||
}
|
||||
|
||||
NS_DECL_NSIRUNNABLE
|
||||
};
|
||||
|
||||
} /* anonymous namespace */
|
||||
|
||||
nsresult
|
||||
nsScriptLoader::ProcessOffThreadRequest(void **aOffThreadToken)
|
||||
nsScriptLoader::ProcessOffThreadRequest(nsScriptLoadRequest* aRequest, void **aOffThreadToken)
|
||||
{
|
||||
nsCOMPtr<nsScriptLoadRequest> request = mOffThreadScriptRequest;
|
||||
mOffThreadScriptRequest = nullptr;
|
||||
mDocument->UnblockOnload(false);
|
||||
|
||||
return ProcessRequest(request, aOffThreadToken);
|
||||
nsresult rv = ProcessRequest(aRequest, aOffThreadToken);
|
||||
mDocument->UnblockOnload(false);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
NotifyOffThreadScriptLoadCompletedRunnable::Run()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
nsresult rv = mLoader->ProcessOffThreadRequest(&mToken);
|
||||
nsresult rv = mLoader->ProcessOffThreadRequest(mRequest, &mToken);
|
||||
|
||||
if (mToken) {
|
||||
// The result of the off thread parse was not actually needed to process
|
||||
// the request (disappearing window, some other error, ...). Finish the
|
||||
// request to avoid leaks in the JS engine.
|
||||
nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
|
||||
NS_ENSURE_TRUE(svc, NS_ERROR_FAILURE);
|
||||
JSRuntime *rt;
|
||||
svc->GetRuntime(&rt);
|
||||
NS_ENSURE_TRUE(rt, NS_ERROR_FAILURE);
|
||||
JS::FinishOffThreadScript(nullptr, rt, mToken);
|
||||
}
|
||||
if (mToken) {
|
||||
// The result of the off thread parse was not actually needed to process
|
||||
// the request (disappearing window, some other error, ...). Finish the
|
||||
// request to avoid leaks in the JS engine.
|
||||
nsCOMPtr<nsIJSRuntimeService> svc = do_GetService("@mozilla.org/js/xpc/RuntimeService;1");
|
||||
NS_ENSURE_TRUE(svc, NS_ERROR_FAILURE);
|
||||
JSRuntime *rt;
|
||||
svc->GetRuntime(&rt);
|
||||
NS_ENSURE_TRUE(rt, NS_ERROR_FAILURE);
|
||||
JS::FinishOffThreadScript(nullptr, rt, mToken);
|
||||
}
|
||||
|
||||
return rv;
|
||||
return rv;
|
||||
}
|
||||
|
||||
static void
|
||||
OffThreadScriptLoaderCallback(void *aToken, void *aCallbackData)
|
||||
{
|
||||
// Be careful not to adjust the refcount on the loader, as this callback
|
||||
// may be invoked off the main thread.
|
||||
nsScriptLoader* aLoader = static_cast<nsScriptLoader*>(aCallbackData);
|
||||
nsRefPtr<NotifyOffThreadScriptLoadCompletedRunnable> notify =
|
||||
new NotifyOffThreadScriptLoadCompletedRunnable(
|
||||
already_AddRefed<nsScriptLoader>(aLoader), aToken);
|
||||
NS_DispatchToMainThread(notify);
|
||||
NotifyOffThreadScriptLoadCompletedRunnable* aRunnable =
|
||||
static_cast<NotifyOffThreadScriptLoadCompletedRunnable*>(aCallbackData);
|
||||
aRunnable->SetToken(aToken);
|
||||
NS_DispatchToMainThread(aRunnable);
|
||||
NS_RELEASE(aRunnable);
|
||||
}
|
||||
|
||||
nsresult
|
||||
@ -762,10 +764,6 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (mOffThreadScriptRequest) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
JSObject *unrootedGlobal;
|
||||
nsCOMPtr<nsIScriptContext> context = GetScriptContext(&unrootedGlobal);
|
||||
if (!context) {
|
||||
@ -781,16 +779,18 @@ nsScriptLoader::AttemptAsyncScriptParse(nsScriptLoadRequest* aRequest)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
mOffThreadScriptRequest = aRequest;
|
||||
nsRefPtr<NotifyOffThreadScriptLoadCompletedRunnable> runnable =
|
||||
new NotifyOffThreadScriptLoadCompletedRunnable(aRequest, this);
|
||||
|
||||
if (!JS::CompileOffThread(cx, global, options,
|
||||
aRequest->mScriptText.get(), aRequest->mScriptText.Length(),
|
||||
OffThreadScriptLoaderCallback,
|
||||
static_cast<void*>(this))) {
|
||||
static_cast<void*>(runnable))) {
|
||||
return NS_ERROR_OUT_OF_MEMORY;
|
||||
}
|
||||
|
||||
// This reference will be consumed by the NotifyOffThreadScriptLoadCompletedRunnable.
|
||||
NS_ADDREF(this);
|
||||
// This reference will be consumed by OffThreadScriptLoaderCallback.
|
||||
runnable.forget();
|
||||
|
||||
mDocument->BlockOnload();
|
||||
|
||||
|
@ -211,7 +211,8 @@ public:
|
||||
* Process a request that was deferred so that the script could be compiled
|
||||
* off thread.
|
||||
*/
|
||||
nsresult ProcessOffThreadRequest(void **aOffThreadToken);
|
||||
nsresult ProcessOffThreadRequest(nsScriptLoadRequest *aRequest,
|
||||
void **aOffThreadToken);
|
||||
|
||||
private:
|
||||
/**
|
||||
@ -316,7 +317,6 @@ private:
|
||||
};
|
||||
nsTArray<PreloadInfo> mPreloads;
|
||||
|
||||
nsCOMPtr<nsScriptLoadRequest> mOffThreadScriptRequest;
|
||||
nsCOMPtr<nsIScriptElement> mCurrentScript;
|
||||
nsCOMPtr<nsIScriptElement> mCurrentParserInsertedScript;
|
||||
// XXXbz do we want to cycle-collect these or something? Not sure.
|
||||
|
Loading…
Reference in New Issue
Block a user