/* -*- 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_JitContext_h #define jit_JitContext_h #include "mozilla/Assertions.h" #include "mozilla/Result.h" #include #include "jstypes.h" struct JS_PUBLIC_API JSContext; namespace js { namespace jit { class CompileRealm; class CompileRuntime; class TempAllocator; enum MethodStatus { Method_Error, Method_CantCompile, Method_Skipped, Method_Compiled }; // Use only even, non-zero values for errors, to allow using the UnusedZero and // HasFreeLSB optimizations for mozilla::Result (see specializations of // UnusedZero/HasFreeLSB below). enum class AbortReason : uint8_t { NoAbort, Alloc = 2, Disable = 4, Error = 6, }; } // namespace jit } // namespace js namespace mozilla::detail { template <> struct UnusedZero : UnusedZeroEnum { }; template <> struct HasFreeLSB { static const bool value = true; }; } // namespace mozilla::detail namespace js { namespace jit { template using AbortReasonOr = mozilla::Result; using mozilla::Err; using mozilla::Ok; static_assert(sizeof(AbortReasonOr) <= sizeof(uintptr_t), "Unexpected size of AbortReasonOr"); static_assert(mozilla::detail::SelectResultImpl::value == mozilla::detail::PackingStrategy::NullIsOk); static_assert(sizeof(AbortReasonOr) <= sizeof(uintptr_t), "Unexpected size of AbortReasonOr"); static_assert(sizeof(AbortReasonOr) == sizeof(uintptr_t), "Unexpected size of AbortReasonOr"); // A JIT context is needed for parts of the compiler backend such as the // MacroAssembler. It points to the JSContext (nullptr for off-thread // compilations or Wasm compilations) and also stores some extra information, // most of it only used in debug builds. // // JIT contexts must not be nested. class MOZ_RAII JitContext { #ifdef DEBUG // Whether this thread is actively Ion compiling (does not include Wasm or // WarpOracle). bool inIonBackend_ = false; bool isCompilingWasm_ = false; bool oom_ = false; #endif public: // Running context when compiling on the main thread. Not available during // off-thread compilation. JSContext* cx = nullptr; // Wrapper with information about the current runtime. nullptr for Wasm // compilations. CompileRuntime* runtime = nullptr; // Constructor for compilations happening on the main thread. explicit JitContext(JSContext* cx); // Constructor for off-thread Ion compilations. explicit JitContext(CompileRuntime* rt); // Constructor for Wasm compilation. JitContext(); ~JitContext(); #ifdef DEBUG bool isCompilingWasm() { return isCompilingWasm_; } bool setIsCompilingWasm(bool flag) { bool oldFlag = isCompilingWasm_; isCompilingWasm_ = flag; return oldFlag; } bool hasOOM() { return oom_; } void setOOM() { oom_ = true; } bool inIonBackend() const { return inIonBackend_; } void enterIonBackend() { MOZ_ASSERT(!inIonBackend_); inIonBackend_ = true; } void leaveIonBackend() { MOZ_ASSERT(inIonBackend_); inIonBackend_ = false; } #endif }; // Process-wide initialization and shutdown of JIT data structures. [[nodiscard]] bool InitializeJit(); void ShutdownJit(); // Get and set the current JIT context. JitContext* GetJitContext(); JitContext* MaybeGetJitContext(); void SetJitContext(JitContext* ctx); enum JitExecStatus { // The method call had to be aborted due to a stack limit check. This // error indicates that Ion never attempted to clean up frames. JitExec_Aborted, // The method call resulted in an error, and IonMonkey has cleaned up // frames. JitExec_Error, // The method call succeeded and returned a value. JitExec_Ok }; static inline bool IsErrorStatus(JitExecStatus status) { return status == JitExec_Error || status == JitExec_Aborted; } bool JitSupportsWasmSimd(); bool JitSupportsAtomics(); } // namespace jit } // namespace js #endif /* jit_JitContext_h */