From 15b5b64c0266d137f4ac528debbb39aff843143b Mon Sep 17 00:00:00 2001 From: Jan de Mooij Date: Wed, 6 Feb 2019 07:56:17 +0000 Subject: [PATCH] Bug 1524499 part 1 - Move active flag from BaselineScript to TypeScript. r=tcampbell Baseline interpreter frames will have a TypeScript/ICScript we want to keep around on GC. The JSScript::typesDontCheckGeneration method will be removed in the next patch. Differential Revision: https://phabricator.services.mozilla.com/D18548 --HG-- extra : moz-landing-system : lando --- js/src/gc/Zone.cpp | 18 ++++++++++++------ js/src/jit/BaselineJIT.cpp | 30 +++++++++++++----------------- js/src/jit/BaselineJIT.h | 14 +++----------- js/src/vm/Debugger.cpp | 11 ++++++----- js/src/vm/JSScript.h | 2 ++ js/src/vm/TypeInference.cpp | 6 ++++-- js/src/vm/TypeInference.h | 8 ++++++++ 7 files changed, 48 insertions(+), 41 deletions(-) diff --git a/js/src/gc/Zone.cpp b/js/src/gc/Zone.cpp index 55341b13c897..15dfb08fc477 100644 --- a/js/src/gc/Zone.cpp +++ b/js/src/gc/Zone.cpp @@ -206,17 +206,18 @@ void Zone::discardJitCode(FreeOp* fop, return; } - if (discardBaselineCode) { + if (discardBaselineCode || releaseTypes) { #ifdef DEBUG - /* Assert no baseline scripts are marked as active. */ + // Assert no TypeScripts are marked as active. for (auto script = cellIter(); !script.done(); script.next()) { - MOZ_ASSERT_IF(script->hasBaselineScript(), - !script->baselineScript()->active()); + if (TypeScript* types = script->typesDontCheckGeneration()) { + MOZ_ASSERT(!types->active()); + } } #endif - /* Mark baseline scripts on the stack as active. */ - jit::MarkActiveBaselineScripts(this); + // Mark TypeScripts on the stack as active. + jit::MarkActiveTypeScripts(this); } /* Only mark OSI points if code is being discarded. */ @@ -262,6 +263,11 @@ void Zone::discardJitCode(FreeOp* fop, if (discardBaselineCode && script->hasICScript()) { script->icScript()->purgeOptimizedStubs(script); } + + // Finally, reset the active flag. + if (TypeScript* types = script->typesDontCheckGeneration()) { + types->resetActive(); + } } /* diff --git a/js/src/jit/BaselineJIT.cpp b/js/src/jit/BaselineJIT.cpp index 20c8c61f3410..ecf27ef4cc13 100644 --- a/js/src/jit/BaselineJIT.cpp +++ b/js/src/jit/BaselineJIT.cpp @@ -1142,11 +1142,7 @@ void jit::FinishDiscardBaselineScript(FreeOp* fop, JSScript* script) { return; } - if (script->baselineScript()->active()) { - // Reset |active| flag so that we don't need a separate script - // iteration to unmark them. - script->baselineScript()->resetActive(); - + if (script->typesDontCheckGeneration()->active()) { // The baseline caches have been wiped out, so the script will need to // warm back up before it can be inlined during Ion compilation. script->baselineScript()->clearIonCompiledOrInlined(); @@ -1216,31 +1212,31 @@ void jit::ToggleBaselineTraceLoggerEngine(JSRuntime* runtime, bool enable) { } #endif -static void MarkActiveBaselineScripts(JSContext* cx, - const JitActivationIterator& activation) { +static void MarkActiveTypeScripts(JSContext* cx, + const JitActivationIterator& activation) { for (OnlyJSJitFrameIter iter(activation); !iter.done(); ++iter) { const JSJitFrameIter& frame = iter.frame(); switch (frame.type()) { case FrameType::BaselineJS: - frame.script()->baselineScript()->setActive(); + frame.script()->typesDontCheckGeneration()->setActive(); break; case FrameType::Exit: if (frame.exitFrame()->is()) { LazyLinkExitFrameLayout* ll = frame.exitFrame()->as(); - ScriptFromCalleeToken(ll->jsFrame()->calleeToken()) - ->baselineScript() - ->setActive(); + JSScript* script = + ScriptFromCalleeToken(ll->jsFrame()->calleeToken()); + script->typesDontCheckGeneration()->setActive(); } break; case FrameType::Bailout: case FrameType::IonJS: { - // Keep the baseline script around, since bailouts from the ion - // jitcode might need to re-enter into the baseline jitcode. - frame.script()->baselineScript()->setActive(); + // Keep the TypeScript and BaselineScript around, since bailouts from + // the ion jitcode need to re-enter into the Baseline code. + frame.script()->typesDontCheckGeneration()->setActive(); for (InlineFrameIterator inlineIter(cx, &frame); inlineIter.more(); ++inlineIter) { - inlineIter.script()->baselineScript()->setActive(); + inlineIter.script()->typesDontCheckGeneration()->setActive(); } break; } @@ -1249,14 +1245,14 @@ static void MarkActiveBaselineScripts(JSContext* cx, } } -void jit::MarkActiveBaselineScripts(Zone* zone) { +void jit::MarkActiveTypeScripts(Zone* zone) { if (zone->isAtomsZone()) { return; } JSContext* cx = TlsContext.get(); for (JitActivationIterator iter(cx); !iter.done(); ++iter) { if (iter->compartment()->zone() == zone) { - MarkActiveBaselineScripts(cx, iter); + MarkActiveTypeScripts(cx, iter); } } } diff --git a/js/src/jit/BaselineJIT.h b/js/src/jit/BaselineJIT.h index b66f63fe3040..d34201032575 100644 --- a/js/src/jit/BaselineJIT.h +++ b/js/src/jit/BaselineJIT.h @@ -252,11 +252,7 @@ struct BaselineScript final { public: enum Flag { - // (1 << 0) is unused. - - // Flag set when discarding JIT code, to indicate this script is - // on the stack and should not be discarded. - ACTIVE = 1 << 1, + // (1 << 0) and (1 << 1) are unused. // Flag set when the script contains any writes to its on-stack // (rather than call object stored) arguments. @@ -354,10 +350,6 @@ struct BaselineScript final { *data += mallocSizeOf(this); } - bool active() const { return flags_ & ACTIVE; } - void setActive() { flags_ |= ACTIVE; } - void resetActive() { flags_ &= ~ACTIVE; } - void setModifiesArguments() { flags_ |= MODIFIES_ARGUMENTS; } bool modifiesArguments() { return flags_ & MODIFIES_ARGUMENTS; } @@ -632,9 +624,9 @@ MOZ_MUST_USE bool BailoutIonToBaseline( bool invalidate, BaselineBailoutInfo** bailoutInfo, const ExceptionBailoutInfo* exceptionInfo); -// Mark baseline scripts on the stack as active, so that they are not discarded +// Mark TypeScripts on the stack as active, so that they are not discarded // during GC. -void MarkActiveBaselineScripts(Zone* zone); +void MarkActiveTypeScripts(Zone* zone); MethodStatus BaselineCompile(JSContext* cx, JSScript* script, bool forceDebugInstrumentation = false); diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index d421ec1adb55..ef98dcf2dd62 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -2705,10 +2705,10 @@ class MOZ_RAII ExecutionObservableScript return true; } -static inline void MarkBaselineScriptActiveIfObservable( +static inline void MarkTypeScriptActiveIfObservable( JSScript* script, const Debugger::ExecutionObservableSet& obs) { if (obs.shouldRecompileOrInvalidate(script)) { - script->baselineScript()->setActive(); + script->typesDontCheckGeneration()->setActive(); } } @@ -2772,13 +2772,13 @@ static bool UpdateExecutionObservabilityOfScriptsInZone( const JSJitFrameIter& frame = iter.frame(); switch (frame.type()) { case FrameType::BaselineJS: - MarkBaselineScriptActiveIfObservable(frame.script(), obs); + MarkTypeScriptActiveIfObservable(frame.script(), obs); break; case FrameType::IonJS: - MarkBaselineScriptActiveIfObservable(frame.script(), obs); + MarkTypeScriptActiveIfObservable(frame.script(), obs); for (InlineFrameIterator inlineIter(cx, &frame); inlineIter.more(); ++inlineIter) { - MarkBaselineScriptActiveIfObservable(inlineIter.script(), obs); + MarkTypeScriptActiveIfObservable(inlineIter.script(), obs); } break; default:; @@ -2792,6 +2792,7 @@ static bool UpdateExecutionObservabilityOfScriptsInZone( for (size_t i = 0; i < scripts.length(); i++) { MOZ_ASSERT_IF(scripts[i]->isDebuggee(), observing); FinishDiscardBaselineScript(fop, scripts[i]); + scripts[i]->typesDontCheckGeneration()->resetActive(); } // Iterate through all wasm instances to find ones that need to be updated. diff --git a/js/src/vm/JSScript.h b/js/src/vm/JSScript.h index 28f9b7a675eb..33e1d95ed6da 100644 --- a/js/src/vm/JSScript.h +++ b/js/src/vm/JSScript.h @@ -2423,6 +2423,8 @@ class JSScript : public js::gc::TenuredCell { inline js::TypeScript* types(const js::AutoSweepTypeScript& sweep); inline bool typesNeedsSweep() const; + js::TypeScript* typesDontCheckGeneration() { return types_; } + void maybeReleaseTypes(); void sweepTypes(const js::AutoSweepTypeScript& sweep); diff --git a/js/src/vm/TypeInference.cpp b/js/src/vm/TypeInference.cpp index 96e3748c7b13..948e95d1ef65 100644 --- a/js/src/vm/TypeInference.cpp +++ b/js/src/vm/TypeInference.cpp @@ -3596,7 +3596,8 @@ TypeScript::TypeScript(JSScript* script, ICScriptPtr&& icScript, uint32_t numTypeSets) : icScript_(std::move(icScript)), numTypeSets_(numTypeSets), - bytecodeTypeMapHint_(0) { + bytecodeTypeMapHint_(0), + active_(false) { StackTypeSet* array = typeArray(); for (unsigned i = 0; i < numTypeSets; i++) { new (&array[i]) StackTypeSet(); @@ -4743,7 +4744,8 @@ void ObjectGroup::sweep(const AutoSweepObjectGroup& sweep) { } void JSScript::maybeReleaseTypes() { - if (!types_ || zone()->types.keepTypeScripts || hasBaselineScript()) { + if (!types_ || zone()->types.keepTypeScripts || hasBaselineScript() || + types_->active()) { return; } diff --git a/js/src/vm/TypeInference.h b/js/src/vm/TypeInference.h index 21fcf41217bf..0daafd077c9b 100644 --- a/js/src/vm/TypeInference.h +++ b/js/src/vm/TypeInference.h @@ -220,6 +220,10 @@ class TypeScript { // bytecode map queries are in linear order. uint32_t bytecodeTypeMapHint_; + // Flag set when discarding JIT code to indicate this script is on the stack + // and type information and JIT code should not be discarded. + bool active_; + // Variable-size array. This is followed by the bytecode type map. StackTypeSet typeArray_[1]; @@ -238,6 +242,10 @@ class TypeScript { uint32_t* bytecodeTypeMapHint() { return &bytecodeTypeMapHint_; } + bool active() const { return active_; } + void setActive() { active_ = true; } + void resetActive() { active_ = false; } + jit::ICScript* icScript() const { MOZ_ASSERT(icScript_); return icScript_.get();