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_Ion_h
8 : #define jit_Ion_h
9 :
10 : #include "mozilla/MemoryReporting.h"
11 : #include "mozilla/Result.h"
12 :
13 : #include "jscntxt.h"
14 : #include "jscompartment.h"
15 :
16 : #include "jit/CompileWrappers.h"
17 : #include "jit/JitOptions.h"
18 :
19 : namespace js {
20 : namespace jit {
21 :
22 : class TempAllocator;
23 :
24 : enum MethodStatus
25 : {
26 : Method_Error,
27 : Method_CantCompile,
28 : Method_Skipped,
29 : Method_Compiled
30 : };
31 :
32 : enum class AbortReason : uint8_t {
33 : Alloc,
34 : Inlining,
35 : PreliminaryObjects,
36 : Disable,
37 : Error,
38 : NoAbort
39 : };
40 :
41 : template <typename V>
42 : using AbortReasonOr = mozilla::Result<V, AbortReason>;
43 : using mozilla::Err;
44 : using mozilla::Ok;
45 :
46 : static_assert(sizeof(AbortReasonOr<Ok>) <= sizeof(uintptr_t),
47 : "Unexpected size of AbortReasonOr<Ok>");
48 : static_assert(sizeof(AbortReasonOr<bool>) <= sizeof(uintptr_t),
49 : "Unexpected size of AbortReasonOr<bool>");
50 :
51 : // A JIT context is needed to enter into either an JIT method or an instance
52 : // of a JIT compiler. It points to a temporary allocator and the active
53 : // JSContext, either of which may be nullptr, and the active compartment, which
54 : // will not be nullptr.
55 :
56 : class JitContext
57 : {
58 : public:
59 : JitContext(JSContext* cx, TempAllocator* temp);
60 : JitContext(CompileRuntime* rt, CompileCompartment* comp, TempAllocator* temp);
61 : JitContext(CompileRuntime* rt, TempAllocator* temp);
62 : explicit JitContext(CompileRuntime* rt);
63 : explicit JitContext(TempAllocator* temp);
64 : JitContext();
65 : ~JitContext();
66 :
67 : // Running context when executing on the active thread. Not available during
68 : // compilation.
69 : JSContext* cx;
70 :
71 : // Allocator for temporary memory during compilation.
72 : TempAllocator* temp;
73 :
74 : // Wrappers with information about the current runtime/compartment for use
75 : // during compilation.
76 : CompileRuntime* runtime;
77 : CompileCompartment* compartment;
78 :
79 8 : bool hasProfilingScripts() const {
80 8 : return runtime && !!runtime->profilingScripts();
81 : }
82 :
83 : int getNextAssemblerId() {
84 : return assemblerCount_++;
85 : }
86 : private:
87 : JitContext* prev_;
88 : int assemblerCount_;
89 : };
90 :
91 : // Initialize Ion statically for all JSRuntimes.
92 : MOZ_MUST_USE bool InitializeIon();
93 :
94 : // Get and set the current JIT context.
95 : JitContext* GetJitContext();
96 : JitContext* MaybeGetJitContext();
97 :
98 : void SetJitContext(JitContext* ctx);
99 :
100 : bool CanIonCompileScript(JSContext* cx, JSScript* script, bool osr);
101 :
102 : MOZ_MUST_USE bool IonCompileScriptForBaseline(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
103 :
104 : MethodStatus CanEnter(JSContext* cx, RunState& state);
105 : MethodStatus CanEnterUsingFastInvoke(JSContext* cx, HandleScript script, uint32_t numActualArgs);
106 :
107 : MethodStatus
108 : Recompile(JSContext* cx, HandleScript script, BaselineFrame* osrFrame, jsbytecode* osrPc,
109 : bool force);
110 :
111 : enum JitExecStatus
112 : {
113 : // The method call had to be aborted due to a stack limit check. This
114 : // error indicates that Ion never attempted to clean up frames.
115 : JitExec_Aborted,
116 :
117 : // The method call resulted in an error, and IonMonkey has cleaned up
118 : // frames.
119 : JitExec_Error,
120 :
121 : // The method call succeeded and returned a value.
122 : JitExec_Ok
123 : };
124 :
125 : static inline bool
126 7532 : IsErrorStatus(JitExecStatus status)
127 : {
128 7532 : return status == JitExec_Error || status == JitExec_Aborted;
129 : }
130 :
131 : struct EnterJitData;
132 :
133 : MOZ_MUST_USE bool SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state,
134 : MutableHandle<GCVector<Value>> vals);
135 :
136 : JitExecStatus IonCannon(JSContext* cx, RunState& state);
137 :
138 : // Used to enter Ion from C++ natives like Array.map. Called from FastInvokeGuard.
139 : JitExecStatus FastInvoke(JSContext* cx, HandleFunction fun, CallArgs& args);
140 :
141 : // Walk the stack and invalidate active Ion frames for the invalid scripts.
142 : void Invalidate(TypeZone& types, FreeOp* fop,
143 : const RecompileInfoVector& invalid, bool resetUses = true,
144 : bool cancelOffThread = true);
145 : void Invalidate(JSContext* cx, const RecompileInfoVector& invalid, bool resetUses = true,
146 : bool cancelOffThread = true);
147 : void Invalidate(JSContext* cx, JSScript* script, bool resetUses = true,
148 : bool cancelOffThread = true);
149 :
150 : class IonBuilder;
151 : class MIRGenerator;
152 : class LIRGraph;
153 : class CodeGenerator;
154 :
155 : MOZ_MUST_USE bool OptimizeMIR(MIRGenerator* mir);
156 : LIRGraph* GenerateLIR(MIRGenerator* mir);
157 : CodeGenerator* GenerateCode(MIRGenerator* mir, LIRGraph* lir);
158 : CodeGenerator* CompileBackEnd(MIRGenerator* mir);
159 :
160 : void AttachFinishedCompilations(ZoneGroup* group, JSContext* maybecx);
161 : void FinishOffThreadBuilder(JSRuntime* runtime, IonBuilder* builder,
162 : const AutoLockHelperThreadState& lock);
163 : void FreeIonBuilder(IonBuilder* builder);
164 :
165 : void LinkIonScript(JSContext* cx, HandleScript calleescript);
166 : uint8_t* LazyLinkTopActivation();
167 :
168 : static inline bool
169 61945 : IsIonEnabled(JSContext* cx)
170 : {
171 : // The ARM64 Ion engine is not yet implemented.
172 : #if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
173 : return false;
174 : #else
175 123890 : return cx->options().ion() &&
176 123890 : cx->options().baseline() &&
177 123890 : cx->runtime()->jitSupportsFloatingPoint;
178 : #endif
179 : }
180 :
181 : inline bool
182 37 : IsIonInlinablePC(jsbytecode* pc) {
183 : // CALL, FUNCALL, FUNAPPLY, EVAL, NEW (Normal Callsites)
184 : // GETPROP, CALLPROP, and LENGTH. (Inlined Getters)
185 : // SETPROP, SETNAME, SETGNAME (Inlined Setters)
186 74 : return (IsCallPC(pc) && !IsSpreadCallPC(pc)) ||
187 37 : IsGetPropPC(pc) ||
188 37 : IsSetPropPC(pc);
189 : }
190 :
191 : inline bool
192 38322 : TooManyActualArguments(unsigned nargs)
193 : {
194 38322 : return nargs > JitOptions.maxStackArgs;
195 : }
196 :
197 : inline bool
198 19206 : TooManyFormalArguments(unsigned nargs)
199 : {
200 19206 : return nargs >= SNAPSHOT_MAX_NARGS || TooManyActualArguments(nargs);
201 : }
202 :
203 : inline size_t
204 16119 : NumLocalsAndArgs(JSScript* script)
205 : {
206 16119 : size_t num = 1 /* this */ + script->nfixed();
207 16119 : if (JSFunction* fun = script->functionNonDelazifying())
208 16097 : num += fun->nargs();
209 16119 : return num;
210 : }
211 :
212 : bool OffThreadCompilationAvailable(JSContext* cx);
213 :
214 : void ForbidCompilation(JSContext* cx, JSScript* script);
215 :
216 : size_t SizeOfIonData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf);
217 : void DestroyJitScripts(FreeOp* fop, JSScript* script);
218 : void TraceJitScripts(JSTracer* trc, JSScript* script);
219 :
220 : bool JitSupportsFloatingPoint();
221 : bool JitSupportsUnalignedAccesses();
222 : bool JitSupportsSimd();
223 : bool JitSupportsAtomics();
224 :
225 : } // namespace jit
226 : } // namespace js
227 :
228 : #endif /* jit_Ion_h */
|