|
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_Ion_h |
|
8 #define jit_Ion_h |
|
9 |
|
10 #ifdef JS_ION |
|
11 |
|
12 #include "mozilla/MemoryReporting.h" |
|
13 |
|
14 #include "jscntxt.h" |
|
15 #include "jscompartment.h" |
|
16 |
|
17 #include "jit/CompileInfo.h" |
|
18 #include "jit/CompileWrappers.h" |
|
19 #include "jit/JitOptions.h" |
|
20 |
|
21 namespace js { |
|
22 namespace jit { |
|
23 |
|
24 class TempAllocator; |
|
25 |
|
26 enum MethodStatus |
|
27 { |
|
28 Method_Error, |
|
29 Method_CantCompile, |
|
30 Method_Skipped, |
|
31 Method_Compiled |
|
32 }; |
|
33 |
|
34 enum AbortReason { |
|
35 AbortReason_Alloc, |
|
36 AbortReason_Inlining, |
|
37 AbortReason_Disable, |
|
38 AbortReason_Error, |
|
39 AbortReason_NoAbort |
|
40 }; |
|
41 |
|
42 // An Ion context is needed to enter into either an Ion method or an instance |
|
43 // of the Ion compiler. It points to a temporary allocator and the active |
|
44 // JSContext, either of which may be nullptr, and the active compartment, which |
|
45 // will not be nullptr. |
|
46 |
|
47 class IonContext |
|
48 { |
|
49 public: |
|
50 IonContext(JSContext *cx, TempAllocator *temp); |
|
51 IonContext(ExclusiveContext *cx, TempAllocator *temp); |
|
52 IonContext(CompileRuntime *rt, CompileCompartment *comp, TempAllocator *temp); |
|
53 IonContext(CompileRuntime *rt); |
|
54 ~IonContext(); |
|
55 |
|
56 // Running context when executing on the main thread. Not available during |
|
57 // compilation. |
|
58 JSContext *cx; |
|
59 |
|
60 // Allocator for temporary memory during compilation. |
|
61 TempAllocator *temp; |
|
62 |
|
63 // Wrappers with information about the current runtime/compartment for use |
|
64 // during compilation. |
|
65 CompileRuntime *runtime; |
|
66 CompileCompartment *compartment; |
|
67 |
|
68 int getNextAssemblerId() { |
|
69 return assemblerCount_++; |
|
70 } |
|
71 private: |
|
72 IonContext *prev_; |
|
73 int assemblerCount_; |
|
74 }; |
|
75 |
|
76 // Initialize Ion statically for all JSRuntimes. |
|
77 bool InitializeIon(); |
|
78 |
|
79 // Get and set the current Ion context. |
|
80 IonContext *GetIonContext(); |
|
81 IonContext *MaybeGetIonContext(); |
|
82 |
|
83 void SetIonContext(IonContext *ctx); |
|
84 |
|
85 bool CanIonCompileScript(JSContext *cx, JSScript *script, bool osr); |
|
86 |
|
87 MethodStatus CanEnterAtBranch(JSContext *cx, JSScript *script, |
|
88 BaselineFrame *frame, jsbytecode *pc, bool isConstructing); |
|
89 MethodStatus CanEnter(JSContext *cx, RunState &state); |
|
90 MethodStatus CompileFunctionForBaseline(JSContext *cx, HandleScript script, BaselineFrame *frame, |
|
91 bool isConstructing); |
|
92 MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs); |
|
93 |
|
94 MethodStatus CanEnterInParallel(JSContext *cx, HandleScript script); |
|
95 |
|
96 MethodStatus |
|
97 Recompile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc, |
|
98 bool constructing); |
|
99 |
|
100 enum IonExecStatus |
|
101 { |
|
102 // The method call had to be aborted due to a stack limit check. This |
|
103 // error indicates that Ion never attempted to clean up frames. |
|
104 IonExec_Aborted, |
|
105 |
|
106 // The method call resulted in an error, and IonMonkey has cleaned up |
|
107 // frames. |
|
108 IonExec_Error, |
|
109 |
|
110 // The method call succeeed and returned a value. |
|
111 IonExec_Ok |
|
112 }; |
|
113 |
|
114 static inline bool |
|
115 IsErrorStatus(IonExecStatus status) |
|
116 { |
|
117 return status == IonExec_Error || status == IonExec_Aborted; |
|
118 } |
|
119 |
|
120 struct EnterJitData; |
|
121 |
|
122 bool SetEnterJitData(JSContext *cx, EnterJitData &data, RunState &state, AutoValueVector &vals); |
|
123 |
|
124 IonExecStatus IonCannon(JSContext *cx, RunState &state); |
|
125 |
|
126 // Used to enter Ion from C++ natives like Array.map. Called from FastInvokeGuard. |
|
127 IonExecStatus FastInvoke(JSContext *cx, HandleFunction fun, CallArgs &args); |
|
128 |
|
129 // Walk the stack and invalidate active Ion frames for the invalid scripts. |
|
130 void Invalidate(types::TypeZone &types, FreeOp *fop, |
|
131 const Vector<types::RecompileInfo> &invalid, bool resetUses = true, |
|
132 bool cancelOffThread = true); |
|
133 void Invalidate(JSContext *cx, const Vector<types::RecompileInfo> &invalid, bool resetUses = true, |
|
134 bool cancelOffThread = true); |
|
135 bool Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses = true, |
|
136 bool cancelOffThread = true); |
|
137 bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true, |
|
138 bool cancelOffThread = true); |
|
139 |
|
140 void MarkValueFromIon(JSRuntime *rt, Value *vp); |
|
141 void MarkShapeFromIon(JSRuntime *rt, Shape **shapep); |
|
142 |
|
143 void ToggleBarriers(JS::Zone *zone, bool needs); |
|
144 |
|
145 class IonBuilder; |
|
146 class MIRGenerator; |
|
147 class LIRGraph; |
|
148 class CodeGenerator; |
|
149 |
|
150 bool OptimizeMIR(MIRGenerator *mir); |
|
151 LIRGraph *GenerateLIR(MIRGenerator *mir); |
|
152 CodeGenerator *GenerateCode(MIRGenerator *mir, LIRGraph *lir); |
|
153 CodeGenerator *CompileBackEnd(MIRGenerator *mir); |
|
154 |
|
155 void AttachFinishedCompilations(JSContext *cx); |
|
156 void FinishOffThreadBuilder(IonBuilder *builder); |
|
157 void StopAllOffThreadCompilations(JSCompartment *comp); |
|
158 |
|
159 static inline bool |
|
160 IsIonEnabled(JSContext *cx) |
|
161 { |
|
162 return cx->runtime()->options().ion() && |
|
163 cx->runtime()->options().baseline() && |
|
164 cx->runtime()->jitSupportsFloatingPoint; |
|
165 } |
|
166 |
|
167 inline bool |
|
168 IsIonInlinablePC(jsbytecode *pc) { |
|
169 // CALL, FUNCALL, FUNAPPLY, EVAL, NEW (Normal Callsites) |
|
170 // GETPROP, CALLPROP, and LENGTH. (Inlined Getters) |
|
171 // SETPROP, SETNAME, SETGNAME (Inlined Setters) |
|
172 return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(pc); |
|
173 } |
|
174 |
|
175 inline bool |
|
176 TooManyArguments(unsigned nargs) |
|
177 { |
|
178 return nargs >= SNAPSHOT_MAX_NARGS || nargs > js_JitOptions.maxStackArgs; |
|
179 } |
|
180 |
|
181 void ForbidCompilation(JSContext *cx, JSScript *script); |
|
182 void ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode); |
|
183 |
|
184 void PurgeCaches(JSScript *script); |
|
185 size_t SizeOfIonData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf); |
|
186 void DestroyIonScripts(FreeOp *fop, JSScript *script); |
|
187 void TraceIonScripts(JSTracer* trc, JSScript *script); |
|
188 |
|
189 void RequestInterruptForIonCode(JSRuntime *rt, JSRuntime::InterruptMode mode); |
|
190 |
|
191 bool RematerializeAllFrames(JSContext *cx, JSCompartment *comp); |
|
192 bool UpdateForDebugMode(JSContext *maybecx, JSCompartment *comp, |
|
193 AutoDebugModeInvalidation &invalidate); |
|
194 |
|
195 } // namespace jit |
|
196 } // namespace js |
|
197 |
|
198 #endif // JS_ION |
|
199 |
|
200 #endif /* jit_Ion_h */ |