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_IonIC_h
8 : #define jit_IonIC_h
9 :
10 : #include "jit/CacheIR.h"
11 :
12 : namespace js {
13 : namespace jit {
14 :
15 : class CacheIRStubInfo;
16 :
17 : // An optimized stub attached to an IonIC.
18 : class IonICStub
19 : {
20 : // Code to jump to when this stub fails. This is either the next optimized
21 : // stub or the OOL fallback path.
22 : uint8_t* nextCodeRaw_;
23 :
24 : // The next optimized stub in this chain, or nullptr if this is the last
25 : // one.
26 : IonICStub* next_;
27 :
28 : // Info about this stub.
29 : CacheIRStubInfo* stubInfo_;
30 :
31 : public:
32 21 : IonICStub(uint8_t* fallbackCode, CacheIRStubInfo* stubInfo)
33 21 : : nextCodeRaw_(fallbackCode), next_(nullptr), stubInfo_(stubInfo)
34 21 : {}
35 :
36 0 : uint8_t* nextCodeRaw() const { return nextCodeRaw_; }
37 32 : uint8_t** nextCodeRawPtr() { return &nextCodeRaw_; }
38 16 : CacheIRStubInfo* stubInfo() const { return stubInfo_; }
39 38 : IonICStub* next() const { return next_; }
40 :
41 : uint8_t* stubDataStart();
42 :
43 6 : void setNext(IonICStub* next, JitCode* nextCode) {
44 6 : MOZ_ASSERT(!next_);
45 6 : MOZ_ASSERT(next && nextCode);
46 6 : next_ = next;
47 6 : nextCodeRaw_ = nextCode->raw();
48 6 : }
49 :
50 : // Null out pointers when we unlink stubs, to ensure we never use
51 : // discarded stubs.
52 6 : void poison() {
53 6 : nextCodeRaw_ = nullptr;
54 6 : next_ = nullptr;
55 6 : stubInfo_ = nullptr;
56 6 : }
57 : };
58 :
59 : class IonGetPropertyIC;
60 : class IonSetPropertyIC;
61 : class IonGetNameIC;
62 : class IonBindNameIC;
63 : class IonHasOwnIC;
64 : class IonInIC;
65 :
66 : class IonIC
67 : {
68 : // This either points at the OOL path for the fallback path, or the code for
69 : // the first stub.
70 : uint8_t* codeRaw_;
71 :
72 : // The first optimized stub, or nullptr.
73 : IonICStub* firstStub_;
74 :
75 : // The address stubs should jump to when done.
76 : CodeLocationLabel rejoinLabel_;
77 :
78 : // The OOL path that calls the IC's update function.
79 : CodeLocationLabel fallbackLabel_;
80 :
81 : // Location of this IC, nullptr for idempotent caches.
82 : JSScript* script_;
83 : jsbytecode* pc_;
84 :
85 : CacheKind kind_;
86 : bool idempotent_ : 1;
87 : ICState state_;
88 :
89 : protected:
90 35 : explicit IonIC(CacheKind kind)
91 35 : : codeRaw_(nullptr),
92 : firstStub_(nullptr),
93 : rejoinLabel_(),
94 : fallbackLabel_(),
95 : script_(nullptr),
96 : pc_(nullptr),
97 : kind_(kind),
98 : idempotent_(false),
99 35 : state_()
100 35 : {}
101 :
102 : void attachStub(IonICStub* newStub, JitCode* code);
103 :
104 : public:
105 32 : void setScriptedLocation(JSScript* script, jsbytecode* pc) {
106 32 : MOZ_ASSERT(!script_ && !pc_);
107 32 : MOZ_ASSERT(script && pc);
108 32 : script_ = script;
109 32 : pc_ = pc;
110 32 : }
111 :
112 1 : JSScript* script() const { MOZ_ASSERT(script_); return script_; }
113 36 : jsbytecode* pc() const { MOZ_ASSERT(pc_); return pc_; }
114 :
115 21 : CodeLocationLabel rejoinLabel() const { return rejoinLabel_; }
116 :
117 : // Discard all stubs.
118 : void discardStubs(Zone* zone);
119 :
120 : // Discard all stubs and reset the ICState.
121 : void reset(Zone* zone);
122 :
123 63 : ICState& state() {
124 63 : return state_;
125 : }
126 :
127 111 : CacheKind kind() const { return kind_; }
128 14 : uint8_t** codeRawPtr() { return &codeRaw_; }
129 :
130 80 : bool idempotent() const { return idempotent_; }
131 3 : void setIdempotent() { idempotent_ = true; }
132 :
133 35 : void setFallbackLabel(CodeOffset fallbackLabel) { fallbackLabel_ = fallbackLabel; }
134 35 : void setRejoinLabel(CodeOffset rejoinLabel) { rejoinLabel_ = rejoinLabel; }
135 :
136 148 : IonGetPropertyIC* asGetPropertyIC() {
137 148 : MOZ_ASSERT(kind_ == CacheKind::GetProp || kind_ == CacheKind::GetElem);
138 148 : return (IonGetPropertyIC*)this;
139 : }
140 12 : IonSetPropertyIC* asSetPropertyIC() {
141 12 : MOZ_ASSERT(kind_ == CacheKind::SetProp || kind_ == CacheKind::SetElem);
142 12 : return (IonSetPropertyIC*)this;
143 : }
144 8 : IonGetNameIC* asGetNameIC() {
145 8 : MOZ_ASSERT(kind_ == CacheKind::GetName);
146 8 : return (IonGetNameIC*)this;
147 : }
148 0 : IonBindNameIC* asBindNameIC() {
149 0 : MOZ_ASSERT(kind_ == CacheKind::BindName);
150 0 : return (IonBindNameIC*)this;
151 : }
152 0 : IonHasOwnIC* asHasOwnIC() {
153 0 : MOZ_ASSERT(kind_ == CacheKind::HasOwn);
154 0 : return (IonHasOwnIC*)this;
155 : }
156 7 : IonInIC* asInIC() {
157 7 : MOZ_ASSERT(kind_ == CacheKind::In);
158 7 : return (IonInIC*)this;
159 : }
160 :
161 : void updateBaseAddress(JitCode* code, MacroAssembler& masm);
162 :
163 : // Returns the Register to use as scratch when entering IC stubs. This
164 : // should either be an output register or a temp.
165 : Register scratchRegisterForEntryJump();
166 :
167 : void trace(JSTracer* trc);
168 :
169 : void attachCacheIRStub(JSContext* cx, const CacheIRWriter& writer, CacheKind kind,
170 : IonScript* ionScript, bool* attached,
171 : const PropertyTypeCheckInfo* typeCheckInfo = nullptr);
172 : };
173 :
174 23 : class IonGetPropertyIC : public IonIC
175 : {
176 : LiveRegisterSet liveRegs_;
177 :
178 : TypedOrValueRegister value_;
179 : ConstantOrRegister id_;
180 : TypedOrValueRegister output_;
181 : Register maybeTemp_; // Might be InvalidReg.
182 :
183 : bool monitoredResult_ : 1;
184 : bool allowDoubleResult_ : 1;
185 :
186 : public:
187 23 : IonGetPropertyIC(CacheKind kind, LiveRegisterSet liveRegs, TypedOrValueRegister value,
188 : const ConstantOrRegister& id, TypedOrValueRegister output, Register maybeTemp,
189 : bool monitoredResult, bool allowDoubleResult)
190 23 : : IonIC(kind),
191 : liveRegs_(liveRegs),
192 : value_(value),
193 : id_(id),
194 : output_(output),
195 : maybeTemp_(maybeTemp),
196 : monitoredResult_(monitoredResult),
197 23 : allowDoubleResult_(allowDoubleResult)
198 23 : { }
199 :
200 40 : bool monitoredResult() const { return monitoredResult_; }
201 43 : TypedOrValueRegister value() const { return value_; }
202 38 : ConstantOrRegister id() const { return id_; }
203 118 : TypedOrValueRegister output() const { return output_; }
204 73 : Register maybeTemp() const { return maybeTemp_; }
205 20 : LiveRegisterSet liveRegs() const { return liveRegs_; }
206 20 : bool allowDoubleResult() const { return allowDoubleResult_; }
207 :
208 : static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonGetPropertyIC* ic,
209 : HandleValue val, HandleValue idVal, MutableHandleValue res);
210 : };
211 :
212 6 : class IonSetPropertyIC : public IonIC
213 : {
214 : LiveRegisterSet liveRegs_;
215 :
216 : Register object_;
217 : Register temp_;
218 : FloatRegister maybeTempDouble_;
219 : FloatRegister maybeTempFloat32_;
220 : ConstantOrRegister id_;
221 : ConstantOrRegister rhs_;
222 : bool strict_ : 1;
223 : bool needsPostBarrier_ : 1;
224 : bool needsTypeBarrier_ : 1;
225 : bool guardHoles_ : 1;
226 :
227 : public:
228 6 : IonSetPropertyIC(CacheKind kind, LiveRegisterSet liveRegs, Register object, Register temp,
229 : FloatRegister maybeTempDouble, FloatRegister maybeTempFloat32,
230 : const ConstantOrRegister& id, const ConstantOrRegister& rhs, bool strict,
231 : bool needsPostBarrier, bool needsTypeBarrier, bool guardHoles)
232 6 : : IonIC(kind),
233 : liveRegs_(liveRegs),
234 : object_(object),
235 : temp_(temp),
236 : maybeTempDouble_(maybeTempDouble),
237 : maybeTempFloat32_(maybeTempFloat32),
238 : id_(id),
239 : rhs_(rhs),
240 : strict_(strict),
241 : needsPostBarrier_(needsPostBarrier),
242 : needsTypeBarrier_(needsTypeBarrier),
243 6 : guardHoles_(guardHoles)
244 6 : { }
245 :
246 0 : LiveRegisterSet liveRegs() const { return liveRegs_; }
247 6 : Register object() const { return object_; }
248 6 : ConstantOrRegister id() const { return id_; }
249 6 : ConstantOrRegister rhs() const { return rhs_; }
250 :
251 6 : Register temp() const { return temp_; }
252 0 : FloatRegister maybeTempDouble() const { return maybeTempDouble_; }
253 0 : FloatRegister maybeTempFloat32() const { return maybeTempFloat32_; }
254 :
255 0 : bool strict() const { return strict_; }
256 0 : bool needsPostBarrier() const { return needsPostBarrier_; }
257 0 : bool needsTypeBarrier() const { return needsTypeBarrier_; }
258 0 : bool guardHoles() const { return guardHoles_; }
259 :
260 : static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonSetPropertyIC* ic,
261 : HandleObject obj, HandleValue idVal, HandleValue rhs);
262 : };
263 :
264 4 : class IonGetNameIC : public IonIC
265 : {
266 : LiveRegisterSet liveRegs_;
267 :
268 : Register environment_;
269 : ValueOperand output_;
270 : Register temp_;
271 :
272 : public:
273 4 : IonGetNameIC(LiveRegisterSet liveRegs, Register environment, ValueOperand output,
274 : Register temp)
275 4 : : IonIC(CacheKind::GetName),
276 : liveRegs_(liveRegs),
277 : environment_(environment),
278 : output_(output),
279 4 : temp_(temp)
280 4 : { }
281 :
282 4 : Register environment() const { return environment_; }
283 8 : ValueOperand output() const { return output_; }
284 4 : Register temp() const { return temp_; }
285 0 : LiveRegisterSet liveRegs() const { return liveRegs_; }
286 :
287 : static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonGetNameIC* ic,
288 : HandleObject envChain, MutableHandleValue res);
289 : };
290 :
291 0 : class IonBindNameIC : public IonIC
292 : {
293 : LiveRegisterSet liveRegs_;
294 :
295 : Register environment_;
296 : Register output_;
297 : Register temp_;
298 :
299 : public:
300 0 : IonBindNameIC(LiveRegisterSet liveRegs, Register environment, Register output, Register temp)
301 0 : : IonIC(CacheKind::BindName),
302 : liveRegs_(liveRegs),
303 : environment_(environment),
304 : output_(output),
305 0 : temp_(temp)
306 0 : { }
307 :
308 0 : Register environment() const { return environment_; }
309 0 : Register output() const { return output_; }
310 0 : Register temp() const { return temp_; }
311 0 : LiveRegisterSet liveRegs() const { return liveRegs_; }
312 :
313 : static JSObject* update(JSContext* cx, HandleScript outerScript, IonBindNameIC* ic,
314 : HandleObject envChain);
315 : };
316 :
317 0 : class IonHasOwnIC : public IonIC
318 : {
319 : LiveRegisterSet liveRegs_;
320 :
321 : TypedOrValueRegister value_;
322 : TypedOrValueRegister id_;
323 : Register output_;
324 :
325 : public:
326 0 : IonHasOwnIC(LiveRegisterSet liveRegs, TypedOrValueRegister value,
327 : TypedOrValueRegister id, Register output)
328 0 : : IonIC(CacheKind::HasOwn),
329 : liveRegs_(liveRegs),
330 : value_(value),
331 : id_(id),
332 0 : output_(output)
333 0 : { }
334 :
335 0 : TypedOrValueRegister value() const { return value_; }
336 0 : TypedOrValueRegister id() const { return id_; }
337 0 : Register output() const { return output_; }
338 0 : LiveRegisterSet liveRegs() const { return liveRegs_; }
339 :
340 : static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonHasOwnIC* ic,
341 : HandleValue val, HandleValue idVal, int32_t* res);
342 : };
343 :
344 2 : class IonInIC : public IonIC
345 : {
346 : LiveRegisterSet liveRegs_;
347 :
348 : ConstantOrRegister key_;
349 : Register object_;
350 : Register output_;
351 : Register temp_;
352 :
353 : public:
354 2 : IonInIC(LiveRegisterSet liveRegs, const ConstantOrRegister& key,
355 : Register object, Register output, Register temp)
356 2 : : IonIC(CacheKind::In),
357 : liveRegs_(liveRegs),
358 : key_(key),
359 : object_(object),
360 : output_(output),
361 2 : temp_(temp)
362 2 : { }
363 :
364 3 : ConstantOrRegister key() const { return key_; }
365 3 : Register object() const { return object_; }
366 5 : Register output() const { return output_; }
367 4 : Register temp() const { return temp_; }
368 1 : LiveRegisterSet liveRegs() const { return liveRegs_; }
369 :
370 : static MOZ_MUST_USE bool update(JSContext* cx, HandleScript outerScript, IonInIC* ic,
371 : HandleValue key, HandleObject obj, bool* res);
372 : };
373 :
374 : } // namespace jit
375 : } // namespace js
376 :
377 : #endif /* jit_IonIC_h */
|