1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sts=2 et sw=2 tw=80:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 #ifndef jit_MIRGenerator_h
8 #define jit_MIRGenerator_h
9 
10 // This file declares the data structures used to build a control-flow graph
11 // containing MIR.
12 
13 #include "mozilla/Assertions.h"
14 #include "mozilla/Atomics.h"
15 #include "mozilla/Attributes.h"
16 #include "mozilla/Result.h"
17 
18 #include <stdarg.h>
19 #include <stddef.h>
20 #include <stdint.h>
21 
22 #include "jit/CompileInfo.h"
23 #include "jit/CompileWrappers.h"
24 #include "jit/JitAllocPolicy.h"
25 #include "jit/JitContext.h"
26 #include "jit/JitSpewer.h"
27 #ifdef JS_ION_PERF
28 #  include "jit/PerfSpewer.h"
29 #endif
30 #include "js/Utility.h"
31 #include "vm/GeckoProfiler.h"
32 
33 namespace js {
34 namespace jit {
35 
36 class JitRuntime;
37 class MIRGraph;
38 class OptimizationInfo;
39 
40 class MIRGenerator final {
41  public:
42   MIRGenerator(CompileRealm* realm, const JitCompileOptions& options,
43                TempAllocator* alloc, MIRGraph* graph,
44                const CompileInfo* outerInfo,
45                const OptimizationInfo* optimizationInfo);
46 
initMinWasmHeapLength(uint64_t init)47   void initMinWasmHeapLength(uint64_t init) { minWasmHeapLength_ = init; }
48 
alloc()49   TempAllocator& alloc() { return *alloc_; }
graph()50   MIRGraph& graph() { return *graph_; }
ensureBallast()51   [[nodiscard]] bool ensureBallast() { return alloc().ensureBallast(); }
jitRuntime()52   const JitRuntime* jitRuntime() const { return runtime->jitRuntime(); }
outerInfo()53   const CompileInfo& outerInfo() const { return *outerInfo_; }
optimizationInfo()54   const OptimizationInfo& optimizationInfo() const {
55     return *optimizationInfo_;
56   }
hasProfilingScripts()57   bool hasProfilingScripts() const {
58     return runtime && runtime->profilingScripts();
59   }
60 
61   template <typename T>
62   T* allocate(size_t count = 1) {
63     size_t bytes;
64     if (MOZ_UNLIKELY(!CalculateAllocSize<T>(count, &bytes))) {
65       return nullptr;
66     }
67     return static_cast<T*>(alloc().allocate(bytes));
68   }
69 
70   // Set an error state and prints a message. Returns false so errors can be
71   // propagated up.
72   mozilla::GenericErrorResult<AbortReason> abort(AbortReason r);
73   mozilla::GenericErrorResult<AbortReason> abort(AbortReason r,
74                                                  const char* message, ...)
75       MOZ_FORMAT_PRINTF(3, 4);
76 
77   mozilla::GenericErrorResult<AbortReason> abortFmt(AbortReason r,
78                                                     const char* message,
79                                                     va_list ap)
80       MOZ_FORMAT_PRINTF(3, 0);
81 
82   // Collect the evaluation result of phases after WarpOracle, such that
83   // off-thread compilation can report what error got encountered.
setOffThreadStatus(AbortReasonOr<Ok> && result)84   void setOffThreadStatus(AbortReasonOr<Ok>&& result) {
85     MOZ_ASSERT(offThreadStatus_.isOk());
86     offThreadStatus_ = std::move(result);
87   }
getOffThreadStatus()88   const AbortReasonOr<Ok>& getOffThreadStatus() const {
89     return offThreadStatus_;
90   }
91 
instrumentedProfiling()92   [[nodiscard]] bool instrumentedProfiling() {
93     if (!instrumentedProfilingIsCached_) {
94       instrumentedProfiling_ = runtime->geckoProfiler().enabled();
95       instrumentedProfilingIsCached_ = true;
96     }
97     return instrumentedProfiling_;
98   }
99 
isProfilerInstrumentationEnabled()100   bool isProfilerInstrumentationEnabled() {
101     return !compilingWasm() && instrumentedProfiling();
102   }
103 
stringsCanBeInNursery()104   bool stringsCanBeInNursery() const { return stringsCanBeInNursery_; }
105 
bigIntsCanBeInNursery()106   bool bigIntsCanBeInNursery() const { return bigIntsCanBeInNursery_; }
107 
108   // Whether the main thread is trying to cancel this build.
shouldCancel(const char * why)109   bool shouldCancel(const char* why) { return cancelBuild_; }
cancel()110   void cancel() { cancelBuild_ = true; }
111 
compilingWasm()112   bool compilingWasm() const { return outerInfo_->compilingWasm(); }
113 
wasmMaxStackArgBytes()114   uint32_t wasmMaxStackArgBytes() const {
115     MOZ_ASSERT(compilingWasm());
116     return wasmMaxStackArgBytes_;
117   }
initWasmMaxStackArgBytes(uint32_t n)118   void initWasmMaxStackArgBytes(uint32_t n) {
119     MOZ_ASSERT(compilingWasm());
120     MOZ_ASSERT(wasmMaxStackArgBytes_ == 0);
121     wasmMaxStackArgBytes_ = n;
122   }
minWasmHeapLength()123   uint64_t minWasmHeapLength() const { return minWasmHeapLength_; }
124 
setNeedsOverrecursedCheck()125   void setNeedsOverrecursedCheck() { needsOverrecursedCheck_ = true; }
needsOverrecursedCheck()126   bool needsOverrecursedCheck() const { return needsOverrecursedCheck_; }
127 
setNeedsStaticStackAlignment()128   void setNeedsStaticStackAlignment() { needsStaticStackAlignment_ = true; }
needsStaticStackAlignment()129   bool needsStaticStackAlignment() const { return needsStaticStackAlignment_; }
130 
131  public:
132   CompileRealm* realm;
133   CompileRuntime* runtime;
134 
135  private:
136   // The CompileInfo for the outermost script.
137   const CompileInfo* outerInfo_;
138 
139   const OptimizationInfo* optimizationInfo_;
140   TempAllocator* alloc_;
141   MIRGraph* graph_;
142   AbortReasonOr<Ok> offThreadStatus_;
143   mozilla::Atomic<bool, mozilla::Relaxed> cancelBuild_;
144 
145   uint32_t wasmMaxStackArgBytes_;
146   bool needsOverrecursedCheck_;
147   bool needsStaticStackAlignment_;
148 
149   bool instrumentedProfiling_;
150   bool instrumentedProfilingIsCached_;
151   bool stringsCanBeInNursery_;
152   bool bigIntsCanBeInNursery_;
153 
154   uint64_t minWasmHeapLength_;
155 
156 #if defined(JS_ION_PERF)
157   WasmPerfSpewer wasmPerfSpewer_;
158 
159  public:
perfSpewer()160   WasmPerfSpewer& perfSpewer() { return wasmPerfSpewer_; }
161 #endif
162 
163  public:
164   const JitCompileOptions options;
165 
166  private:
167   GraphSpewer gs_;
168 
169  public:
graphSpewer()170   GraphSpewer& graphSpewer() { return gs_; }
171 };
172 
173 }  // namespace jit
174 }  // namespace js
175 
176 #endif /* jit_MIRGenerator_h */
177