Skip to content

Commit

Permalink
Bug 1809861 - Part 1: Simplify and clean up off-main thread script co…
Browse files Browse the repository at this point in the history
…mpilation r=smaug

The main change in this patch is to prevent access to main-thread objects
while off-thread. This is done by using nsMainThreadPtrHandle to wrap main
thread pointers in the runnable. This prevents access to their targets when
off thread and ensure they are only released on the main thread.

This means that mRunnable is now only accessed on the main thread and so it
doesn't need to be atomic and can be a normal RefPtr. We also don't need to
leak a reference to it in AttemptOffThreadScriptCompile.

This also requires that timing data is moved to the runnable.

Cancellation should always have happened by unlink or destruction of
ScriptLoadContext so handling for that is removed.

Differential Revision: https://phabricator.services.mozilla.com/D166667
  • Loading branch information
jonco3 committed Jan 17, 2023
1 parent 69f4bb8 commit 34aa24b
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 177 deletions.
32 changes: 14 additions & 18 deletions dom/script/ScriptLoadContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ NS_IMPL_CYCLE_COLLECTION_CLASS(ScriptLoadContext)

NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ScriptLoadContext,
JS::loader::LoadContextBase)
if (Runnable* runnable = tmp->mRunnable.exchange(nullptr)) {
runnable->Release();
}
MOZ_ASSERT(!tmp->mOffThreadToken);
MOZ_ASSERT(!tmp->mRunnable);
tmp->MaybeUnblockOnload();
NS_IMPL_CYCLE_COLLECTION_UNLINK_END

Expand Down Expand Up @@ -70,16 +69,12 @@ ScriptLoadContext::ScriptLoadContext()
mUnreportedPreloadError(NS_OK) {}

ScriptLoadContext::~ScriptLoadContext() {
// When speculative parsing is enabled, it is possible to off-main-thread
// compile scripts that are never executed. These should be cleaned up here
// if they exist.
mRequest = nullptr;
MOZ_ASSERT_IF(
!StaticPrefs::
dom_script_loader_external_scripts_speculative_omt_parse_enabled(),
!mOffThreadToken);
MOZ_ASSERT(NS_IsMainThread());

// Off-thread parsing must have completed by this point.
MOZ_DIAGNOSTIC_ASSERT(!mOffThreadToken && !mRunnable);

MaybeCancelOffThreadScript();
mRequest = nullptr;

MaybeUnblockOnload();
}
Expand All @@ -104,17 +99,18 @@ void ScriptLoadContext::MaybeCancelOffThreadScript() {
return;
}

// Cancel parse if it hasn't been started yet or wait for it to finish and
// clean up finished parse data.
JSContext* cx = danger::GetJSContext();
JS::CancelOffThreadToken(cx, mOffThreadToken);
mOffThreadToken = nullptr;

// Cancellation request above should guarantee removal of the parse task, so
// releasing the runnable should be safe to do here.
if (Runnable* runnable = mRunnable.exchange(nullptr)) {
runnable->Release();
}
// Clear the pointer to the runnable. It may still run later if we didn't
// cancel in time. In this case the runnable is held live by the reference
// passed to Dispatch, which is dropped after it runs.
mRunnable = nullptr;

MaybeUnblockOnload();
mOffThreadToken = nullptr;
}

void ScriptLoadContext::SetScriptMode(bool aDeferAttr, bool aAsyncAttr,
Expand Down
13 changes: 6 additions & 7 deletions dom/script/ScriptLoadContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,6 @@ class ScriptLoadContext : public JS::loader::LoadContextBase,

void MaybeCancelOffThreadScript();

TimeStamp mOffThreadParseStartTime;
TimeStamp mOffThreadParseStopTime;

ScriptMode mScriptMode; // Whether this is a blocking, defer or async script.
bool mScriptFromHead; // Synchronous head script block loading of other non
// js/css content.
Expand All @@ -172,11 +169,13 @@ class ScriptLoadContext : public JS::loader::LoadContextBase,
bool mWasCompiledOMT; // True if the script has been compiled off main
// thread.

JS::OffThreadToken* mOffThreadToken; // Off-thread parsing token.
// Off-thread parsing token. Set at the start of off-thread parsing and
// cleared when the result of the parse is used.
JS::OffThreadToken* mOffThreadToken;

Atomic<Runnable*> mRunnable; // Runnable created when dispatching off thread
// compile. Tracked here so that it can be
// properly released during cancellation.
// Runnable that is dispatched to the main thread when off-thread compilation
// completes.
RefPtr<Runnable> mRunnable;

int32_t mLineNo;

Expand Down
Loading

0 comments on commit 34aa24b

Please sign in to comment.