/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- * vim: set ts=8 sts=2 et sw=2 tw=80: * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef jit_BaselineCompileTask_h #define jit_BaselineCompileTask_h #include "mozilla/LinkedList.h" #include "mozilla/Maybe.h" #include "jit/BaselineCodeGen.h" #include "jit/JitScript.h" #include "jit/OffthreadSnapshot.h" #include "vm/HelperThreadTask.h" namespace js::jit { class BaselineSnapshot { OffthreadGCPtr script_; OffthreadGCPtr globalLexical_; OffthreadGCPtr globalThis_; OffthreadGCPtr callObjectTemplate_; OffthreadGCPtr namedLambdaTemplate_; size_t nargs_; uint32_t baseWarmUpThreshold_; bool isIonCompileable_; bool compileDebugInstrumentation_; public: BaselineSnapshot(JSScript* script, GlobalLexicalEnvironmentObject* globalLexical, JSObject* globalThis, uint32_t baseWarmUpThreshold, bool isIonCompileable, bool compileDebugInstrumentation) : script_(script), globalLexical_(globalLexical), globalThis_(globalThis), callObjectTemplate_(nullptr), namedLambdaTemplate_(nullptr), nargs_(script->function() ? script->function()->nargs() : 0), baseWarmUpThreshold_(baseWarmUpThreshold), isIonCompileable_(isIonCompileable), compileDebugInstrumentation_(compileDebugInstrumentation) { if (script->needsFunctionEnvironmentObjects()) { auto [callObjectTemplate, namedLambdaTemplate] = script->jitScript()->functionEnvironmentTemplates(script->function()); callObjectTemplate_.init(callObjectTemplate); namedLambdaTemplate_.init(namedLambdaTemplate); } } JSScript* script() const { return script_; } GlobalLexicalEnvironmentObject* globalLexical() const { return globalLexical_; } JSObject* globalThis() const { return globalThis_; } CallObject* callObjectTemplate() const { return callObjectTemplate_; } NamedLambdaObject* namedLambdaTemplate() const { return namedLambdaTemplate_; } size_t nargs() const { return nargs_; } uint32_t baseWarmUpThreshold() const { return baseWarmUpThreshold_; } bool isIonCompileable() const { return isIonCompileable_; } bool compileDebugInstrumentation() const { return compileDebugInstrumentation_; } void trace(JSTracer* trc); }; class OffThreadBaselineSnapshot : public BaselineSnapshot, public mozilla::LinkedListElement { public: OffThreadBaselineSnapshot(JSScript* script, GlobalLexicalEnvironmentObject* globalLexical, JSObject* globalThis, uint32_t baseWarmUpThreshold, bool isIonCompileable, bool compileDebugInstrumentation) : BaselineSnapshot(script, globalLexical, globalThis, baseWarmUpThreshold, isIonCompileable, compileDebugInstrumentation) {} explicit OffThreadBaselineSnapshot(BaselineSnapshot other) : BaselineSnapshot(other) {} bool compileOffThread(TempAllocator& temp, CompileRealm* realm); private: mozilla::Maybe masm_; mozilla::Maybe compiler_; friend class BaselineCompileTask; }; using BaselineSnapshotList = mozilla::LinkedList; class BaselineCompileTask final : public HelperThreadTask { public: BaselineCompileTask(CompileRealm* realm, LifoAlloc* alloc, BaselineSnapshotList&& snapshots) : realm_(realm), alloc_(alloc), snapshots_(std::move(snapshots)) { #ifdef DEBUG for (auto* snapshot : snapshots_) { MOZ_ASSERT(CompileRealm::get(snapshot->script()->realm()) == realm); } #endif } static bool OffThreadBaselineCompilationAvailable(JSContext* cx, JSScript* script, bool isEager = false); ThreadType threadType() override { return THREAD_TYPE_BASELINE; } void runTask(); void runHelperThreadTask(AutoLockHelperThreadState& locked) override; void markScriptsAsCompiling(); void finishOnMainThread(JSContext* cx); JSRuntime* runtimeFromAnyThread() const { return firstScript()->runtimeFromAnyThread(); } Zone* zoneFromAnyThread() const { return firstScript()->zoneFromAnyThread(); } bool scriptMatches(JSScript* script) { for (auto* snapshot : snapshots_) { if (snapshot->script() == script) { return true; } } return false; } const char* getName() override { return "BaselineCompileTask"; } void trace(JSTracer* trc); static void FinishOffThreadTask(BaselineCompileTask* task); bool failed() const { return failed_; } private: // All scripts are in the same realm, so we can use an arbitrary script // to access the realm/zone/runtime. JSScript* firstScript() const { return snapshots_.getFirst()->script(); } CompileRealm* realm_; LifoAlloc* alloc_; BaselineSnapshotList snapshots_; bool failed_ = false; }; } // namespace js::jit #endif /* jit_BaselineCompileTask_h */