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 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 bool usesSignalHandlersForAsmJSOOB = false); 42 alloc()43 TempAllocator& alloc() { 44 return *alloc_; 45 } graph()46 MIRGraph& graph() { 47 return *graph_; 48 } ensureBallast()49 bool ensureBallast() { 50 return alloc().ensureBallast(); 51 } jitRuntime()52 const JitRuntime* jitRuntime() const { 53 return GetJitContext()->runtime->jitRuntime(); 54 } info()55 const CompileInfo& info() const { 56 return *info_; 57 } optimizationInfo()58 const OptimizationInfo& optimizationInfo() const { 59 return *optimizationInfo_; 60 } 61 62 template <typename T> 63 T* allocate(size_t count = 1) { 64 size_t bytes; 65 if (MOZ_UNLIKELY(!CalculateAllocSize<T>(count, &bytes))) 66 return nullptr; 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 bool abort(const char* message, ...); 73 bool abortFmt(const char* message, va_list ap); 74 errored()75 bool errored() const { 76 return error_; 77 } 78 instrumentedProfiling()79 bool instrumentedProfiling() { 80 if (!instrumentedProfilingIsCached_) { 81 instrumentedProfiling_ = GetJitContext()->runtime->spsProfiler().enabled(); 82 instrumentedProfilingIsCached_ = true; 83 } 84 return instrumentedProfiling_; 85 } 86 isProfilerInstrumentationEnabled()87 bool isProfilerInstrumentationEnabled() { 88 return !compilingAsmJS() && instrumentedProfiling(); 89 } 90 isOptimizationTrackingEnabled()91 bool isOptimizationTrackingEnabled() { 92 return isProfilerInstrumentationEnabled() && !info().isAnalysis(); 93 } 94 safeForMinorGC()95 bool safeForMinorGC() const { 96 return safeForMinorGC_; 97 } setNotSafeForMinorGC()98 void setNotSafeForMinorGC() { 99 safeForMinorGC_ = false; 100 } 101 102 // Whether the main thread is trying to cancel this build. shouldCancel(const char * why)103 bool shouldCancel(const char* why) { 104 maybePause(); 105 return cancelBuild_; 106 } cancel()107 void cancel() { 108 cancelBuild_ = true; 109 } 110 maybePause()111 void maybePause() { 112 if (pauseBuild_ && *pauseBuild_) 113 PauseCurrentHelperThread(); 114 } setPauseFlag(mozilla::Atomic<bool,mozilla::Relaxed> * pauseBuild)115 void setPauseFlag(mozilla::Atomic<bool, mozilla::Relaxed>* pauseBuild) { 116 pauseBuild_ = pauseBuild; 117 } 118 disable()119 void disable() { 120 abortReason_ = AbortReason_Disable; 121 } abortReason()122 AbortReason abortReason() { 123 return abortReason_; 124 } 125 compilingAsmJS()126 bool compilingAsmJS() const { 127 return info_->compilingAsmJS(); 128 } 129 maxAsmJSStackArgBytes()130 uint32_t maxAsmJSStackArgBytes() const { 131 MOZ_ASSERT(compilingAsmJS()); 132 return maxAsmJSStackArgBytes_; 133 } resetAsmJSMaxStackArgBytes()134 uint32_t resetAsmJSMaxStackArgBytes() { 135 MOZ_ASSERT(compilingAsmJS()); 136 uint32_t old = maxAsmJSStackArgBytes_; 137 maxAsmJSStackArgBytes_ = 0; 138 return old; 139 } setAsmJSMaxStackArgBytes(uint32_t n)140 void setAsmJSMaxStackArgBytes(uint32_t n) { 141 MOZ_ASSERT(compilingAsmJS()); 142 maxAsmJSStackArgBytes_ = n; 143 } setPerformsCall()144 void setPerformsCall() { 145 performsCall_ = true; 146 } performsCall()147 bool performsCall() const { 148 return performsCall_; 149 } 150 // Traverses the graph to find if there's any SIMD instruction. Costful but 151 // the value is cached, so don't worry about calling it several times. 152 bool usesSimd(); 153 modifiesFrameArguments()154 bool modifiesFrameArguments() const { 155 return modifiesFrameArguments_; 156 } 157 158 typedef Vector<ObjectGroup*, 0, JitAllocPolicy> ObjectGroupVector; 159 160 // When abortReason() == AbortReason_PreliminaryObjects, all groups with 161 // preliminary objects which haven't been analyzed yet. abortedPreliminaryGroups()162 const ObjectGroupVector& abortedPreliminaryGroups() const { 163 return abortedPreliminaryGroups_; 164 } 165 166 public: 167 CompileCompartment* compartment; 168 169 protected: 170 const CompileInfo* info_; 171 const OptimizationInfo* optimizationInfo_; 172 TempAllocator* alloc_; 173 JSFunction* fun_; 174 uint32_t nslots_; 175 MIRGraph* graph_; 176 AbortReason abortReason_; 177 bool shouldForceAbort_; // Force AbortReason_Disable 178 ObjectGroupVector abortedPreliminaryGroups_; 179 bool error_; 180 mozilla::Atomic<bool, mozilla::Relaxed>* pauseBuild_; 181 mozilla::Atomic<bool, mozilla::Relaxed> cancelBuild_; 182 183 uint32_t maxAsmJSStackArgBytes_; 184 bool performsCall_; 185 bool usesSimd_; 186 bool usesSimdCached_; 187 188 // Keep track of whether frame arguments are modified during execution. 189 // RegAlloc needs to know this as spilling values back to their register 190 // slots is not compatible with that. 191 bool modifiesFrameArguments_; 192 193 bool instrumentedProfiling_; 194 bool instrumentedProfilingIsCached_; 195 bool safeForMinorGC_; 196 197 void addAbortedPreliminaryGroup(ObjectGroup* group); 198 199 #if defined(ASMJS_MAY_USE_SIGNAL_HANDLERS_FOR_OOB) 200 bool usesSignalHandlersForAsmJSOOB_; 201 #endif 202 setForceAbort()203 void setForceAbort() { 204 shouldForceAbort_ = true; 205 } shouldForceAbort()206 bool shouldForceAbort() { 207 return shouldForceAbort_; 208 } 209 210 #if defined(JS_ION_PERF) 211 AsmJSPerfSpewer asmJSPerfSpewer_; 212 213 public: perfSpewer()214 AsmJSPerfSpewer& perfSpewer() { return asmJSPerfSpewer_; } 215 #endif 216 217 public: 218 const JitCompileOptions options; 219 220 bool needsAsmJSBoundsCheckBranch(const MAsmJSHeapAccess* access) const; 221 size_t foldableOffsetRange(const MAsmJSHeapAccess* access) const; 222 223 private: 224 GraphSpewer gs_; 225 226 public: graphSpewer()227 GraphSpewer& graphSpewer() { 228 return gs_; 229 } 230 }; 231 232 } // namespace jit 233 } // namespace js 234 235 #endif /* jit_MIRGenerator_h */ 236