LCOV - code coverage report
Current view: top level - js/src/jit - SharedIC.h (source / functions) Hit Total Coverage
Test: output.info Lines: 680 842 80.8 %
Date: 2017-07-14 16:53:18 Functions: 399 506 78.9 %
Legend: Lines: hit not hit

          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_SharedIC_h
       8             : #define jit_SharedIC_h
       9             : 
      10             : #include "jscntxt.h"
      11             : #include "jscompartment.h"
      12             : #include "jsgc.h"
      13             : 
      14             : #include "jit/BaselineICList.h"
      15             : #include "jit/BaselineJIT.h"
      16             : #include "jit/ICState.h"
      17             : #include "jit/MacroAssembler.h"
      18             : #include "jit/SharedICList.h"
      19             : #include "jit/SharedICRegisters.h"
      20             : #include "vm/ReceiverGuard.h"
      21             : #include "vm/TypedArrayObject.h"
      22             : 
      23             : namespace js {
      24             : namespace jit {
      25             : 
      26             : //
      27             : // Baseline Inline Caches are polymorphic caches that aggressively
      28             : // share their stub code.
      29             : //
      30             : // Every polymorphic site contains a linked list of stubs which are
      31             : // specific to that site.  These stubs are composed of a |StubData|
      32             : // structure that stores parametrization information (e.g.
      33             : // the shape pointer for a shape-check-and-property-get stub), any
      34             : // dynamic information (e.g. warm-up counters), a pointer to the stub code,
      35             : // and a pointer to the next stub state in the linked list.
      36             : //
      37             : // Every BaselineScript keeps an table of |CacheDescriptor| data
      38             : // structures, which store the following:
      39             : //      A pointer to the first StubData in the cache.
      40             : //      The bytecode PC of the relevant IC.
      41             : //      The machine-code PC where the call to the stubcode returns.
      42             : //
      43             : // A diagram:
      44             : //
      45             : //        Control flow                  Pointers
      46             : //      =======#                     ----.     .---->
      47             : //             #                         |     |
      48             : //             #======>                  \-----/
      49             : //
      50             : //
      51             : //                                   .---------------------------------------.
      52             : //                                   |         .-------------------------.   |
      53             : //                                   |         |         .----.          |   |
      54             : //         Baseline                  |         |         |    |          |   |
      55             : //         JIT Code              0   ^     1   ^     2   ^    |          |   |
      56             : //     +--------------+    .-->+-----+   +-----+   +-----+    |          |   |
      57             : //     |              |  #=|==>|     |==>|     |==>| FB  |    |          |   |
      58             : //     |              |  # |   +-----+   +-----+   +-----+    |          |   |
      59             : //     |              |  # |      #         #         #       |          |   |
      60             : //     |==============|==# |      #         #         #       |          |   |
      61             : //     |=== IC =======|    |      #         #         #       |          |   |
      62             : //  .->|==============|<===|======#=========#=========#       |          |   |
      63             : //  |  |              |    |                                  |          |   |
      64             : //  |  |              |    |                                  |          |   |
      65             : //  |  |              |    |                                  |          |   |
      66             : //  |  |              |    |                                  v          |   |
      67             : //  |  |              |    |                              +---------+    |   |
      68             : //  |  |              |    |                              | Fallback|    |   |
      69             : //  |  |              |    |                              | Stub    |    |   |
      70             : //  |  |              |    |                              | Code    |    |   |
      71             : //  |  |              |    |                              +---------+    |   |
      72             : //  |  +--------------+    |                                             |   |
      73             : //  |         |_______     |                              +---------+    |   |
      74             : //  |                |     |                              | Stub    |<---/   |
      75             : //  |        IC      |     \--.                           | Code    |        |
      76             : //  |    Descriptor  |        |                           +---------+        |
      77             : //  |      Table     v        |                                              |
      78             : //  |  +-----------------+    |                           +---------+        |
      79             : //  \--| Ins | PC | Stub |----/                           | Stub    |<-------/
      80             : //     +-----------------+                                | Code    |
      81             : //     |       ...       |                                +---------+
      82             : //     +-----------------+
      83             : //                                                          Shared
      84             : //                                                          Stub Code
      85             : //
      86             : //
      87             : // Type ICs
      88             : // ========
      89             : //
      90             : // Type ICs are otherwise regular ICs that are actually nested within
      91             : // other IC chains.  They serve to optimize locations in the code where the
      92             : // baseline compiler would have otherwise had to perform a type Monitor operation
      93             : // (e.g. the result of GetProp, GetElem, etc.), or locations where the baseline
      94             : // compiler would have had to modify a heap typeset using the type of an input
      95             : // value (e.g. SetProp, SetElem, etc.)
      96             : //
      97             : // There are two kinds of Type ICs: Monitor and Update.
      98             : //
      99             : // Note that type stub bodies are no-ops.  The stubs only exist for their
     100             : // guards, and their existence simply signifies that the typeset (implicit)
     101             : // that is being checked already contains that type.
     102             : //
     103             : // TypeMonitor ICs
     104             : // ---------------
     105             : // Monitor ICs are shared between stubs in the general IC, and monitor the resulting
     106             : // types of getter operations (call returns, getprop outputs, etc.)
     107             : //
     108             : //        +-----------+     +-----------+     +-----------+     +-----------+
     109             : //   ---->| Stub 1    |---->| Stub 2    |---->| Stub 3    |---->| FB Stub   |
     110             : //        +-----------+     +-----------+     +-----------+     +-----------+
     111             : //             |                  |                 |                  |
     112             : //             |------------------/-----------------/                  |
     113             : //             v                                                       |
     114             : //        +-----------+     +-----------+     +-----------+            |
     115             : //        | Type 1    |---->| Type 2    |---->| Type FB   |            |
     116             : //        +-----------+     +-----------+     +-----------+            |
     117             : //             |                 |                  |                  |
     118             : //  <----------/-----------------/------------------/------------------/
     119             : //                r e t u r n    p a t h
     120             : //
     121             : // After an optimized IC stub successfully executes, it passes control to the type stub
     122             : // chain to check the resulting type.  If no type stub succeeds, and the monitor fallback
     123             : // stub is reached, the monitor fallback stub performs a manual monitor, and also adds the
     124             : // appropriate type stub to the chain.
     125             : //
     126             : // The IC's main fallback, in addition to generating new mainline stubs, also generates
     127             : // type stubs as reflected by its returned value.
     128             : //
     129             : // NOTE: The type IC chain returns directly to the mainline code, not back to the
     130             : // stub it was entered from.  Thus, entering a type IC is a matter of a |jump|, not
     131             : // a |call|.  This allows us to safely call a VM Monitor function from within the monitor IC's
     132             : // fallback chain, since the return address (needed for stack inspection) is preserved.
     133             : //
     134             : //
     135             : // TypeUpdate ICs
     136             : // --------------
     137             : // Update ICs update heap typesets and monitor the input types of setter operations
     138             : // (setelem, setprop inputs, etc.).  Unlike monitor ICs, they are not shared
     139             : // between stubs on an IC, but instead are kept track of on a per-stub basis.
     140             : //
     141             : // This is because the main stubs for the operation will each identify a potentially
     142             : // different ObjectGroup to update.  New input types must be tracked on a group-to-
     143             : // group basis.
     144             : //
     145             : // Type-update ICs cannot be called in tail position (they must return to the
     146             : // the stub that called them so that the stub may continue to perform its original
     147             : // purpose).  This means that any VMCall to perform a manual type update from C++ must be
     148             : // done from within the main IC stub.  This necessitates that the stub enter a
     149             : // "BaselineStub" frame before making the call.
     150             : //
     151             : // If the type-update IC chain could itself make the VMCall, then the BaselineStub frame
     152             : // must be entered before calling the type-update chain, and exited afterward.  This
     153             : // is very expensive for a common case where we expect the type-update fallback to not
     154             : // be called.  To avoid the cost of entering and exiting a BaselineStub frame when
     155             : // using the type-update IC chain, we design the chain to not perform any VM-calls
     156             : // in its fallback.
     157             : //
     158             : // Instead, the type-update IC chain is responsible for returning 1 or 0, depending
     159             : // on if a type is represented in the chain or not.  The fallback stub simply returns
     160             : // 0, and all other optimized stubs return 1.
     161             : // If the chain returns 1, then the IC stub goes ahead and performs its operation.
     162             : // If the chain returns 0, then the IC stub performs a call to the fallback function
     163             : // inline (doing the requisite BaselineStub frame enter/exit).
     164             : // This allows us to avoid the expensive subfram enter/exit in the common case.
     165             : //
     166             : //                                 r e t u r n    p a t h
     167             : //   <--------------.-----------------.-----------------.-----------------.
     168             : //                  |                 |                 |                 |
     169             : //        +-----------+     +-----------+     +-----------+     +-----------+
     170             : //   ---->| Stub 1    |---->| Stub 2    |---->| Stub 3    |---->| FB Stub   |
     171             : //        +-----------+     +-----------+     +-----------+     +-----------+
     172             : //          |   ^             |   ^             |   ^
     173             : //          |   |             |   |             |   |
     174             : //          |   |             |   |             |   |----------------.
     175             : //          |   |             |   |             v   |1               |0
     176             : //          |   |             |   |         +-----------+    +-----------+
     177             : //          |   |             |   |         | Type 3.1  |--->|    FB 3   |
     178             : //          |   |             |   |         +-----------+    +-----------+
     179             : //          |   |             |   |
     180             : //          |   |             |   \-------------.-----------------.
     181             : //          |   |             |   |             |                 |
     182             : //          |   |             v   |1            |1                |0
     183             : //          |   |         +-----------+     +-----------+     +-----------+
     184             : //          |   |         | Type 2.1  |---->| Type 2.2  |---->|    FB 2   |
     185             : //          |   |         +-----------+     +-----------+     +-----------+
     186             : //          |   |
     187             : //          |   \-------------.-----------------.
     188             : //          |   |             |                 |
     189             : //          v   |1            |1                |0
     190             : //     +-----------+     +-----------+     +-----------+
     191             : //     | Type 1.1  |---->| Type 1.2  |---->|   FB 1    |
     192             : //     +-----------+     +-----------+     +-----------+
     193             : //
     194             : 
     195             : class ICStub;
     196             : class ICFallbackStub;
     197             : 
     198             : #define FORWARD_DECLARE_STUBS(kindName) class IC##kindName;
     199             :     IC_BASELINE_STUB_KIND_LIST(FORWARD_DECLARE_STUBS)
     200             :     IC_SHARED_STUB_KIND_LIST(FORWARD_DECLARE_STUBS)
     201             : #undef FORWARD_DECLARE_STUBS
     202             : 
     203             : #ifdef JS_JITSPEW
     204             : void FallbackICSpew(JSContext* cx, ICFallbackStub* stub, const char* fmt, ...)
     205             :     MOZ_FORMAT_PRINTF(3, 4);
     206             : void TypeFallbackICSpew(JSContext* cx, ICTypeMonitor_Fallback* stub, const char* fmt, ...)
     207             :     MOZ_FORMAT_PRINTF(3, 4);
     208             : #else
     209             : #define FallbackICSpew(...)
     210             : #define TypeFallbackICSpew(...)
     211             : #endif
     212             : 
     213             : //
     214             : // An entry in the JIT IC descriptor table.
     215             : //
     216             : class ICEntry
     217             : {
     218             :   private:
     219             :     // A pointer to the shared IC stub for this instruction.
     220             :     ICStub* firstStub_;
     221             : 
     222             :     // Offset from the start of the JIT code where the IC
     223             :     // load and call instructions are.
     224             :     uint32_t returnOffset_;
     225             : 
     226             :     // The PC of this IC's bytecode op within the JSScript.
     227             :     uint32_t pcOffset_ : 28;
     228             : 
     229             :   public:
     230             :     enum Kind {
     231             :         // A for-op IC entry.
     232             :         Kind_Op = 0,
     233             : 
     234             :         // A non-op IC entry.
     235             :         Kind_NonOp,
     236             : 
     237             :         // A fake IC entry for returning from a callVM for an op.
     238             :         Kind_CallVM,
     239             : 
     240             :         // A fake IC entry for returning from a callVM not for an op (e.g., in
     241             :         // the prologue).
     242             :         Kind_NonOpCallVM,
     243             : 
     244             :         // A fake IC entry for returning from a callVM to after the
     245             :         // warmup counter.
     246             :         Kind_WarmupCounter,
     247             : 
     248             :         // A fake IC entry for returning from a callVM to the interrupt
     249             :         // handler via the over-recursion check on function entry.
     250             :         Kind_StackCheck,
     251             : 
     252             :         // As above, but for the early check. See emitStackCheck.
     253             :         Kind_EarlyStackCheck,
     254             : 
     255             :         // A fake IC entry for returning from DebugTrapHandler.
     256             :         Kind_DebugTrap,
     257             : 
     258             :         // A fake IC entry for returning from a callVM to
     259             :         // Debug{Prologue,Epilogue}.
     260             :         Kind_DebugPrologue,
     261             :         Kind_DebugEpilogue,
     262             : 
     263             :         Kind_Invalid
     264             :     };
     265             : 
     266             :   private:
     267             :     // What this IC is for.
     268             :     Kind kind_ : 4;
     269             : 
     270             :     // Set the kind and asserts that it's sane.
     271       24731 :     void setKind(Kind kind) {
     272       24731 :         MOZ_ASSERT(kind < Kind_Invalid);
     273       24731 :         kind_ = kind;
     274       24731 :         MOZ_ASSERT(this->kind() == kind);
     275       24731 :     }
     276             : 
     277             :   public:
     278       22785 :     ICEntry(uint32_t pcOffset, Kind kind)
     279       22785 :       : firstStub_(nullptr), returnOffset_(), pcOffset_(pcOffset)
     280             :     {
     281             :         // The offset must fit in at least 28 bits, since we shave off 4 for
     282             :         // the Kind enum.
     283       22785 :         MOZ_ASSERT(pcOffset_ == pcOffset);
     284             :         JS_STATIC_ASSERT(BaselineScript::MAX_JSSCRIPT_LENGTH <= (1u << 28) - 1);
     285       22785 :         MOZ_ASSERT(pcOffset <= BaselineScript::MAX_JSSCRIPT_LENGTH);
     286       22785 :         setKind(kind);
     287       22785 :     }
     288             : 
     289       34700 :     CodeOffset returnOffset() const {
     290       34700 :         return CodeOffset(returnOffset_);
     291             :     }
     292             : 
     293       22785 :     void setReturnOffset(CodeOffset offset) {
     294       22785 :         MOZ_ASSERT(offset.offset() <= (size_t) UINT32_MAX);
     295       22785 :         returnOffset_ = (uint32_t) offset.offset();
     296       22785 :     }
     297             : 
     298      727421 :     uint32_t pcOffset() const {
     299      727421 :         return pcOffset_;
     300             :     }
     301             : 
     302       28618 :     jsbytecode* pc(JSScript* script) const {
     303       28618 :         return script->offsetToPC(pcOffset_);
     304             :     }
     305             : 
     306      152095 :     Kind kind() const {
     307             :         // MSVC compiles enums as signed.
     308      152095 :         return Kind(kind_ & 0xf);
     309             :     }
     310      127364 :     bool isForOp() const {
     311      127364 :         return kind() == Kind_Op;
     312             :     }
     313             : 
     314        1946 :     void setFakeKind(Kind kind) {
     315        1946 :         MOZ_ASSERT(kind != Kind_Op && kind != Kind_NonOp);
     316        1946 :         setKind(kind);
     317        1946 :     }
     318             : 
     319      240336 :     bool hasStub() const {
     320      240336 :         return firstStub_ != nullptr;
     321             :     }
     322      217540 :     ICStub* firstStub() const {
     323      217540 :         MOZ_ASSERT(hasStub());
     324      217540 :         return firstStub_;
     325             :     }
     326             : 
     327             :     ICFallbackStub* fallbackStub() const;
     328             : 
     329       20297 :     void setFirstStub(ICStub* stub) {
     330       20297 :         firstStub_ = stub;
     331       20297 :     }
     332             : 
     333       19345 :     static inline size_t offsetOfFirstStub() {
     334       19345 :         return offsetof(ICEntry, firstStub_);
     335             :     }
     336             : 
     337       19559 :     inline ICStub** addressOfFirstStub() {
     338       19559 :         return &firstStub_;
     339             :     }
     340             : 
     341             :   protected:
     342             :     void traceEntry(JSTracer* trc);
     343             : };
     344             : 
     345             : class BaselineICEntry : public ICEntry
     346             : {
     347             :   public:
     348       22785 :     BaselineICEntry(uint32_t pcOffset, Kind kind)
     349       22785 :       : ICEntry(pcOffset, kind)
     350       22785 :     { }
     351             : 
     352             :     void trace(JSTracer* trc);
     353             : };
     354             : 
     355             : class IonICEntry : public ICEntry
     356             : {
     357             :     JSScript* script_;
     358             : 
     359             :   public:
     360           0 :     IonICEntry(uint32_t pcOffset, Kind kind, JSScript* script)
     361           0 :       : ICEntry(pcOffset, kind),
     362           0 :         script_(script)
     363           0 :     { }
     364             : 
     365           0 :     JSScript* script() {
     366           0 :         return script_;
     367             :     }
     368             : 
     369             :     void trace(JSTracer* trc);
     370             : };
     371             : 
     372             : class ICMonitoredStub;
     373             : class ICMonitoredFallbackStub;
     374             : class ICUpdatedStub;
     375             : 
     376             : // Constant iterator that traverses arbitrary chains of ICStubs.
     377             : // No requirements are made of the ICStub used to construct this
     378             : // iterator, aside from that the stub be part of a nullptr-terminated
     379             : // chain.
     380             : // The iterator is considered to be at its end once it has been
     381             : // incremented _past_ the last stub.  Thus, if 'atEnd()' returns
     382             : // true, the '*' and '->' operations are not valid.
     383             : class ICStubConstIterator
     384             : {
     385             :     friend class ICStub;
     386             :     friend class ICFallbackStub;
     387             : 
     388             :   private:
     389             :     ICStub* currentStub_;
     390             : 
     391             :   public:
     392       31476 :     explicit ICStubConstIterator(ICStub* currentStub) : currentStub_(currentStub) {}
     393             : 
     394             :     static ICStubConstIterator StartingAt(ICStub* stub) {
     395             :         return ICStubConstIterator(stub);
     396             :     }
     397             :     static ICStubConstIterator End(ICStub* stub) {
     398             :         return ICStubConstIterator(nullptr);
     399             :     }
     400             : 
     401             :     bool operator ==(const ICStubConstIterator& other) const {
     402             :         return currentStub_ == other.currentStub_;
     403             :     }
     404             :     bool operator !=(const ICStubConstIterator& other) const {
     405             :         return !(*this == other);
     406             :     }
     407             : 
     408             :     ICStubConstIterator& operator++();
     409             : 
     410       36705 :     ICStubConstIterator operator++(int) {
     411       36705 :         ICStubConstIterator oldThis(*this);
     412       36705 :         ++(*this);
     413       36705 :         return oldThis;
     414             :     }
     415             : 
     416          17 :     ICStub* operator*() const {
     417          17 :         MOZ_ASSERT(currentStub_);
     418          17 :         return currentStub_;
     419             :     }
     420             : 
     421       68735 :     ICStub* operator ->() const {
     422       68735 :         MOZ_ASSERT(currentStub_);
     423       68735 :         return currentStub_;
     424             :     }
     425             : 
     426       68181 :     bool atEnd() const {
     427       68181 :         return currentStub_ == nullptr;
     428             :     }
     429             : };
     430             : 
     431             : // Iterator that traverses "regular" IC chains that start at an ICEntry
     432             : // and are terminated with an ICFallbackStub.
     433             : //
     434             : // The iterator is considered to be at its end once it is _at_ the
     435             : // fallback stub.  Thus, unlike the ICStubConstIterator, operators
     436             : // '*' and '->' are valid even if 'atEnd()' returns true - they
     437             : // will act on the fallback stub.
     438             : //
     439             : // This iterator also allows unlinking of stubs being traversed.
     440             : // Note that 'unlink' does not implicitly advance the iterator -
     441             : // it must be advanced explicitly using '++'.
     442             : class ICStubIterator
     443             : {
     444             :     friend class ICFallbackStub;
     445             : 
     446             :   private:
     447             :     ICEntry* icEntry_;
     448             :     ICFallbackStub* fallbackStub_;
     449             :     ICStub* previousStub_;
     450             :     ICStub* currentStub_;
     451             :     bool unlinked_;
     452             : 
     453             :     explicit ICStubIterator(ICFallbackStub* fallbackStub, bool end=false);
     454             :   public:
     455             : 
     456             :     bool operator ==(const ICStubIterator& other) const {
     457             :         // == should only ever be called on stubs from the same chain.
     458             :         MOZ_ASSERT(icEntry_ == other.icEntry_);
     459             :         MOZ_ASSERT(fallbackStub_ == other.fallbackStub_);
     460             :         return currentStub_ == other.currentStub_;
     461             :     }
     462             :     bool operator !=(const ICStubIterator& other) const {
     463             :         return !(*this == other);
     464             :     }
     465             : 
     466             :     ICStubIterator& operator++();
     467             : 
     468        5756 :     ICStubIterator operator++(int) {
     469        5756 :         ICStubIterator oldThis(*this);
     470        5756 :         ++(*this);
     471        5756 :         return oldThis;
     472             :     }
     473             : 
     474             :     ICStub* operator*() const {
     475             :         return currentStub_;
     476             :     }
     477             : 
     478       16959 :     ICStub* operator ->() const {
     479       16959 :         return currentStub_;
     480             :     }
     481             : 
     482       12140 :     bool atEnd() const {
     483       12140 :         return currentStub_ == (ICStub*) fallbackStub_;
     484             :     }
     485             : 
     486             :     void unlink(JSContext* cx);
     487             : };
     488             : 
     489             : //
     490             : // Base class for all IC stubs.
     491             : //
     492             : class ICStub
     493             : {
     494             :     friend class ICFallbackStub;
     495             : 
     496             :   public:
     497             :     enum Kind {
     498             :         INVALID = 0,
     499             : #define DEF_ENUM_KIND(kindName) kindName,
     500             :         IC_BASELINE_STUB_KIND_LIST(DEF_ENUM_KIND)
     501             :         IC_SHARED_STUB_KIND_LIST(DEF_ENUM_KIND)
     502             : #undef DEF_ENUM_KIND
     503             :         LIMIT
     504             :     };
     505             : 
     506       15235 :     static bool IsValidKind(Kind k) {
     507       15235 :         return (k > INVALID) && (k < LIMIT);
     508             :     }
     509       15235 :     static bool IsCacheIRKind(Kind k) {
     510       15235 :         return k == CacheIR_Regular || k == CacheIR_Monitored || k == CacheIR_Updated;
     511             :     }
     512             : 
     513         618 :     static const char* KindString(Kind k) {
     514         618 :         switch(k) {
     515             : #define DEF_KIND_STR(kindName) case kindName: return #kindName;
     516           0 :             IC_BASELINE_STUB_KIND_LIST(DEF_KIND_STR)
     517           0 :             IC_SHARED_STUB_KIND_LIST(DEF_KIND_STR)
     518             : #undef DEF_KIND_STR
     519             :           default:
     520           0 :             MOZ_CRASH("Invalid kind.");
     521             :         }
     522             :     }
     523             : 
     524             :     enum Trait {
     525             :         Regular             = 0x0,
     526             :         Fallback            = 0x1,
     527             :         Monitored           = 0x2,
     528             :         MonitoredFallback   = 0x3,
     529             :         Updated             = 0x4
     530             :     };
     531             : 
     532             :     void traceCode(JSTracer* trc, const char* name);
     533             :     void updateCode(JitCode* stubCode);
     534             :     void trace(JSTracer* trc);
     535             : 
     536             :     template <typename T, typename... Args>
     537       44504 :     static T* New(JSContext* cx, ICStubSpace* space, JitCode* code, Args&&... args) {
     538       44504 :         if (!code)
     539           0 :             return nullptr;
     540       44504 :         T* result = space->allocate<T>(code, mozilla::Forward<Args>(args)...);
     541       44504 :         if (!result)
     542           0 :             ReportOutOfMemory(cx);
     543       44504 :         return result;
     544             :     }
     545             : 
     546             :   protected:
     547             :     // The raw jitcode to call for this stub.
     548             :     uint8_t* stubCode_;
     549             : 
     550             :     // Pointer to next IC stub.  This is null for the last IC stub, which should
     551             :     // either be a fallback or inert IC stub.
     552             :     ICStub* next_;
     553             : 
     554             :     // A 16-bit field usable by subtypes of ICStub for subtype-specific small-info
     555             :     uint16_t extra_;
     556             : 
     557             :     // The kind of the stub.
     558             :     //  High bit is 'isFallback' flag.
     559             :     //  Second high bit is 'isMonitored' flag.
     560             :     Trait trait_ : 3;
     561             :     Kind kind_ : 13;
     562             : 
     563       25890 :     inline ICStub(Kind kind, JitCode* stubCode)
     564       25890 :       : stubCode_(stubCode->raw()),
     565             :         next_(nullptr),
     566             :         extra_(0),
     567             :         trait_(Regular),
     568       25890 :         kind_(kind)
     569             :     {
     570       25890 :         MOZ_ASSERT(stubCode != nullptr);
     571       25890 :     }
     572             : 
     573       24600 :     inline ICStub(Kind kind, Trait trait, JitCode* stubCode)
     574       24600 :       : stubCode_(stubCode->raw()),
     575             :         next_(nullptr),
     576             :         extra_(0),
     577             :         trait_(trait),
     578       24600 :         kind_(kind)
     579             :     {
     580       24600 :         MOZ_ASSERT(stubCode != nullptr);
     581       24600 :     }
     582             : 
     583      512250 :     inline Trait trait() const {
     584             :         // Workaround for MSVC reading trait_ as signed value.
     585      512250 :         return (Trait)(trait_ & 0x7);
     586             :     }
     587             : 
     588             :   public:
     589             : 
     590      139016 :     inline Kind kind() const {
     591      139016 :         return static_cast<Kind>(kind_);
     592             :     }
     593             : 
     594      274165 :     inline bool isFallback() const {
     595      274165 :         return trait() == Fallback || trait() == MonitoredFallback;
     596             :     }
     597             : 
     598       20173 :     inline bool isMonitored() const {
     599       20173 :         return trait() == Monitored;
     600             :     }
     601             : 
     602         149 :     inline bool isUpdated() const {
     603         149 :         return trait() == Updated;
     604             :     }
     605             : 
     606        4772 :     inline bool isMonitoredFallback() const {
     607        4772 :         return trait() == MonitoredFallback;
     608             :     }
     609             : 
     610             :     inline const ICFallbackStub* toFallbackStub() const {
     611             :         MOZ_ASSERT(isFallback());
     612             :         return reinterpret_cast<const ICFallbackStub*>(this);
     613             :     }
     614             : 
     615      136011 :     inline ICFallbackStub* toFallbackStub() {
     616      136011 :         MOZ_ASSERT(isFallback());
     617      136011 :         return reinterpret_cast<ICFallbackStub*>(this);
     618             :     }
     619             : 
     620             :     inline const ICMonitoredStub* toMonitoredStub() const {
     621             :         MOZ_ASSERT(isMonitored());
     622             :         return reinterpret_cast<const ICMonitoredStub*>(this);
     623             :     }
     624             : 
     625        9715 :     inline ICMonitoredStub* toMonitoredStub() {
     626        9715 :         MOZ_ASSERT(isMonitored());
     627        9715 :         return reinterpret_cast<ICMonitoredStub*>(this);
     628             :     }
     629             : 
     630             :     inline const ICMonitoredFallbackStub* toMonitoredFallbackStub() const {
     631             :         MOZ_ASSERT(isMonitoredFallback());
     632             :         return reinterpret_cast<const ICMonitoredFallbackStub*>(this);
     633             :     }
     634             : 
     635        4638 :     inline ICMonitoredFallbackStub* toMonitoredFallbackStub() {
     636        4638 :         MOZ_ASSERT(isMonitoredFallback());
     637        4638 :         return reinterpret_cast<ICMonitoredFallbackStub*>(this);
     638             :     }
     639             : 
     640             :     inline const ICUpdatedStub* toUpdatedStub() const {
     641             :         MOZ_ASSERT(isUpdated());
     642             :         return reinterpret_cast<const ICUpdatedStub*>(this);
     643             :     }
     644             : 
     645          15 :     inline ICUpdatedStub* toUpdatedStub() {
     646          15 :         MOZ_ASSERT(isUpdated());
     647          15 :         return reinterpret_cast<ICUpdatedStub*>(this);
     648             :     }
     649             : 
     650             : #define KIND_METHODS(kindName)   \
     651             :     inline bool is##kindName() const { return kind() == kindName; } \
     652             :     inline const IC##kindName* to##kindName() const { \
     653             :         MOZ_ASSERT(is##kindName()); \
     654             :         return reinterpret_cast<const IC##kindName*>(this); \
     655             :     } \
     656             :     inline IC##kindName* to##kindName() { \
     657             :         MOZ_ASSERT(is##kindName()); \
     658             :         return reinterpret_cast<IC##kindName*>(this); \
     659             :     }
     660      106078 :     IC_BASELINE_STUB_KIND_LIST(KIND_METHODS)
     661       52269 :     IC_SHARED_STUB_KIND_LIST(KIND_METHODS)
     662             : #undef KIND_METHODS
     663             : 
     664       67205 :     inline ICStub* next() const {
     665       67205 :         return next_;
     666             :     }
     667             : 
     668             :     inline bool hasNext() const {
     669             :         return next_ != nullptr;
     670             :     }
     671             : 
     672       18839 :     inline void setNext(ICStub* stub) {
     673             :         // Note: next_ only needs to be changed under the compilation lock for
     674             :         // non-type-monitor/update ICs.
     675       18839 :         next_ = stub;
     676       18839 :     }
     677             : 
     678       18365 :     inline ICStub** addressOfNext() {
     679       18365 :         return &next_;
     680             :     }
     681             : 
     682         334 :     inline JitCode* jitCode() {
     683         334 :         return JitCode::FromExecutable(stubCode_);
     684             :     }
     685             : 
     686             :     inline uint8_t* rawStubCode() const {
     687             :         return stubCode_;
     688             :     }
     689             : 
     690             :     // This method is not valid on TypeUpdate stub chains!
     691      118803 :     inline ICFallbackStub* getChainFallback() {
     692      118803 :         ICStub* lastStub = this;
     693      236079 :         while (lastStub->next_)
     694       58638 :             lastStub = lastStub->next_;
     695      118803 :         MOZ_ASSERT(lastStub->isFallback());
     696      118803 :         return lastStub->toFallbackStub();
     697             :     }
     698             : 
     699             :     inline ICStubConstIterator beginHere() {
     700             :         return ICStubConstIterator::StartingAt(this);
     701             :     }
     702             : 
     703        1900 :     static inline size_t offsetOfNext() {
     704        1900 :         return offsetof(ICStub, next_);
     705             :     }
     706             : 
     707       21710 :     static inline size_t offsetOfStubCode() {
     708       21710 :         return offsetof(ICStub, stubCode_);
     709             :     }
     710             : 
     711             :     static inline size_t offsetOfExtra() {
     712             :         return offsetof(ICStub, extra_);
     713             :     }
     714             : 
     715             :     static bool NonCacheIRStubMakesGCCalls(Kind kind);
     716             :     bool makesGCCalls() const;
     717             : 
     718             :     // Optimized stubs get purged on GC.  But some stubs can be active on the
     719             :     // stack during GC - specifically the ones that can make calls.  To ensure
     720             :     // that these do not get purged, all stubs that can make calls are allocated
     721             :     // in the fallback stub space.
     722           0 :     bool allocatedInFallbackSpace() const {
     723           0 :         MOZ_ASSERT(next());
     724           0 :         return makesGCCalls();
     725             :     }
     726             : };
     727             : 
     728             : class ICFallbackStub : public ICStub
     729             : {
     730             :     friend class ICStubConstIterator;
     731             :   protected:
     732             :     // Fallback stubs need these fields to easily add new stubs to
     733             :     // the linked list of stubs for an IC.
     734             : 
     735             :     // The IC entry for this linked list of stubs.
     736             :     ICEntry* icEntry_;
     737             : 
     738             :     // The number of stubs kept in the IC entry.
     739             :     ICState state_;
     740             : 
     741             :     // A pointer to the location stub pointer that needs to be
     742             :     // changed to add a new "last" stub immediately before the fallback
     743             :     // stub.  This'll start out pointing to the icEntry's "firstStub_"
     744             :     // field, and as new stubs are added, it'll point to the current
     745             :     // last stub's "next_" field.
     746             :     ICStub** lastStubPtrAddr_;
     747             : 
     748        5922 :     ICFallbackStub(Kind kind, JitCode* stubCode)
     749        5922 :       : ICStub(kind, ICStub::Fallback, stubCode),
     750             :         icEntry_(nullptr),
     751             :         state_(),
     752        5922 :         lastStubPtrAddr_(nullptr) {}
     753             : 
     754       11286 :     ICFallbackStub(Kind kind, Trait trait, JitCode* stubCode)
     755       11286 :       : ICStub(kind, trait, stubCode),
     756             :         icEntry_(nullptr),
     757             :         state_(),
     758       11286 :         lastStubPtrAddr_(nullptr)
     759             :     {
     760       11286 :         MOZ_ASSERT(trait == ICStub::Fallback ||
     761             :                    trait == ICStub::MonitoredFallback);
     762       11286 :     }
     763             : 
     764             :   public:
     765       51101 :     inline ICEntry* icEntry() const {
     766       51101 :         return icEntry_;
     767             :     }
     768             : 
     769       17083 :     inline size_t numOptimizedStubs() const {
     770       17083 :         return state_.numOptimizedStubs();
     771             :     }
     772             : 
     773           0 :     void setInvalid() {
     774           0 :         state_.setInvalid();
     775           0 :     }
     776             : 
     777       10091 :     bool invalid() const {
     778       10091 :         return state_.invalid();
     779             :     }
     780             : 
     781       37876 :     ICState& state() {
     782       37876 :         return state_;
     783             :     }
     784             : 
     785             :     // The icEntry and lastStubPtrAddr_ fields can't be initialized when the stub is
     786             :     // created since the stub is created at compile time, and we won't know the IC entry
     787             :     // address until after compile when the JitScript is created.  This method
     788             :     // allows these fields to be fixed up at that point.
     789       17208 :     void fixupICEntry(ICEntry* icEntry) {
     790       17208 :         MOZ_ASSERT(icEntry_ == nullptr);
     791       17208 :         MOZ_ASSERT(lastStubPtrAddr_ == nullptr);
     792       17208 :         icEntry_ = icEntry;
     793       17208 :         lastStubPtrAddr_ = icEntry_->addressOfFirstStub();
     794       17208 :     }
     795             : 
     796             :     // Add a new stub to the IC chain terminated by this fallback stub.
     797       10013 :     void addNewStub(ICStub* stub) {
     798       10013 :         MOZ_ASSERT(!invalid());
     799       10013 :         MOZ_ASSERT(*lastStubPtrAddr_ == this);
     800       10013 :         MOZ_ASSERT(stub->next() == nullptr);
     801       10013 :         stub->setNext(this);
     802       10013 :         *lastStubPtrAddr_ = stub;
     803       10013 :         lastStubPtrAddr_ = stub->addressOfNext();
     804       10013 :         state_.trackAttached();
     805       10013 :     }
     806             : 
     807        9068 :     ICStubConstIterator beginChainConst() const {
     808        9068 :         return ICStubConstIterator(icEntry_->firstStub());
     809             :     }
     810             : 
     811        6384 :     ICStubIterator beginChain() {
     812        6384 :         return ICStubIterator(this);
     813             :     }
     814             : 
     815         760 :     bool hasStub(ICStub::Kind kind) const {
     816        1807 :         for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
     817        1047 :             if (iter->kind() == kind)
     818           0 :                 return true;
     819             :         }
     820         760 :         return false;
     821             :     }
     822             : 
     823        1852 :     unsigned numStubsWithKind(ICStub::Kind kind) const {
     824        1852 :         unsigned count = 0;
     825        4289 :         for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
     826        2437 :             if (iter->kind() == kind)
     827         585 :                 count++;
     828             :         }
     829        1852 :         return count;
     830             :     }
     831             : 
     832             :     void discardStubs(JSContext* cx);
     833             : 
     834             :     void unlinkStub(Zone* zone, ICStub* prev, ICStub* stub);
     835             :     void unlinkStubsWithKind(JSContext* cx, ICStub::Kind kind);
     836             : };
     837             : 
     838             : // Base class for Trait::Regular CacheIR stubs
     839             : class ICCacheIR_Regular : public ICStub
     840             : {
     841             :     const CacheIRStubInfo* stubInfo_;
     842             : 
     843             :   public:
     844         394 :     ICCacheIR_Regular(JitCode* stubCode, const CacheIRStubInfo* stubInfo)
     845         394 :       : ICStub(ICStub::CacheIR_Regular, stubCode),
     846         394 :         stubInfo_(stubInfo)
     847         394 :     {}
     848             : 
     849             :     void notePreliminaryObject() {
     850             :         extra_ = 1;
     851             :     }
     852           0 :     bool hasPreliminaryObject() const {
     853           0 :         return extra_;
     854             :     }
     855             : 
     856         739 :     const CacheIRStubInfo* stubInfo() const {
     857         739 :         return stubInfo_;
     858             :     }
     859             : 
     860             :     uint8_t* stubDataStart();
     861             : };
     862             : 
     863             : // Monitored stubs are IC stubs that feed a single resulting value out to a
     864             : // type monitor operation.
     865             : class ICMonitoredStub : public ICStub
     866             : {
     867             :   protected:
     868             :     // Pointer to the start of the type monitoring stub chain.
     869             :     ICStub* firstMonitorStub_;
     870             : 
     871             :     ICMonitoredStub(Kind kind, JitCode* stubCode, ICStub* firstMonitorStub);
     872             : 
     873             :   public:
     874        4756 :     inline void updateFirstMonitorStub(ICStub* monitorStub) {
     875             :         // This should only be called once: when the first optimized monitor stub
     876             :         // is added to the type monitor IC chain.
     877        4756 :         MOZ_ASSERT(firstMonitorStub_ && firstMonitorStub_->isTypeMonitor_Fallback());
     878        4756 :         firstMonitorStub_ = monitorStub;
     879        4756 :     }
     880         203 :     inline void resetFirstMonitorStub(ICStub* monitorFallback) {
     881         203 :         MOZ_ASSERT(monitorFallback->isTypeMonitor_Fallback());
     882         203 :         firstMonitorStub_ = monitorFallback;
     883         203 :     }
     884        4756 :     inline ICStub* firstMonitorStub() const {
     885        4756 :         return firstMonitorStub_;
     886             :     }
     887             : 
     888         239 :     static inline size_t offsetOfFirstMonitorStub() {
     889         239 :         return offsetof(ICMonitoredStub, firstMonitorStub_);
     890             :     }
     891             : };
     892             : 
     893             : class ICCacheIR_Monitored : public ICMonitoredStub
     894             : {
     895             :     const CacheIRStubInfo* stubInfo_;
     896             : 
     897             :   public:
     898        4523 :     ICCacheIR_Monitored(JitCode* stubCode, ICStub* firstMonitorStub,
     899             :                         const CacheIRStubInfo* stubInfo)
     900        4523 :       : ICMonitoredStub(ICStub::CacheIR_Monitored, stubCode, firstMonitorStub),
     901        4523 :         stubInfo_(stubInfo)
     902        4523 :     {}
     903             : 
     904             :     static ICCacheIR_Monitored* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
     905             :                                       ICCacheIR_Monitored& other);
     906             : 
     907         427 :     void notePreliminaryObject() {
     908         427 :         extra_ = 1;
     909         427 :     }
     910        3018 :     bool hasPreliminaryObject() const {
     911        3018 :         return extra_;
     912             :     }
     913             : 
     914        4150 :     const CacheIRStubInfo* stubInfo() const {
     915        4150 :         return stubInfo_;
     916             :     }
     917             : 
     918             :     uint8_t* stubDataStart();
     919             : };
     920             : 
     921             : // Updated stubs are IC stubs that use a TypeUpdate IC to track
     922             : // the status of heap typesets that need to be updated.
     923             : class ICUpdatedStub : public ICStub
     924             : {
     925             :   protected:
     926             :     // Pointer to the start of the type updating stub chain.
     927             :     ICStub* firstUpdateStub_;
     928             : 
     929             :     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
     930             :     uint32_t numOptimizedStubs_;
     931             : 
     932        1069 :     ICUpdatedStub(Kind kind, JitCode* stubCode)
     933        1069 :       : ICStub(kind, ICStub::Updated, stubCode),
     934             :         firstUpdateStub_(nullptr),
     935        1069 :         numOptimizedStubs_(0)
     936        1069 :     {}
     937             : 
     938             :   public:
     939             :     MOZ_MUST_USE bool initUpdatingChain(JSContext* cx, ICStubSpace* space);
     940             : 
     941             :     MOZ_MUST_USE bool addUpdateStubForValue(JSContext* cx, HandleScript script, HandleObject obj,
     942             :                                             HandleObjectGroup group, HandleId id, HandleValue val);
     943             : 
     944         596 :     void addOptimizedUpdateStub(ICStub* stub) {
     945         596 :         if (firstUpdateStub_->isTypeUpdate_Fallback()) {
     946         562 :             stub->setNext(firstUpdateStub_);
     947         562 :             firstUpdateStub_ = stub;
     948             :         } else {
     949          34 :             ICStub* iter = firstUpdateStub_;
     950          34 :             MOZ_ASSERT(iter->next() != nullptr);
     951          23 :             while (!iter->next()->isTypeUpdate_Fallback())
     952          23 :                 iter = iter->next();
     953          34 :             MOZ_ASSERT(iter->next()->next() == nullptr);
     954          34 :             stub->setNext(iter->next());
     955          34 :             iter->setNext(stub);
     956             :         }
     957             : 
     958         596 :         numOptimizedStubs_++;
     959         596 :     }
     960             : 
     961          15 :     inline ICStub* firstUpdateStub() const {
     962          15 :         return firstUpdateStub_;
     963             :     }
     964             : 
     965             :     void resetUpdateStubChain(Zone* zone);
     966             : 
     967         445 :     bool hasTypeUpdateStub(ICStub::Kind kind) {
     968         445 :         ICStub* stub = firstUpdateStub_;
     969           4 :         do {
     970         449 :             if (stub->kind() == kind)
     971           0 :                 return true;
     972             : 
     973         449 :             stub = stub->next();
     974         449 :         } while (stub);
     975             : 
     976         445 :         return false;
     977             :     }
     978             : 
     979             :     inline uint32_t numOptimizedStubs() const {
     980             :         return numOptimizedStubs_;
     981             :     }
     982             : 
     983          52 :     static inline size_t offsetOfFirstUpdateStub() {
     984          52 :         return offsetof(ICUpdatedStub, firstUpdateStub_);
     985             :     }
     986             : };
     987             : 
     988             : class ICCacheIR_Updated : public ICUpdatedStub
     989             : {
     990             :     const CacheIRStubInfo* stubInfo_;
     991             :     GCPtrObjectGroup updateStubGroup_;
     992             :     GCPtrId updateStubId_;
     993             : 
     994             :   public:
     995        1069 :     ICCacheIR_Updated(JitCode* stubCode, const CacheIRStubInfo* stubInfo)
     996        1069 :       : ICUpdatedStub(ICStub::CacheIR_Updated, stubCode),
     997             :         stubInfo_(stubInfo),
     998             :         updateStubGroup_(nullptr),
     999        1069 :         updateStubId_(JSID_EMPTY)
    1000        1069 :     {}
    1001             : 
    1002             :     static ICCacheIR_Updated* Clone(JSContext* cx, ICStubSpace* space, ICStub* firstMonitorStub,
    1003             :                                     ICCacheIR_Updated& other);
    1004             : 
    1005        1667 :     GCPtrObjectGroup& updateStubGroup() {
    1006        1667 :         return updateStubGroup_;
    1007             :     }
    1008        1667 :     GCPtrId& updateStubId() {
    1009        1667 :         return updateStubId_;
    1010             :     }
    1011             : 
    1012         464 :     void notePreliminaryObject() {
    1013         464 :         extra_ = 1;
    1014         464 :     }
    1015        1031 :     bool hasPreliminaryObject() const {
    1016        1031 :         return extra_;
    1017             :     }
    1018             : 
    1019        1394 :     const CacheIRStubInfo* stubInfo() const {
    1020        1394 :         return stubInfo_;
    1021             :     }
    1022             : 
    1023             :     uint8_t* stubDataStart();
    1024             : };
    1025             : 
    1026             : // Base class for stubcode compilers.
    1027       44626 : class ICStubCompiler
    1028             : {
    1029             :     // Prevent GC in the middle of stub compilation.
    1030             :     js::gc::AutoSuppressGC suppressGC;
    1031             : 
    1032             :   public:
    1033             :     using Engine = ICStubEngine;
    1034             : 
    1035             :   protected:
    1036             :     JSContext* cx;
    1037             :     ICStub::Kind kind;
    1038             :     Engine engine_;
    1039             :     bool inStubFrame_;
    1040             : 
    1041             : #ifdef DEBUG
    1042             :     bool entersStubFrame_;
    1043             :     uint32_t framePushedAtEnterStubFrame_;
    1044             : #endif
    1045             : 
    1046             :     // By default the stubcode key is just the kind.
    1047       29619 :     virtual int32_t getKey() const {
    1048       29619 :         return static_cast<int32_t>(engine_) |
    1049       29619 :               (static_cast<int32_t>(kind) << 1);
    1050             :     }
    1051             : 
    1052             :     virtual MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm) = 0;
    1053        2149 :     virtual void postGenerateStubCode(MacroAssembler& masm, Handle<JitCode*> genCode) {}
    1054             : 
    1055             :     JitCode* getStubCode();
    1056             : 
    1057       44626 :     ICStubCompiler(JSContext* cx, ICStub::Kind kind, Engine engine)
    1058       44626 :       : suppressGC(cx), cx(cx), kind(kind), engine_(engine), inStubFrame_(false)
    1059             : #ifdef DEBUG
    1060       44626 :       , entersStubFrame_(false), framePushedAtEnterStubFrame_(0)
    1061             : #endif
    1062       44626 :     {}
    1063             : 
    1064             :     // Push a payload specialized per compiler needed to execute stubs.
    1065             :     void PushStubPayload(MacroAssembler& masm, Register scratch);
    1066             :     void pushStubPayload(MacroAssembler& masm, Register scratch);
    1067             : 
    1068             :     // Emits a tail call to a VMFunction wrapper.
    1069             :     MOZ_MUST_USE bool tailCallVM(const VMFunction& fun, MacroAssembler& masm);
    1070             : 
    1071             :     // Emits a normal (non-tail) call to a VMFunction wrapper.
    1072             :     MOZ_MUST_USE bool callVM(const VMFunction& fun, MacroAssembler& masm);
    1073             : 
    1074             :     // A stub frame is used when a stub wants to call into the VM without
    1075             :     // performing a tail call. This is required for the return address
    1076             :     // to pc mapping to work.
    1077             :     void enterStubFrame(MacroAssembler& masm, Register scratch);
    1078             :     void assumeStubFrame(MacroAssembler& masm);
    1079             :     void leaveStubFrame(MacroAssembler& masm, bool calledIntoIon = false);
    1080             : 
    1081             :     // Some stubs need to emit Gecko Profiler updates.  This emits the guarding
    1082             :     // jitcode for those stubs.  If profiling is not enabled, jumps to the
    1083             :     // given label.
    1084             :     void guardProfilingEnabled(MacroAssembler& masm, Register scratch, Label* skip);
    1085             : 
    1086             :   public:
    1087         556 :     static inline AllocatableGeneralRegisterSet availableGeneralRegs(size_t numInputs) {
    1088         556 :         AllocatableGeneralRegisterSet regs(GeneralRegisterSet::All());
    1089             : #if defined(JS_CODEGEN_ARM)
    1090             :         MOZ_ASSERT(!regs.has(BaselineStackReg));
    1091             :         MOZ_ASSERT(!regs.has(ICTailCallReg));
    1092             :         regs.take(BaselineSecondScratchReg);
    1093             : #elif defined(JS_CODEGEN_MIPS32) || defined(JS_CODEGEN_MIPS64)
    1094             :         MOZ_ASSERT(!regs.has(BaselineStackReg));
    1095             :         MOZ_ASSERT(!regs.has(ICTailCallReg));
    1096             :         MOZ_ASSERT(!regs.has(BaselineSecondScratchReg));
    1097             : #elif defined(JS_CODEGEN_ARM64)
    1098             :         MOZ_ASSERT(!regs.has(PseudoStackPointer));
    1099             :         MOZ_ASSERT(!regs.has(RealStackPointer));
    1100             :         MOZ_ASSERT(!regs.has(ICTailCallReg));
    1101             : #else
    1102         556 :         MOZ_ASSERT(!regs.has(BaselineStackReg));
    1103             : #endif
    1104         556 :         regs.take(BaselineFrameReg);
    1105         556 :         regs.take(ICStubReg);
    1106             : #ifdef JS_CODEGEN_X64
    1107         556 :         regs.take(ExtractTemp0);
    1108         556 :         regs.take(ExtractTemp1);
    1109             : #endif
    1110             : 
    1111         556 :         switch (numInputs) {
    1112             :           case 0:
    1113         297 :             break;
    1114             :           case 1:
    1115         120 :             regs.take(R0);
    1116         120 :             break;
    1117             :           case 2:
    1118         139 :             regs.take(R0);
    1119         139 :             regs.take(R1);
    1120         139 :             break;
    1121             :           default:
    1122           0 :             MOZ_CRASH("Invalid numInputs");
    1123             :         }
    1124             : 
    1125         556 :         return regs;
    1126             :     }
    1127             : 
    1128             :   protected:
    1129             :     template <typename T, typename... Args>
    1130       44426 :     T* newStub(Args&&... args) {
    1131       44426 :         return ICStub::New<T>(cx, mozilla::Forward<Args>(args)...);
    1132             :     }
    1133             : 
    1134             :   public:
    1135             :     virtual ICStub* getStub(ICStubSpace* space) = 0;
    1136             : 
    1137       18790 :     static ICStubSpace* StubSpaceForStub(bool makesGCCalls, JSScript* outerScript, Engine engine) {
    1138       18790 :         if (makesGCCalls) {
    1139        2138 :             if (engine == ICStubCompiler::Engine::Baseline)
    1140        2138 :                 return outerScript->baselineScript()->fallbackStubSpace();
    1141           0 :             return outerScript->ionScript()->fallbackStubSpace();
    1142             :         }
    1143       16652 :         return outerScript->zone()->jitZone()->optimizedStubSpace();
    1144             :     }
    1145       12726 :     ICStubSpace* getStubSpace(JSScript* outerScript) {
    1146       12726 :         return StubSpaceForStub(ICStub::NonCacheIRStubMakesGCCalls(kind), outerScript, engine_);
    1147             :     }
    1148             : };
    1149             : 
    1150        3385 : class SharedStubInfo
    1151             : {
    1152             :     BaselineFrame* maybeFrame_;
    1153             :     RootedScript outerScript_;
    1154             :     RootedScript innerScript_;
    1155             :     ICEntry* icEntry_;
    1156             : 
    1157             :   public:
    1158             :     SharedStubInfo(JSContext* cx, void* payload, ICEntry* entry);
    1159             : 
    1160        1273 :     ICStubCompiler::Engine engine() const {
    1161        1273 :         return maybeFrame_
    1162        1273 :                ? ICStubCompiler::Engine::Baseline
    1163        1273 :                : ICStubCompiler::Engine::IonSharedIC;
    1164             :     }
    1165             : 
    1166         934 :     HandleScript script() const {
    1167         934 :         MOZ_ASSERT(innerScript_);
    1168         934 :         return innerScript_;
    1169             :     }
    1170             : 
    1171        2209 :     HandleScript innerScript() const {
    1172        2209 :         MOZ_ASSERT(innerScript_);
    1173        2209 :         return innerScript_;
    1174             :     }
    1175             : 
    1176             :     HandleScript outerScript(JSContext* cx);
    1177             : 
    1178        2207 :     jsbytecode* pc() const {
    1179        2207 :         return icEntry()->pc(innerScript());
    1180             :     }
    1181             : 
    1182             :     uint32_t pcOffset() const {
    1183             :         return script()->pcToOffset(pc());
    1184             :     }
    1185             : 
    1186             :     BaselineFrame* frame() const {
    1187             :         MOZ_ASSERT(maybeFrame_);
    1188             :         return maybeFrame_;
    1189             :     }
    1190             : 
    1191        1273 :     BaselineFrame* maybeFrame() const {
    1192        1273 :         return maybeFrame_;
    1193             :     }
    1194             : 
    1195        2207 :     ICEntry* icEntry() const {
    1196        2207 :         return icEntry_;
    1197             :     }
    1198             : };
    1199             : 
    1200             : // Monitored fallback stubs - as the name implies.
    1201             : class ICMonitoredFallbackStub : public ICFallbackStub
    1202             : {
    1203             :   protected:
    1204             :     // Pointer to the fallback monitor stub.
    1205             :     ICTypeMonitor_Fallback* fallbackMonitorStub_;
    1206             : 
    1207       11286 :     ICMonitoredFallbackStub(Kind kind, JitCode* stubCode)
    1208       11286 :       : ICFallbackStub(kind, ICStub::MonitoredFallback, stubCode),
    1209       11286 :         fallbackMonitorStub_(nullptr) {}
    1210             : 
    1211             :   public:
    1212             :     MOZ_MUST_USE bool initMonitoringChain(JSContext* cx, ICStubSpace* space);
    1213             :     MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
    1214             :                                              StackTypeSet* types, HandleValue val);
    1215             : 
    1216        6438 :     inline ICTypeMonitor_Fallback* fallbackMonitorStub() const {
    1217        6438 :         return fallbackMonitorStub_;
    1218             :     }
    1219             : 
    1220         170 :     static inline size_t offsetOfFallbackMonitorStub() {
    1221         170 :         return offsetof(ICMonitoredFallbackStub, fallbackMonitorStub_);
    1222             :     }
    1223             : };
    1224             : 
    1225             : 
    1226             : // Base class for stub compilers that can generate multiple stubcodes.
    1227             : // These compilers need access to the JSOp they are compiling for.
    1228         525 : class ICMultiStubCompiler : public ICStubCompiler
    1229             : {
    1230             :   protected:
    1231             :     JSOp op;
    1232             : 
    1233             :     // Stub keys for multi-stub kinds are composed of both the kind
    1234             :     // and the op they are compiled for.
    1235         345 :     virtual int32_t getKey() const {
    1236         690 :         return static_cast<int32_t>(engine_) |
    1237         345 :               (static_cast<int32_t>(kind) << 1) |
    1238         345 :               (static_cast<int32_t>(op) << 17);
    1239             :     }
    1240             : 
    1241         525 :     ICMultiStubCompiler(JSContext* cx, ICStub::Kind kind, JSOp op, Engine engine)
    1242         525 :       : ICStubCompiler(cx, kind, engine), op(op) {}
    1243             : };
    1244             : 
    1245             : // TypeCheckPrimitiveSetStub
    1246             : //   Base class for IC stubs (TypeUpdate or TypeMonitor) that check that a given
    1247             : //   value's type falls within a set of primitive types.
    1248             : 
    1249             : class TypeCheckPrimitiveSetStub : public ICStub
    1250             : {
    1251             :     friend class ICStubSpace;
    1252             :   protected:
    1253       21777 :     inline static uint16_t TypeToFlag(JSValueType type) {
    1254       21777 :         return 1u << static_cast<unsigned>(type);
    1255             :     }
    1256             : 
    1257        4638 :     inline static uint16_t ValidFlags() {
    1258        4638 :         return ((TypeToFlag(JSVAL_TYPE_OBJECT) << 1) - 1) & ~TypeToFlag(JSVAL_TYPE_MAGIC);
    1259             :     }
    1260             : 
    1261        4438 :     TypeCheckPrimitiveSetStub(Kind kind, JitCode* stubCode, uint16_t flags)
    1262        4438 :         : ICStub(kind, stubCode)
    1263             :     {
    1264        4438 :         MOZ_ASSERT(kind == TypeMonitor_PrimitiveSet || kind == TypeUpdate_PrimitiveSet);
    1265        4438 :         MOZ_ASSERT(flags && !(flags & ~ValidFlags()));
    1266        4438 :         extra_ = flags;
    1267        4438 :     }
    1268             : 
    1269         200 :     TypeCheckPrimitiveSetStub* updateTypesAndCode(uint16_t flags, JitCode* code) {
    1270         200 :         MOZ_ASSERT(flags && !(flags & ~ValidFlags()));
    1271         200 :         if (!code)
    1272           0 :             return nullptr;
    1273         200 :         extra_ = flags;
    1274         200 :         updateCode(code);
    1275         200 :         return this;
    1276             :     }
    1277             : 
    1278             :   public:
    1279         400 :     uint16_t typeFlags() const {
    1280         400 :         return extra_;
    1281             :     }
    1282             : 
    1283        3265 :     bool containsType(JSValueType type) const {
    1284        3265 :         MOZ_ASSERT(type <= JSVAL_TYPE_OBJECT);
    1285        3265 :         MOZ_ASSERT(type != JSVAL_TYPE_MAGIC);
    1286        3265 :         return extra_ & TypeToFlag(type);
    1287             :     }
    1288             : 
    1289         170 :     ICTypeMonitor_PrimitiveSet* toMonitorStub() {
    1290         170 :         return toTypeMonitor_PrimitiveSet();
    1291             :     }
    1292             : 
    1293          30 :     ICTypeUpdate_PrimitiveSet* toUpdateStub() {
    1294          30 :         return toTypeUpdate_PrimitiveSet();
    1295             :     }
    1296             : 
    1297        4638 :     class Compiler : public ICStubCompiler {
    1298             :       protected:
    1299             :         TypeCheckPrimitiveSetStub* existingStub_;
    1300             :         uint16_t flags_;
    1301             : 
    1302        4638 :         virtual int32_t getKey() const {
    1303        9276 :             return static_cast<int32_t>(engine_) |
    1304        4638 :                   (static_cast<int32_t>(kind) << 1) |
    1305        4638 :                   (static_cast<int32_t>(flags_) << 17);
    1306             :         }
    1307             : 
    1308             :       public:
    1309        4638 :         Compiler(JSContext* cx, Kind kind, TypeCheckPrimitiveSetStub* existingStub,
    1310             :                  JSValueType type)
    1311        4638 :           : ICStubCompiler(cx, kind, Engine::Baseline),
    1312             :             existingStub_(existingStub),
    1313        4638 :             flags_((existingStub ? existingStub->typeFlags() : 0) | TypeToFlag(type))
    1314             :         {
    1315        4638 :             MOZ_ASSERT_IF(existingStub_, flags_ != existingStub_->typeFlags());
    1316        4638 :         }
    1317             : 
    1318         200 :         TypeCheckPrimitiveSetStub* updateStub() {
    1319         200 :             MOZ_ASSERT(existingStub_);
    1320         200 :             return existingStub_->updateTypesAndCode(flags_, getStubCode());
    1321             :         }
    1322             :     };
    1323             : };
    1324             : 
    1325             : // TypeMonitor
    1326             : 
    1327             : // The TypeMonitor fallback stub is not always a regular fallback stub. When
    1328             : // used for monitoring the values pushed by a bytecode it doesn't hold a
    1329             : // pointer to the IC entry, but rather back to the main fallback stub for the
    1330             : // IC (from which a pointer to the IC entry can be retrieved). When monitoring
    1331             : // the types of 'this', arguments or other values with no associated IC, there
    1332             : // is no main fallback stub, and the IC entry is referenced directly.
    1333             : class ICTypeMonitor_Fallback : public ICStub
    1334             : {
    1335             :     friend class ICStubSpace;
    1336             : 
    1337             :     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
    1338             : 
    1339             :     // Pointer to the main fallback stub for the IC or to the main IC entry,
    1340             :     // depending on hasFallbackStub.
    1341             :     union {
    1342             :         ICMonitoredFallbackStub* mainFallbackStub_;
    1343             :         ICEntry* icEntry_;
    1344             :     };
    1345             : 
    1346             :     // Pointer to the first monitor stub.
    1347             :     ICStub* firstMonitorStub_;
    1348             : 
    1349             :     // Address of the last monitor stub's field pointing to this
    1350             :     // fallback monitor stub.  This will get updated when new
    1351             :     // monitor stubs are created and added.
    1352             :     ICStub** lastMonitorStubPtrAddr_;
    1353             : 
    1354             :     // Count of optimized type monitor stubs in this chain.
    1355             :     uint32_t numOptimizedMonitorStubs_ : 7;
    1356             : 
    1357             :     uint32_t invalid_ : 1;
    1358             : 
    1359             :     // Whether this has a fallback stub referring to the IC entry.
    1360             :     bool hasFallbackStub_ : 1;
    1361             : 
    1362             :     // Index of 'this' or argument which is being monitored, or BYTECODE_INDEX
    1363             :     // if this is monitoring the types of values pushed at some bytecode.
    1364             :     uint32_t argumentIndex_ : 23;
    1365             : 
    1366             :     static const uint32_t BYTECODE_INDEX = (1 << 23) - 1;
    1367             : 
    1368       13412 :     ICTypeMonitor_Fallback(JitCode* stubCode, ICMonitoredFallbackStub* mainFallbackStub,
    1369             :                            uint32_t argumentIndex)
    1370       13412 :       : ICStub(ICStub::TypeMonitor_Fallback, stubCode),
    1371             :         mainFallbackStub_(mainFallbackStub),
    1372       13412 :         firstMonitorStub_(thisFromCtor()),
    1373             :         lastMonitorStubPtrAddr_(nullptr),
    1374             :         numOptimizedMonitorStubs_(0),
    1375             :         invalid_(false),
    1376       13412 :         hasFallbackStub_(mainFallbackStub != nullptr),
    1377       40236 :         argumentIndex_(argumentIndex)
    1378       13412 :     { }
    1379             : 
    1380       13412 :     ICTypeMonitor_Fallback* thisFromCtor() {
    1381       13412 :         return this;
    1382             :     }
    1383             : 
    1384        8189 :     void addOptimizedMonitorStub(ICStub* stub) {
    1385        8189 :         MOZ_ASSERT(!invalid());
    1386        8189 :         stub->setNext(this);
    1387             : 
    1388        8189 :         MOZ_ASSERT((lastMonitorStubPtrAddr_ != nullptr) ==
    1389             :                    (numOptimizedMonitorStubs_ || !hasFallbackStub_));
    1390             : 
    1391        8189 :         if (lastMonitorStubPtrAddr_)
    1392        2795 :             *lastMonitorStubPtrAddr_ = stub;
    1393             : 
    1394        8189 :         if (numOptimizedMonitorStubs_ == 0) {
    1395        7237 :             MOZ_ASSERT(firstMonitorStub_ == this);
    1396        7237 :             firstMonitorStub_ = stub;
    1397             :         } else {
    1398         952 :             MOZ_ASSERT(firstMonitorStub_ != nullptr);
    1399             :         }
    1400             : 
    1401        8189 :         lastMonitorStubPtrAddr_ = stub->addressOfNext();
    1402        8189 :         numOptimizedMonitorStubs_++;
    1403        8189 :     }
    1404             : 
    1405             :   public:
    1406        4020 :     bool hasStub(ICStub::Kind kind) {
    1407        4020 :         ICStub* stub = firstMonitorStub_;
    1408          25 :         do {
    1409        4045 :             if (stub->kind() == kind)
    1410           0 :                 return true;
    1411             : 
    1412        4045 :             stub = stub->next();
    1413        4045 :         } while (stub);
    1414             : 
    1415        4020 :         return false;
    1416             :     }
    1417             : 
    1418         545 :     inline ICFallbackStub* mainFallbackStub() const {
    1419         545 :         MOZ_ASSERT(hasFallbackStub_);
    1420         545 :         return mainFallbackStub_;
    1421             :     }
    1422             : 
    1423        2849 :     inline ICEntry* icEntry() const {
    1424        2849 :         return hasFallbackStub_ ? mainFallbackStub()->icEntry() : icEntry_;
    1425             :     }
    1426             : 
    1427       27385 :     inline ICStub* firstMonitorStub() const {
    1428       27385 :         return firstMonitorStub_;
    1429             :     }
    1430             : 
    1431         170 :     static inline size_t offsetOfFirstMonitorStub() {
    1432         170 :         return offsetof(ICTypeMonitor_Fallback, firstMonitorStub_);
    1433             :     }
    1434             : 
    1435           0 :     inline uint32_t numOptimizedMonitorStubs() const {
    1436           0 :         return numOptimizedMonitorStubs_;
    1437             :     }
    1438             : 
    1439           0 :     void setInvalid() {
    1440           0 :         invalid_ = 1;
    1441           0 :     }
    1442             : 
    1443       11037 :     bool invalid() const {
    1444       11037 :         return invalid_;
    1445             :     }
    1446             : 
    1447        3438 :     inline bool monitorsThis() const {
    1448        3438 :         return argumentIndex_ == 0;
    1449             :     }
    1450             : 
    1451        5696 :     inline bool monitorsArgument(uint32_t* pargument) const {
    1452        5696 :         if (argumentIndex_ > 0 && argumentIndex_ < BYTECODE_INDEX) {
    1453        2260 :             *pargument = argumentIndex_ - 1;
    1454        2260 :             return true;
    1455             :         }
    1456        3436 :         return false;
    1457             :     }
    1458             : 
    1459             :     inline bool monitorsBytecode() const {
    1460             :         return argumentIndex_ == BYTECODE_INDEX;
    1461             :     }
    1462             : 
    1463             :     // Fixup the IC entry as for a normal fallback stub, for this/arguments.
    1464        2122 :     void fixupICEntry(ICEntry* icEntry) {
    1465        2122 :         MOZ_ASSERT(!hasFallbackStub_);
    1466        2122 :         MOZ_ASSERT(icEntry_ == nullptr);
    1467        2122 :         MOZ_ASSERT(lastMonitorStubPtrAddr_ == nullptr);
    1468        2122 :         icEntry_ = icEntry;
    1469        2122 :         lastMonitorStubPtrAddr_ = icEntry_->addressOfFirstStub();
    1470        2122 :     }
    1471             : 
    1472             :     // Create a new monitor stub for the type of the given value, and
    1473             :     // add it to this chain.
    1474             :     MOZ_MUST_USE bool addMonitorStubForValue(JSContext* cx, BaselineFrame* frame,
    1475             :                                              StackTypeSet* types, HandleValue val);
    1476             : 
    1477             :     void resetMonitorStubChain(Zone* zone);
    1478             : 
    1479             :     // Compiler for this stub kind.
    1480       13412 :     class Compiler : public ICStubCompiler {
    1481             :         ICMonitoredFallbackStub* mainFallbackStub_;
    1482             :         uint32_t argumentIndex_;
    1483             : 
    1484             :       protected:
    1485             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1486             : 
    1487             :       public:
    1488       11923 :         Compiler(JSContext* cx, ICMonitoredFallbackStub* mainFallbackStub)
    1489       11923 :           : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback, Engine::Baseline),
    1490             :             mainFallbackStub_(mainFallbackStub),
    1491       11923 :             argumentIndex_(BYTECODE_INDEX)
    1492       11923 :         { }
    1493             : 
    1494        1489 :         Compiler(JSContext* cx, uint32_t argumentIndex)
    1495        1489 :           : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback, Engine::Baseline),
    1496             :             mainFallbackStub_(nullptr),
    1497        1489 :             argumentIndex_(argumentIndex)
    1498        1489 :         { }
    1499             : 
    1500       13412 :         ICTypeMonitor_Fallback* getStub(ICStubSpace* space) {
    1501       26824 :             return newStub<ICTypeMonitor_Fallback>(space, getStubCode(), mainFallbackStub_,
    1502       26824 :                                                        argumentIndex_);
    1503             :         }
    1504             :     };
    1505             : };
    1506             : 
    1507             : class ICTypeMonitor_PrimitiveSet : public TypeCheckPrimitiveSetStub
    1508             : {
    1509             :     friend class ICStubSpace;
    1510             : 
    1511        4020 :     ICTypeMonitor_PrimitiveSet(JitCode* stubCode, uint16_t flags)
    1512        4020 :         : TypeCheckPrimitiveSetStub(TypeMonitor_PrimitiveSet, stubCode, flags)
    1513        4020 :     {}
    1514             : 
    1515             :   public:
    1516        4190 :     class Compiler : public TypeCheckPrimitiveSetStub::Compiler {
    1517             :       protected:
    1518             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1519             : 
    1520             :       public:
    1521        4190 :         Compiler(JSContext* cx, ICTypeMonitor_PrimitiveSet* existingStub,
    1522             :                  JSValueType type)
    1523        4190 :           : TypeCheckPrimitiveSetStub::Compiler(cx, TypeMonitor_PrimitiveSet, existingStub,
    1524        4190 :                                                 type)
    1525        4190 :         {}
    1526             : 
    1527         170 :         ICTypeMonitor_PrimitiveSet* updateStub() {
    1528             :             TypeCheckPrimitiveSetStub* stub =
    1529         170 :                 this->TypeCheckPrimitiveSetStub::Compiler::updateStub();
    1530         170 :             if (!stub)
    1531           0 :                 return nullptr;
    1532         170 :             return stub->toMonitorStub();
    1533             :         }
    1534             : 
    1535        4020 :         ICTypeMonitor_PrimitiveSet* getStub(ICStubSpace* space) {
    1536        4020 :             MOZ_ASSERT(!existingStub_);
    1537        4020 :             return newStub<ICTypeMonitor_PrimitiveSet>(space, getStubCode(), flags_);
    1538             :         }
    1539             :     };
    1540             : };
    1541             : 
    1542             : class ICTypeMonitor_SingleObject : public ICStub
    1543             : {
    1544             :     friend class ICStubSpace;
    1545             : 
    1546             :     GCPtrObject obj_;
    1547             : 
    1548             :     ICTypeMonitor_SingleObject(JitCode* stubCode, JSObject* obj);
    1549             : 
    1550             :   public:
    1551        2668 :     GCPtrObject& object() {
    1552        2668 :         return obj_;
    1553             :     }
    1554             : 
    1555          59 :     static size_t offsetOfObject() {
    1556          59 :         return offsetof(ICTypeMonitor_SingleObject, obj_);
    1557             :     }
    1558             : 
    1559        1377 :     class Compiler : public ICStubCompiler {
    1560             :       protected:
    1561             :         HandleObject obj_;
    1562             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1563             : 
    1564             :       public:
    1565        1377 :         Compiler(JSContext* cx, HandleObject obj)
    1566        1377 :           : ICStubCompiler(cx, TypeMonitor_SingleObject, Engine::Baseline),
    1567        1377 :             obj_(obj)
    1568        1377 :         { }
    1569             : 
    1570        1377 :         ICTypeMonitor_SingleObject* getStub(ICStubSpace* space) {
    1571        1377 :             return newStub<ICTypeMonitor_SingleObject>(space, getStubCode(), obj_);
    1572             :         }
    1573             :     };
    1574             : };
    1575             : 
    1576             : class ICTypeMonitor_ObjectGroup : public ICStub
    1577             : {
    1578             :     friend class ICStubSpace;
    1579             : 
    1580             :     GCPtrObjectGroup group_;
    1581             : 
    1582             :     ICTypeMonitor_ObjectGroup(JitCode* stubCode, ObjectGroup* group);
    1583             : 
    1584             :   public:
    1585        3801 :     GCPtrObjectGroup& group() {
    1586        3801 :         return group_;
    1587             :     }
    1588             : 
    1589          66 :     static size_t offsetOfGroup() {
    1590          66 :         return offsetof(ICTypeMonitor_ObjectGroup, group_);
    1591             :     }
    1592             : 
    1593        2792 :     class Compiler : public ICStubCompiler {
    1594             :       protected:
    1595             :         HandleObjectGroup group_;
    1596             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1597             : 
    1598             :       public:
    1599        2792 :         Compiler(JSContext* cx, HandleObjectGroup group)
    1600        2792 :           : ICStubCompiler(cx, TypeMonitor_ObjectGroup, Engine::Baseline),
    1601        2792 :             group_(group)
    1602        2792 :         { }
    1603             : 
    1604        2792 :         ICTypeMonitor_ObjectGroup* getStub(ICStubSpace* space) {
    1605        2792 :             return newStub<ICTypeMonitor_ObjectGroup>(space, getStubCode(), group_);
    1606             :         }
    1607             :     };
    1608             : };
    1609             : 
    1610             : class ICTypeMonitor_AnyValue : public ICStub
    1611             : {
    1612             :     friend class ICStubSpace;
    1613             : 
    1614           0 :     explicit ICTypeMonitor_AnyValue(JitCode* stubCode)
    1615           0 :       : ICStub(TypeMonitor_AnyValue, stubCode)
    1616           0 :     {}
    1617             : 
    1618             :   public:
    1619           0 :     class Compiler : public ICStubCompiler {
    1620             :       protected:
    1621             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1622             : 
    1623             :       public:
    1624           0 :         explicit Compiler(JSContext* cx)
    1625           0 :           : ICStubCompiler(cx, TypeMonitor_AnyValue, Engine::Baseline)
    1626           0 :         { }
    1627             : 
    1628           0 :         ICTypeMonitor_AnyValue* getStub(ICStubSpace* space) {
    1629           0 :             return newStub<ICTypeMonitor_AnyValue>(space, getStubCode());
    1630             :         }
    1631             :     };
    1632             : };
    1633             : 
    1634             : // BinaryArith
    1635             : //      JSOP_ADD, JSOP_SUB, JSOP_MUL, JOP_DIV, JSOP_MOD
    1636             : //      JSOP_BITAND, JSOP_BITXOR, JSOP_BITOR
    1637             : //      JSOP_LSH, JSOP_RSH, JSOP_URSH
    1638             : 
    1639             : class ICBinaryArith_Fallback : public ICFallbackStub
    1640             : {
    1641             :     friend class ICStubSpace;
    1642             : 
    1643         645 :     explicit ICBinaryArith_Fallback(JitCode* stubCode)
    1644         645 :       : ICFallbackStub(BinaryArith_Fallback, stubCode)
    1645             :     {
    1646         645 :         extra_ = 0;
    1647         645 :     }
    1648             : 
    1649             :     static const uint16_t SAW_DOUBLE_RESULT_BIT = 0x1;
    1650             :     static const uint16_t UNOPTIMIZABLE_OPERANDS_BIT = 0x2;
    1651             : 
    1652             :   public:
    1653             :     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
    1654             : 
    1655          13 :     bool sawDoubleResult() const {
    1656          13 :         return extra_ & SAW_DOUBLE_RESULT_BIT;
    1657             :     }
    1658           1 :     void setSawDoubleResult() {
    1659           1 :         extra_ |= SAW_DOUBLE_RESULT_BIT;
    1660           1 :     }
    1661           0 :     bool hadUnoptimizableOperands() const {
    1662           0 :         return extra_ & UNOPTIMIZABLE_OPERANDS_BIT;
    1663             :     }
    1664          11 :     void noteUnoptimizableOperands() {
    1665          11 :         extra_ |= UNOPTIMIZABLE_OPERANDS_BIT;
    1666          11 :     }
    1667             : 
    1668             :     // Compiler for this stub kind.
    1669         645 :     class Compiler : public ICStubCompiler {
    1670             :       protected:
    1671             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1672             : 
    1673             :       public:
    1674         645 :         explicit Compiler(JSContext* cx, Engine engine)
    1675         645 :           : ICStubCompiler(cx, ICStub::BinaryArith_Fallback, engine) {}
    1676             : 
    1677         645 :         ICStub* getStub(ICStubSpace* space) {
    1678         645 :             return newStub<ICBinaryArith_Fallback>(space, getStubCode());
    1679             :         }
    1680             :     };
    1681             : };
    1682             : 
    1683             : class ICBinaryArith_Int32 : public ICStub
    1684             : {
    1685             :     friend class ICStubSpace;
    1686             : 
    1687         191 :     ICBinaryArith_Int32(JitCode* stubCode, bool allowDouble)
    1688         191 :       : ICStub(BinaryArith_Int32, stubCode)
    1689             :     {
    1690         191 :         extra_ = allowDouble;
    1691         191 :     }
    1692             : 
    1693             :   public:
    1694           6 :     bool allowDouble() const {
    1695           6 :         return extra_;
    1696             :     }
    1697             : 
    1698             :     // Compiler for this stub kind.
    1699         191 :     class Compiler : public ICStubCompiler {
    1700             :       protected:
    1701             :         JSOp op_;
    1702             :         bool allowDouble_;
    1703             : 
    1704             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1705             : 
    1706             :         // Stub keys shift-stubs need to encode the kind, the JSOp and if we allow doubles.
    1707         191 :         virtual int32_t getKey() const {
    1708         382 :             return static_cast<int32_t>(engine_) |
    1709         382 :                   (static_cast<int32_t>(kind) << 1) |
    1710         191 :                   (static_cast<int32_t>(op_) << 17) |
    1711         191 :                   (static_cast<int32_t>(allowDouble_) << 25);
    1712             :         }
    1713             : 
    1714             :       public:
    1715         191 :         Compiler(JSContext* cx, JSOp op, Engine engine, bool allowDouble)
    1716         191 :           : ICStubCompiler(cx, ICStub::BinaryArith_Int32, engine),
    1717         191 :             op_(op), allowDouble_(allowDouble) {}
    1718             : 
    1719         191 :         ICStub* getStub(ICStubSpace* space) {
    1720         191 :             return newStub<ICBinaryArith_Int32>(space, getStubCode(), allowDouble_);
    1721             :         }
    1722             :     };
    1723             : };
    1724             : 
    1725             : class ICBinaryArith_StringConcat : public ICStub
    1726             : {
    1727             :     friend class ICStubSpace;
    1728             : 
    1729          62 :     explicit ICBinaryArith_StringConcat(JitCode* stubCode)
    1730          62 :       : ICStub(BinaryArith_StringConcat, stubCode)
    1731          62 :     {}
    1732             : 
    1733             :   public:
    1734          62 :     class Compiler : public ICStubCompiler {
    1735             :       protected:
    1736             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1737             : 
    1738             :       public:
    1739          62 :         explicit Compiler(JSContext* cx, Engine engine)
    1740          62 :           : ICStubCompiler(cx, ICStub::BinaryArith_StringConcat, engine)
    1741          62 :         {}
    1742             : 
    1743          62 :         ICStub* getStub(ICStubSpace* space) {
    1744          62 :             return newStub<ICBinaryArith_StringConcat>(space, getStubCode());
    1745             :         }
    1746             :     };
    1747             : };
    1748             : 
    1749             : class ICBinaryArith_StringObjectConcat : public ICStub
    1750             : {
    1751             :     friend class ICStubSpace;
    1752             : 
    1753           0 :     ICBinaryArith_StringObjectConcat(JitCode* stubCode, bool lhsIsString)
    1754           0 :       : ICStub(BinaryArith_StringObjectConcat, stubCode)
    1755             :     {
    1756           0 :         extra_ = lhsIsString;
    1757           0 :     }
    1758             : 
    1759             :   public:
    1760             :     bool lhsIsString() const {
    1761             :         return extra_;
    1762             :     }
    1763             : 
    1764           0 :     class Compiler : public ICStubCompiler {
    1765             :       protected:
    1766             :         bool lhsIsString_;
    1767             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1768             : 
    1769           0 :         virtual int32_t getKey() const {
    1770           0 :             return static_cast<int32_t>(engine_) |
    1771           0 :                   (static_cast<int32_t>(kind) << 1) |
    1772           0 :                   (static_cast<int32_t>(lhsIsString_) << 17);
    1773             :         }
    1774             : 
    1775             :       public:
    1776           0 :         Compiler(JSContext* cx, Engine engine, bool lhsIsString)
    1777           0 :           : ICStubCompiler(cx, ICStub::BinaryArith_StringObjectConcat, engine),
    1778           0 :             lhsIsString_(lhsIsString)
    1779           0 :         {}
    1780             : 
    1781           0 :         ICStub* getStub(ICStubSpace* space) {
    1782           0 :             return newStub<ICBinaryArith_StringObjectConcat>(space, getStubCode(),
    1783           0 :                                                                  lhsIsString_);
    1784             :         }
    1785             :     };
    1786             : };
    1787             : 
    1788             : class ICBinaryArith_Double : public ICStub
    1789             : {
    1790             :     friend class ICStubSpace;
    1791             : 
    1792           1 :     explicit ICBinaryArith_Double(JitCode* stubCode)
    1793           1 :       : ICStub(BinaryArith_Double, stubCode)
    1794           1 :     {}
    1795             : 
    1796             :   public:
    1797           1 :     class Compiler : public ICMultiStubCompiler {
    1798             :       protected:
    1799             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1800             : 
    1801             :       public:
    1802           1 :         Compiler(JSContext* cx, JSOp op, Engine engine)
    1803           1 :           : ICMultiStubCompiler(cx, ICStub::BinaryArith_Double, op, engine)
    1804           1 :         {}
    1805             : 
    1806           1 :         ICStub* getStub(ICStubSpace* space) {
    1807           1 :             return newStub<ICBinaryArith_Double>(space, getStubCode());
    1808             :         }
    1809             :     };
    1810             : };
    1811             : 
    1812             : class ICBinaryArith_BooleanWithInt32 : public ICStub
    1813             : {
    1814             :     friend class ICStubSpace;
    1815             : 
    1816           4 :     ICBinaryArith_BooleanWithInt32(JitCode* stubCode, bool lhsIsBool, bool rhsIsBool)
    1817           4 :       : ICStub(BinaryArith_BooleanWithInt32, stubCode)
    1818             :     {
    1819           4 :         MOZ_ASSERT(lhsIsBool || rhsIsBool);
    1820           4 :         extra_ = 0;
    1821           4 :         if (lhsIsBool)
    1822           0 :             extra_ |= 1;
    1823           4 :         if (rhsIsBool)
    1824           4 :             extra_ |= 2;
    1825           4 :     }
    1826             : 
    1827             :   public:
    1828             :     bool lhsIsBoolean() const {
    1829             :         return extra_ & 1;
    1830             :     }
    1831             : 
    1832             :     bool rhsIsBoolean() const {
    1833             :         return extra_ & 2;
    1834             :     }
    1835             : 
    1836           4 :     class Compiler : public ICStubCompiler {
    1837             :       protected:
    1838             :         JSOp op_;
    1839             :         bool lhsIsBool_;
    1840             :         bool rhsIsBool_;
    1841             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1842             : 
    1843           4 :         virtual int32_t getKey() const {
    1844           8 :             return static_cast<int32_t>(engine_) |
    1845           8 :                   (static_cast<int32_t>(kind) << 1) |
    1846           8 :                   (static_cast<int32_t>(op_) << 17) |
    1847           4 :                   (static_cast<int32_t>(lhsIsBool_) << 25) |
    1848           4 :                   (static_cast<int32_t>(rhsIsBool_) << 26);
    1849             :         }
    1850             : 
    1851             :       public:
    1852           4 :         Compiler(JSContext* cx, JSOp op, Engine engine, bool lhsIsBool, bool rhsIsBool)
    1853           4 :           : ICStubCompiler(cx, ICStub::BinaryArith_BooleanWithInt32, engine),
    1854           4 :             op_(op), lhsIsBool_(lhsIsBool), rhsIsBool_(rhsIsBool)
    1855             :         {
    1856           4 :             MOZ_ASSERT(op_ == JSOP_ADD || op_ == JSOP_SUB || op_ == JSOP_BITOR ||
    1857             :                        op_ == JSOP_BITAND || op_ == JSOP_BITXOR);
    1858           4 :             MOZ_ASSERT(lhsIsBool_ || rhsIsBool_);
    1859           4 :         }
    1860             : 
    1861           4 :         ICStub* getStub(ICStubSpace* space) {
    1862           8 :             return newStub<ICBinaryArith_BooleanWithInt32>(space, getStubCode(),
    1863           8 :                                                                lhsIsBool_, rhsIsBool_);
    1864             :         }
    1865             :     };
    1866             : };
    1867             : 
    1868             : class ICBinaryArith_DoubleWithInt32 : public ICStub
    1869             : {
    1870             :     friend class ICStubSpace;
    1871             : 
    1872           0 :     ICBinaryArith_DoubleWithInt32(JitCode* stubCode, bool lhsIsDouble)
    1873           0 :       : ICStub(BinaryArith_DoubleWithInt32, stubCode)
    1874             :     {
    1875           0 :         extra_ = lhsIsDouble;
    1876           0 :     }
    1877             : 
    1878             :   public:
    1879             :     bool lhsIsDouble() const {
    1880             :         return extra_;
    1881             :     }
    1882             : 
    1883           0 :     class Compiler : public ICMultiStubCompiler {
    1884             :       protected:
    1885             :         bool lhsIsDouble_;
    1886             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1887             : 
    1888           0 :         virtual int32_t getKey() const {
    1889           0 :             return static_cast<int32_t>(engine_) |
    1890           0 :                   (static_cast<int32_t>(kind) << 1) |
    1891           0 :                   (static_cast<int32_t>(op) << 17) |
    1892           0 :                   (static_cast<int32_t>(lhsIsDouble_) << 25);
    1893             :         }
    1894             : 
    1895             :       public:
    1896           0 :         Compiler(JSContext* cx, JSOp op, Engine engine, bool lhsIsDouble)
    1897           0 :           : ICMultiStubCompiler(cx, ICStub::BinaryArith_DoubleWithInt32, op, engine),
    1898           0 :             lhsIsDouble_(lhsIsDouble)
    1899           0 :         {}
    1900             : 
    1901           0 :         ICStub* getStub(ICStubSpace* space) {
    1902           0 :             return newStub<ICBinaryArith_DoubleWithInt32>(space, getStubCode(),
    1903           0 :                                                               lhsIsDouble_);
    1904             :         }
    1905             :     };
    1906             : };
    1907             : 
    1908             : // UnaryArith
    1909             : //     JSOP_BITNOT
    1910             : //     JSOP_NEG
    1911             : 
    1912             : class ICUnaryArith_Fallback : public ICFallbackStub
    1913             : {
    1914             :     friend class ICStubSpace;
    1915             : 
    1916           2 :     explicit ICUnaryArith_Fallback(JitCode* stubCode)
    1917           2 :       : ICFallbackStub(UnaryArith_Fallback, stubCode)
    1918             :     {
    1919           2 :         extra_ = 0;
    1920           2 :     }
    1921             : 
    1922             :   public:
    1923             :     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
    1924             : 
    1925           0 :     bool sawDoubleResult() {
    1926           0 :         return extra_;
    1927             :     }
    1928           0 :     void setSawDoubleResult() {
    1929           0 :         extra_ = 1;
    1930           0 :     }
    1931             : 
    1932             :     // Compiler for this stub kind.
    1933           2 :     class Compiler : public ICStubCompiler {
    1934             :       protected:
    1935             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1936             : 
    1937             :       public:
    1938           2 :         explicit Compiler(JSContext* cx, Engine engine)
    1939           2 :           : ICStubCompiler(cx, ICStub::UnaryArith_Fallback, engine)
    1940           2 :         {}
    1941             : 
    1942           2 :         ICStub* getStub(ICStubSpace* space) {
    1943           2 :             return newStub<ICUnaryArith_Fallback>(space, getStubCode());
    1944             :         }
    1945             :     };
    1946             : };
    1947             : 
    1948             : class ICUnaryArith_Int32 : public ICStub
    1949             : {
    1950             :     friend class ICStubSpace;
    1951             : 
    1952           1 :     explicit ICUnaryArith_Int32(JitCode* stubCode)
    1953           1 :       : ICStub(UnaryArith_Int32, stubCode)
    1954           1 :     {}
    1955             : 
    1956             :   public:
    1957           1 :     class Compiler : public ICMultiStubCompiler {
    1958             :       protected:
    1959             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1960             : 
    1961             :       public:
    1962           1 :         Compiler(JSContext* cx, JSOp op, Engine engine)
    1963           1 :           : ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op, engine)
    1964           1 :         {}
    1965             : 
    1966           1 :         ICStub* getStub(ICStubSpace* space) {
    1967           1 :             return newStub<ICUnaryArith_Int32>(space, getStubCode());
    1968             :         }
    1969             :     };
    1970             : };
    1971             : 
    1972             : class ICUnaryArith_Double : public ICStub
    1973             : {
    1974             :     friend class ICStubSpace;
    1975             : 
    1976           0 :     explicit ICUnaryArith_Double(JitCode* stubCode)
    1977           0 :       : ICStub(UnaryArith_Double, stubCode)
    1978           0 :     {}
    1979             : 
    1980             :   public:
    1981           0 :     class Compiler : public ICMultiStubCompiler {
    1982             :       protected:
    1983             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    1984             : 
    1985             :       public:
    1986           0 :         Compiler(JSContext* cx, JSOp op, Engine engine)
    1987           0 :           : ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op, engine)
    1988           0 :         {}
    1989             : 
    1990           0 :         ICStub* getStub(ICStubSpace* space) {
    1991           0 :             return newStub<ICUnaryArith_Double>(space, getStubCode());
    1992             :         }
    1993             :     };
    1994             : };
    1995             : 
    1996             : // Compare
    1997             : //      JSOP_LT
    1998             : //      JSOP_LE
    1999             : //      JSOP_GT
    2000             : //      JSOP_GE
    2001             : //      JSOP_EQ
    2002             : //      JSOP_NE
    2003             : //      JSOP_STRICTEQ
    2004             : //      JSOP_STRICTNE
    2005             : 
    2006             : class ICCompare_Fallback : public ICFallbackStub
    2007             : {
    2008             :     friend class ICStubSpace;
    2009             : 
    2010        1202 :     explicit ICCompare_Fallback(JitCode* stubCode)
    2011        1202 :       : ICFallbackStub(ICStub::Compare_Fallback, stubCode) {}
    2012             : 
    2013             :   public:
    2014             :     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
    2015             : 
    2016             :     static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
    2017          90 :     void noteUnoptimizableAccess() {
    2018          90 :         extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
    2019          90 :     }
    2020           2 :     bool hadUnoptimizableAccess() const {
    2021           2 :         return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
    2022             :     }
    2023             : 
    2024             :     // Compiler for this stub kind.
    2025        1202 :     class Compiler : public ICStubCompiler {
    2026             :       protected:
    2027             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2028             : 
    2029             :       public:
    2030        1202 :         explicit Compiler(JSContext* cx, Engine engine)
    2031        1202 :           : ICStubCompiler(cx, ICStub::Compare_Fallback, engine) {}
    2032             : 
    2033        1202 :         ICStub* getStub(ICStubSpace* space) {
    2034        1202 :             return newStub<ICCompare_Fallback>(space, getStubCode());
    2035             :         }
    2036             :     };
    2037             : };
    2038             : 
    2039             : class ICCompare_Int32 : public ICStub
    2040             : {
    2041             :     friend class ICStubSpace;
    2042             : 
    2043         330 :     explicit ICCompare_Int32(JitCode* stubCode)
    2044         330 :       : ICStub(ICStub::Compare_Int32, stubCode) {}
    2045             : 
    2046             :   public:
    2047             :     // Compiler for this stub kind.
    2048         330 :     class Compiler : public ICMultiStubCompiler {
    2049             :       protected:
    2050             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2051             : 
    2052             :       public:
    2053         330 :         Compiler(JSContext* cx, JSOp op, Engine engine)
    2054         330 :           : ICMultiStubCompiler(cx, ICStub::Compare_Int32, op, engine) {}
    2055             : 
    2056         330 :         ICStub* getStub(ICStubSpace* space) {
    2057         330 :             return newStub<ICCompare_Int32>(space, getStubCode());
    2058             :         }
    2059             :     };
    2060             : };
    2061             : 
    2062             : class ICCompare_Double : public ICStub
    2063             : {
    2064             :     friend class ICStubSpace;
    2065             : 
    2066          11 :     explicit ICCompare_Double(JitCode* stubCode)
    2067          11 :       : ICStub(ICStub::Compare_Double, stubCode)
    2068          11 :     {}
    2069             : 
    2070             :   public:
    2071          11 :     class Compiler : public ICMultiStubCompiler {
    2072             :       protected:
    2073             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2074             : 
    2075             :       public:
    2076          11 :         Compiler(JSContext* cx, JSOp op, Engine engine)
    2077          11 :           : ICMultiStubCompiler(cx, ICStub::Compare_Double, op, engine)
    2078          11 :         {}
    2079             : 
    2080          11 :         ICStub* getStub(ICStubSpace* space) {
    2081          11 :             return newStub<ICCompare_Double>(space, getStubCode());
    2082             :         }
    2083             :     };
    2084             : };
    2085             : 
    2086             : class ICCompare_NumberWithUndefined : public ICStub
    2087             : {
    2088             :     friend class ICStubSpace;
    2089             : 
    2090           2 :     ICCompare_NumberWithUndefined(JitCode* stubCode, bool lhsIsUndefined)
    2091           2 :       : ICStub(ICStub::Compare_NumberWithUndefined, stubCode)
    2092             :     {
    2093           2 :         extra_ = lhsIsUndefined;
    2094           2 :     }
    2095             : 
    2096             :   public:
    2097           0 :     bool lhsIsUndefined() {
    2098           0 :         return extra_;
    2099             :     }
    2100             : 
    2101           2 :     class Compiler : public ICMultiStubCompiler {
    2102             :       protected:
    2103             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2104             : 
    2105             :         bool lhsIsUndefined;
    2106             : 
    2107             :       public:
    2108           2 :         Compiler(JSContext* cx, JSOp op, Engine engine, bool lhsIsUndefined)
    2109           2 :           : ICMultiStubCompiler(cx, ICStub::Compare_NumberWithUndefined, op, engine),
    2110           2 :             lhsIsUndefined(lhsIsUndefined)
    2111           2 :         {}
    2112             : 
    2113           2 :         virtual int32_t getKey() const {
    2114           4 :             return static_cast<int32_t>(engine_) |
    2115           4 :                   (static_cast<int32_t>(kind) << 1) |
    2116           2 :                   (static_cast<int32_t>(op) << 17) |
    2117           2 :                   (static_cast<int32_t>(lhsIsUndefined) << 25);
    2118             :         }
    2119             : 
    2120           2 :         ICStub* getStub(ICStubSpace* space) {
    2121           4 :             return newStub<ICCompare_NumberWithUndefined>(space, getStubCode(),
    2122           4 :                                                               lhsIsUndefined);
    2123             :         }
    2124             :     };
    2125             : };
    2126             : 
    2127             : class ICCompare_String : public ICStub
    2128             : {
    2129             :     friend class ICStubSpace;
    2130             : 
    2131           0 :     explicit ICCompare_String(JitCode* stubCode)
    2132           0 :       : ICStub(ICStub::Compare_String, stubCode)
    2133           0 :     {}
    2134             : 
    2135             :   public:
    2136           0 :     class Compiler : public ICMultiStubCompiler {
    2137             :       protected:
    2138             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2139             : 
    2140             :       public:
    2141           0 :         Compiler(JSContext* cx, JSOp op, Engine engine)
    2142           0 :           : ICMultiStubCompiler(cx, ICStub::Compare_String, op, engine)
    2143           0 :         {}
    2144             : 
    2145           0 :         ICStub* getStub(ICStubSpace* space) {
    2146           0 :             return newStub<ICCompare_String>(space, getStubCode());
    2147             :         }
    2148             :     };
    2149             : };
    2150             : 
    2151             : class ICCompare_Symbol : public ICStub
    2152             : {
    2153             :     friend class ICStubSpace;
    2154             : 
    2155           0 :     explicit ICCompare_Symbol(JitCode* stubCode)
    2156           0 :       : ICStub(ICStub::Compare_Symbol, stubCode)
    2157           0 :     {}
    2158             : 
    2159             :   public:
    2160           0 :     class Compiler : public ICMultiStubCompiler {
    2161             :       protected:
    2162             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2163             : 
    2164             :       public:
    2165           0 :         Compiler(JSContext* cx, JSOp op, Engine engine)
    2166           0 :           : ICMultiStubCompiler(cx, ICStub::Compare_Symbol, op, engine)
    2167           0 :         {}
    2168             : 
    2169           0 :         ICStub* getStub(ICStubSpace* space) {
    2170           0 :             return newStub<ICCompare_Symbol>(space, getStubCode());
    2171             :         }
    2172             :     };
    2173             : };
    2174             : 
    2175             : class ICCompare_Boolean : public ICStub
    2176             : {
    2177             :     friend class ICStubSpace;
    2178             : 
    2179           2 :     explicit ICCompare_Boolean(JitCode* stubCode)
    2180           2 :       : ICStub(ICStub::Compare_Boolean, stubCode)
    2181           2 :     {}
    2182             : 
    2183             :   public:
    2184           2 :     class Compiler : public ICMultiStubCompiler {
    2185             :       protected:
    2186             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2187             : 
    2188             :       public:
    2189           2 :         Compiler(JSContext* cx, JSOp op, Engine engine)
    2190           2 :           : ICMultiStubCompiler(cx, ICStub::Compare_Boolean, op, engine)
    2191           2 :         {}
    2192             : 
    2193           2 :         ICStub* getStub(ICStubSpace* space) {
    2194           2 :             return newStub<ICCompare_Boolean>(space, getStubCode());
    2195             :         }
    2196             :     };
    2197             : };
    2198             : 
    2199             : class ICCompare_Object : public ICStub
    2200             : {
    2201             :     friend class ICStubSpace;
    2202             : 
    2203           0 :     explicit ICCompare_Object(JitCode* stubCode)
    2204           0 :       : ICStub(ICStub::Compare_Object, stubCode)
    2205           0 :     {}
    2206             : 
    2207             :   public:
    2208           0 :     class Compiler : public ICMultiStubCompiler {
    2209             :       protected:
    2210             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2211             : 
    2212             :       public:
    2213           0 :         Compiler(JSContext* cx, JSOp op, Engine engine)
    2214           0 :           : ICMultiStubCompiler(cx, ICStub::Compare_Object, op, engine)
    2215           0 :         {}
    2216             : 
    2217           0 :         ICStub* getStub(ICStubSpace* space) {
    2218           0 :             return newStub<ICCompare_Object>(space, getStubCode());
    2219             :         }
    2220             :     };
    2221             : };
    2222             : 
    2223             : class ICCompare_ObjectWithUndefined : public ICStub
    2224             : {
    2225             :     friend class ICStubSpace;
    2226             : 
    2227         178 :     explicit ICCompare_ObjectWithUndefined(JitCode* stubCode)
    2228         178 :       : ICStub(ICStub::Compare_ObjectWithUndefined, stubCode)
    2229         178 :     {}
    2230             : 
    2231             :   public:
    2232         178 :     class Compiler : public ICMultiStubCompiler {
    2233             :       protected:
    2234             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2235             : 
    2236             :         bool lhsIsUndefined;
    2237             :         bool compareWithNull;
    2238             : 
    2239             :       public:
    2240         178 :         Compiler(JSContext* cx, JSOp op, Engine engine, bool lhsIsUndefined, bool compareWithNull)
    2241         178 :           : ICMultiStubCompiler(cx, ICStub::Compare_ObjectWithUndefined, op, engine),
    2242             :             lhsIsUndefined(lhsIsUndefined),
    2243         178 :             compareWithNull(compareWithNull)
    2244         178 :         {}
    2245             : 
    2246         178 :         virtual int32_t getKey() const {
    2247         356 :             return static_cast<int32_t>(engine_) |
    2248         356 :                   (static_cast<int32_t>(kind) << 1) |
    2249         356 :                   (static_cast<int32_t>(op) << 17) |
    2250         178 :                   (static_cast<int32_t>(lhsIsUndefined) << 25) |
    2251         178 :                   (static_cast<int32_t>(compareWithNull) << 26);
    2252             :         }
    2253             : 
    2254         178 :         ICStub* getStub(ICStubSpace* space) {
    2255         178 :             return newStub<ICCompare_ObjectWithUndefined>(space, getStubCode());
    2256             :         }
    2257             :     };
    2258             : };
    2259             : 
    2260             : class ICCompare_Int32WithBoolean : public ICStub
    2261             : {
    2262             :     friend class ICStubSpace;
    2263             : 
    2264           0 :     ICCompare_Int32WithBoolean(JitCode* stubCode, bool lhsIsInt32)
    2265           0 :       : ICStub(ICStub::Compare_Int32WithBoolean, stubCode)
    2266             :     {
    2267           0 :         extra_ = lhsIsInt32;
    2268           0 :     }
    2269             : 
    2270             :   public:
    2271           0 :     bool lhsIsInt32() const {
    2272           0 :         return extra_;
    2273             :     }
    2274             : 
    2275             :     // Compiler for this stub kind.
    2276           0 :     class Compiler : public ICStubCompiler {
    2277             :       protected:
    2278             :         JSOp op_;
    2279             :         bool lhsIsInt32_;
    2280             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2281             : 
    2282           0 :         virtual int32_t getKey() const {
    2283           0 :             return static_cast<int32_t>(engine_) |
    2284           0 :                   (static_cast<int32_t>(kind) << 1) |
    2285           0 :                   (static_cast<int32_t>(op_) << 17) |
    2286           0 :                   (static_cast<int32_t>(lhsIsInt32_) << 25);
    2287             :         }
    2288             : 
    2289             :       public:
    2290           0 :         Compiler(JSContext* cx, JSOp op, Engine engine, bool lhsIsInt32)
    2291           0 :           : ICStubCompiler(cx, ICStub::Compare_Int32WithBoolean, engine),
    2292             :             op_(op),
    2293           0 :             lhsIsInt32_(lhsIsInt32)
    2294           0 :         {}
    2295             : 
    2296           0 :         ICStub* getStub(ICStubSpace* space) {
    2297           0 :             return newStub<ICCompare_Int32WithBoolean>(space, getStubCode(), lhsIsInt32_);
    2298             :         }
    2299             :     };
    2300             : };
    2301             : 
    2302             : // Enum for stubs handling a combination of typed arrays and typed objects.
    2303             : enum TypedThingLayout {
    2304             :     Layout_TypedArray,
    2305             :     Layout_OutlineTypedObject,
    2306             :     Layout_InlineTypedObject
    2307             : };
    2308             : 
    2309             : static inline TypedThingLayout
    2310           0 : GetTypedThingLayout(const Class* clasp)
    2311             : {
    2312           0 :     if (IsTypedArrayClass(clasp))
    2313           0 :         return Layout_TypedArray;
    2314           0 :     if (IsOutlineTypedObjectClass(clasp))
    2315           0 :         return Layout_OutlineTypedObject;
    2316           0 :     if (IsInlineTypedObjectClass(clasp))
    2317           0 :         return Layout_InlineTypedObject;
    2318           0 :     MOZ_CRASH("Bad object class");
    2319             : }
    2320             : 
    2321             : bool
    2322             : IsPreliminaryObject(JSObject* obj);
    2323             : 
    2324             : void
    2325             : StripPreliminaryObjectStubs(JSContext* cx, ICFallbackStub* stub);
    2326             : 
    2327             : MOZ_MUST_USE bool
    2328             : CheckHasNoSuchOwnProperty(JSContext* cx, JSObject* obj, jsid id);
    2329             : 
    2330             : MOZ_MUST_USE bool
    2331             : CheckHasNoSuchProperty(JSContext* cx, JSObject* obj, jsid id,
    2332             :                        JSObject** lastProto = nullptr, size_t* protoChainDepthOut = nullptr);
    2333             : 
    2334             : void
    2335             : CheckForTypedObjectWithDetachedStorage(JSContext* cx, MacroAssembler& masm, Label* failure);
    2336             : 
    2337             : void
    2338             : LoadTypedThingData(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result);
    2339             : 
    2340             : bool
    2341             : IsPrimitiveArrayTypedObject(JSObject* obj);
    2342             : 
    2343             : Scalar::Type
    2344             : TypedThingElementType(JSObject* obj);
    2345             : 
    2346             : bool
    2347             : TypedThingRequiresFloatingPoint(JSObject* obj);
    2348             : 
    2349             : void
    2350             : LoadTypedThingLength(MacroAssembler& masm, TypedThingLayout layout, Register obj, Register result);
    2351             : 
    2352             : class ICGetProp_Fallback : public ICMonitoredFallbackStub
    2353             : {
    2354             :     friend class ICStubSpace;
    2355             : 
    2356        3722 :     explicit ICGetProp_Fallback(JitCode* stubCode)
    2357        3722 :       : ICMonitoredFallbackStub(ICStub::GetProp_Fallback, stubCode)
    2358        3722 :     { }
    2359             : 
    2360             :   public:
    2361             :     static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
    2362             :     static const size_t ACCESSED_GETTER_BIT = 1;
    2363             : 
    2364        2328 :     void noteUnoptimizableAccess() {
    2365        2328 :         extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
    2366        2328 :     }
    2367          22 :     bool hadUnoptimizableAccess() const {
    2368          22 :         return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
    2369             :     }
    2370             : 
    2371         715 :     void noteAccessedGetter() {
    2372         715 :         extra_ |= (1u << ACCESSED_GETTER_BIT);
    2373         715 :     }
    2374          14 :     bool hasAccessedGetter() const {
    2375          14 :         return extra_ & (1u << ACCESSED_GETTER_BIT);
    2376             :     }
    2377             : 
    2378        3722 :     class Compiler : public ICStubCompiler {
    2379             :       protected:
    2380             :         CodeOffset bailoutReturnOffset_;
    2381             :         bool hasReceiver_;
    2382             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2383             :         void postGenerateStubCode(MacroAssembler& masm, Handle<JitCode*> code);
    2384             : 
    2385        3792 :         virtual int32_t getKey() const {
    2386        7584 :             return static_cast<int32_t>(engine_) |
    2387        3792 :                   (static_cast<int32_t>(kind) << 1) |
    2388        3792 :                   (static_cast<int32_t>(hasReceiver_) << 17);
    2389             :         }
    2390             : 
    2391             :       public:
    2392        3722 :         explicit Compiler(JSContext* cx, Engine engine, bool hasReceiver = false)
    2393        3722 :           : ICStubCompiler(cx, ICStub::GetProp_Fallback, engine),
    2394        3722 :             hasReceiver_(hasReceiver)
    2395        3722 :         { }
    2396             : 
    2397        3722 :         ICStub* getStub(ICStubSpace* space) {
    2398        3722 :             ICGetProp_Fallback* stub = newStub<ICGetProp_Fallback>(space, getStubCode());
    2399        3722 :             if (!stub || !stub->initMonitoringChain(cx, space))
    2400           0 :                 return nullptr;
    2401        3722 :             return stub;
    2402             :         }
    2403             :     };
    2404             : };
    2405             : 
    2406             : static inline uint32_t
    2407           0 : SimpleTypeDescrKey(SimpleTypeDescr* descr)
    2408             : {
    2409           0 :     if (descr->is<ScalarTypeDescr>())
    2410           0 :         return uint32_t(descr->as<ScalarTypeDescr>().type()) << 1;
    2411           0 :     return (uint32_t(descr->as<ReferenceTypeDescr>().type()) << 1) | 1;
    2412             : }
    2413             : 
    2414             : inline bool
    2415           0 : SimpleTypeDescrKeyIsScalar(uint32_t key)
    2416             : {
    2417           0 :     return !(key & 1);
    2418             : }
    2419             : 
    2420             : inline ScalarTypeDescr::Type
    2421           0 : ScalarTypeFromSimpleTypeDescrKey(uint32_t key)
    2422             : {
    2423           0 :     MOZ_ASSERT(SimpleTypeDescrKeyIsScalar(key));
    2424           0 :     return ScalarTypeDescr::Type(key >> 1);
    2425             : }
    2426             : 
    2427             : inline ReferenceTypeDescr::Type
    2428           0 : ReferenceTypeFromSimpleTypeDescrKey(uint32_t key)
    2429             : {
    2430           0 :     MOZ_ASSERT(!SimpleTypeDescrKeyIsScalar(key));
    2431           0 :     return ReferenceTypeDescr::Type(key >> 1);
    2432             : }
    2433             : 
    2434             : // JSOP_NEWARRAY
    2435             : // JSOP_NEWINIT
    2436             : 
    2437             : class ICNewArray_Fallback : public ICFallbackStub
    2438             : {
    2439             :     friend class ICStubSpace;
    2440             : 
    2441             :     GCPtrObject templateObject_;
    2442             : 
    2443             :     // The group used for objects created here is always available, even if the
    2444             :     // template object itself is not.
    2445             :     GCPtrObjectGroup templateGroup_;
    2446             : 
    2447         138 :     ICNewArray_Fallback(JitCode* stubCode, ObjectGroup* templateGroup)
    2448         138 :       : ICFallbackStub(ICStub::NewArray_Fallback, stubCode),
    2449         138 :         templateObject_(nullptr), templateGroup_(templateGroup)
    2450         138 :     {}
    2451             : 
    2452             :   public:
    2453         138 :     class Compiler : public ICStubCompiler {
    2454             :         RootedObjectGroup templateGroup;
    2455             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2456             : 
    2457             :       public:
    2458         138 :         Compiler(JSContext* cx, ObjectGroup* templateGroup, Engine engine)
    2459         138 :           : ICStubCompiler(cx, ICStub::NewArray_Fallback, engine),
    2460         138 :             templateGroup(cx, templateGroup)
    2461         138 :         {}
    2462             : 
    2463         138 :         ICStub* getStub(ICStubSpace* space) {
    2464         138 :             return newStub<ICNewArray_Fallback>(space, getStubCode(), templateGroup);
    2465             :         }
    2466             :     };
    2467             : 
    2468        2347 :     GCPtrObject& templateObject() {
    2469        2347 :         return templateObject_;
    2470             :     }
    2471             : 
    2472          46 :     void setTemplateObject(JSObject* obj) {
    2473          46 :         MOZ_ASSERT(obj->group() == templateGroup());
    2474          46 :         templateObject_ = obj;
    2475          46 :     }
    2476             : 
    2477          55 :     GCPtrObjectGroup& templateGroup() {
    2478          55 :         return templateGroup_;
    2479             :     }
    2480             : 
    2481           0 :     void setTemplateGroup(ObjectGroup* group) {
    2482           0 :         templateObject_ = nullptr;
    2483           0 :         templateGroup_ = group;
    2484           0 :     }
    2485             : };
    2486             : 
    2487             : // JSOP_NEWOBJECT
    2488             : 
    2489             : class ICNewObject_Fallback : public ICFallbackStub
    2490             : {
    2491             :     friend class ICStubSpace;
    2492             : 
    2493             :     GCPtrObject templateObject_;
    2494             : 
    2495         214 :     explicit ICNewObject_Fallback(JitCode* stubCode)
    2496         214 :       : ICFallbackStub(ICStub::NewObject_Fallback, stubCode), templateObject_(nullptr)
    2497         214 :     {}
    2498             : 
    2499             :   public:
    2500         214 :     class Compiler : public ICStubCompiler {
    2501             :         MOZ_MUST_USE bool generateStubCode(MacroAssembler& masm);
    2502             : 
    2503             :       public:
    2504         214 :         explicit Compiler(JSContext* cx, Engine engine)
    2505         214 :           : ICStubCompiler(cx, ICStub::NewObject_Fallback, engine)
    2506         214 :         {}
    2507             : 
    2508         214 :         ICStub* getStub(ICStubSpace* space) {
    2509         214 :             return newStub<ICNewObject_Fallback>(space, getStubCode());
    2510             :         }
    2511             :     };
    2512             : 
    2513         928 :     GCPtrObject& templateObject() {
    2514         928 :         return templateObject_;
    2515             :     }
    2516             : 
    2517          82 :     void setTemplateObject(JSObject* obj) {
    2518          82 :         templateObject_ = obj;
    2519          82 :     }
    2520             : };
    2521             : 
    2522             : class ICNewObject_WithTemplate : public ICStub
    2523             : {
    2524             :     friend class ICStubSpace;
    2525             : 
    2526          78 :     explicit ICNewObject_WithTemplate(JitCode* stubCode)
    2527          78 :       : ICStub(ICStub::NewObject_WithTemplate, stubCode)
    2528          78 :     {}
    2529             : };
    2530             : 
    2531             : } // namespace jit
    2532             : } // namespace js
    2533             : 
    2534             : #endif /* jit_SharedIC_h */

Generated by: LCOV version 1.13