Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
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/Atomics.h"
14 :
15 : #include <stdarg.h>
16 :
17 : #include "jscntxt.h"
18 : #include "jscompartment.h"
19 :
20 : #include "jit/CompileInfo.h"
21 : #include "jit/JitAllocPolicy.h"
22 : #include "jit/JitCompartment.h"
23 : #include "jit/MIR.h"
24 : #ifdef JS_ION_PERF
25 : # include "jit/PerfSpewer.h"
26 : #endif
27 : #include "jit/RegisterSets.h"
28 :
29 : namespace js {
30 : namespace jit {
31 :
32 : class MIRGraph;
33 : class OptimizationInfo;
34 :
35 169 : class MIRGenerator
36 : {
37 : public:
38 : MIRGenerator(CompileCompartment* compartment, const JitCompileOptions& options,
39 : TempAllocator* alloc, MIRGraph* graph,
40 : const CompileInfo* info, const OptimizationInfo* optimizationInfo);
41 :
42 0 : void initMinWasmHeapLength(uint32_t init) {
43 0 : minWasmHeapLength_ = init;
44 0 : }
45 :
46 156831 : TempAllocator& alloc() {
47 156831 : return *alloc_;
48 : }
49 10686 : MIRGraph& graph() {
50 10686 : return *graph_;
51 : }
52 1841 : MOZ_MUST_USE bool ensureBallast() {
53 1841 : return alloc().ensureBallast();
54 : }
55 145 : const JitRuntime* jitRuntime() const {
56 145 : return GetJitContext()->runtime->jitRuntime();
57 : }
58 67434 : const CompileInfo& info() const {
59 67434 : return *info_;
60 : }
61 882 : const OptimizationInfo& optimizationInfo() const {
62 882 : return *optimizationInfo_;
63 : }
64 :
65 : template <typename T>
66 334 : T* allocate(size_t count = 1) {
67 : size_t bytes;
68 334 : if (MOZ_UNLIKELY(!CalculateAllocSize<T>(count, &bytes)))
69 0 : return nullptr;
70 334 : return static_cast<T*>(alloc().allocate(bytes));
71 : }
72 :
73 : // Set an error state and prints a message. Returns false so errors can be
74 : // propagated up.
75 : mozilla::GenericErrorResult<AbortReason> abort(AbortReason r);
76 : mozilla::GenericErrorResult<AbortReason>
77 : abort(AbortReason r, const char* message, ...) MOZ_FORMAT_PRINTF(3, 4);
78 :
79 : mozilla::GenericErrorResult<AbortReason>
80 : abortFmt(AbortReason r, const char* message, va_list ap) MOZ_FORMAT_PRINTF(3, 0);
81 :
82 : // Collect the evaluation result of phases after IonBuilder, such that
83 : // off-thread compilation can report what error got encountered.
84 0 : void setOffThreadStatus(AbortReasonOr<Ok> result) {
85 0 : MOZ_ASSERT(offThreadStatus_.isOk());
86 0 : offThreadStatus_ = result;
87 0 : }
88 1411 : AbortReasonOr<Ok> getOffThreadStatus() const {
89 1411 : return offThreadStatus_;
90 : }
91 :
92 27891 : MOZ_MUST_USE bool instrumentedProfiling() {
93 27891 : if (!instrumentedProfilingIsCached_) {
94 179 : instrumentedProfiling_ = GetJitContext()->runtime->geckoProfiler().enabled();
95 179 : instrumentedProfilingIsCached_ = true;
96 : }
97 27891 : return instrumentedProfiling_;
98 : }
99 :
100 27883 : bool isProfilerInstrumentationEnabled() {
101 27883 : return !compilingWasm() && instrumentedProfiling();
102 : }
103 :
104 26518 : bool isOptimizationTrackingEnabled() {
105 26518 : return isProfilerInstrumentationEnabled() && !info().isAnalysis() &&
106 26518 : !JitOptions.disableOptimizationTracking;
107 : }
108 :
109 8 : bool safeForMinorGC() const {
110 8 : return safeForMinorGC_;
111 : }
112 1 : void setNotSafeForMinorGC() {
113 1 : safeForMinorGC_ = false;
114 1 : }
115 :
116 : // Whether the active thread is trying to cancel this build.
117 36328 : bool shouldCancel(const char* why) {
118 36328 : maybePause();
119 36328 : return cancelBuild_;
120 : }
121 0 : void cancel() {
122 0 : cancelBuild_ = true;
123 0 : }
124 :
125 36328 : void maybePause() {
126 36328 : if (pauseBuild_ && *pauseBuild_)
127 1 : PauseCurrentHelperThread();
128 36328 : }
129 8 : void setPauseFlag(mozilla::Atomic<bool, mozilla::Relaxed>* pauseBuild) {
130 8 : pauseBuild_ = pauseBuild;
131 8 : }
132 :
133 29905 : bool compilingWasm() const {
134 29905 : return info_->compilingWasm();
135 : }
136 :
137 0 : uint32_t wasmMaxStackArgBytes() const {
138 0 : MOZ_ASSERT(compilingWasm());
139 0 : return wasmMaxStackArgBytes_;
140 : }
141 0 : void initWasmMaxStackArgBytes(uint32_t n) {
142 0 : MOZ_ASSERT(compilingWasm());
143 0 : MOZ_ASSERT(wasmMaxStackArgBytes_ == 0);
144 0 : wasmMaxStackArgBytes_ = n;
145 0 : }
146 0 : uint32_t minWasmHeapLength() const {
147 0 : return minWasmHeapLength_;
148 : }
149 :
150 65 : void setNeedsOverrecursedCheck() {
151 65 : needsOverrecursedCheck_ = true;
152 65 : }
153 3 : bool needsOverrecursedCheck() const {
154 3 : return needsOverrecursedCheck_;
155 : }
156 :
157 75 : void setNeedsStaticStackAlignment() {
158 75 : needsStaticStackAlignment_ = true;
159 75 : }
160 0 : bool needsStaticStackAlignment() const {
161 0 : return needsOverrecursedCheck_;
162 : }
163 :
164 : // Traverses the graph to find if there's any SIMD instruction. Costful but
165 : // the value is cached, so don't worry about calling it several times.
166 : bool usesSimd();
167 :
168 : bool modifiesFrameArguments() const {
169 : return modifiesFrameArguments_;
170 : }
171 :
172 : typedef Vector<ObjectGroup*, 0, JitAllocPolicy> ObjectGroupVector;
173 :
174 : // When aborting with AbortReason::PreliminaryObjects, all groups with
175 : // preliminary objects which haven't been analyzed yet.
176 45 : const ObjectGroupVector& abortedPreliminaryGroups() const {
177 45 : return abortedPreliminaryGroups_;
178 : }
179 :
180 : public:
181 : CompileCompartment* compartment;
182 :
183 : protected:
184 : const CompileInfo* info_;
185 : const OptimizationInfo* optimizationInfo_;
186 : TempAllocator* alloc_;
187 : MIRGraph* graph_;
188 : AbortReasonOr<Ok> offThreadStatus_;
189 : ObjectGroupVector abortedPreliminaryGroups_;
190 : mozilla::Atomic<bool, mozilla::Relaxed>* pauseBuild_;
191 : mozilla::Atomic<bool, mozilla::Relaxed> cancelBuild_;
192 :
193 : uint32_t wasmMaxStackArgBytes_;
194 : bool needsOverrecursedCheck_;
195 : bool needsStaticStackAlignment_;
196 : bool usesSimd_;
197 : bool cachedUsesSimd_;
198 :
199 : // Keep track of whether frame arguments are modified during execution.
200 : // RegAlloc needs to know this as spilling values back to their register
201 : // slots is not compatible with that.
202 : bool modifiesFrameArguments_;
203 :
204 : bool instrumentedProfiling_;
205 : bool instrumentedProfilingIsCached_;
206 : bool safeForMinorGC_;
207 :
208 : void addAbortedPreliminaryGroup(ObjectGroup* group);
209 :
210 : uint32_t minWasmHeapLength_;
211 :
212 : #if defined(JS_ION_PERF)
213 : WasmPerfSpewer wasmPerfSpewer_;
214 :
215 : public:
216 : WasmPerfSpewer& perfSpewer() { return wasmPerfSpewer_; }
217 : #endif
218 :
219 : public:
220 : const JitCompileOptions options;
221 :
222 : private:
223 : GraphSpewer gs_;
224 :
225 : public:
226 46 : GraphSpewer& graphSpewer() {
227 46 : return gs_;
228 : }
229 : };
230 :
231 : } // namespace jit
232 : } // namespace js
233 :
234 : #endif /* jit_MIRGenerator_h */
|