1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: set ts=8 sts=2 et sw=2 tw=80:
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/. */
10 #include "jit/CacheIR.h"
15 class CacheIRStubInfo
;
17 // An optimized stub attached to an IonIC.
19 // Code to jump to when this stub fails. This is either the next optimized
20 // stub or the OOL fallback path.
21 uint8_t* nextCodeRaw_
;
23 // The next optimized stub in this chain, or nullptr if this is the last
27 // Info about this stub.
28 CacheIRStubInfo
* stubInfo_
;
31 IonICStub(uint8_t* fallbackCode
, CacheIRStubInfo
* stubInfo
)
32 : nextCodeRaw_(fallbackCode
), next_(nullptr), stubInfo_(stubInfo
) {}
34 uint8_t* nextCodeRaw() const { return nextCodeRaw_
; }
35 uint8_t** nextCodeRawPtr() { return &nextCodeRaw_
; }
36 CacheIRStubInfo
* stubInfo() const { return stubInfo_
; }
37 IonICStub
* next() const { return next_
; }
39 uint8_t* stubDataStart();
41 void setNext(IonICStub
* next
, uint8_t* nextCodeRaw
) {
43 MOZ_ASSERT(next
&& nextCodeRaw
);
45 nextCodeRaw_
= nextCodeRaw
;
48 // Null out pointers when we unlink stubs, to ensure we never use
51 nextCodeRaw_
= nullptr;
57 class IonGetPropertyIC
;
58 class IonSetPropertyIC
;
59 class IonGetPropSuperIC
;
62 class IonGetIteratorIC
;
64 class IonCheckPrivateFieldIC
;
66 class IonInstanceOfIC
;
68 class IonUnaryArithIC
;
69 class IonBinaryArithIC
;
70 class IonToPropertyKeyIC
;
73 // This either points at the OOL path for the fallback path, or the code for
77 // The first optimized stub, or nullptr.
78 IonICStub
* firstStub_
;
80 // Location of this IC, nullptr for idempotent caches.
84 // The offset of the rejoin location in the IonScript's code (stubs jump to
86 uint32_t rejoinOffset_
;
88 // The offset of the OOL path in the IonScript's code that calls the IC's
90 uint32_t fallbackOffset_
;
97 explicit IonIC(CacheKind kind
)
108 void attachStub(IonICStub
* newStub
, JitCode
* code
);
111 void setScriptedLocation(JSScript
* script
, jsbytecode
* pc
) {
112 MOZ_ASSERT(!script_
&& !pc_
);
113 MOZ_ASSERT(script
&& pc
);
118 JSScript
* script() const {
122 jsbytecode
* pc() const {
127 // Discard all stubs.
128 void discardStubs(Zone
* zone
, IonScript
* ionScript
);
130 // Discard all stubs and reset the ICState.
131 void reset(Zone
* zone
, IonScript
* ionScript
);
133 ICState
& state() { return state_
; }
135 CacheKind
kind() const { return kind_
; }
136 uint8_t** codeRawPtr() { return &codeRaw_
; }
138 bool idempotent() const { return idempotent_
; }
139 void setIdempotent() { idempotent_
= true; }
141 void setFallbackOffset(CodeOffset offset
) {
142 fallbackOffset_
= offset
.offset();
144 void setRejoinOffset(CodeOffset offset
) { rejoinOffset_
= offset
.offset(); }
146 void resetCodeRaw(IonScript
* ionScript
);
148 uint8_t* fallbackAddr(IonScript
* ionScript
) const;
149 uint8_t* rejoinAddr(IonScript
* ionScript
) const;
151 IonGetPropertyIC
* asGetPropertyIC() {
152 MOZ_ASSERT(kind_
== CacheKind::GetProp
|| kind_
== CacheKind::GetElem
);
153 return (IonGetPropertyIC
*)this;
155 IonSetPropertyIC
* asSetPropertyIC() {
156 MOZ_ASSERT(kind_
== CacheKind::SetProp
|| kind_
== CacheKind::SetElem
);
157 return (IonSetPropertyIC
*)this;
159 IonGetPropSuperIC
* asGetPropSuperIC() {
160 MOZ_ASSERT(kind_
== CacheKind::GetPropSuper
||
161 kind_
== CacheKind::GetElemSuper
);
162 return (IonGetPropSuperIC
*)this;
164 IonGetNameIC
* asGetNameIC() {
165 MOZ_ASSERT(kind_
== CacheKind::GetName
);
166 return (IonGetNameIC
*)this;
168 IonBindNameIC
* asBindNameIC() {
169 MOZ_ASSERT(kind_
== CacheKind::BindName
);
170 return (IonBindNameIC
*)this;
172 IonGetIteratorIC
* asGetIteratorIC() {
173 MOZ_ASSERT(kind_
== CacheKind::GetIterator
);
174 return (IonGetIteratorIC
*)this;
176 IonHasOwnIC
* asHasOwnIC() {
177 MOZ_ASSERT(kind_
== CacheKind::HasOwn
);
178 return (IonHasOwnIC
*)this;
180 IonCheckPrivateFieldIC
* asCheckPrivateFieldIC() {
181 MOZ_ASSERT(kind_
== CacheKind::CheckPrivateField
);
182 return (IonCheckPrivateFieldIC
*)this;
185 MOZ_ASSERT(kind_
== CacheKind::In
);
186 return (IonInIC
*)this;
188 IonInstanceOfIC
* asInstanceOfIC() {
189 MOZ_ASSERT(kind_
== CacheKind::InstanceOf
);
190 return (IonInstanceOfIC
*)this;
192 IonCompareIC
* asCompareIC() {
193 MOZ_ASSERT(kind_
== CacheKind::Compare
);
194 return (IonCompareIC
*)this;
196 IonUnaryArithIC
* asUnaryArithIC() {
197 MOZ_ASSERT(kind_
== CacheKind::UnaryArith
);
198 return (IonUnaryArithIC
*)this;
200 IonBinaryArithIC
* asBinaryArithIC() {
201 MOZ_ASSERT(kind_
== CacheKind::BinaryArith
);
202 return (IonBinaryArithIC
*)this;
204 IonToPropertyKeyIC
* asToPropertyKeyIC() {
205 MOZ_ASSERT(kind_
== CacheKind::ToPropertyKey
);
206 return (IonToPropertyKeyIC
*)this;
209 // Returns the Register to use as scratch when entering IC stubs. This
210 // should either be an output register or a temp.
211 Register
scratchRegisterForEntryJump();
213 void trace(JSTracer
* trc
, IonScript
* ionScript
);
215 void attachCacheIRStub(JSContext
* cx
, const CacheIRWriter
& writer
,
216 CacheKind kind
, IonScript
* ionScript
, bool* attached
,
217 const PropertyTypeCheckInfo
* typeCheckInfo
= nullptr);
220 class IonGetPropertyIC
: public IonIC
{
222 LiveRegisterSet liveRegs_
;
224 TypedOrValueRegister value_
;
225 ConstantOrRegister id_
;
226 TypedOrValueRegister output_
;
227 Register maybeTemp_
; // Might be InvalidReg.
229 GetPropertyResultFlags resultFlags_
;
232 IonGetPropertyIC(CacheKind kind
, LiveRegisterSet liveRegs
,
233 TypedOrValueRegister value
, const ConstantOrRegister
& id
,
234 TypedOrValueRegister output
, Register maybeTemp
,
235 GetPropertyResultFlags resultFlags
)
241 maybeTemp_(maybeTemp
),
242 resultFlags_(resultFlags
) {}
244 TypedOrValueRegister
value() const { return value_
; }
245 ConstantOrRegister
id() const { return id_
; }
246 TypedOrValueRegister
output() const { return output_
; }
247 Register
maybeTemp() const { return maybeTemp_
; }
248 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
249 GetPropertyResultFlags
resultFlags() const { return resultFlags_
; }
250 bool monitoredResult() const {
251 return resultFlags_
& GetPropertyResultFlags::Monitored
;
253 bool allowDoubleResult() const {
254 return resultFlags_
& GetPropertyResultFlags::AllowDouble
;
257 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
258 IonGetPropertyIC
* ic
, HandleValue val
,
259 HandleValue idVal
, MutableHandleValue res
);
262 class IonGetPropSuperIC
: public IonIC
{
263 LiveRegisterSet liveRegs_
;
266 TypedOrValueRegister receiver_
;
267 ConstantOrRegister id_
;
268 TypedOrValueRegister output_
;
271 IonGetPropSuperIC(CacheKind kind
, LiveRegisterSet liveRegs
, Register object
,
272 TypedOrValueRegister receiver
, const ConstantOrRegister
& id
,
273 TypedOrValueRegister output
)
281 Register
object() const { return object_
; }
282 TypedOrValueRegister
receiver() const { return receiver_
; }
283 ConstantOrRegister
id() const { return id_
; }
284 TypedOrValueRegister
output() const { return output_
; }
285 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
287 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
288 IonGetPropSuperIC
* ic
, HandleObject obj
,
289 HandleValue receiver
, HandleValue idVal
,
290 MutableHandleValue res
);
293 class IonSetPropertyIC
: public IonIC
{
294 LiveRegisterSet liveRegs_
;
298 ConstantOrRegister id_
;
299 ConstantOrRegister rhs_
;
301 bool needsPostBarrier_
: 1;
302 bool needsTypeBarrier_
: 1;
303 bool guardHoles_
: 1;
306 IonSetPropertyIC(CacheKind kind
, LiveRegisterSet liveRegs
, Register object
,
307 Register temp
, const ConstantOrRegister
& id
,
308 const ConstantOrRegister
& rhs
, bool strict
,
309 bool needsPostBarrier
, bool needsTypeBarrier
,
318 needsPostBarrier_(needsPostBarrier
),
319 needsTypeBarrier_(needsTypeBarrier
),
320 guardHoles_(guardHoles
) {}
322 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
323 Register
object() const { return object_
; }
324 ConstantOrRegister
id() const { return id_
; }
325 ConstantOrRegister
rhs() const { return rhs_
; }
327 Register
temp() const { return temp_
; }
329 bool strict() const { return strict_
; }
330 bool needsPostBarrier() const { return needsPostBarrier_
; }
331 bool needsTypeBarrier() const { return needsTypeBarrier_
; }
332 bool guardHoles() const { return guardHoles_
; }
334 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
335 IonSetPropertyIC
* ic
, HandleObject obj
,
336 HandleValue idVal
, HandleValue rhs
);
339 class IonGetNameIC
: public IonIC
{
340 LiveRegisterSet liveRegs_
;
342 Register environment_
;
343 ValueOperand output_
;
347 IonGetNameIC(LiveRegisterSet liveRegs
, Register environment
,
348 ValueOperand output
, Register temp
)
349 : IonIC(CacheKind::GetName
),
351 environment_(environment
),
355 Register
environment() const { return environment_
; }
356 ValueOperand
output() const { return output_
; }
357 Register
temp() const { return temp_
; }
358 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
360 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
361 IonGetNameIC
* ic
, HandleObject envChain
,
362 MutableHandleValue res
);
365 class IonBindNameIC
: public IonIC
{
366 LiveRegisterSet liveRegs_
;
368 Register environment_
;
373 IonBindNameIC(LiveRegisterSet liveRegs
, Register environment
, Register output
,
375 : IonIC(CacheKind::BindName
),
377 environment_(environment
),
381 Register
environment() const { return environment_
; }
382 Register
output() const { return output_
; }
383 Register
temp() const { return temp_
; }
384 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
386 static JSObject
* update(JSContext
* cx
, HandleScript outerScript
,
387 IonBindNameIC
* ic
, HandleObject envChain
);
390 class IonGetIteratorIC
: public IonIC
{
391 LiveRegisterSet liveRegs_
;
392 TypedOrValueRegister value_
;
398 IonGetIteratorIC(LiveRegisterSet liveRegs
, TypedOrValueRegister value
,
399 Register output
, Register temp1
, Register temp2
)
400 : IonIC(CacheKind::GetIterator
),
407 TypedOrValueRegister
value() const { return value_
; }
408 Register
output() const { return output_
; }
409 Register
temp1() const { return temp1_
; }
410 Register
temp2() const { return temp2_
; }
411 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
413 static JSObject
* update(JSContext
* cx
, HandleScript outerScript
,
414 IonGetIteratorIC
* ic
, HandleValue value
);
417 class IonHasOwnIC
: public IonIC
{
418 LiveRegisterSet liveRegs_
;
420 TypedOrValueRegister value_
;
421 TypedOrValueRegister id_
;
425 IonHasOwnIC(LiveRegisterSet liveRegs
, TypedOrValueRegister value
,
426 TypedOrValueRegister id
, Register output
)
427 : IonIC(CacheKind::HasOwn
),
433 TypedOrValueRegister
value() const { return value_
; }
434 TypedOrValueRegister
id() const { return id_
; }
435 Register
output() const { return output_
; }
436 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
438 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
439 IonHasOwnIC
* ic
, HandleValue val
,
440 HandleValue idVal
, int32_t* res
);
443 class IonCheckPrivateFieldIC
: public IonIC
{
444 LiveRegisterSet liveRegs_
;
446 TypedOrValueRegister value_
;
447 TypedOrValueRegister id_
;
451 IonCheckPrivateFieldIC(LiveRegisterSet liveRegs
, TypedOrValueRegister value
,
452 TypedOrValueRegister id
, Register output
)
453 : IonIC(CacheKind::CheckPrivateField
),
459 TypedOrValueRegister
value() const { return value_
; }
460 TypedOrValueRegister
id() const { return id_
; }
461 Register
output() const { return output_
; }
462 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
464 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
465 IonCheckPrivateFieldIC
* ic
, HandleValue val
,
466 HandleValue idVal
, bool* res
);
469 class IonInIC
: public IonIC
{
470 LiveRegisterSet liveRegs_
;
472 ConstantOrRegister key_
;
478 IonInIC(LiveRegisterSet liveRegs
, const ConstantOrRegister
& key
,
479 Register object
, Register output
, Register temp
)
480 : IonIC(CacheKind::In
),
487 ConstantOrRegister
key() const { return key_
; }
488 Register
object() const { return object_
; }
489 Register
output() const { return output_
; }
490 Register
temp() const { return temp_
; }
491 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
493 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
494 IonInIC
* ic
, HandleValue key
,
495 HandleObject obj
, bool* res
);
498 class IonInstanceOfIC
: public IonIC
{
499 LiveRegisterSet liveRegs_
;
501 TypedOrValueRegister lhs_
;
506 IonInstanceOfIC(LiveRegisterSet liveRegs
, TypedOrValueRegister lhs
,
507 Register rhs
, Register output
)
508 : IonIC(CacheKind::InstanceOf
),
514 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
515 TypedOrValueRegister
lhs() const { return lhs_
; }
516 Register
rhs() const { return rhs_
; }
517 Register
output() const { return output_
; }
519 // This signature mimics that of TryAttachInstanceOfStub in baseline
520 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
521 IonInstanceOfIC
* ic
, HandleValue lhs
,
522 HandleObject rhs
, bool* attached
);
525 class IonCompareIC
: public IonIC
{
526 LiveRegisterSet liveRegs_
;
528 TypedOrValueRegister lhs_
;
529 TypedOrValueRegister rhs_
;
533 IonCompareIC(LiveRegisterSet liveRegs
, TypedOrValueRegister lhs
,
534 TypedOrValueRegister rhs
, Register output
)
535 : IonIC(CacheKind::Compare
),
541 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
542 TypedOrValueRegister
lhs() const { return lhs_
; }
543 TypedOrValueRegister
rhs() const { return rhs_
; }
544 Register
output() const { return output_
; }
546 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
547 IonCompareIC
* stub
, HandleValue lhs
,
548 HandleValue rhs
, bool* res
);
551 class IonUnaryArithIC
: public IonIC
{
552 LiveRegisterSet liveRegs_
;
554 TypedOrValueRegister input_
;
555 ValueOperand output_
;
558 IonUnaryArithIC(LiveRegisterSet liveRegs
, TypedOrValueRegister input
,
560 : IonIC(CacheKind::UnaryArith
),
565 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
566 TypedOrValueRegister
input() const { return input_
; }
567 ValueOperand
output() const { return output_
; }
569 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
570 IonUnaryArithIC
* stub
, HandleValue val
,
571 MutableHandleValue res
);
574 class IonToPropertyKeyIC
: public IonIC
{
575 LiveRegisterSet liveRegs_
;
577 ValueOperand output_
;
580 IonToPropertyKeyIC(LiveRegisterSet liveRegs
, ValueOperand input
,
582 : IonIC(CacheKind::ToPropertyKey
),
587 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
588 ValueOperand
input() const { return input_
; }
589 ValueOperand
output() const { return output_
; }
591 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
592 IonToPropertyKeyIC
* ic
, HandleValue val
,
593 MutableHandleValue res
);
596 class IonBinaryArithIC
: public IonIC
{
597 LiveRegisterSet liveRegs_
;
599 TypedOrValueRegister lhs_
;
600 TypedOrValueRegister rhs_
;
601 ValueOperand output_
;
604 IonBinaryArithIC(LiveRegisterSet liveRegs
, TypedOrValueRegister lhs
,
605 TypedOrValueRegister rhs
, ValueOperand output
)
606 : IonIC(CacheKind::BinaryArith
),
612 LiveRegisterSet
liveRegs() const { return liveRegs_
; }
613 TypedOrValueRegister
lhs() const { return lhs_
; }
614 TypedOrValueRegister
rhs() const { return rhs_
; }
615 ValueOperand
output() const { return output_
; }
617 static MOZ_MUST_USE
bool update(JSContext
* cx
, HandleScript outerScript
,
618 IonBinaryArithIC
* stub
, HandleValue lhs
,
619 HandleValue rhs
, MutableHandleValue res
);
625 #endif /* jit_IonIC_h */