/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- * vim: set ts=8 sts=4 et sw=4 tw=99: * 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_MIRGenerator_h #define jit_MIRGenerator_h // This file declares the data structures used to build a control-flow graph // containing MIR. #include "mozilla/Atomics.h" #include #include "jscntxt.h" #include "jscompartment.h" #include "jit/CompileInfo.h" #include "jit/JitAllocPolicy.h" #include "jit/JitCompartment.h" #include "jit/MIR.h" #ifdef JS_ION_PERF # include "jit/PerfSpewer.h" #endif #include "jit/RegisterSets.h" namespace js { namespace jit { class MIRGraph; class OptimizationInfo; class MIRGenerator { public: MIRGenerator(CompileCompartment* compartment, const JitCompileOptions& options, TempAllocator* alloc, MIRGraph* graph, const CompileInfo* info, const OptimizationInfo* optimizationInfo); void initMinWasmHeapLength(uint32_t init) { minWasmHeapLength_ = init; } TempAllocator& alloc() { return *alloc_; } MIRGraph& graph() { return *graph_; } MOZ_MUST_USE bool ensureBallast() { return alloc().ensureBallast(); } const JitRuntime* jitRuntime() const { return GetJitContext()->runtime->jitRuntime(); } const CompileInfo& info() const { return *info_; } const OptimizationInfo& optimizationInfo() const { return *optimizationInfo_; } template T* allocate(size_t count = 1) { size_t bytes; if (MOZ_UNLIKELY(!CalculateAllocSize(count, &bytes))) return nullptr; return static_cast(alloc().allocate(bytes)); } // Set an error state and prints a message. Returns false so errors can be // propagated up. bool abort(const char* message, ...) MOZ_FORMAT_PRINTF(2, 3); // always returns false bool abortFmt(const char* message, va_list ap); // always returns false bool errored() const { return error_; } MOZ_MUST_USE bool instrumentedProfiling() { if (!instrumentedProfilingIsCached_) { instrumentedProfiling_ = GetJitContext()->runtime->spsProfiler().enabled(); instrumentedProfilingIsCached_ = true; } return instrumentedProfiling_; } bool isProfilerInstrumentationEnabled() { return !compilingWasm() && instrumentedProfiling(); } bool isOptimizationTrackingEnabled() { return isProfilerInstrumentationEnabled() && !info().isAnalysis(); } bool safeForMinorGC() const { return safeForMinorGC_; } void setNotSafeForMinorGC() { safeForMinorGC_ = false; } // Whether the main thread is trying to cancel this build. bool shouldCancel(const char* why) { maybePause(); return cancelBuild_; } void cancel() { cancelBuild_ = true; } void maybePause() { if (pauseBuild_ && *pauseBuild_) PauseCurrentHelperThread(); } void setPauseFlag(mozilla::Atomic* pauseBuild) { pauseBuild_ = pauseBuild; } void disable() { abortReason_ = AbortReason_Disable; } AbortReason abortReason() { return abortReason_; } bool compilingWasm() const { return info_->compilingWasm(); } uint32_t wasmMaxStackArgBytes() const { MOZ_ASSERT(compilingWasm()); return wasmMaxStackArgBytes_; } void initWasmMaxStackArgBytes(uint32_t n) { MOZ_ASSERT(compilingWasm()); MOZ_ASSERT(wasmMaxStackArgBytes_ == 0); wasmMaxStackArgBytes_ = n; } uint32_t minWasmHeapLength() const { return minWasmHeapLength_; } void setPerformsCall() { performsCall_ = true; } bool performsCall() const { return performsCall_; } // Traverses the graph to find if there's any SIMD instruction. Costful but // the value is cached, so don't worry about calling it several times. bool usesSimd(); bool modifiesFrameArguments() const { return modifiesFrameArguments_; } typedef Vector ObjectGroupVector; // When abortReason() == AbortReason_PreliminaryObjects, all groups with // preliminary objects which haven't been analyzed yet. const ObjectGroupVector& abortedPreliminaryGroups() const { return abortedPreliminaryGroups_; } public: CompileCompartment* compartment; protected: const CompileInfo* info_; const OptimizationInfo* optimizationInfo_; TempAllocator* alloc_; MIRGraph* graph_; AbortReason abortReason_; bool shouldForceAbort_; // Force AbortReason_Disable ObjectGroupVector abortedPreliminaryGroups_; bool error_; mozilla::Atomic* pauseBuild_; mozilla::Atomic cancelBuild_; uint32_t wasmMaxStackArgBytes_; bool performsCall_; bool usesSimd_; bool cachedUsesSimd_; // Keep track of whether frame arguments are modified during execution. // RegAlloc needs to know this as spilling values back to their register // slots is not compatible with that. bool modifiesFrameArguments_; bool instrumentedProfiling_; bool instrumentedProfilingIsCached_; bool safeForMinorGC_; void addAbortedPreliminaryGroup(ObjectGroup* group); uint32_t minWasmHeapLength_; void setForceAbort() { shouldForceAbort_ = true; } bool shouldForceAbort() { return shouldForceAbort_; } #if defined(JS_ION_PERF) WasmPerfSpewer wasmPerfSpewer_; public: WasmPerfSpewer& perfSpewer() { return wasmPerfSpewer_; } #endif public: const JitCompileOptions options; private: GraphSpewer gs_; public: GraphSpewer& graphSpewer() { return gs_; } }; } // namespace jit } // namespace js #endif /* jit_MIRGenerator_h */