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_BaselineIC_h
8 : #define jit_BaselineIC_h
9 :
10 : #include "mozilla/Assertions.h"
11 :
12 : #include "jscntxt.h"
13 : #include "jscompartment.h"
14 : #include "jsgc.h"
15 : #include "jsopcode.h"
16 :
17 : #include "builtin/TypedObject.h"
18 : #include "gc/Barrier.h"
19 : #include "jit/BaselineICList.h"
20 : #include "jit/BaselineJIT.h"
21 : #include "jit/SharedIC.h"
22 : #include "jit/SharedICRegisters.h"
23 : #include "js/GCVector.h"
24 : #include "vm/ArrayObject.h"
25 : #include "vm/UnboxedObject.h"
26 :
27 : namespace js {
28 : namespace jit {
29 :
30 : // WarmUpCounter_Fallback
31 :
32 : // A WarmUpCounter IC chain has only the fallback stub.
33 : class ICWarmUpCounter_Fallback : public ICFallbackStub
34 : {
35 : friend class ICStubSpace;
36 :
37 245 : explicit ICWarmUpCounter_Fallback(JitCode* stubCode)
38 245 : : ICFallbackStub(ICStub::WarmUpCounter_Fallback, stubCode)
39 245 : { }
40 :
41 : public:
42 : // Compiler for this stub kind.
43 245 : class Compiler : public ICStubCompiler {
44 : protected:
45 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
46 :
47 : public:
48 245 : explicit Compiler(JSContext* cx)
49 245 : : ICStubCompiler(cx, ICStub::WarmUpCounter_Fallback, Engine::Baseline)
50 245 : { }
51 :
52 245 : ICWarmUpCounter_Fallback* getStub(ICStubSpace* space) {
53 245 : return newStub<ICWarmUpCounter_Fallback>(space, getStubCode());
54 : }
55 : };
56 : };
57 :
58 :
59 : // TypeUpdate
60 :
61 : extern const VMFunction DoTypeUpdateFallbackInfo;
62 :
63 : // The TypeUpdate fallback is not a regular fallback, since it just
64 : // forwards to a different entry point in the main fallback stub.
65 : class ICTypeUpdate_Fallback : public ICStub
66 : {
67 : friend class ICStubSpace;
68 :
69 1069 : explicit ICTypeUpdate_Fallback(JitCode* stubCode)
70 1069 : : ICStub(ICStub::TypeUpdate_Fallback, stubCode)
71 1069 : {}
72 :
73 : public:
74 : // Compiler for this stub kind.
75 1069 : class Compiler : public ICStubCompiler {
76 : protected:
77 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
78 :
79 : public:
80 1069 : explicit Compiler(JSContext* cx)
81 1069 : : ICStubCompiler(cx, ICStub::TypeUpdate_Fallback, Engine::Baseline)
82 1069 : { }
83 :
84 1069 : ICTypeUpdate_Fallback* getStub(ICStubSpace* space) {
85 1069 : return newStub<ICTypeUpdate_Fallback>(space, getStubCode());
86 : }
87 : };
88 : };
89 :
90 : class ICTypeUpdate_PrimitiveSet : public TypeCheckPrimitiveSetStub
91 : {
92 : friend class ICStubSpace;
93 :
94 418 : ICTypeUpdate_PrimitiveSet(JitCode* stubCode, uint16_t flags)
95 418 : : TypeCheckPrimitiveSetStub(TypeUpdate_PrimitiveSet, stubCode, flags)
96 418 : {}
97 :
98 : public:
99 448 : class Compiler : public TypeCheckPrimitiveSetStub::Compiler {
100 : protected:
101 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
102 :
103 : public:
104 448 : Compiler(JSContext* cx, ICTypeUpdate_PrimitiveSet* existingStub, JSValueType type)
105 448 : : TypeCheckPrimitiveSetStub::Compiler(cx, TypeUpdate_PrimitiveSet,
106 448 : existingStub, type)
107 448 : {}
108 :
109 30 : ICTypeUpdate_PrimitiveSet* updateStub() {
110 : TypeCheckPrimitiveSetStub* stub =
111 30 : this->TypeCheckPrimitiveSetStub::Compiler::updateStub();
112 30 : if (!stub)
113 0 : return nullptr;
114 30 : return stub->toUpdateStub();
115 : }
116 :
117 418 : ICTypeUpdate_PrimitiveSet* getStub(ICStubSpace* space) {
118 418 : MOZ_ASSERT(!existingStub_);
119 418 : return newStub<ICTypeUpdate_PrimitiveSet>(space, getStubCode(), flags_);
120 : }
121 : };
122 : };
123 :
124 : // Type update stub to handle a singleton object.
125 : class ICTypeUpdate_SingleObject : public ICStub
126 : {
127 : friend class ICStubSpace;
128 :
129 : GCPtrObject obj_;
130 :
131 : ICTypeUpdate_SingleObject(JitCode* stubCode, JSObject* obj);
132 :
133 : public:
134 4 : GCPtrObject& object() {
135 4 : return obj_;
136 : }
137 :
138 2 : static size_t offsetOfObject() {
139 2 : return offsetof(ICTypeUpdate_SingleObject, obj_);
140 : }
141 :
142 7 : class Compiler : public ICStubCompiler {
143 : protected:
144 : HandleObject obj_;
145 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
146 :
147 : public:
148 7 : Compiler(JSContext* cx, HandleObject obj)
149 7 : : ICStubCompiler(cx, TypeUpdate_SingleObject, Engine::Baseline),
150 7 : obj_(obj)
151 7 : { }
152 :
153 7 : ICTypeUpdate_SingleObject* getStub(ICStubSpace* space) {
154 7 : return newStub<ICTypeUpdate_SingleObject>(space, getStubCode(), obj_);
155 : }
156 : };
157 : };
158 :
159 : // Type update stub to handle a single ObjectGroup.
160 : class ICTypeUpdate_ObjectGroup : public ICStub
161 : {
162 : friend class ICStubSpace;
163 :
164 : GCPtrObjectGroup group_;
165 :
166 : ICTypeUpdate_ObjectGroup(JitCode* stubCode, ObjectGroup* group);
167 :
168 : public:
169 40 : GCPtrObjectGroup& group() {
170 40 : return group_;
171 : }
172 :
173 19 : static size_t offsetOfGroup() {
174 19 : return offsetof(ICTypeUpdate_ObjectGroup, group_);
175 : }
176 :
177 136 : class Compiler : public ICStubCompiler {
178 : protected:
179 : HandleObjectGroup group_;
180 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
181 :
182 : public:
183 136 : Compiler(JSContext* cx, HandleObjectGroup group)
184 136 : : ICStubCompiler(cx, TypeUpdate_ObjectGroup, Engine::Baseline),
185 136 : group_(group)
186 136 : { }
187 :
188 136 : ICTypeUpdate_ObjectGroup* getStub(ICStubSpace* space) {
189 136 : return newStub<ICTypeUpdate_ObjectGroup>(space, getStubCode(), group_);
190 : }
191 : };
192 : };
193 :
194 : class ICTypeUpdate_AnyValue : public ICStub
195 : {
196 : friend class ICStubSpace;
197 :
198 27 : explicit ICTypeUpdate_AnyValue(JitCode* stubCode)
199 27 : : ICStub(TypeUpdate_AnyValue, stubCode)
200 27 : {}
201 :
202 : public:
203 27 : class Compiler : public ICStubCompiler {
204 : protected:
205 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
206 :
207 : public:
208 27 : explicit Compiler(JSContext* cx)
209 27 : : ICStubCompiler(cx, TypeUpdate_AnyValue, Engine::Baseline)
210 27 : {}
211 :
212 27 : ICTypeUpdate_AnyValue* getStub(ICStubSpace* space) {
213 27 : return newStub<ICTypeUpdate_AnyValue>(space, getStubCode());
214 : }
215 : };
216 : };
217 :
218 : // ToBool
219 : // JSOP_IFNE
220 :
221 : class ICToBool_Fallback : public ICFallbackStub
222 : {
223 : friend class ICStubSpace;
224 :
225 1473 : explicit ICToBool_Fallback(JitCode* stubCode)
226 1473 : : ICFallbackStub(ICStub::ToBool_Fallback, stubCode) {}
227 :
228 : public:
229 : static const uint32_t MAX_OPTIMIZED_STUBS = 8;
230 :
231 : // Compiler for this stub kind.
232 1473 : class Compiler : public ICStubCompiler {
233 : protected:
234 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
235 :
236 : public:
237 1473 : explicit Compiler(JSContext* cx)
238 1473 : : ICStubCompiler(cx, ICStub::ToBool_Fallback, Engine::Baseline) {}
239 :
240 1473 : ICStub* getStub(ICStubSpace* space) {
241 1473 : return newStub<ICToBool_Fallback>(space, getStubCode());
242 : }
243 : };
244 : };
245 :
246 : class ICToBool_Int32 : public ICStub
247 : {
248 : friend class ICStubSpace;
249 :
250 26 : explicit ICToBool_Int32(JitCode* stubCode)
251 26 : : ICStub(ICStub::ToBool_Int32, stubCode) {}
252 :
253 : public:
254 : // Compiler for this stub kind.
255 26 : class Compiler : public ICStubCompiler {
256 : protected:
257 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
258 :
259 : public:
260 26 : explicit Compiler(JSContext* cx)
261 26 : : ICStubCompiler(cx, ICStub::ToBool_Int32, Engine::Baseline) {}
262 :
263 26 : ICStub* getStub(ICStubSpace* space) {
264 26 : return newStub<ICToBool_Int32>(space, getStubCode());
265 : }
266 : };
267 : };
268 :
269 : class ICToBool_String : public ICStub
270 : {
271 : friend class ICStubSpace;
272 :
273 55 : explicit ICToBool_String(JitCode* stubCode)
274 55 : : ICStub(ICStub::ToBool_String, stubCode) {}
275 :
276 : public:
277 : // Compiler for this stub kind.
278 55 : class Compiler : public ICStubCompiler {
279 : protected:
280 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
281 :
282 : public:
283 55 : explicit Compiler(JSContext* cx)
284 55 : : ICStubCompiler(cx, ICStub::ToBool_String, Engine::Baseline) {}
285 :
286 55 : ICStub* getStub(ICStubSpace* space) {
287 55 : return newStub<ICToBool_String>(space, getStubCode());
288 : }
289 : };
290 : };
291 :
292 : class ICToBool_NullUndefined : public ICStub
293 : {
294 : friend class ICStubSpace;
295 :
296 128 : explicit ICToBool_NullUndefined(JitCode* stubCode)
297 128 : : ICStub(ICStub::ToBool_NullUndefined, stubCode) {}
298 :
299 : public:
300 : // Compiler for this stub kind.
301 128 : class Compiler : public ICStubCompiler {
302 : protected:
303 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
304 :
305 : public:
306 128 : explicit Compiler(JSContext* cx)
307 128 : : ICStubCompiler(cx, ICStub::ToBool_NullUndefined, Engine::Baseline) {}
308 :
309 128 : ICStub* getStub(ICStubSpace* space) {
310 128 : return newStub<ICToBool_NullUndefined>(space, getStubCode());
311 : }
312 : };
313 : };
314 :
315 : class ICToBool_Double : public ICStub
316 : {
317 : friend class ICStubSpace;
318 :
319 1 : explicit ICToBool_Double(JitCode* stubCode)
320 1 : : ICStub(ICStub::ToBool_Double, stubCode) {}
321 :
322 : public:
323 : // Compiler for this stub kind.
324 1 : class Compiler : public ICStubCompiler {
325 : protected:
326 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
327 :
328 : public:
329 1 : explicit Compiler(JSContext* cx)
330 1 : : ICStubCompiler(cx, ICStub::ToBool_Double, Engine::Baseline) {}
331 :
332 1 : ICStub* getStub(ICStubSpace* space) {
333 1 : return newStub<ICToBool_Double>(space, getStubCode());
334 : }
335 : };
336 : };
337 :
338 : class ICToBool_Object : public ICStub
339 : {
340 : friend class ICStubSpace;
341 :
342 106 : explicit ICToBool_Object(JitCode* stubCode)
343 106 : : ICStub(ICStub::ToBool_Object, stubCode) {}
344 :
345 : public:
346 : // Compiler for this stub kind.
347 106 : class Compiler : public ICStubCompiler {
348 : protected:
349 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
350 :
351 : public:
352 106 : explicit Compiler(JSContext* cx)
353 106 : : ICStubCompiler(cx, ICStub::ToBool_Object, Engine::Baseline) {}
354 :
355 106 : ICStub* getStub(ICStubSpace* space) {
356 106 : return newStub<ICToBool_Object>(space, getStubCode());
357 : }
358 : };
359 : };
360 :
361 : // ToNumber
362 : // JSOP_POS
363 :
364 : class ICToNumber_Fallback : public ICFallbackStub
365 : {
366 : friend class ICStubSpace;
367 :
368 151 : explicit ICToNumber_Fallback(JitCode* stubCode)
369 151 : : ICFallbackStub(ICStub::ToNumber_Fallback, stubCode) {}
370 :
371 : public:
372 : // Compiler for this stub kind.
373 151 : class Compiler : public ICStubCompiler {
374 : protected:
375 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
376 :
377 : public:
378 151 : explicit Compiler(JSContext* cx)
379 151 : : ICStubCompiler(cx, ICStub::ToNumber_Fallback, Engine::Baseline) {}
380 :
381 151 : ICStub* getStub(ICStubSpace* space) {
382 151 : return newStub<ICToNumber_Fallback>(space, getStubCode());
383 : }
384 : };
385 : };
386 :
387 : // GetElem
388 : // JSOP_GETELEM
389 : // JSOP_GETELEM_SUPER
390 :
391 : class ICGetElem_Fallback : public ICMonitoredFallbackStub
392 : {
393 : friend class ICStubSpace;
394 :
395 650 : explicit ICGetElem_Fallback(JitCode* stubCode)
396 650 : : ICMonitoredFallbackStub(ICStub::GetElem_Fallback, stubCode)
397 650 : { }
398 :
399 : static const uint16_t EXTRA_NEGATIVE_INDEX = 0x1;
400 : static const uint16_t EXTRA_UNOPTIMIZABLE_ACCESS = 0x2;
401 :
402 : public:
403 0 : void noteNegativeIndex() {
404 0 : extra_ |= EXTRA_NEGATIVE_INDEX;
405 0 : }
406 1 : bool hasNegativeIndex() const {
407 1 : return extra_ & EXTRA_NEGATIVE_INDEX;
408 : }
409 794 : void noteUnoptimizableAccess() {
410 794 : extra_ |= EXTRA_UNOPTIMIZABLE_ACCESS;
411 794 : }
412 0 : bool hadUnoptimizableAccess() const {
413 0 : return extra_ & EXTRA_UNOPTIMIZABLE_ACCESS;
414 : }
415 :
416 : // Compiler for this stub kind.
417 650 : class Compiler : public ICStubCompiler {
418 : protected:
419 : bool hasReceiver_;
420 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
421 :
422 650 : virtual int32_t getKey() const {
423 1300 : return static_cast<int32_t>(engine_) |
424 650 : (static_cast<int32_t>(kind) << 1) |
425 650 : (static_cast<int32_t>(hasReceiver_) << 17);
426 : }
427 :
428 : public:
429 650 : explicit Compiler(JSContext* cx, bool hasReceiver = false)
430 650 : : ICStubCompiler(cx, ICStub::GetElem_Fallback, Engine::Baseline),
431 650 : hasReceiver_(hasReceiver)
432 650 : { }
433 :
434 650 : ICStub* getStub(ICStubSpace* space) {
435 650 : ICGetElem_Fallback* stub = newStub<ICGetElem_Fallback>(space, getStubCode());
436 650 : if (!stub)
437 0 : return nullptr;
438 650 : if (!stub->initMonitoringChain(cx, space))
439 0 : return nullptr;
440 650 : return stub;
441 : }
442 : };
443 : };
444 :
445 : // SetElem
446 : // JSOP_SETELEM
447 : // JSOP_INITELEM
448 :
449 : class ICSetElem_Fallback : public ICFallbackStub
450 : {
451 : friend class ICStubSpace;
452 :
453 372 : explicit ICSetElem_Fallback(JitCode* stubCode)
454 372 : : ICFallbackStub(ICStub::SetElem_Fallback, stubCode)
455 372 : { }
456 :
457 : static const size_t HasDenseAddFlag = 0x1;
458 : static const size_t HasTypedArrayOOBFlag = 0x2;
459 :
460 : public:
461 42 : void noteHasDenseAdd() { extra_ |= HasDenseAddFlag; }
462 0 : bool hasDenseAdd() const { return extra_ & HasDenseAddFlag; }
463 :
464 0 : void noteHasTypedArrayOOB() { extra_ |= HasTypedArrayOOBFlag; }
465 0 : bool hasTypedArrayOOB() const { return extra_ & HasTypedArrayOOBFlag; }
466 :
467 : // Compiler for this stub kind.
468 372 : class Compiler : public ICStubCompiler {
469 : protected:
470 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
471 :
472 : public:
473 372 : explicit Compiler(JSContext* cx)
474 372 : : ICStubCompiler(cx, ICStub::SetElem_Fallback, Engine::Baseline)
475 372 : { }
476 :
477 372 : ICStub* getStub(ICStubSpace* space) {
478 372 : return newStub<ICSetElem_Fallback>(space, getStubCode());
479 : }
480 : };
481 : };
482 :
483 : // In
484 : // JSOP_IN
485 : class ICIn_Fallback : public ICFallbackStub
486 : {
487 : friend class ICStubSpace;
488 :
489 76 : explicit ICIn_Fallback(JitCode* stubCode)
490 76 : : ICFallbackStub(ICStub::In_Fallback, stubCode)
491 76 : { }
492 :
493 : public:
494 76 : class Compiler : public ICStubCompiler {
495 : protected:
496 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
497 :
498 : public:
499 76 : explicit Compiler(JSContext* cx)
500 76 : : ICStubCompiler(cx, ICStub::In_Fallback, Engine::Baseline)
501 76 : { }
502 :
503 76 : ICStub* getStub(ICStubSpace* space) {
504 76 : return newStub<ICIn_Fallback>(space, getStubCode());
505 : }
506 : };
507 : };
508 :
509 : // HasOwn
510 : // JSOP_HASOWN
511 : class ICHasOwn_Fallback : public ICFallbackStub
512 : {
513 : friend class ICStubSpace;
514 :
515 0 : explicit ICHasOwn_Fallback(JitCode* stubCode)
516 0 : : ICFallbackStub(ICStub::HasOwn_Fallback, stubCode)
517 0 : { }
518 :
519 : public:
520 0 : class Compiler : public ICStubCompiler {
521 : protected:
522 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
523 :
524 : public:
525 0 : explicit Compiler(JSContext* cx)
526 0 : : ICStubCompiler(cx, ICStub::HasOwn_Fallback, Engine::Baseline)
527 0 : { }
528 :
529 0 : ICStub* getStub(ICStubSpace* space) {
530 0 : return newStub<ICHasOwn_Fallback>(space, getStubCode());
531 : }
532 : };
533 : };
534 :
535 : // GetName
536 : // JSOP_GETNAME
537 : // JSOP_GETGNAME
538 : class ICGetName_Fallback : public ICMonitoredFallbackStub
539 : {
540 : friend class ICStubSpace;
541 :
542 1656 : explicit ICGetName_Fallback(JitCode* stubCode)
543 1656 : : ICMonitoredFallbackStub(ICStub::GetName_Fallback, stubCode)
544 1656 : { }
545 :
546 : public:
547 : static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
548 :
549 985 : void noteUnoptimizableAccess() {
550 985 : extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
551 985 : }
552 0 : bool hadUnoptimizableAccess() const {
553 0 : return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
554 : }
555 :
556 1656 : class Compiler : public ICStubCompiler {
557 : protected:
558 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
559 :
560 : public:
561 1656 : explicit Compiler(JSContext* cx)
562 1656 : : ICStubCompiler(cx, ICStub::GetName_Fallback, Engine::Baseline)
563 1656 : { }
564 :
565 1656 : ICStub* getStub(ICStubSpace* space) {
566 1656 : ICGetName_Fallback* stub = newStub<ICGetName_Fallback>(space, getStubCode());
567 1656 : if (!stub || !stub->initMonitoringChain(cx, space))
568 0 : return nullptr;
569 1656 : return stub;
570 : }
571 : };
572 : };
573 :
574 : // BindName
575 : // JSOP_BINDNAME
576 : class ICBindName_Fallback : public ICFallbackStub
577 : {
578 : friend class ICStubSpace;
579 :
580 0 : explicit ICBindName_Fallback(JitCode* stubCode)
581 0 : : ICFallbackStub(ICStub::BindName_Fallback, stubCode)
582 0 : { }
583 :
584 : public:
585 0 : class Compiler : public ICStubCompiler {
586 : protected:
587 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
588 :
589 : public:
590 0 : explicit Compiler(JSContext* cx)
591 0 : : ICStubCompiler(cx, ICStub::BindName_Fallback, Engine::Baseline)
592 0 : { }
593 :
594 0 : ICStub* getStub(ICStubSpace* space) {
595 0 : return newStub<ICBindName_Fallback>(space, getStubCode());
596 : }
597 : };
598 : };
599 :
600 : // GetIntrinsic
601 : // JSOP_GETINTRINSIC
602 : class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub
603 : {
604 : friend class ICStubSpace;
605 :
606 1724 : explicit ICGetIntrinsic_Fallback(JitCode* stubCode)
607 1724 : : ICMonitoredFallbackStub(ICStub::GetIntrinsic_Fallback, stubCode)
608 1724 : { }
609 :
610 : public:
611 1724 : class Compiler : public ICStubCompiler {
612 : protected:
613 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
614 :
615 : public:
616 1724 : explicit Compiler(JSContext* cx)
617 1724 : : ICStubCompiler(cx, ICStub::GetIntrinsic_Fallback, Engine::Baseline)
618 1724 : { }
619 :
620 1724 : ICStub* getStub(ICStubSpace* space) {
621 : ICGetIntrinsic_Fallback* stub =
622 1724 : newStub<ICGetIntrinsic_Fallback>(space, getStubCode());
623 1724 : if (!stub || !stub->initMonitoringChain(cx, space))
624 0 : return nullptr;
625 1724 : return stub;
626 : }
627 : };
628 : };
629 :
630 : // Stub that loads the constant result of a GETINTRINSIC operation.
631 : class ICGetIntrinsic_Constant : public ICStub
632 : {
633 : friend class ICStubSpace;
634 :
635 : GCPtrValue value_;
636 :
637 : ICGetIntrinsic_Constant(JitCode* stubCode, const Value& value);
638 : ~ICGetIntrinsic_Constant();
639 :
640 : public:
641 0 : GCPtrValue& value() {
642 0 : return value_;
643 : }
644 45 : static size_t offsetOfValue() {
645 45 : return offsetof(ICGetIntrinsic_Constant, value_);
646 : }
647 :
648 1024 : class Compiler : public ICStubCompiler {
649 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
650 :
651 : HandleValue value_;
652 :
653 : public:
654 1024 : Compiler(JSContext* cx, HandleValue value)
655 1024 : : ICStubCompiler(cx, ICStub::GetIntrinsic_Constant, Engine::Baseline),
656 1024 : value_(value)
657 1024 : {}
658 :
659 1024 : ICStub* getStub(ICStubSpace* space) {
660 1024 : return newStub<ICGetIntrinsic_Constant>(space, getStubCode(), value_);
661 : }
662 : };
663 : };
664 :
665 : // SetProp
666 : // JSOP_SETPROP
667 : // JSOP_SETNAME
668 : // JSOP_SETGNAME
669 : // JSOP_INITPROP
670 :
671 : class ICSetProp_Fallback : public ICFallbackStub
672 : {
673 : friend class ICStubSpace;
674 :
675 1207 : explicit ICSetProp_Fallback(JitCode* stubCode)
676 1207 : : ICFallbackStub(ICStub::SetProp_Fallback, stubCode)
677 1207 : { }
678 :
679 : public:
680 : static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
681 12 : void noteUnoptimizableAccess() {
682 12 : extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
683 12 : }
684 50 : bool hadUnoptimizableAccess() const {
685 50 : return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
686 : }
687 :
688 1207 : class Compiler : public ICStubCompiler {
689 : protected:
690 : CodeOffset bailoutReturnOffset_;
691 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
692 : void postGenerateStubCode(MacroAssembler& masm, Handle<JitCode*> code);
693 :
694 : public:
695 1207 : explicit Compiler(JSContext* cx)
696 1207 : : ICStubCompiler(cx, ICStub::SetProp_Fallback, Engine::Baseline)
697 1207 : { }
698 :
699 1207 : ICStub* getStub(ICStubSpace* space) {
700 1207 : return newStub<ICSetProp_Fallback>(space, getStubCode());
701 : }
702 : };
703 : };
704 :
705 : // Call
706 : // JSOP_CALL
707 : // JSOP_CALL_IGNORES_RV
708 : // JSOP_FUNAPPLY
709 : // JSOP_FUNCALL
710 : // JSOP_NEW
711 : // JSOP_SPREADCALL
712 : // JSOP_SPREADNEW
713 : // JSOP_SPREADEVAL
714 :
715 5334 : class ICCallStubCompiler : public ICStubCompiler
716 : {
717 : protected:
718 5334 : ICCallStubCompiler(JSContext* cx, ICStub::Kind kind)
719 5334 : : ICStubCompiler(cx, kind, Engine::Baseline)
720 5334 : { }
721 :
722 : enum FunApplyThing {
723 : FunApply_MagicArgs,
724 : FunApply_Array
725 : };
726 :
727 : void pushCallArguments(MacroAssembler& masm, AllocatableGeneralRegisterSet regs,
728 : Register argcReg, bool isJitCall, bool isConstructing = false);
729 : void pushSpreadCallArguments(MacroAssembler& masm, AllocatableGeneralRegisterSet regs,
730 : Register argcReg, bool isJitCall, bool isConstructing);
731 : void guardSpreadCall(MacroAssembler& masm, Register argcReg, Label* failure,
732 : bool isConstructing);
733 : Register guardFunApply(MacroAssembler& masm, AllocatableGeneralRegisterSet regs,
734 : Register argcReg, bool checkNative, FunApplyThing applyThing,
735 : Label* failure);
736 : void pushCallerArguments(MacroAssembler& masm, AllocatableGeneralRegisterSet regs);
737 : void pushArrayArguments(MacroAssembler& masm, Address arrayVal,
738 : AllocatableGeneralRegisterSet regs);
739 : };
740 :
741 : class ICCall_Fallback : public ICMonitoredFallbackStub
742 : {
743 : friend class ICStubSpace;
744 : public:
745 : static const unsigned UNOPTIMIZABLE_CALL_FLAG = 0x1;
746 :
747 : static const uint32_t MAX_OPTIMIZED_STUBS = 16;
748 : static const uint32_t MAX_SCRIPTED_STUBS = 7;
749 : static const uint32_t MAX_NATIVE_STUBS = 7;
750 : private:
751 :
752 3534 : explicit ICCall_Fallback(JitCode* stubCode)
753 3534 : : ICMonitoredFallbackStub(ICStub::Call_Fallback, stubCode)
754 3534 : { }
755 :
756 : public:
757 1129 : void noteUnoptimizableCall() {
758 1129 : extra_ |= UNOPTIMIZABLE_CALL_FLAG;
759 1129 : }
760 6 : bool hadUnoptimizableCall() const {
761 6 : return extra_ & UNOPTIMIZABLE_CALL_FLAG;
762 : }
763 :
764 742 : unsigned scriptedStubCount() const {
765 742 : return numStubsWithKind(Call_Scripted);
766 : }
767 742 : bool scriptedStubsAreGeneralized() const {
768 742 : return hasStub(Call_AnyScripted);
769 : }
770 :
771 1110 : unsigned nativeStubCount() const {
772 1110 : return numStubsWithKind(Call_Native);
773 : }
774 1382 : bool nativeStubsAreGeneralized() const {
775 : // Return hasStub(Call_AnyNative) after Call_AnyNative stub is added.
776 1382 : return false;
777 : }
778 :
779 : // Compiler for this stub kind.
780 3534 : class Compiler : public ICCallStubCompiler {
781 : protected:
782 : bool isConstructing_;
783 : bool isSpread_;
784 : CodeOffset bailoutReturnOffset_;
785 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
786 : void postGenerateStubCode(MacroAssembler& masm, Handle<JitCode*> code);
787 :
788 3634 : virtual int32_t getKey() const {
789 7268 : return static_cast<int32_t>(engine_) |
790 7268 : (static_cast<int32_t>(kind) << 1) |
791 3634 : (static_cast<int32_t>(isSpread_) << 17) |
792 3634 : (static_cast<int32_t>(isConstructing_) << 18);
793 : }
794 :
795 : public:
796 3534 : Compiler(JSContext* cx, bool isConstructing, bool isSpread)
797 3534 : : ICCallStubCompiler(cx, ICStub::Call_Fallback),
798 : isConstructing_(isConstructing),
799 3534 : isSpread_(isSpread)
800 3534 : { }
801 :
802 3534 : ICStub* getStub(ICStubSpace* space) {
803 3534 : ICCall_Fallback* stub = newStub<ICCall_Fallback>(space, getStubCode());
804 3534 : if (!stub || !stub->initMonitoringChain(cx, space))
805 0 : return nullptr;
806 3534 : return stub;
807 : }
808 : };
809 : };
810 :
811 : class ICCall_Scripted : public ICMonitoredStub
812 : {
813 : friend class ICStubSpace;
814 : public:
815 : // The maximum number of inlineable spread call arguments. Keep this small
816 : // to avoid controllable stack overflows by attackers passing large arrays
817 : // to spread call. This value is shared with ICCall_Native.
818 : static const uint32_t MAX_ARGS_SPREAD_LENGTH = 16;
819 :
820 : protected:
821 : GCPtrFunction callee_;
822 : GCPtrObject templateObject_;
823 : uint32_t pcOffset_;
824 :
825 : ICCall_Scripted(JitCode* stubCode, ICStub* firstMonitorStub,
826 : JSFunction* callee, JSObject* templateObject,
827 : uint32_t pcOffset);
828 :
829 : public:
830 : static ICCall_Scripted* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
831 : ICCall_Scripted& other);
832 :
833 3 : GCPtrFunction& callee() {
834 3 : return callee_;
835 : }
836 3 : GCPtrObject& templateObject() {
837 3 : return templateObject_;
838 : }
839 :
840 48 : static size_t offsetOfCallee() {
841 48 : return offsetof(ICCall_Scripted, callee_);
842 : }
843 : static size_t offsetOfPCOffset() {
844 : return offsetof(ICCall_Scripted, pcOffset_);
845 : }
846 : };
847 :
848 : class ICCall_AnyScripted : public ICMonitoredStub
849 : {
850 : friend class ICStubSpace;
851 :
852 : protected:
853 : uint32_t pcOffset_;
854 :
855 7 : ICCall_AnyScripted(JitCode* stubCode, ICStub* firstMonitorStub, uint32_t pcOffset)
856 7 : : ICMonitoredStub(ICStub::Call_AnyScripted, stubCode, firstMonitorStub),
857 7 : pcOffset_(pcOffset)
858 7 : { }
859 :
860 : public:
861 : static ICCall_AnyScripted* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
862 : ICCall_AnyScripted& other);
863 :
864 : static size_t offsetOfPCOffset() {
865 : return offsetof(ICCall_AnyScripted, pcOffset_);
866 : }
867 : };
868 :
869 : // Compiler for Call_Scripted and Call_AnyScripted stubs.
870 708 : class ICCallScriptedCompiler : public ICCallStubCompiler {
871 : protected:
872 : ICStub* firstMonitorStub_;
873 : bool isConstructing_;
874 : bool isSpread_;
875 : RootedFunction callee_;
876 : RootedObject templateObject_;
877 : uint32_t pcOffset_;
878 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
879 :
880 708 : virtual int32_t getKey() const {
881 1416 : return static_cast<int32_t>(engine_) |
882 1416 : (static_cast<int32_t>(kind) << 1) |
883 708 : (static_cast<int32_t>(isConstructing_) << 17) |
884 708 : (static_cast<int32_t>(isSpread_) << 18);
885 : }
886 :
887 : public:
888 701 : ICCallScriptedCompiler(JSContext* cx, ICStub* firstMonitorStub,
889 : JSFunction* callee, JSObject* templateObject,
890 : bool isConstructing, bool isSpread, uint32_t pcOffset)
891 701 : : ICCallStubCompiler(cx, ICStub::Call_Scripted),
892 : firstMonitorStub_(firstMonitorStub),
893 : isConstructing_(isConstructing),
894 : isSpread_(isSpread),
895 : callee_(cx, callee),
896 : templateObject_(cx, templateObject),
897 701 : pcOffset_(pcOffset)
898 701 : { }
899 :
900 7 : ICCallScriptedCompiler(JSContext* cx, ICStub* firstMonitorStub, bool isConstructing,
901 : bool isSpread, uint32_t pcOffset)
902 7 : : ICCallStubCompiler(cx, ICStub::Call_AnyScripted),
903 : firstMonitorStub_(firstMonitorStub),
904 : isConstructing_(isConstructing),
905 : isSpread_(isSpread),
906 : callee_(cx, nullptr),
907 : templateObject_(cx, nullptr),
908 7 : pcOffset_(pcOffset)
909 7 : { }
910 :
911 708 : ICStub* getStub(ICStubSpace* space) {
912 708 : if (callee_) {
913 1402 : return newStub<ICCall_Scripted>(space, getStubCode(), firstMonitorStub_, callee_,
914 701 : templateObject_, pcOffset_);
915 : }
916 7 : return newStub<ICCall_AnyScripted>(space, getStubCode(), firstMonitorStub_, pcOffset_);
917 : }
918 : };
919 :
920 : class ICCall_Native : public ICMonitoredStub
921 : {
922 : friend class ICStubSpace;
923 :
924 : protected:
925 : GCPtrFunction callee_;
926 : GCPtrObject templateObject_;
927 : uint32_t pcOffset_;
928 :
929 : #ifdef JS_SIMULATOR
930 : void *native_;
931 : #endif
932 :
933 : ICCall_Native(JitCode* stubCode, ICStub* firstMonitorStub,
934 : JSFunction* callee, JSObject* templateObject,
935 : uint32_t pcOffset);
936 :
937 : public:
938 : static ICCall_Native* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
939 : ICCall_Native& other);
940 :
941 10 : GCPtrFunction& callee() {
942 10 : return callee_;
943 : }
944 10 : GCPtrObject& templateObject() {
945 10 : return templateObject_;
946 : }
947 :
948 75 : static size_t offsetOfCallee() {
949 75 : return offsetof(ICCall_Native, callee_);
950 : }
951 : static size_t offsetOfPCOffset() {
952 : return offsetof(ICCall_Native, pcOffset_);
953 : }
954 :
955 : #ifdef JS_SIMULATOR
956 : static size_t offsetOfNative() {
957 : return offsetof(ICCall_Native, native_);
958 : }
959 : #endif
960 :
961 : // Compiler for this stub kind.
962 1084 : class Compiler : public ICCallStubCompiler {
963 : protected:
964 : ICStub* firstMonitorStub_;
965 : bool isConstructing_;
966 : bool ignoresReturnValue_;
967 : bool isSpread_;
968 : RootedFunction callee_;
969 : RootedObject templateObject_;
970 : uint32_t pcOffset_;
971 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
972 :
973 1084 : virtual int32_t getKey() const {
974 2168 : return static_cast<int32_t>(engine_) |
975 2168 : (static_cast<int32_t>(kind) << 1) |
976 2168 : (static_cast<int32_t>(isSpread_) << 17) |
977 1084 : (static_cast<int32_t>(isConstructing_) << 18) |
978 1084 : (static_cast<int32_t>(ignoresReturnValue_) << 19);
979 : }
980 :
981 : public:
982 1084 : Compiler(JSContext* cx, ICStub* firstMonitorStub,
983 : HandleFunction callee, HandleObject templateObject,
984 : bool isConstructing, bool ignoresReturnValue, bool isSpread, uint32_t pcOffset)
985 1084 : : ICCallStubCompiler(cx, ICStub::Call_Native),
986 : firstMonitorStub_(firstMonitorStub),
987 : isConstructing_(isConstructing),
988 : ignoresReturnValue_(ignoresReturnValue),
989 : isSpread_(isSpread),
990 : callee_(cx, callee),
991 : templateObject_(cx, templateObject),
992 1084 : pcOffset_(pcOffset)
993 1084 : { }
994 :
995 1084 : ICStub* getStub(ICStubSpace* space) {
996 2168 : return newStub<ICCall_Native>(space, getStubCode(), firstMonitorStub_, callee_,
997 2168 : templateObject_, pcOffset_);
998 : }
999 : };
1000 : };
1001 :
1002 : class ICCall_ClassHook : public ICMonitoredStub
1003 : {
1004 : friend class ICStubSpace;
1005 :
1006 : protected:
1007 : const Class* clasp_;
1008 : void* native_;
1009 : GCPtrObject templateObject_;
1010 : uint32_t pcOffset_;
1011 :
1012 : ICCall_ClassHook(JitCode* stubCode, ICStub* firstMonitorStub,
1013 : const Class* clasp, Native native, JSObject* templateObject,
1014 : uint32_t pcOffset);
1015 :
1016 : public:
1017 : static ICCall_ClassHook* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
1018 : ICCall_ClassHook& other);
1019 :
1020 0 : const Class* clasp() {
1021 0 : return clasp_;
1022 : }
1023 0 : void* native() {
1024 0 : return native_;
1025 : }
1026 0 : GCPtrObject& templateObject() {
1027 0 : return templateObject_;
1028 : }
1029 :
1030 2 : static size_t offsetOfClass() {
1031 2 : return offsetof(ICCall_ClassHook, clasp_);
1032 : }
1033 2 : static size_t offsetOfNative() {
1034 2 : return offsetof(ICCall_ClassHook, native_);
1035 : }
1036 : static size_t offsetOfPCOffset() {
1037 : return offsetof(ICCall_ClassHook, pcOffset_);
1038 : }
1039 :
1040 : // Compiler for this stub kind.
1041 4 : class Compiler : public ICCallStubCompiler {
1042 : protected:
1043 : ICStub* firstMonitorStub_;
1044 : bool isConstructing_;
1045 : const Class* clasp_;
1046 : Native native_;
1047 : RootedObject templateObject_;
1048 : uint32_t pcOffset_;
1049 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1050 :
1051 4 : virtual int32_t getKey() const {
1052 8 : return static_cast<int32_t>(engine_) |
1053 4 : (static_cast<int32_t>(kind) << 1) |
1054 4 : (static_cast<int32_t>(isConstructing_) << 17);
1055 : }
1056 :
1057 : public:
1058 4 : Compiler(JSContext* cx, ICStub* firstMonitorStub,
1059 : const Class* clasp, Native native,
1060 : HandleObject templateObject, uint32_t pcOffset,
1061 : bool isConstructing)
1062 4 : : ICCallStubCompiler(cx, ICStub::Call_ClassHook),
1063 : firstMonitorStub_(firstMonitorStub),
1064 : isConstructing_(isConstructing),
1065 : clasp_(clasp),
1066 : native_(native),
1067 : templateObject_(cx, templateObject),
1068 4 : pcOffset_(pcOffset)
1069 4 : { }
1070 :
1071 4 : ICStub* getStub(ICStubSpace* space) {
1072 8 : return newStub<ICCall_ClassHook>(space, getStubCode(), firstMonitorStub_, clasp_,
1073 8 : native_, templateObject_, pcOffset_);
1074 : }
1075 : };
1076 : };
1077 :
1078 : class ICCall_ScriptedApplyArray : public ICMonitoredStub
1079 : {
1080 : friend class ICStubSpace;
1081 : public:
1082 : // The maximum length of an inlineable funcall array.
1083 : // Keep this small to avoid controllable stack overflows by attackers passing large
1084 : // arrays to fun.apply.
1085 : static const uint32_t MAX_ARGS_ARRAY_LENGTH = 16;
1086 :
1087 : protected:
1088 : uint32_t pcOffset_;
1089 :
1090 0 : ICCall_ScriptedApplyArray(JitCode* stubCode, ICStub* firstMonitorStub, uint32_t pcOffset)
1091 0 : : ICMonitoredStub(ICStub::Call_ScriptedApplyArray, stubCode, firstMonitorStub),
1092 0 : pcOffset_(pcOffset)
1093 0 : {}
1094 :
1095 : public:
1096 : static ICCall_ScriptedApplyArray* Clone(JSContext* cx,
1097 : ICStubSpace* space,
1098 : ICStub* firstMonitorStub,
1099 : ICCall_ScriptedApplyArray& other);
1100 :
1101 : static size_t offsetOfPCOffset() {
1102 : return offsetof(ICCall_ScriptedApplyArray, pcOffset_);
1103 : }
1104 :
1105 : // Compiler for this stub kind.
1106 0 : class Compiler : public ICCallStubCompiler {
1107 : protected:
1108 : ICStub* firstMonitorStub_;
1109 : uint32_t pcOffset_;
1110 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1111 :
1112 0 : virtual int32_t getKey() const {
1113 0 : return static_cast<int32_t>(engine_) |
1114 0 : (static_cast<int32_t>(kind) << 1);
1115 : }
1116 :
1117 : public:
1118 0 : Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset)
1119 0 : : ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArray),
1120 : firstMonitorStub_(firstMonitorStub),
1121 0 : pcOffset_(pcOffset)
1122 0 : { }
1123 :
1124 0 : ICStub* getStub(ICStubSpace* space) {
1125 0 : return newStub<ICCall_ScriptedApplyArray>(space, getStubCode(), firstMonitorStub_,
1126 0 : pcOffset_);
1127 : }
1128 : };
1129 : };
1130 :
1131 : class ICCall_ScriptedApplyArguments : public ICMonitoredStub
1132 : {
1133 : friend class ICStubSpace;
1134 :
1135 : protected:
1136 : uint32_t pcOffset_;
1137 :
1138 0 : ICCall_ScriptedApplyArguments(JitCode* stubCode, ICStub* firstMonitorStub, uint32_t pcOffset)
1139 0 : : ICMonitoredStub(ICStub::Call_ScriptedApplyArguments, stubCode, firstMonitorStub),
1140 0 : pcOffset_(pcOffset)
1141 0 : {}
1142 :
1143 : public:
1144 : static ICCall_ScriptedApplyArguments* Clone(JSContext* cx,
1145 : ICStubSpace* space,
1146 : ICStub* firstMonitorStub,
1147 : ICCall_ScriptedApplyArguments& other);
1148 :
1149 : static size_t offsetOfPCOffset() {
1150 : return offsetof(ICCall_ScriptedApplyArguments, pcOffset_);
1151 : }
1152 :
1153 : // Compiler for this stub kind.
1154 0 : class Compiler : public ICCallStubCompiler {
1155 : protected:
1156 : ICStub* firstMonitorStub_;
1157 : uint32_t pcOffset_;
1158 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1159 :
1160 0 : virtual int32_t getKey() const {
1161 0 : return static_cast<int32_t>(engine_) |
1162 0 : (static_cast<int32_t>(kind) << 1);
1163 : }
1164 :
1165 : public:
1166 0 : Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset)
1167 0 : : ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArguments),
1168 : firstMonitorStub_(firstMonitorStub),
1169 0 : pcOffset_(pcOffset)
1170 0 : { }
1171 :
1172 0 : ICStub* getStub(ICStubSpace* space) {
1173 0 : return newStub<ICCall_ScriptedApplyArguments>(space, getStubCode(), firstMonitorStub_,
1174 0 : pcOffset_);
1175 : }
1176 : };
1177 : };
1178 :
1179 : // Handles calls of the form |fun.call(...)| where fun is a scripted function.
1180 : class ICCall_ScriptedFunCall : public ICMonitoredStub
1181 : {
1182 : friend class ICStubSpace;
1183 :
1184 : protected:
1185 : uint32_t pcOffset_;
1186 :
1187 2 : ICCall_ScriptedFunCall(JitCode* stubCode, ICStub* firstMonitorStub, uint32_t pcOffset)
1188 2 : : ICMonitoredStub(ICStub::Call_ScriptedFunCall, stubCode, firstMonitorStub),
1189 2 : pcOffset_(pcOffset)
1190 2 : {}
1191 :
1192 : public:
1193 : static ICCall_ScriptedFunCall* Clone(JSContext* cx, ICStubSpace* space,
1194 : ICStub* firstMonitorStub, ICCall_ScriptedFunCall& other);
1195 :
1196 : static size_t offsetOfPCOffset() {
1197 : return offsetof(ICCall_ScriptedFunCall, pcOffset_);
1198 : }
1199 :
1200 : // Compiler for this stub kind.
1201 2 : class Compiler : public ICCallStubCompiler {
1202 : protected:
1203 : ICStub* firstMonitorStub_;
1204 : uint32_t pcOffset_;
1205 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1206 :
1207 2 : virtual int32_t getKey() const {
1208 2 : return static_cast<int32_t>(engine_) |
1209 2 : (static_cast<int32_t>(kind) << 1);
1210 : }
1211 :
1212 : public:
1213 2 : Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset)
1214 2 : : ICCallStubCompiler(cx, ICStub::Call_ScriptedFunCall),
1215 : firstMonitorStub_(firstMonitorStub),
1216 2 : pcOffset_(pcOffset)
1217 2 : { }
1218 :
1219 2 : ICStub* getStub(ICStubSpace* space) {
1220 4 : return newStub<ICCall_ScriptedFunCall>(space, getStubCode(), firstMonitorStub_,
1221 4 : pcOffset_);
1222 : }
1223 : };
1224 : };
1225 :
1226 : class ICCall_ConstStringSplit : public ICMonitoredStub
1227 : {
1228 : friend class ICStubSpace;
1229 :
1230 : protected:
1231 : uint32_t pcOffset_;
1232 : GCPtrString expectedStr_;
1233 : GCPtrString expectedSep_;
1234 : GCPtrObject templateObject_;
1235 :
1236 2 : ICCall_ConstStringSplit(JitCode* stubCode, ICStub* firstMonitorStub, uint32_t pcOffset,
1237 : JSString* str, JSString* sep, JSObject* templateObject)
1238 2 : : ICMonitoredStub(ICStub::Call_ConstStringSplit, stubCode, firstMonitorStub),
1239 : pcOffset_(pcOffset), expectedStr_(str), expectedSep_(sep),
1240 2 : templateObject_(templateObject)
1241 2 : { }
1242 :
1243 : public:
1244 2 : static size_t offsetOfExpectedStr() {
1245 2 : return offsetof(ICCall_ConstStringSplit, expectedStr_);
1246 : }
1247 :
1248 2 : static size_t offsetOfExpectedSep() {
1249 2 : return offsetof(ICCall_ConstStringSplit, expectedSep_);
1250 : }
1251 :
1252 2 : static size_t offsetOfTemplateObject() {
1253 2 : return offsetof(ICCall_ConstStringSplit, templateObject_);
1254 : }
1255 :
1256 0 : GCPtrString& expectedStr() {
1257 0 : return expectedStr_;
1258 : }
1259 :
1260 0 : GCPtrString& expectedSep() {
1261 0 : return expectedSep_;
1262 : }
1263 :
1264 0 : GCPtrObject& templateObject() {
1265 0 : return templateObject_;
1266 : }
1267 :
1268 2 : class Compiler : public ICCallStubCompiler {
1269 : protected:
1270 : ICStub* firstMonitorStub_;
1271 : uint32_t pcOffset_;
1272 : RootedString expectedStr_;
1273 : RootedString expectedSep_;
1274 : RootedObject templateObject_;
1275 :
1276 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1277 :
1278 2 : virtual int32_t getKey() const {
1279 2 : return static_cast<int32_t>(engine_) |
1280 2 : (static_cast<int32_t>(kind) << 1);
1281 : }
1282 :
1283 : public:
1284 2 : Compiler(JSContext* cx, ICStub* firstMonitorStub, uint32_t pcOffset, HandleString str,
1285 : HandleString sep, HandleValue templateObject)
1286 2 : : ICCallStubCompiler(cx, ICStub::Call_ConstStringSplit),
1287 : firstMonitorStub_(firstMonitorStub),
1288 : pcOffset_(pcOffset),
1289 : expectedStr_(cx, str),
1290 : expectedSep_(cx, sep),
1291 2 : templateObject_(cx, &templateObject.toObject())
1292 2 : { }
1293 :
1294 2 : ICStub* getStub(ICStubSpace* space) {
1295 4 : return newStub<ICCall_ConstStringSplit>(space, getStubCode(), firstMonitorStub_,
1296 : pcOffset_, expectedStr_, expectedSep_,
1297 4 : templateObject_);
1298 : }
1299 : };
1300 : };
1301 :
1302 : class ICCall_IsSuspendedStarGenerator : public ICStub
1303 : {
1304 : friend class ICStubSpace;
1305 :
1306 : protected:
1307 4 : explicit ICCall_IsSuspendedStarGenerator(JitCode* stubCode)
1308 4 : : ICStub(ICStub::Call_IsSuspendedStarGenerator, stubCode)
1309 4 : {}
1310 :
1311 : public:
1312 4 : class Compiler : public ICStubCompiler {
1313 : protected:
1314 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1315 :
1316 : public:
1317 4 : explicit Compiler(JSContext* cx)
1318 4 : : ICStubCompiler(cx, ICStub::Call_IsSuspendedStarGenerator, Engine::Baseline)
1319 4 : {}
1320 4 : ICStub* getStub(ICStubSpace* space) {
1321 4 : return newStub<ICCall_IsSuspendedStarGenerator>(space, getStubCode());
1322 : }
1323 : };
1324 : };
1325 :
1326 : // Stub for performing a TableSwitch, updating the IC's return address to jump
1327 : // to whatever point the switch is branching to.
1328 : class ICTableSwitch : public ICStub
1329 : {
1330 : friend class ICStubSpace;
1331 :
1332 : protected: // Protected to silence Clang warning.
1333 : void** table_;
1334 : int32_t min_;
1335 : int32_t length_;
1336 : void* defaultTarget_;
1337 :
1338 11 : ICTableSwitch(JitCode* stubCode, void** table,
1339 : int32_t min, int32_t length, void* defaultTarget)
1340 11 : : ICStub(TableSwitch, stubCode), table_(table),
1341 11 : min_(min), length_(length), defaultTarget_(defaultTarget)
1342 11 : {}
1343 :
1344 : public:
1345 : void fixupJumpTable(JSScript* script, BaselineScript* baseline);
1346 :
1347 11 : class Compiler : public ICStubCompiler {
1348 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1349 :
1350 : jsbytecode* pc_;
1351 :
1352 : public:
1353 11 : Compiler(JSContext* cx, jsbytecode* pc)
1354 11 : : ICStubCompiler(cx, ICStub::TableSwitch, Engine::Baseline), pc_(pc)
1355 11 : {}
1356 :
1357 : ICStub* getStub(ICStubSpace* space);
1358 : };
1359 : };
1360 :
1361 : // IC for constructing an iterator from an input value.
1362 : class ICIteratorNew_Fallback : public ICFallbackStub
1363 : {
1364 : friend class ICStubSpace;
1365 :
1366 20 : explicit ICIteratorNew_Fallback(JitCode* stubCode)
1367 20 : : ICFallbackStub(ICStub::IteratorNew_Fallback, stubCode)
1368 20 : { }
1369 :
1370 : public:
1371 20 : class Compiler : public ICStubCompiler {
1372 : protected:
1373 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1374 :
1375 : public:
1376 20 : explicit Compiler(JSContext* cx)
1377 20 : : ICStubCompiler(cx, ICStub::IteratorNew_Fallback, Engine::Baseline)
1378 20 : { }
1379 :
1380 20 : ICStub* getStub(ICStubSpace* space) {
1381 20 : return newStub<ICIteratorNew_Fallback>(space, getStubCode());
1382 : }
1383 : };
1384 : };
1385 :
1386 : // IC for testing if there are more values in an iterator.
1387 : class ICIteratorMore_Fallback : public ICFallbackStub
1388 : {
1389 : friend class ICStubSpace;
1390 :
1391 20 : explicit ICIteratorMore_Fallback(JitCode* stubCode)
1392 20 : : ICFallbackStub(ICStub::IteratorMore_Fallback, stubCode)
1393 20 : { }
1394 :
1395 : public:
1396 0 : void setHasNonStringResult() {
1397 0 : extra_ = 1;
1398 0 : }
1399 0 : bool hasNonStringResult() const {
1400 0 : MOZ_ASSERT(extra_ <= 1);
1401 0 : return extra_;
1402 : }
1403 :
1404 20 : class Compiler : public ICStubCompiler {
1405 : protected:
1406 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1407 :
1408 : public:
1409 20 : explicit Compiler(JSContext* cx)
1410 20 : : ICStubCompiler(cx, ICStub::IteratorMore_Fallback, Engine::Baseline)
1411 20 : { }
1412 :
1413 20 : ICStub* getStub(ICStubSpace* space) {
1414 20 : return newStub<ICIteratorMore_Fallback>(space, getStubCode());
1415 : }
1416 : };
1417 : };
1418 :
1419 : // IC for testing if there are more values in a native iterator.
1420 : class ICIteratorMore_Native : public ICStub
1421 : {
1422 : friend class ICStubSpace;
1423 :
1424 16 : explicit ICIteratorMore_Native(JitCode* stubCode)
1425 16 : : ICStub(ICStub::IteratorMore_Native, stubCode)
1426 16 : { }
1427 :
1428 : public:
1429 16 : class Compiler : public ICStubCompiler {
1430 : protected:
1431 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1432 :
1433 : public:
1434 16 : explicit Compiler(JSContext* cx)
1435 16 : : ICStubCompiler(cx, ICStub::IteratorMore_Native, Engine::Baseline)
1436 16 : { }
1437 :
1438 16 : ICStub* getStub(ICStubSpace* space) {
1439 16 : return newStub<ICIteratorMore_Native>(space, getStubCode());
1440 : }
1441 : };
1442 : };
1443 :
1444 : // IC for closing an iterator.
1445 : class ICIteratorClose_Fallback : public ICFallbackStub
1446 : {
1447 : friend class ICStubSpace;
1448 :
1449 20 : explicit ICIteratorClose_Fallback(JitCode* stubCode)
1450 20 : : ICFallbackStub(ICStub::IteratorClose_Fallback, stubCode)
1451 20 : { }
1452 :
1453 : public:
1454 20 : class Compiler : public ICStubCompiler {
1455 : protected:
1456 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1457 :
1458 : public:
1459 20 : explicit Compiler(JSContext* cx)
1460 20 : : ICStubCompiler(cx, ICStub::IteratorClose_Fallback, Engine::Baseline)
1461 20 : { }
1462 :
1463 20 : ICStub* getStub(ICStubSpace* space) {
1464 20 : return newStub<ICIteratorClose_Fallback>(space, getStubCode());
1465 : }
1466 : };
1467 : };
1468 :
1469 : // InstanceOf
1470 : // JSOP_INSTANCEOF
1471 : class ICInstanceOf_Fallback : public ICFallbackStub
1472 : {
1473 : friend class ICStubSpace;
1474 :
1475 10 : explicit ICInstanceOf_Fallback(JitCode* stubCode)
1476 10 : : ICFallbackStub(ICStub::InstanceOf_Fallback, stubCode)
1477 10 : { }
1478 :
1479 : static const uint16_t UNOPTIMIZABLE_ACCESS_BIT = 0x1;
1480 :
1481 : public:
1482 : static const uint32_t MAX_OPTIMIZED_STUBS = 4;
1483 :
1484 73 : void noteUnoptimizableAccess() {
1485 73 : extra_ |= UNOPTIMIZABLE_ACCESS_BIT;
1486 73 : }
1487 0 : bool hadUnoptimizableAccess() const {
1488 0 : return extra_ & UNOPTIMIZABLE_ACCESS_BIT;
1489 : }
1490 :
1491 10 : class Compiler : public ICStubCompiler {
1492 : protected:
1493 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1494 :
1495 : public:
1496 10 : explicit Compiler(JSContext* cx)
1497 10 : : ICStubCompiler(cx, ICStub::InstanceOf_Fallback, Engine::Baseline)
1498 10 : { }
1499 :
1500 10 : ICStub* getStub(ICStubSpace* space) {
1501 10 : return newStub<ICInstanceOf_Fallback>(space, getStubCode());
1502 : }
1503 : };
1504 : };
1505 :
1506 : class ICInstanceOf_Function : public ICStub
1507 : {
1508 : friend class ICStubSpace;
1509 :
1510 : GCPtrShape shape_;
1511 : GCPtrObject prototypeObj_;
1512 : uint32_t slot_;
1513 :
1514 : ICInstanceOf_Function(JitCode* stubCode, Shape* shape, JSObject* prototypeObj, uint32_t slot);
1515 :
1516 : public:
1517 0 : GCPtrShape& shape() {
1518 0 : return shape_;
1519 : }
1520 0 : GCPtrObject& prototypeObject() {
1521 0 : return prototypeObj_;
1522 : }
1523 0 : uint32_t slot() const {
1524 0 : return slot_;
1525 : }
1526 2 : static size_t offsetOfShape() {
1527 2 : return offsetof(ICInstanceOf_Function, shape_);
1528 : }
1529 2 : static size_t offsetOfPrototypeObject() {
1530 2 : return offsetof(ICInstanceOf_Function, prototypeObj_);
1531 : }
1532 2 : static size_t offsetOfSlot() {
1533 2 : return offsetof(ICInstanceOf_Function, slot_);
1534 : }
1535 :
1536 3 : class Compiler : public ICStubCompiler {
1537 : RootedShape shape_;
1538 : RootedObject prototypeObj_;
1539 : uint32_t slot_;
1540 :
1541 : protected:
1542 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1543 :
1544 : public:
1545 3 : Compiler(JSContext* cx, Shape* shape, JSObject* prototypeObj, uint32_t slot)
1546 3 : : ICStubCompiler(cx, ICStub::InstanceOf_Function, Engine::Baseline),
1547 : shape_(cx, shape),
1548 : prototypeObj_(cx, prototypeObj),
1549 3 : slot_(slot)
1550 3 : {}
1551 :
1552 3 : ICStub* getStub(ICStubSpace* space) {
1553 6 : return newStub<ICInstanceOf_Function>(space, getStubCode(), shape_, prototypeObj_,
1554 6 : slot_);
1555 : }
1556 : };
1557 : };
1558 :
1559 : // TypeOf
1560 : // JSOP_TYPEOF
1561 : // JSOP_TYPEOFEXPR
1562 : class ICTypeOf_Fallback : public ICFallbackStub
1563 : {
1564 : friend class ICStubSpace;
1565 :
1566 101 : explicit ICTypeOf_Fallback(JitCode* stubCode)
1567 101 : : ICFallbackStub(ICStub::TypeOf_Fallback, stubCode)
1568 101 : { }
1569 :
1570 : public:
1571 : static const uint32_t MAX_OPTIMIZED_STUBS = 6;
1572 :
1573 101 : class Compiler : public ICStubCompiler {
1574 : protected:
1575 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1576 :
1577 : public:
1578 101 : explicit Compiler(JSContext* cx)
1579 101 : : ICStubCompiler(cx, ICStub::TypeOf_Fallback, Engine::Baseline)
1580 101 : { }
1581 :
1582 101 : ICStub* getStub(ICStubSpace* space) {
1583 101 : return newStub<ICTypeOf_Fallback>(space, getStubCode());
1584 : }
1585 : };
1586 : };
1587 :
1588 : class ICRest_Fallback : public ICFallbackStub
1589 : {
1590 : friend class ICStubSpace;
1591 :
1592 : GCPtrArrayObject templateObject_;
1593 :
1594 14 : ICRest_Fallback(JitCode* stubCode, ArrayObject* templateObject)
1595 14 : : ICFallbackStub(ICStub::Rest_Fallback, stubCode), templateObject_(templateObject)
1596 14 : { }
1597 :
1598 : public:
1599 : static const uint32_t MAX_OPTIMIZED_STUBS = 8;
1600 :
1601 2 : GCPtrArrayObject& templateObject() {
1602 2 : return templateObject_;
1603 : }
1604 :
1605 14 : class Compiler : public ICStubCompiler {
1606 : protected:
1607 : RootedArrayObject templateObject;
1608 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1609 :
1610 : public:
1611 14 : Compiler(JSContext* cx, ArrayObject* templateObject)
1612 14 : : ICStubCompiler(cx, ICStub::Rest_Fallback, Engine::Baseline),
1613 14 : templateObject(cx, templateObject)
1614 14 : { }
1615 :
1616 14 : ICStub* getStub(ICStubSpace* space) {
1617 14 : return newStub<ICRest_Fallback>(space, getStubCode(), templateObject);
1618 : }
1619 : };
1620 : };
1621 :
1622 : // Stub for JSOP_RETSUB ("returning" from a |finally| block).
1623 : class ICRetSub_Fallback : public ICFallbackStub
1624 : {
1625 : friend class ICStubSpace;
1626 :
1627 12 : explicit ICRetSub_Fallback(JitCode* stubCode)
1628 12 : : ICFallbackStub(ICStub::RetSub_Fallback, stubCode)
1629 12 : { }
1630 :
1631 : public:
1632 : static const uint32_t MAX_OPTIMIZED_STUBS = 8;
1633 :
1634 12 : class Compiler : public ICStubCompiler {
1635 : protected:
1636 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1637 :
1638 : public:
1639 12 : explicit Compiler(JSContext* cx)
1640 12 : : ICStubCompiler(cx, ICStub::RetSub_Fallback, Engine::Baseline)
1641 12 : { }
1642 :
1643 12 : ICStub* getStub(ICStubSpace* space) {
1644 12 : return newStub<ICRetSub_Fallback>(space, getStubCode());
1645 : }
1646 : };
1647 : };
1648 :
1649 : // Optimized JSOP_RETSUB stub. Every stub maps a single pc offset to its
1650 : // native code address.
1651 : class ICRetSub_Resume : public ICStub
1652 : {
1653 : friend class ICStubSpace;
1654 :
1655 : protected:
1656 : uint32_t pcOffset_;
1657 : uint8_t* addr_;
1658 :
1659 4 : ICRetSub_Resume(JitCode* stubCode, uint32_t pcOffset, uint8_t* addr)
1660 4 : : ICStub(ICStub::RetSub_Resume, stubCode),
1661 : pcOffset_(pcOffset),
1662 4 : addr_(addr)
1663 4 : { }
1664 :
1665 : public:
1666 2 : static size_t offsetOfPCOffset() {
1667 2 : return offsetof(ICRetSub_Resume, pcOffset_);
1668 : }
1669 2 : static size_t offsetOfAddr() {
1670 2 : return offsetof(ICRetSub_Resume, addr_);
1671 : }
1672 :
1673 4 : class Compiler : public ICStubCompiler {
1674 : uint32_t pcOffset_;
1675 : uint8_t* addr_;
1676 :
1677 : MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
1678 :
1679 : public:
1680 4 : Compiler(JSContext* cx, uint32_t pcOffset, uint8_t* addr)
1681 4 : : ICStubCompiler(cx, ICStub::RetSub_Resume, Engine::Baseline),
1682 : pcOffset_(pcOffset),
1683 4 : addr_(addr)
1684 4 : { }
1685 :
1686 4 : ICStub* getStub(ICStubSpace* space) {
1687 4 : return newStub<ICRetSub_Resume>(space, getStubCode(), pcOffset_, addr_);
1688 : }
1689 : };
1690 : };
1691 :
1692 : inline bool
1693 145 : IsCacheableDOMProxy(JSObject* obj)
1694 : {
1695 145 : if (!obj->is<ProxyObject>())
1696 0 : return false;
1697 :
1698 145 : const BaseProxyHandler* handler = obj->as<ProxyObject>().handler();
1699 145 : return handler->family() == GetDOMProxyHandlerFamily();
1700 : }
1701 :
1702 : struct IonOsrTempData;
1703 :
1704 : template <typename T>
1705 : void EmitICUnboxedPreBarrier(MacroAssembler &masm, const T& address, JSValueType type);
1706 :
1707 : // Write an arbitrary value to a typed array or typed object address at dest.
1708 : // If the value could not be converted to the appropriate format, jump to
1709 : // failure.
1710 : template <typename T>
1711 : void StoreToTypedArray(JSContext* cx, MacroAssembler& masm, Scalar::Type type,
1712 : const ValueOperand& value, const T& dest, Register scratch,
1713 : Label* failure);
1714 :
1715 : } // namespace jit
1716 : } // namespace js
1717 :
1718 : #endif /* jit_BaselineIC_h */
|