From 4736d3662ea3409d798fb5833ede6d050a255ffe Mon Sep 17 00:00:00 2001 From: Brian Hackett Date: Mon, 24 Jul 2017 07:34:40 -0600 Subject: [PATCH] Bug 1383467 - Only cancel Ion compilations that use nursery pointers when performing a minor GC, r=jonco. --HG-- extra : rebase_source : 9032ca56a38b2be96bc2cc5dfb6a0163a54b06c3 --- js/src/gc/Nursery.cpp | 5 +++-- js/src/vm/HelperThreads.cpp | 32 +++++++++++++++++++------------- js/src/vm/HelperThreads.h | 8 ++++++++ 3 files changed, 30 insertions(+), 15 deletions(-) diff --git a/js/src/gc/Nursery.cpp b/js/src/gc/Nursery.cpp index f132e7cb6229..624945163369 100644 --- a/js/src/gc/Nursery.cpp +++ b/js/src/gc/Nursery.cpp @@ -701,10 +701,11 @@ js::Nursery::doCollection(JS::gcreason::Reason reason, StoreBuffer& sb = runtime()->gc.storeBuffer(); // The MIR graph only contains nursery pointers if cancelIonCompilations() - // is set on the store buffer, in which case we cancel all compilations. + // is set on the store buffer, in which case we cancel all compilations + // of such graphs. startProfile(ProfileKey::CancelIonCompilations); if (sb.cancelIonCompilations()) - js::CancelOffThreadIonCompile(rt); + js::CancelOffThreadIonCompilesUsingNurseryPointers(rt); endProfile(ProfileKey::CancelIonCompilations); startProfile(ProfileKey::TraceValues); diff --git a/js/src/vm/HelperThreads.cpp b/js/src/vm/HelperThreads.cpp index af56832ab007..00f947addc41 100644 --- a/js/src/vm/HelperThreads.cpp +++ b/js/src/vm/HelperThreads.cpp @@ -148,6 +148,7 @@ GetSelectorRuntime(const CompilationSelector& selector) JSRuntime* match(ZonesInState zbs) { return zbs.runtime; } JSRuntime* match(JSRuntime* runtime) { return runtime; } JSRuntime* match(AllCompilations all) { return nullptr; } + JSRuntime* match(CompilationsUsingNursery cun) { return cun.runtime; } }; return selector.match(Matcher()); @@ -163,29 +164,34 @@ JitDataStructuresExist(const CompilationSelector& selector) bool match(ZonesInState zbs) { return zbs.runtime->hasJitRuntime(); } bool match(JSRuntime* runtime) { return runtime->hasJitRuntime(); } bool match(AllCompilations all) { return true; } + bool match(CompilationsUsingNursery cun) { return cun.runtime->hasJitRuntime(); } }; return selector.match(Matcher()); } static bool -CompiledScriptMatches(const CompilationSelector& selector, JSScript* target) +IonBuilderMatches(const CompilationSelector& selector, jit::IonBuilder* builder) { - struct ScriptMatches + struct BuilderMatches { - JSScript* target_; + jit::IonBuilder* builder_; - bool match(JSScript* script) { return script == target_; } - bool match(JSCompartment* comp) { return comp == target_->compartment(); } - bool match(JSRuntime* runtime) { return runtime == target_->runtimeFromAnyThread(); } + bool match(JSScript* script) { return script == builder_->script(); } + bool match(JSCompartment* comp) { return comp == builder_->script()->compartment(); } + bool match(JSRuntime* runtime) { return runtime == builder_->script()->runtimeFromAnyThread(); } bool match(AllCompilations all) { return true; } bool match(ZonesInState zbs) { - return zbs.runtime == target_->runtimeFromAnyThread() && - zbs.state == target_->zoneFromAnyThread()->gcState(); + return zbs.runtime == builder_->script()->runtimeFromAnyThread() && + zbs.state == builder_->script()->zoneFromAnyThread()->gcState(); + } + bool match(CompilationsUsingNursery cun) { + return cun.runtime == builder_->script()->runtimeFromAnyThread() && + !builder_->safeForMinorGC(); } }; - return selector.match(ScriptMatches{target}); + return selector.match(BuilderMatches{builder}); } void @@ -203,7 +209,7 @@ js::CancelOffThreadIonCompile(const CompilationSelector& selector, bool discardL GlobalHelperThreadState::IonBuilderVector& worklist = HelperThreadState().ionWorklist(lock); for (size_t i = 0; i < worklist.length(); i++) { jit::IonBuilder* builder = worklist[i]; - if (CompiledScriptMatches(selector, builder->script())) { + if (IonBuilderMatches(selector, builder)) { FinishOffThreadIonCompile(builder, lock); HelperThreadState().remove(worklist, &i); } @@ -216,7 +222,7 @@ js::CancelOffThreadIonCompile(const CompilationSelector& selector, bool discardL bool unpaused = false; for (auto& helper : *HelperThreadState().threads) { if (helper.ionBuilder() && - CompiledScriptMatches(selector, helper.ionBuilder()->script())) + IonBuilderMatches(selector, helper.ionBuilder())) { helper.ionBuilder()->cancel(); if (helper.pause) { @@ -236,7 +242,7 @@ js::CancelOffThreadIonCompile(const CompilationSelector& selector, bool discardL GlobalHelperThreadState::IonBuilderVector& finished = HelperThreadState().ionFinishedList(lock); for (size_t i = 0; i < finished.length(); i++) { jit::IonBuilder* builder = finished[i]; - if (CompiledScriptMatches(selector, builder->script())) { + if (IonBuilderMatches(selector, builder)) { builder->script()->zone()->group()->numFinishedBuilders--; jit::FinishOffThreadBuilder(nullptr, builder, lock); HelperThreadState().remove(finished, &i); @@ -251,7 +257,7 @@ js::CancelOffThreadIonCompile(const CompilationSelector& selector, bool discardL jit::IonBuilder* builder = group->ionLazyLinkList().getFirst(); while (builder) { jit::IonBuilder* next = builder->getNext(); - if (CompiledScriptMatches(selector, builder->script())) + if (IonBuilderMatches(selector, builder)) jit::FinishOffThreadBuilder(runtime, builder, lock); builder = next; } diff --git a/js/src/vm/HelperThreads.h b/js/src/vm/HelperThreads.h index 5e91de653bfd..ce06b121e79a 100644 --- a/js/src/vm/HelperThreads.h +++ b/js/src/vm/HelperThreads.h @@ -494,11 +494,13 @@ StartOffThreadIonFree(jit::IonBuilder* builder, const AutoLockHelperThreadState& struct AllCompilations {}; struct ZonesInState { JSRuntime* runtime; JS::Zone::GCState state; }; +struct CompilationsUsingNursery { JSRuntime* runtime; }; using CompilationSelector = mozilla::Variant; /* @@ -531,6 +533,12 @@ CancelOffThreadIonCompile(JSRuntime* runtime) CancelOffThreadIonCompile(CompilationSelector(runtime), true); } +inline void +CancelOffThreadIonCompilesUsingNurseryPointers(JSRuntime* runtime) +{ + CancelOffThreadIonCompile(CompilationSelector(CompilationsUsingNursery{runtime}), true); +} + inline void CancelOffThreadIonCompile() {