/* -*- 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_Ion_h #define jit_Ion_h #include "mozilla/Assertions.h" #include "mozilla/Attributes.h" #include "mozilla/Likely.h" #include "mozilla/MemoryReporting.h" #include #include #include "jsfriendapi.h" #include "jspubtd.h" #include "jit/BaselineJIT.h" #include "jit/IonTypes.h" #include "jit/JitContext.h" #include "jit/JitOptions.h" #include "js/Principals.h" #include "js/TypeDecls.h" #include "vm/BytecodeUtil.h" #include "vm/JSContext.h" #include "vm/JSFunction.h" #include "vm/JSScript.h" namespace js { class RunState; namespace jit { class BaselineFrame; bool CanIonCompileScript(JSContext* cx, JSScript* script); bool CanIonInlineScript(JSScript* script); [[nodiscard]] bool IonCompileScriptForBaselineAtEntry(JSContext* cx, BaselineFrame* frame); struct IonOsrTempData { void* jitcode; uint8_t* baselineFrame; static constexpr size_t offsetOfJitCode() { return offsetof(IonOsrTempData, jitcode); } static constexpr size_t offsetOfBaselineFrame() { return offsetof(IonOsrTempData, baselineFrame); } }; [[nodiscard]] bool IonCompileScriptForBaselineOSR(JSContext* cx, BaselineFrame* frame, uint32_t frameSize, jsbytecode* pc, IonOsrTempData** infoPtr); MethodStatus CanEnterIon(JSContext* cx, RunState& state); class MIRGenerator; class LIRGraph; class CodeGenerator; class LazyLinkExitFrameLayout; class WarpSnapshot; [[nodiscard]] bool OptimizeMIR(MIRGenerator* mir); LIRGraph* GenerateLIR(MIRGenerator* mir); CodeGenerator* GenerateCode(MIRGenerator* mir, LIRGraph* lir); CodeGenerator* CompileBackEnd(MIRGenerator* mir, WarpSnapshot* snapshot); void LinkIonScript(JSContext* cx, HandleScript calleescript); uint8_t* LazyLinkTopActivation(JSContext* cx, LazyLinkExitFrameLayout* frame); inline bool IsIonInlinableGetterOrSetterOp(JSOp op) { // JSOp::GetProp, JSOp::CallProp, JSOp::Length, JSOp::GetElem, // and JSOp::CallElem. (Inlined Getters) // JSOp::SetProp, JSOp::SetName, JSOp::SetGName (Inlined Setters) return IsGetPropOp(op) || IsGetElemOp(op) || IsSetPropOp(op); } inline bool IsIonInlinableOp(JSOp op) { // JSOp::Call, JSOp::FunCall, JSOp::Eval, JSOp::New (Normal Callsites) or an // inlinable getter or setter. return (IsInvokeOp(op) && !IsSpreadOp(op)) || IsIonInlinableGetterOrSetterOp(op); } inline bool TooManyActualArguments(unsigned nargs) { return nargs > JitOptions.maxStackArgs; } inline bool TooManyFormalArguments(unsigned nargs) { return nargs >= SNAPSHOT_MAX_NARGS || TooManyActualArguments(nargs); } inline size_t NumLocalsAndArgs(JSScript* script) { size_t num = 1 /* this */ + script->nfixed(); if (JSFunction* fun = script->function()) { num += fun->nargs(); } return num; } // Debugging RAII class which marks the current thread as performing an Ion // backend compilation. class MOZ_RAII AutoEnterIonBackend { public: AutoEnterIonBackend() { #ifdef DEBUG JitContext* jcx = GetJitContext(); jcx->enterIonBackend(); #endif } #ifdef DEBUG ~AutoEnterIonBackend() { JitContext* jcx = GetJitContext(); jcx->leaveIonBackend(); } #endif }; bool OffThreadCompilationAvailable(JSContext* cx); void ForbidCompilation(JSContext* cx, JSScript* script); size_t SizeOfIonData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf); inline bool IsIonEnabled(JSContext* cx) { if (MOZ_UNLIKELY(!IsBaselineJitEnabled(cx) || cx->options().disableIon())) { return false; } if (MOZ_LIKELY(JitOptions.ion)) { return true; } if (JitOptions.jitForTrustedPrincipals) { JS::Realm* realm = js::GetContextRealm(cx); return realm && JS::GetRealmPrincipals(realm) && JS::GetRealmPrincipals(realm)->isSystemOrAddonPrincipal(); } return false; } // Implemented per-platform. Returns true if the flags will not require // further (lazy) computation. bool CPUFlagsHaveBeenComputed(); } // namespace jit } // namespace js #endif /* jit_Ion_h */