Skip to content

Commit

Permalink
Backed out changeset 8f99f3809630 (bug 1683220) for performance regre…
Browse files Browse the repository at this point in the history
…ssion (bug 1684434). CLOSED TREE
  • Loading branch information
Razvan Maries committed Jan 7, 2021
1 parent f2d5237 commit 6565293
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 0 deletions.
5 changes: 5 additions & 0 deletions docshell/base/nsDocShell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10429,6 +10429,11 @@ nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
rv = aURILoader->OpenURI(aChannel, aOpenFlags, this);
NS_ENSURE_SUCCESS(rv, rv);

// We're about to load a new page and it may take time before necko
// gives back any data, so main thread might have a chance to process a
// collector slice
nsJSContext::MaybeRunNextCollectorSlice(this, JS::GCReason::DOCSHELL);

// Success. Keep the initial ClientSource if it exists.
cleanupInitialClient.release();

Expand Down
58 changes: 58 additions & 0 deletions dom/base/nsJSEnvironment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1738,6 +1738,64 @@ void nsJSContext::RunNextCollectorTimer(JS::GCReason aReason,
}
}

// static
void nsJSContext::MaybeRunNextCollectorSlice(nsIDocShell* aDocShell,
JS::GCReason aReason) {
if (!aDocShell || !XRE_IsContentProcess()) {
return;
}

BrowsingContext* bc = aDocShell->GetBrowsingContext();
if (!bc) {
return;
}

BrowsingContext* root = bc->Top();
if (bc == root) {
// We don't want to run collectors when loading the top level page.
return;
}

nsIDocShell* rootDocShell = root->GetDocShell();
if (!rootDocShell) {
return;
}

Document* rootDocument = rootDocShell->GetDocument();
if (!rootDocument ||
rootDocument->GetReadyStateEnum() != Document::READYSTATE_COMPLETE ||
rootDocument->IsInBackgroundWindow()) {
return;
}

PresShell* presShell = rootDocument->GetPresShell();
if (!presShell) {
return;
}

nsViewManager* vm = presShell->GetViewManager();
if (!vm) {
return;
}

// GetLastUserEventTime returns microseconds.
uint32_t lastEventTime = 0;
vm->GetLastUserEventTime(lastEventTime);
uint32_t currentTime = PR_IntervalToMicroseconds(PR_IntervalNow());
// Only try to trigger collectors more often if user hasn't interacted with
// the page for awhile.
if ((currentTime - lastEventTime) >
(StaticPrefs::dom_events_user_interaction_interval() *
PR_USEC_PER_MSEC)) {
Maybe<TimeStamp> next = nsRefreshDriver::GetNextTickHint();
// Try to not delay the next RefreshDriver tick, so give a reasonable
// deadline for collectors.
if (next.isSome()) {
nsJSContext::RunNextCollectorTimer(aReason, next.value());
}
}
}

// static
void nsJSContext::PokeGC(JS::GCReason aReason, JSObject* aObj,
uint32_t aDelay) {
Expand Down
5 changes: 5 additions & 0 deletions dom/base/nsJSEnvironment.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,11 @@ class nsJSContext : public nsIScriptContext {
static void RunNextCollectorTimer(
JS::GCReason aReason,
mozilla::TimeStamp aDeadline = mozilla::TimeStamp());
// If user has been idle and aDocShell is for an iframe being loaded in an
// already loaded top level docshell, this will run a CC or GC
// timer/runner if there is such pending.
static void MaybeRunNextCollectorSlice(nsIDocShell* aDocShell,
JS::GCReason aReason);

// The GC should probably run soon, in the zone of object aObj (if given).
static void PokeGC(JS::GCReason aReason, JSObject* aObj, uint32_t aDelay = 0);
Expand Down
24 changes: 24 additions & 0 deletions parser/html/nsHtml5StreamParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -999,6 +999,20 @@ void nsHtml5StreamParser::CommitLocalFileToEncoding() {
}
}

class MaybeRunCollector : public Runnable {
public:
explicit MaybeRunCollector(nsIDocShell* aDocShell)
: Runnable("MaybeRunCollector"), mDocShell(aDocShell) {}

NS_IMETHOD Run() override {
nsJSContext::MaybeRunNextCollectorSlice(mDocShell,
JS::GCReason::HTML_PARSER);
return NS_OK;
}

nsCOMPtr<nsIDocShell> mDocShell;
};

nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest) {
MOZ_RELEASE_ASSERT(STREAM_NOT_STARTED == mStreamState,
"Got OnStartRequest when the stream had already started.");
Expand Down Expand Up @@ -1150,6 +1164,16 @@ nsresult nsHtml5StreamParser::OnStartRequest(nsIRequest* aRequest) {
do_QueryInterface(mRequest, &rv);
if (threadRetargetableRequest) {
rv = threadRetargetableRequest->RetargetDeliveryTo(mEventTarget);
if (NS_SUCCEEDED(rv)) {
// Parser thread should be now ready to get data from necko and parse it
// and main thread might have a chance to process a collector slice.
// We need to do this asynchronously so that necko may continue processing
// the request.
nsCOMPtr<nsIRunnable> runnable =
new MaybeRunCollector(mExecutor->GetDocument()->GetDocShell());
mozilla::SchedulerGroup::Dispatch(
mozilla::TaskCategory::GarbageCollection, runnable.forget());
}
}

if (NS_FAILED(rv)) {
Expand Down

0 comments on commit 6565293

Please sign in to comment.