Bug 1639153 - Part 6.2: Establish dependency from tls for x86 callWithABI div/mod...
[gecko.git] / js / src / jit / IonIC.h
blob20006b8ed9911d8784d6c1680c0ae1b9649769ca
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/. */
7 #ifndef jit_IonIC_h
8 #define jit_IonIC_h
10 #include "jit/CacheIR.h"
12 namespace js {
13 namespace jit {
15 class CacheIRStubInfo;
17 // An optimized stub attached to an IonIC.
18 class IonICStub {
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
24 // one.
25 IonICStub* next_;
27 // Info about this stub.
28 CacheIRStubInfo* stubInfo_;
30 public:
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) {
42 MOZ_ASSERT(!next_);
43 MOZ_ASSERT(next && nextCodeRaw);
44 next_ = next;
45 nextCodeRaw_ = nextCodeRaw;
48 // Null out pointers when we unlink stubs, to ensure we never use
49 // discarded stubs.
50 void poison() {
51 nextCodeRaw_ = nullptr;
52 next_ = nullptr;
53 stubInfo_ = nullptr;
57 class IonGetPropertyIC;
58 class IonSetPropertyIC;
59 class IonGetPropSuperIC;
60 class IonGetNameIC;
61 class IonBindNameIC;
62 class IonGetIteratorIC;
63 class IonHasOwnIC;
64 class IonCheckPrivateFieldIC;
65 class IonInIC;
66 class IonInstanceOfIC;
67 class IonCompareIC;
68 class IonUnaryArithIC;
69 class IonBinaryArithIC;
70 class IonToPropertyKeyIC;
72 class IonIC {
73 // This either points at the OOL path for the fallback path, or the code for
74 // the first stub.
75 uint8_t* codeRaw_;
77 // The first optimized stub, or nullptr.
78 IonICStub* firstStub_;
80 // Location of this IC, nullptr for idempotent caches.
81 JSScript* script_;
82 jsbytecode* pc_;
84 // The offset of the rejoin location in the IonScript's code (stubs jump to
85 // this location).
86 uint32_t rejoinOffset_;
88 // The offset of the OOL path in the IonScript's code that calls the IC's
89 // update function.
90 uint32_t fallbackOffset_;
92 CacheKind kind_;
93 bool idempotent_ : 1;
94 ICState state_;
96 protected:
97 explicit IonIC(CacheKind kind)
98 : codeRaw_(nullptr),
99 firstStub_(nullptr),
100 script_(nullptr),
101 pc_(nullptr),
102 rejoinOffset_(0),
103 fallbackOffset_(0),
104 kind_(kind),
105 idempotent_(false),
106 state_() {}
108 void attachStub(IonICStub* newStub, JitCode* code);
110 public:
111 void setScriptedLocation(JSScript* script, jsbytecode* pc) {
112 MOZ_ASSERT(!script_ && !pc_);
113 MOZ_ASSERT(script && pc);
114 script_ = script;
115 pc_ = pc;
118 JSScript* script() const {
119 MOZ_ASSERT(script_);
120 return script_;
122 jsbytecode* pc() const {
123 MOZ_ASSERT(pc_);
124 return pc_;
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;
184 IonInIC* asInIC() {
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 {
221 private:
222 LiveRegisterSet liveRegs_;
224 TypedOrValueRegister value_;
225 ConstantOrRegister id_;
226 TypedOrValueRegister output_;
227 Register maybeTemp_; // Might be InvalidReg.
229 GetPropertyResultFlags resultFlags_;
231 public:
232 IonGetPropertyIC(CacheKind kind, LiveRegisterSet liveRegs,
233 TypedOrValueRegister value, const ConstantOrRegister& id,
234 TypedOrValueRegister output, Register maybeTemp,
235 GetPropertyResultFlags resultFlags)
236 : IonIC(kind),
237 liveRegs_(liveRegs),
238 value_(value),
239 id_(id),
240 output_(output),
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_;
265 Register object_;
266 TypedOrValueRegister receiver_;
267 ConstantOrRegister id_;
268 TypedOrValueRegister output_;
270 public:
271 IonGetPropSuperIC(CacheKind kind, LiveRegisterSet liveRegs, Register object,
272 TypedOrValueRegister receiver, const ConstantOrRegister& id,
273 TypedOrValueRegister output)
274 : IonIC(kind),
275 liveRegs_(liveRegs),
276 object_(object),
277 receiver_(receiver),
278 id_(id),
279 output_(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_;
296 Register object_;
297 Register temp_;
298 ConstantOrRegister id_;
299 ConstantOrRegister rhs_;
300 bool strict_ : 1;
301 bool needsPostBarrier_ : 1;
302 bool needsTypeBarrier_ : 1;
303 bool guardHoles_ : 1;
305 public:
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,
310 bool guardHoles)
311 : IonIC(kind),
312 liveRegs_(liveRegs),
313 object_(object),
314 temp_(temp),
315 id_(id),
316 rhs_(rhs),
317 strict_(strict),
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_;
344 Register temp_;
346 public:
347 IonGetNameIC(LiveRegisterSet liveRegs, Register environment,
348 ValueOperand output, Register temp)
349 : IonIC(CacheKind::GetName),
350 liveRegs_(liveRegs),
351 environment_(environment),
352 output_(output),
353 temp_(temp) {}
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_;
369 Register output_;
370 Register temp_;
372 public:
373 IonBindNameIC(LiveRegisterSet liveRegs, Register environment, Register output,
374 Register temp)
375 : IonIC(CacheKind::BindName),
376 liveRegs_(liveRegs),
377 environment_(environment),
378 output_(output),
379 temp_(temp) {}
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_;
393 Register output_;
394 Register temp1_;
395 Register temp2_;
397 public:
398 IonGetIteratorIC(LiveRegisterSet liveRegs, TypedOrValueRegister value,
399 Register output, Register temp1, Register temp2)
400 : IonIC(CacheKind::GetIterator),
401 liveRegs_(liveRegs),
402 value_(value),
403 output_(output),
404 temp1_(temp1),
405 temp2_(temp2) {}
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_;
422 Register output_;
424 public:
425 IonHasOwnIC(LiveRegisterSet liveRegs, TypedOrValueRegister value,
426 TypedOrValueRegister id, Register output)
427 : IonIC(CacheKind::HasOwn),
428 liveRegs_(liveRegs),
429 value_(value),
430 id_(id),
431 output_(output) {}
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_;
448 Register output_;
450 public:
451 IonCheckPrivateFieldIC(LiveRegisterSet liveRegs, TypedOrValueRegister value,
452 TypedOrValueRegister id, Register output)
453 : IonIC(CacheKind::CheckPrivateField),
454 liveRegs_(liveRegs),
455 value_(value),
456 id_(id),
457 output_(output) {}
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_;
473 Register object_;
474 Register output_;
475 Register temp_;
477 public:
478 IonInIC(LiveRegisterSet liveRegs, const ConstantOrRegister& key,
479 Register object, Register output, Register temp)
480 : IonIC(CacheKind::In),
481 liveRegs_(liveRegs),
482 key_(key),
483 object_(object),
484 output_(output),
485 temp_(temp) {}
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_;
502 Register rhs_;
503 Register output_;
505 public:
506 IonInstanceOfIC(LiveRegisterSet liveRegs, TypedOrValueRegister lhs,
507 Register rhs, Register output)
508 : IonIC(CacheKind::InstanceOf),
509 liveRegs_(liveRegs),
510 lhs_(lhs),
511 rhs_(rhs),
512 output_(output) {}
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_;
530 Register output_;
532 public:
533 IonCompareIC(LiveRegisterSet liveRegs, TypedOrValueRegister lhs,
534 TypedOrValueRegister rhs, Register output)
535 : IonIC(CacheKind::Compare),
536 liveRegs_(liveRegs),
537 lhs_(lhs),
538 rhs_(rhs),
539 output_(output) {}
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_;
557 public:
558 IonUnaryArithIC(LiveRegisterSet liveRegs, TypedOrValueRegister input,
559 ValueOperand output)
560 : IonIC(CacheKind::UnaryArith),
561 liveRegs_(liveRegs),
562 input_(input),
563 output_(output) {}
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_;
576 ValueOperand input_;
577 ValueOperand output_;
579 public:
580 IonToPropertyKeyIC(LiveRegisterSet liveRegs, ValueOperand input,
581 ValueOperand output)
582 : IonIC(CacheKind::ToPropertyKey),
583 liveRegs_(liveRegs),
584 input_(input),
585 output_(output) {}
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_;
603 public:
604 IonBinaryArithIC(LiveRegisterSet liveRegs, TypedOrValueRegister lhs,
605 TypedOrValueRegister rhs, ValueOperand output)
606 : IonIC(CacheKind::BinaryArith),
607 liveRegs_(liveRegs),
608 lhs_(lhs),
609 rhs_(rhs),
610 output_(output) {}
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);
622 } // namespace jit
623 } // namespace js
625 #endif /* jit_IonIC_h */