summaryrefslogtreecommitdiffstats
path: root/js/src/jit/MIRGenerator.h
diff options
context:
space:
mode:
Diffstat (limited to 'js/src/jit/MIRGenerator.h')
-rw-r--r--js/src/jit/MIRGenerator.h229
1 files changed, 229 insertions, 0 deletions
diff --git a/js/src/jit/MIRGenerator.h b/js/src/jit/MIRGenerator.h
new file mode 100644
index 000000000..d184bab1a
--- /dev/null
+++ b/js/src/jit/MIRGenerator.h
@@ -0,0 +1,229 @@
+/* -*- 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 <stdarg.h>
+
+#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 <typename T>
+ T* allocate(size_t count = 1) {
+ size_t bytes;
+ if (MOZ_UNLIKELY(!CalculateAllocSize<T>(count, &bytes)))
+ return nullptr;
+ return static_cast<T*>(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<bool, mozilla::Relaxed>* 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<ObjectGroup*, 0, JitAllocPolicy> 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<bool, mozilla::Relaxed>* pauseBuild_;
+ mozilla::Atomic<bool, mozilla::Relaxed> 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 */