js/src/jit/BaselineIC.h

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

     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/. */
     7 #ifndef jit_BaselineIC_h
     8 #define jit_BaselineIC_h
    10 #ifdef JS_ION
    12 #include "mozilla/Assertions.h"
    14 #include "jscntxt.h"
    15 #include "jscompartment.h"
    16 #include "jsgc.h"
    17 #include "jsopcode.h"
    19 #include "jit/BaselineJIT.h"
    20 #include "jit/BaselineRegisters.h"
    22 namespace js {
    23 namespace jit {
    25 //
    26 // Baseline Inline Caches are polymorphic caches that aggressively
    27 // share their stub code.
    28 //
    29 // Every polymorphic site contains a linked list of stubs which are
    30 // specific to that site.  These stubs are composed of a |StubData|
    31 // structure that stores parametrization information (e.g.
    32 // the shape pointer for a shape-check-and-property-get stub), any
    33 // dynamic information (e.g. use counts), a pointer to the stub code,
    34 // and a pointer to the next stub state in the linked list.
    35 //
    36 // Every BaselineScript keeps an table of |CacheDescriptor| data
    37 // structures, which store the following:
    38 //      A pointer to the first StubData in the cache.
    39 //      The bytecode PC of the relevant IC.
    40 //      The machine-code PC where the call to the stubcode returns.
    41 //
    42 // A diagram:
    43 //
    44 //        Control flow                  Pointers
    45 //      =======#                     ----.     .---->
    46 //             #                         |     |
    47 //             #======>                  \-----/
    48 //
    49 //
    50 //                                   .---------------------------------------.
    51 //                                   |         .-------------------------.   |
    52 //                                   |         |         .----.          |   |
    53 //         Baseline                  |         |         |    |          |   |
    54 //         JIT Code              0   ^     1   ^     2   ^    |          |   |
    55 //     +--------------+    .-->+-----+   +-----+   +-----+    |          |   |
    56 //     |              |  #=|==>|     |==>|     |==>| FB  |    |          |   |
    57 //     |              |  # |   +-----+   +-----+   +-----+    |          |   |
    58 //     |              |  # |      #         #         #       |          |   |
    59 //     |==============|==# |      #         #         #       |          |   |
    60 //     |=== IC =======|    |      #         #         #       |          |   |
    61 //  .->|==============|<===|======#=========#=========#       |          |   |
    62 //  |  |              |    |                                  |          |   |
    63 //  |  |              |    |                                  |          |   |
    64 //  |  |              |    |                                  |          |   |
    65 //  |  |              |    |                                  v          |   |
    66 //  |  |              |    |                              +---------+    |   |
    67 //  |  |              |    |                              | Fallback|    |   |
    68 //  |  |              |    |                              | Stub    |    |   |
    69 //  |  |              |    |                              | Code    |    |   |
    70 //  |  |              |    |                              +---------+    |   |
    71 //  |  +--------------+    |                                             |   |
    72 //  |         |_______     |                              +---------+    |   |
    73 //  |                |     |                              | Stub    |<---/   |
    74 //  |        IC      |     \--.                           | Code    |        |
    75 //  |    Descriptor  |        |                           +---------+        |
    76 //  |      Table     v        |                                              |
    77 //  |  +-----------------+    |                           +---------+        |
    78 //  \--| Ins | PC | Stub |----/                           | Stub    |<-------/
    79 //     +-----------------+                                | Code    |
    80 //     |       ...       |                                +---------+
    81 //     +-----------------+
    82 //                                                          Shared
    83 //                                                          Stub Code
    84 //
    85 //
    86 // Type ICs
    87 // ========
    88 //
    89 // Type ICs are otherwise regular ICs that are actually nested within
    90 // other IC chains.  They serve to optimize locations in the code where the
    91 // baseline compiler would have otherwise had to perform a type Monitor operation
    92 // (e.g. the result of GetProp, GetElem, etc.), or locations where the baseline
    93 // compiler would have had to modify a heap typeset using the type of an input
    94 // value (e.g. SetProp, SetElem, etc.)
    95 //
    96 // There are two kinds of Type ICs: Monitor and Update.
    97 //
    98 // Note that type stub bodies are no-ops.  The stubs only exist for their
    99 // guards, and their existence simply signifies that the typeset (implicit)
   100 // that is being checked already contains that type.
   101 //
   102 // TypeMonitor ICs
   103 // ---------------
   104 // Monitor ICs are shared between stubs in the general IC, and monitor the resulting
   105 // types of getter operations (call returns, getprop outputs, etc.)
   106 //
   107 //        +-----------+     +-----------+     +-----------+     +-----------+
   108 //   ---->| Stub 1    |---->| Stub 2    |---->| Stub 3    |---->| FB Stub   |
   109 //        +-----------+     +-----------+     +-----------+     +-----------+
   110 //             |                  |                 |                  |
   111 //             |------------------/-----------------/                  |
   112 //             v                                                       |
   113 //        +-----------+     +-----------+     +-----------+            |
   114 //        | Type 1    |---->| Type 2    |---->| Type FB   |            |
   115 //        +-----------+     +-----------+     +-----------+            |
   116 //             |                 |                  |                  |
   117 //  <----------/-----------------/------------------/------------------/
   118 //                r e t u r n    p a t h
   119 //
   120 // After an optimized IC stub successfully executes, it passes control to the type stub
   121 // chain to check the resulting type.  If no type stub succeeds, and the monitor fallback
   122 // stub is reached, the monitor fallback stub performs a manual monitor, and also adds the
   123 // appropriate type stub to the chain.
   124 //
   125 // The IC's main fallback, in addition to generating new mainline stubs, also generates
   126 // type stubs as reflected by its returned value.
   127 //
   128 // NOTE: The type IC chain returns directly to the mainline code, not back to the
   129 // stub it was entered from.  Thus, entering a type IC is a matter of a |jump|, not
   130 // a |call|.  This allows us to safely call a VM Monitor function from within the monitor IC's
   131 // fallback chain, since the return address (needed for stack inspection) is preserved.
   132 //
   133 //
   134 // TypeUpdate ICs
   135 // --------------
   136 // Update ICs update heap typesets and monitor the input types of setter operations
   137 // (setelem, setprop inputs, etc.).  Unlike monitor ICs, they are not shared
   138 // between stubs on an IC, but instead are kept track of on a per-stub basis.
   139 //
   140 // This is because the main stubs for the operation will each identify a potentially
   141 // different TypeObject to update.  New input types must be tracked on a typeobject-to-
   142 // typeobject basis.
   143 //
   144 // Type-update ICs cannot be called in tail position (they must return to the
   145 // the stub that called them so that the stub may continue to perform its original
   146 // purpose).  This means that any VMCall to perform a manual type update from C++ must be
   147 // done from within the main IC stub.  This necessitates that the stub enter a
   148 // "BaselineStub" frame before making the call.
   149 //
   150 // If the type-update IC chain could itself make the VMCall, then the BaselineStub frame
   151 // must be entered before calling the type-update chain, and exited afterward.  This
   152 // is very expensive for a common case where we expect the type-update fallback to not
   153 // be called.  To avoid the cost of entering and exiting a BaselineStub frame when
   154 // using the type-update IC chain, we design the chain to not perform any VM-calls
   155 // in its fallback.
   156 //
   157 // Instead, the type-update IC chain is responsible for returning 1 or 0, depending
   158 // on if a type is represented in the chain or not.  The fallback stub simply returns
   159 // 0, and all other optimized stubs return 1.
   160 // If the chain returns 1, then the IC stub goes ahead and performs its operation.
   161 // If the chain returns 0, then the IC stub performs a call to the fallback function
   162 // inline (doing the requisite BaselineStub frame enter/exit).
   163 // This allows us to avoid the expensive subfram enter/exit in the common case.
   164 //
   165 //                                 r e t u r n    p a t h
   166 //   <--------------.-----------------.-----------------.-----------------.
   167 //                  |                 |                 |                 |
   168 //        +-----------+     +-----------+     +-----------+     +-----------+
   169 //   ---->| Stub 1    |---->| Stub 2    |---->| Stub 3    |---->| FB Stub   |
   170 //        +-----------+     +-----------+     +-----------+     +-----------+
   171 //          |   ^             |   ^             |   ^
   172 //          |   |             |   |             |   |
   173 //          |   |             |   |             |   |----------------.
   174 //          |   |             |   |             v   |1               |0
   175 //          |   |             |   |         +-----------+    +-----------+
   176 //          |   |             |   |         | Type 3.1  |--->|    FB 3   |
   177 //          |   |             |   |         +-----------+    +-----------+
   178 //          |   |             |   |
   179 //          |   |             |   \-------------.-----------------.
   180 //          |   |             |   |             |                 |
   181 //          |   |             v   |1            |1                |0
   182 //          |   |         +-----------+     +-----------+     +-----------+
   183 //          |   |         | Type 2.1  |---->| Type 2.2  |---->|    FB 2   |
   184 //          |   |         +-----------+     +-----------+     +-----------+
   185 //          |   |
   186 //          |   \-------------.-----------------.
   187 //          |   |             |                 |
   188 //          v   |1            |1                |0
   189 //     +-----------+     +-----------+     +-----------+
   190 //     | Type 1.1  |---->| Type 1.2  |---->|   FB 1    |
   191 //     +-----------+     +-----------+     +-----------+
   192 //
   194 class ICStub;
   195 class ICFallbackStub;
   197 //
   198 // An entry in the Baseline IC descriptor table.
   199 //
   200 class ICEntry
   201 {
   202   private:
   203     // A pointer to the baseline IC stub for this instruction.
   204     ICStub *firstStub_;
   206     // Offset from the start of the JIT code where the IC
   207     // load and call instructions are.
   208     uint32_t returnOffset_;
   210     // The PC of this IC's bytecode op within the JSScript.
   211     uint32_t pcOffset_ : 29;
   213   public:
   214     enum Kind {
   215         // A for-op IC entry.
   216         Kind_Op = 0,
   218         // A non-op IC entry.
   219         Kind_NonOp,
   221         // A fake IC entry for returning from a callVM.
   222         Kind_CallVM,
   224         // A fake IC entry for returning from DebugTrapHandler.
   225         Kind_DebugTrap,
   227         // A fake IC entry for returning from a callVM to
   228         // Debug{Prologue,Epilogue}.
   229         Kind_DebugPrologue,
   230         Kind_DebugEpilogue
   231     };
   233   private:
   234     // What this IC is for.
   235     Kind kind_ : 3;
   237     // Set the kind and asserts that it's sane.
   238     void setKind(Kind kind) {
   239         kind_ = kind;
   240         MOZ_ASSERT(this->kind() == kind);
   241     }
   243   public:
   244     ICEntry(uint32_t pcOffset, Kind kind)
   245       : firstStub_(nullptr), returnOffset_(), pcOffset_(pcOffset)
   246     {
   247         // The offset must fit in at least 29 bits, since we shave off 3 for
   248         // the Kind enum.
   249         MOZ_ASSERT(pcOffset_ == pcOffset);
   250         JS_STATIC_ASSERT(BaselineScript::MAX_JSSCRIPT_LENGTH < 0x1fffffffu);
   251         MOZ_ASSERT(pcOffset <= BaselineScript::MAX_JSSCRIPT_LENGTH);
   252         setKind(kind);
   253     }
   255     CodeOffsetLabel returnOffset() const {
   256         return CodeOffsetLabel(returnOffset_);
   257     }
   259     void setReturnOffset(CodeOffsetLabel offset) {
   260         JS_ASSERT(offset.offset() <= (size_t) UINT32_MAX);
   261         returnOffset_ = (uint32_t) offset.offset();
   262     }
   264     void fixupReturnOffset(MacroAssembler &masm) {
   265         CodeOffsetLabel offset = returnOffset();
   266         offset.fixup(&masm);
   267         JS_ASSERT(offset.offset() <= UINT32_MAX);
   268         returnOffset_ = (uint32_t) offset.offset();
   269     }
   271     uint32_t pcOffset() const {
   272         return pcOffset_;
   273     }
   275     jsbytecode *pc(JSScript *script) const {
   276         return script->offsetToPC(pcOffset_);
   277     }
   279     Kind kind() const {
   280         // MSVC compiles enums as signed.
   281         return (Kind)(kind_ & 0x7);
   282     }
   283     bool isForOp() const {
   284         return kind() == Kind_Op;
   285     }
   287     void setForDebugPrologue() {
   288         MOZ_ASSERT(kind() == Kind_CallVM);
   289         setKind(Kind_DebugPrologue);
   290     }
   291     void setForDebugEpilogue() {
   292         MOZ_ASSERT(kind() == Kind_CallVM);
   293         setKind(Kind_DebugEpilogue);
   294     }
   296     bool hasStub() const {
   297         return firstStub_ != nullptr;
   298     }
   299     ICStub *firstStub() const {
   300         JS_ASSERT(hasStub());
   301         return firstStub_;
   302     }
   304     ICFallbackStub *fallbackStub() const;
   306     void setFirstStub(ICStub *stub) {
   307         firstStub_ = stub;
   308     }
   310     static inline size_t offsetOfFirstStub() {
   311         return offsetof(ICEntry, firstStub_);
   312     }
   314     inline ICStub **addressOfFirstStub() {
   315         return &firstStub_;
   316     }
   317 };
   319 // List of baseline IC stub kinds.
   320 #define IC_STUB_KIND_LIST(_)    \
   321     _(UseCount_Fallback)        \
   322                                 \
   323     _(Profiler_Fallback)        \
   324     _(Profiler_PushFunction)    \
   325                                 \
   326     _(TypeMonitor_Fallback)     \
   327     _(TypeMonitor_SingleObject) \
   328     _(TypeMonitor_TypeObject)   \
   329     _(TypeMonitor_PrimitiveSet) \
   330                                 \
   331     _(TypeUpdate_Fallback)      \
   332     _(TypeUpdate_SingleObject)  \
   333     _(TypeUpdate_TypeObject)    \
   334     _(TypeUpdate_PrimitiveSet)  \
   335                                 \
   336     _(This_Fallback)            \
   337                                 \
   338     _(NewArray_Fallback)        \
   339     _(NewObject_Fallback)       \
   340                                 \
   341     _(Compare_Fallback)         \
   342     _(Compare_Int32)            \
   343     _(Compare_Double)           \
   344     _(Compare_NumberWithUndefined) \
   345     _(Compare_String)           \
   346     _(Compare_Boolean)          \
   347     _(Compare_Object)           \
   348     _(Compare_ObjectWithUndefined) \
   349     _(Compare_Int32WithBoolean) \
   350                                 \
   351     _(ToBool_Fallback)          \
   352     _(ToBool_Int32)             \
   353     _(ToBool_String)            \
   354     _(ToBool_NullUndefined)     \
   355     _(ToBool_Double)            \
   356     _(ToBool_Object)            \
   357                                 \
   358     _(ToNumber_Fallback)        \
   359                                 \
   360     _(BinaryArith_Fallback)     \
   361     _(BinaryArith_Int32)        \
   362     _(BinaryArith_Double)       \
   363     _(BinaryArith_StringConcat) \
   364     _(BinaryArith_StringObjectConcat) \
   365     _(BinaryArith_BooleanWithInt32) \
   366     _(BinaryArith_DoubleWithInt32) \
   367                                 \
   368     _(UnaryArith_Fallback)      \
   369     _(UnaryArith_Int32)         \
   370     _(UnaryArith_Double)        \
   371                                 \
   372     _(Call_Fallback)            \
   373     _(Call_Scripted)            \
   374     _(Call_AnyScripted)         \
   375     _(Call_Native)              \
   376     _(Call_ScriptedApplyArray)  \
   377     _(Call_ScriptedApplyArguments) \
   378     _(Call_ScriptedFunCall)     \
   379                                 \
   380     _(GetElem_Fallback)         \
   381     _(GetElem_NativeSlot)       \
   382     _(GetElem_NativePrototypeSlot) \
   383     _(GetElem_NativePrototypeCallNative) \
   384     _(GetElem_NativePrototypeCallScripted) \
   385     _(GetElem_String)           \
   386     _(GetElem_Dense)            \
   387     _(GetElem_TypedArray)       \
   388     _(GetElem_Arguments)        \
   389                                 \
   390     _(SetElem_Fallback)         \
   391     _(SetElem_Dense)            \
   392     _(SetElem_DenseAdd)         \
   393     _(SetElem_TypedArray)       \
   394                                 \
   395     _(In_Fallback)              \
   396                                 \
   397     _(GetName_Fallback)         \
   398     _(GetName_Global)           \
   399     _(GetName_Scope0)           \
   400     _(GetName_Scope1)           \
   401     _(GetName_Scope2)           \
   402     _(GetName_Scope3)           \
   403     _(GetName_Scope4)           \
   404     _(GetName_Scope5)           \
   405     _(GetName_Scope6)           \
   406                                 \
   407     _(BindName_Fallback)        \
   408                                 \
   409     _(GetIntrinsic_Fallback)    \
   410     _(GetIntrinsic_Constant)    \
   411                                 \
   412     _(GetProp_Fallback)         \
   413     _(GetProp_ArrayLength)      \
   414     _(GetProp_TypedArrayLength) \
   415     _(GetProp_Primitive)        \
   416     _(GetProp_StringLength)     \
   417     _(GetProp_Native)           \
   418     _(GetProp_NativePrototype)  \
   419     _(GetProp_CallScripted)     \
   420     _(GetProp_CallNative)       \
   421     _(GetProp_CallNativePrototype)\
   422     _(GetProp_CallDOMProxyNative)\
   423     _(GetProp_CallDOMProxyWithGenerationNative)\
   424     _(GetProp_DOMProxyShadowed) \
   425     _(GetProp_ArgumentsLength)  \
   426                                 \
   427     _(SetProp_Fallback)         \
   428     _(SetProp_Native)           \
   429     _(SetProp_NativeAdd)        \
   430     _(SetProp_CallScripted)     \
   431     _(SetProp_CallNative)       \
   432                                 \
   433     _(TableSwitch)              \
   434                                 \
   435     _(IteratorNew_Fallback)     \
   436     _(IteratorMore_Fallback)    \
   437     _(IteratorMore_Native)      \
   438     _(IteratorNext_Fallback)    \
   439     _(IteratorNext_Native)      \
   440     _(IteratorClose_Fallback)   \
   441                                 \
   442     _(InstanceOf_Fallback)      \
   443                                 \
   444     _(TypeOf_Fallback)          \
   445     _(TypeOf_Typed)             \
   446                                 \
   447     _(Rest_Fallback)            \
   448                                 \
   449     _(RetSub_Fallback)          \
   450     _(RetSub_Resume)
   452 #define FORWARD_DECLARE_STUBS(kindName) class IC##kindName;
   453     IC_STUB_KIND_LIST(FORWARD_DECLARE_STUBS)
   454 #undef FORWARD_DECLARE_STUBS
   456 class ICMonitoredStub;
   457 class ICMonitoredFallbackStub;
   458 class ICUpdatedStub;
   460 // Constant iterator that traverses arbitrary chains of ICStubs.
   461 // No requirements are made of the ICStub used to construct this
   462 // iterator, aside from that the stub be part of a nullptr-terminated
   463 // chain.
   464 // The iterator is considered to be at its end once it has been
   465 // incremented _past_ the last stub.  Thus, if 'atEnd()' returns
   466 // true, the '*' and '->' operations are not valid.
   467 class ICStubConstIterator
   468 {
   469     friend class ICStub;
   470     friend class ICFallbackStub;
   472   private:
   473     ICStub *currentStub_;
   475   public:
   476     ICStubConstIterator(ICStub *currentStub) : currentStub_(currentStub) {}
   478     static ICStubConstIterator StartingAt(ICStub *stub) {
   479         return ICStubConstIterator(stub);
   480     }
   481     static ICStubConstIterator End(ICStub *stub) {
   482         return ICStubConstIterator(nullptr);
   483     }
   485     bool operator ==(const ICStubConstIterator &other) const {
   486         return currentStub_ == other.currentStub_;
   487     }
   488     bool operator !=(const ICStubConstIterator &other) const {
   489         return !(*this == other);
   490     }
   492     ICStubConstIterator &operator++();
   494     ICStubConstIterator operator++(int) {
   495         ICStubConstIterator oldThis(*this);
   496         ++(*this);
   497         return oldThis;
   498     }
   500     ICStub *operator *() const {
   501         JS_ASSERT(currentStub_);
   502         return currentStub_;
   503     }
   505     ICStub *operator ->() const {
   506         JS_ASSERT(currentStub_);
   507         return currentStub_;
   508     }
   510     bool atEnd() const {
   511         return currentStub_ == nullptr;
   512     }
   513 };
   515 // Iterator that traverses "regular" IC chains that start at an ICEntry
   516 // and are terminated with an ICFallbackStub.
   517 //
   518 // The iterator is considered to be at its end once it is _at_ the
   519 // fallback stub.  Thus, unlike the ICStubConstIterator, operators
   520 // '*' and '->' are valid even if 'atEnd()' returns true - they
   521 // will act on the fallback stub.
   522 //
   523 // This iterator also allows unlinking of stubs being traversed.
   524 // Note that 'unlink' does not implicitly advance the iterator -
   525 // it must be advanced explicitly using '++'.
   526 class ICStubIterator
   527 {
   528     friend class ICFallbackStub;
   530   private:
   531     ICEntry *icEntry_;
   532     ICFallbackStub *fallbackStub_;
   533     ICStub *previousStub_;
   534     ICStub *currentStub_;
   535     bool unlinked_;
   537     ICStubIterator(ICFallbackStub *fallbackStub, bool end=false);
   538   public:
   540     bool operator ==(const ICStubIterator &other) const {
   541         // == should only ever be called on stubs from the same chain.
   542         JS_ASSERT(icEntry_ == other.icEntry_);
   543         JS_ASSERT(fallbackStub_ == other.fallbackStub_);
   544         return currentStub_ == other.currentStub_;
   545     }
   546     bool operator !=(const ICStubIterator &other) const {
   547         return !(*this == other);
   548     }
   550     ICStubIterator &operator++();
   552     ICStubIterator operator++(int) {
   553         ICStubIterator oldThis(*this);
   554         ++(*this);
   555         return oldThis;
   556     }
   558     ICStub *operator *() const {
   559         return currentStub_;
   560     }
   562     ICStub *operator ->() const {
   563         return currentStub_;
   564     }
   566     bool atEnd() const {
   567         return currentStub_ == (ICStub *) fallbackStub_;
   568     }
   570     void unlink(JSContext *cx);
   571 };
   573 //
   574 // Base class for all IC stubs.
   575 //
   576 class ICStub
   577 {
   578     friend class ICFallbackStub;
   580   public:
   581     enum Kind {
   582         INVALID = 0,
   583 #define DEF_ENUM_KIND(kindName) kindName,
   584         IC_STUB_KIND_LIST(DEF_ENUM_KIND)
   585 #undef DEF_ENUM_KIND
   586         LIMIT
   587     };
   589     static inline bool IsValidKind(Kind k) {
   590         return (k > INVALID) && (k < LIMIT);
   591     }
   593     static const char *KindString(Kind k) {
   594         switch(k) {
   595 #define DEF_KIND_STR(kindName) case kindName: return #kindName;
   596             IC_STUB_KIND_LIST(DEF_KIND_STR)
   597 #undef DEF_KIND_STR
   598           default:
   599             MOZ_ASSUME_UNREACHABLE("Invalid kind.");
   600         }
   601     }
   603     enum Trait {
   604         Regular             = 0x0,
   605         Fallback            = 0x1,
   606         Monitored           = 0x2,
   607         MonitoredFallback   = 0x3,
   608         Updated             = 0x4
   609     };
   611     void markCode(JSTracer *trc, const char *name);
   612     void updateCode(JitCode *stubCode);
   613     void trace(JSTracer *trc);
   615   protected:
   616     // The raw jitcode to call for this stub.
   617     uint8_t *stubCode_;
   619     // Pointer to next IC stub.  This is null for the last IC stub, which should
   620     // either be a fallback or inert IC stub.
   621     ICStub *next_;
   623     // A 16-bit field usable by subtypes of ICStub for subtype-specific small-info
   624     uint16_t extra_;
   626     // The kind of the stub.
   627     //  High bit is 'isFallback' flag.
   628     //  Second high bit is 'isMonitored' flag.
   629     Trait trait_ : 3;
   630     Kind kind_ : 13;
   632     inline ICStub(Kind kind, JitCode *stubCode)
   633       : stubCode_(stubCode->raw()),
   634         next_(nullptr),
   635         extra_(0),
   636         trait_(Regular),
   637         kind_(kind)
   638     {
   639         JS_ASSERT(stubCode != nullptr);
   640     }
   642     inline ICStub(Kind kind, Trait trait, JitCode *stubCode)
   643       : stubCode_(stubCode->raw()),
   644         next_(nullptr),
   645         extra_(0),
   646         trait_(trait),
   647         kind_(kind)
   648     {
   649         JS_ASSERT(stubCode != nullptr);
   650     }
   652     inline Trait trait() const {
   653         // Workaround for MSVC reading trait_ as signed value.
   654         return (Trait)(trait_ & 0x7);
   655     }
   657   public:
   659     inline Kind kind() const {
   660         return static_cast<Kind>(kind_);
   661     }
   663     inline bool isFallback() const {
   664         return trait() == Fallback || trait() == MonitoredFallback;
   665     }
   667     inline bool isMonitored() const {
   668         return trait() == Monitored;
   669     }
   671     inline bool isUpdated() const {
   672         return trait() == Updated;
   673     }
   675     inline bool isMonitoredFallback() const {
   676         return trait() == MonitoredFallback;
   677     }
   679     inline const ICFallbackStub *toFallbackStub() const {
   680         JS_ASSERT(isFallback());
   681         return reinterpret_cast<const ICFallbackStub *>(this);
   682     }
   684     inline ICFallbackStub *toFallbackStub() {
   685         JS_ASSERT(isFallback());
   686         return reinterpret_cast<ICFallbackStub *>(this);
   687     }
   689     inline const ICMonitoredStub *toMonitoredStub() const {
   690         JS_ASSERT(isMonitored());
   691         return reinterpret_cast<const ICMonitoredStub *>(this);
   692     }
   694     inline ICMonitoredStub *toMonitoredStub() {
   695         JS_ASSERT(isMonitored());
   696         return reinterpret_cast<ICMonitoredStub *>(this);
   697     }
   699     inline const ICMonitoredFallbackStub *toMonitoredFallbackStub() const {
   700         JS_ASSERT(isMonitoredFallback());
   701         return reinterpret_cast<const ICMonitoredFallbackStub *>(this);
   702     }
   704     inline ICMonitoredFallbackStub *toMonitoredFallbackStub() {
   705         JS_ASSERT(isMonitoredFallback());
   706         return reinterpret_cast<ICMonitoredFallbackStub *>(this);
   707     }
   709     inline const ICUpdatedStub *toUpdatedStub() const {
   710         JS_ASSERT(isUpdated());
   711         return reinterpret_cast<const ICUpdatedStub *>(this);
   712     }
   714     inline ICUpdatedStub *toUpdatedStub() {
   715         JS_ASSERT(isUpdated());
   716         return reinterpret_cast<ICUpdatedStub *>(this);
   717     }
   719 #define KIND_METHODS(kindName)   \
   720     inline bool is##kindName() const { return kind() == kindName; } \
   721     inline const IC##kindName *to##kindName() const { \
   722         JS_ASSERT(is##kindName()); \
   723         return reinterpret_cast<const IC##kindName *>(this); \
   724     } \
   725     inline IC##kindName *to##kindName() { \
   726         JS_ASSERT(is##kindName()); \
   727         return reinterpret_cast<IC##kindName *>(this); \
   728     }
   729     IC_STUB_KIND_LIST(KIND_METHODS)
   730 #undef KIND_METHODS
   732     inline ICStub *next() const {
   733         return next_;
   734     }
   736     inline bool hasNext() const {
   737         return next_ != nullptr;
   738     }
   740     inline void setNext(ICStub *stub) {
   741         // Note: next_ only needs to be changed under the compilation lock for
   742         // non-type-monitor/update ICs.
   743         next_ = stub;
   744     }
   746     inline ICStub **addressOfNext() {
   747         return &next_;
   748     }
   750     inline JitCode *jitCode() {
   751         return JitCode::FromExecutable(stubCode_);
   752     }
   754     inline uint8_t *rawStubCode() const {
   755         return stubCode_;
   756     }
   758     // This method is not valid on TypeUpdate stub chains!
   759     inline ICFallbackStub *getChainFallback() {
   760         ICStub *lastStub = this;
   761         while (lastStub->next_)
   762             lastStub = lastStub->next_;
   763         JS_ASSERT(lastStub->isFallback());
   764         return lastStub->toFallbackStub();
   765     }
   767     inline ICStubConstIterator beginHere() {
   768         return ICStubConstIterator::StartingAt(this);
   769     }
   771     static inline size_t offsetOfNext() {
   772         return offsetof(ICStub, next_);
   773     }
   775     static inline size_t offsetOfStubCode() {
   776         return offsetof(ICStub, stubCode_);
   777     }
   779     static inline size_t offsetOfExtra() {
   780         return offsetof(ICStub, extra_);
   781     }
   783     static bool CanMakeCalls(ICStub::Kind kind) {
   784         JS_ASSERT(IsValidKind(kind));
   785         switch (kind) {
   786           case Call_Fallback:
   787           case Call_Scripted:
   788           case Call_AnyScripted:
   789           case Call_Native:
   790           case Call_ScriptedApplyArray:
   791           case Call_ScriptedApplyArguments:
   792           case Call_ScriptedFunCall:
   793           case UseCount_Fallback:
   794           case GetElem_NativeSlot:
   795           case GetElem_NativePrototypeSlot:
   796           case GetElem_NativePrototypeCallNative:
   797           case GetElem_NativePrototypeCallScripted:
   798           case GetProp_CallScripted:
   799           case GetProp_CallNative:
   800           case GetProp_CallNativePrototype:
   801           case GetProp_CallDOMProxyNative:
   802           case GetProp_CallDOMProxyWithGenerationNative:
   803           case GetProp_DOMProxyShadowed:
   804           case SetProp_CallScripted:
   805           case SetProp_CallNative:
   806           case RetSub_Fallback:
   807           // These two fallback stubs don't actually make non-tail calls,
   808           // but the fallback code for the bailout path needs to pop the stub frame
   809           // pushed during the bailout.
   810           case GetProp_Fallback:
   811           case SetProp_Fallback:
   812 #if JS_HAS_NO_SUCH_METHOD
   813           case GetElem_Dense:
   814           case GetElem_Arguments:
   815           case GetProp_NativePrototype:
   816           case GetProp_Native:
   817 #endif
   818             return true;
   819           default:
   820             return false;
   821         }
   822     }
   824     // Optimized stubs get purged on GC.  But some stubs can be active on the
   825     // stack during GC - specifically the ones that can make calls.  To ensure
   826     // that these do not get purged, all stubs that can make calls are allocated
   827     // in the fallback stub space.
   828     bool allocatedInFallbackSpace() const {
   829         JS_ASSERT(next());
   830         return CanMakeCalls(kind());
   831     }
   832 };
   834 class ICFallbackStub : public ICStub
   835 {
   836     friend class ICStubConstIterator;
   837   protected:
   838     // Fallback stubs need these fields to easily add new stubs to
   839     // the linked list of stubs for an IC.
   841     // The IC entry for this linked list of stubs.
   842     ICEntry *icEntry_;
   844     // The number of stubs kept in the IC entry.
   845     uint32_t numOptimizedStubs_;
   847     // A pointer to the location stub pointer that needs to be
   848     // changed to add a new "last" stub immediately before the fallback
   849     // stub.  This'll start out pointing to the icEntry's "firstStub_"
   850     // field, and as new stubs are addd, it'll point to the current
   851     // last stub's "next_" field.
   852     ICStub **lastStubPtrAddr_;
   854     ICFallbackStub(Kind kind, JitCode *stubCode)
   855       : ICStub(kind, ICStub::Fallback, stubCode),
   856         icEntry_(nullptr),
   857         numOptimizedStubs_(0),
   858         lastStubPtrAddr_(nullptr) {}
   860     ICFallbackStub(Kind kind, Trait trait, JitCode *stubCode)
   861       : ICStub(kind, trait, stubCode),
   862         icEntry_(nullptr),
   863         numOptimizedStubs_(0),
   864         lastStubPtrAddr_(nullptr)
   865     {
   866         JS_ASSERT(trait == ICStub::Fallback ||
   867                   trait == ICStub::MonitoredFallback);
   868     }
   870   public:
   871     inline ICEntry *icEntry() const {
   872         return icEntry_;
   873     }
   875     inline size_t numOptimizedStubs() const {
   876         return (size_t) numOptimizedStubs_;
   877     }
   879     // The icEntry and lastStubPtrAddr_ fields can't be initialized when the stub is
   880     // created since the stub is created at compile time, and we won't know the IC entry
   881     // address until after compile when the BaselineScript is created.  This method
   882     // allows these fields to be fixed up at that point.
   883     void fixupICEntry(ICEntry *icEntry) {
   884         JS_ASSERT(icEntry_ == nullptr);
   885         JS_ASSERT(lastStubPtrAddr_ == nullptr);
   886         icEntry_ = icEntry;
   887         lastStubPtrAddr_ = icEntry_->addressOfFirstStub();
   888     }
   890     // Add a new stub to the IC chain terminated by this fallback stub.
   891     void addNewStub(ICStub *stub) {
   892         JS_ASSERT(*lastStubPtrAddr_ == this);
   893         JS_ASSERT(stub->next() == nullptr);
   894         stub->setNext(this);
   895         *lastStubPtrAddr_ = stub;
   896         lastStubPtrAddr_ = stub->addressOfNext();
   897         numOptimizedStubs_++;
   898     }
   900     ICStubConstIterator beginChainConst() const {
   901         return ICStubConstIterator(icEntry_->firstStub());
   902     }
   904     ICStubIterator beginChain() {
   905         return ICStubIterator(this);
   906     }
   908     bool hasStub(ICStub::Kind kind) const {
   909         for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
   910             if (iter->kind() == kind)
   911                 return true;
   912         }
   913         return false;
   914     }
   916     unsigned numStubsWithKind(ICStub::Kind kind) const {
   917         unsigned count = 0;
   918         for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
   919             if (iter->kind() == kind)
   920                 count++;
   921         }
   922         return count;
   923     }
   925     void unlinkStub(Zone *zone, ICStub *prev, ICStub *stub);
   926     void unlinkStubsWithKind(JSContext *cx, ICStub::Kind kind);
   927 };
   929 // Monitored stubs are IC stubs that feed a single resulting value out to a
   930 // type monitor operation.
   931 class ICMonitoredStub : public ICStub
   932 {
   933   protected:
   934     // Pointer to the start of the type monitoring stub chain.
   935     ICStub *firstMonitorStub_;
   937     ICMonitoredStub(Kind kind, JitCode *stubCode, ICStub *firstMonitorStub);
   939   public:
   940     inline void updateFirstMonitorStub(ICStub *monitorStub) {
   941         // This should only be called once: when the first optimized monitor stub
   942         // is added to the type monitor IC chain.
   943         JS_ASSERT(firstMonitorStub_ && firstMonitorStub_->isTypeMonitor_Fallback());
   944         firstMonitorStub_ = monitorStub;
   945     }
   946     inline void resetFirstMonitorStub(ICStub *monitorFallback) {
   947         JS_ASSERT(monitorFallback->isTypeMonitor_Fallback());
   948         firstMonitorStub_ = monitorFallback;
   949     }
   950     inline ICStub *firstMonitorStub() const {
   951         return firstMonitorStub_;
   952     }
   954     static inline size_t offsetOfFirstMonitorStub() {
   955         return offsetof(ICMonitoredStub, firstMonitorStub_);
   956     }
   957 };
   959 // Monitored fallback stubs - as the name implies.
   960 class ICMonitoredFallbackStub : public ICFallbackStub
   961 {
   962   protected:
   963     // Pointer to the fallback monitor stub.
   964     ICTypeMonitor_Fallback *fallbackMonitorStub_;
   966     ICMonitoredFallbackStub(Kind kind, JitCode *stubCode)
   967       : ICFallbackStub(kind, ICStub::MonitoredFallback, stubCode),
   968         fallbackMonitorStub_(nullptr) {}
   970   public:
   971     bool initMonitoringChain(JSContext *cx, ICStubSpace *space);
   972     bool addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val);
   974     inline ICTypeMonitor_Fallback *fallbackMonitorStub() const {
   975         return fallbackMonitorStub_;
   976     }
   978     static inline size_t offsetOfFallbackMonitorStub() {
   979         return offsetof(ICMonitoredFallbackStub, fallbackMonitorStub_);
   980     }
   981 };
   983 // Updated stubs are IC stubs that use a TypeUpdate IC to track
   984 // the status of heap typesets that need to be updated.
   985 class ICUpdatedStub : public ICStub
   986 {
   987   protected:
   988     // Pointer to the start of the type updating stub chain.
   989     ICStub *firstUpdateStub_;
   991     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
   992     uint32_t numOptimizedStubs_;
   994     ICUpdatedStub(Kind kind, JitCode *stubCode)
   995       : ICStub(kind, ICStub::Updated, stubCode),
   996         firstUpdateStub_(nullptr),
   997         numOptimizedStubs_(0)
   998     {}
  1000   public:
  1001     bool initUpdatingChain(JSContext *cx, ICStubSpace *space);
  1003     bool addUpdateStubForValue(JSContext *cx, HandleScript script, HandleObject obj, HandleId id,
  1004                                HandleValue val);
  1006     void addOptimizedUpdateStub(ICStub *stub) {
  1007         if (firstUpdateStub_->isTypeUpdate_Fallback()) {
  1008             stub->setNext(firstUpdateStub_);
  1009             firstUpdateStub_ = stub;
  1010         } else {
  1011             ICStub *iter = firstUpdateStub_;
  1012             JS_ASSERT(iter->next() != nullptr);
  1013             while (!iter->next()->isTypeUpdate_Fallback())
  1014                 iter = iter->next();
  1015             JS_ASSERT(iter->next()->next() == nullptr);
  1016             stub->setNext(iter->next());
  1017             iter->setNext(stub);
  1020         numOptimizedStubs_++;
  1023     inline ICStub *firstUpdateStub() const {
  1024         return firstUpdateStub_;
  1027     bool hasTypeUpdateStub(ICStub::Kind kind) {
  1028         ICStub *stub = firstUpdateStub_;
  1029         do {
  1030             if (stub->kind() == kind)
  1031                 return true;
  1033             stub = stub->next();
  1034         } while (stub);
  1036         return false;
  1039     inline uint32_t numOptimizedStubs() const {
  1040         return numOptimizedStubs_;
  1043     static inline size_t offsetOfFirstUpdateStub() {
  1044         return offsetof(ICUpdatedStub, firstUpdateStub_);
  1046 };
  1048 // Base class for stubcode compilers.
  1049 class ICStubCompiler
  1051     // Prevent GC in the middle of stub compilation.
  1052     js::gc::AutoSuppressGC suppressGC;
  1055   protected:
  1056     JSContext *cx;
  1057     ICStub::Kind kind;
  1058 #ifdef DEBUG
  1059     bool entersStubFrame_;
  1060 #endif
  1062     // By default the stubcode key is just the kind.
  1063     virtual int32_t getKey() const {
  1064         return static_cast<int32_t>(kind);
  1067     virtual bool generateStubCode(MacroAssembler &masm) = 0;
  1068     virtual bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> genCode) {
  1069         return true;
  1071     JitCode *getStubCode();
  1073     ICStubCompiler(JSContext *cx, ICStub::Kind kind)
  1074       : suppressGC(cx), cx(cx), kind(kind)
  1075 #ifdef DEBUG
  1076       , entersStubFrame_(false)
  1077 #endif
  1078     {}
  1080     // Emits a tail call to a VMFunction wrapper.
  1081     bool tailCallVM(const VMFunction &fun, MacroAssembler &masm);
  1083     // Emits a normal (non-tail) call to a VMFunction wrapper.
  1084     bool callVM(const VMFunction &fun, MacroAssembler &masm);
  1086     // Emits a call to a type-update IC, assuming that the value to be
  1087     // checked is already in R0.
  1088     bool callTypeUpdateIC(MacroAssembler &masm, uint32_t objectOffset);
  1090     // A stub frame is used when a stub wants to call into the VM without
  1091     // performing a tail call. This is required for the return address
  1092     // to pc mapping to work.
  1093     void enterStubFrame(MacroAssembler &masm, Register scratch);
  1094     void leaveStubFrame(MacroAssembler &masm, bool calledIntoIon = false);
  1095     void leaveStubFrameHead(MacroAssembler &masm, bool calledIntoIon = false);
  1096     void leaveStubFrameCommonTail(MacroAssembler &masm);
  1098     // Some stubs need to emit SPS profiler updates.  This emits the guarding
  1099     // jitcode for those stubs.  If profiling is not enabled, jumps to the
  1100     // given label.
  1101     void guardProfilingEnabled(MacroAssembler &masm, Register scratch, Label *skip);
  1103     // Higher-level helper to emit an update to the profiler pseudo-stack.
  1104     void emitProfilingUpdate(MacroAssembler &masm, Register pcIdx, Register scratch,
  1105                              uint32_t stubPcOffset);
  1106     void emitProfilingUpdate(MacroAssembler &masm, GeneralRegisterSet regs, uint32_t stubPcOffset);
  1108     inline GeneralRegisterSet availableGeneralRegs(size_t numInputs) const {
  1109         GeneralRegisterSet regs(GeneralRegisterSet::All());
  1110         JS_ASSERT(!regs.has(BaselineStackReg));
  1111 #if defined(JS_CODEGEN_ARM)
  1112         JS_ASSERT(!regs.has(BaselineTailCallReg));
  1113         regs.take(BaselineSecondScratchReg);
  1114 #elif defined(JS_CODEGEN_MIPS)
  1115         JS_ASSERT(!regs.has(BaselineTailCallReg));
  1116         JS_ASSERT(!regs.has(BaselineSecondScratchReg));
  1117 #endif
  1118         regs.take(BaselineFrameReg);
  1119         regs.take(BaselineStubReg);
  1120 #ifdef JS_CODEGEN_X64
  1121         regs.take(ExtractTemp0);
  1122         regs.take(ExtractTemp1);
  1123 #endif
  1125         switch (numInputs) {
  1126           case 0:
  1127             break;
  1128           case 1:
  1129             regs.take(R0);
  1130             break;
  1131           case 2:
  1132             regs.take(R0);
  1133             regs.take(R1);
  1134             break;
  1135           default:
  1136             MOZ_ASSUME_UNREACHABLE("Invalid numInputs");
  1139         return regs;
  1142 #ifdef JSGC_GENERATIONAL
  1143     inline bool emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, ValueOperand val,
  1144                                          Register scratch, GeneralRegisterSet saveRegs);
  1145 #endif
  1147   public:
  1148     virtual ICStub *getStub(ICStubSpace *space) = 0;
  1150     ICStubSpace *getStubSpace(JSScript *script) {
  1151         if (ICStub::CanMakeCalls(kind))
  1152             return script->baselineScript()->fallbackStubSpace();
  1153         return script->zone()->jitZone()->optimizedStubSpace();
  1155 };
  1157 // Base class for stub compilers that can generate multiple stubcodes.
  1158 // These compilers need access to the JSOp they are compiling for.
  1159 class ICMultiStubCompiler : public ICStubCompiler
  1161   protected:
  1162     JSOp op;
  1164     // Stub keys for multi-stub kinds are composed of both the kind
  1165     // and the op they are compiled for.
  1166     virtual int32_t getKey() const {
  1167         return static_cast<int32_t>(kind) | (static_cast<int32_t>(op) << 16);
  1170     ICMultiStubCompiler(JSContext *cx, ICStub::Kind kind, JSOp op)
  1171       : ICStubCompiler(cx, kind), op(op) {}
  1172 };
  1174 // UseCount_Fallback
  1176 // A UseCount IC chain has only the fallback stub.
  1177 class ICUseCount_Fallback : public ICFallbackStub
  1179     friend class ICStubSpace;
  1181     ICUseCount_Fallback(JitCode *stubCode)
  1182       : ICFallbackStub(ICStub::UseCount_Fallback, stubCode)
  1183     { }
  1185   public:
  1186     static inline ICUseCount_Fallback *New(ICStubSpace *space, JitCode *code) {
  1187         if (!code)
  1188             return nullptr;
  1189         return space->allocate<ICUseCount_Fallback>(code);
  1192     // Compiler for this stub kind.
  1193     class Compiler : public ICStubCompiler {
  1194       protected:
  1195         bool generateStubCode(MacroAssembler &masm);
  1197       public:
  1198         Compiler(JSContext *cx)
  1199           : ICStubCompiler(cx, ICStub::UseCount_Fallback)
  1200         { }
  1202         ICUseCount_Fallback *getStub(ICStubSpace *space) {
  1203             return ICUseCount_Fallback::New(space, getStubCode());
  1205     };
  1206 };
  1208 // Profiler_Fallback
  1210 class ICProfiler_Fallback : public ICFallbackStub
  1212     friend class ICStubSpace;
  1214     ICProfiler_Fallback(JitCode *stubCode)
  1215       : ICFallbackStub(ICStub::Profiler_Fallback, stubCode)
  1216     { }
  1218   public:
  1219     static inline ICProfiler_Fallback *New(ICStubSpace *space, JitCode *code) {
  1220         if (!code)
  1221             return nullptr;
  1222         return space->allocate<ICProfiler_Fallback>(code);
  1225     // Compiler for this stub kind.
  1226     class Compiler : public ICStubCompiler {
  1227       protected:
  1228         bool generateStubCode(MacroAssembler &masm);
  1230       public:
  1231         Compiler(JSContext *cx)
  1232           : ICStubCompiler(cx, ICStub::Profiler_Fallback)
  1233         { }
  1235         ICProfiler_Fallback *getStub(ICStubSpace *space) {
  1236             return ICProfiler_Fallback::New(space, getStubCode());
  1238     };
  1239 };
  1241 // Profiler_PushFunction
  1243 class ICProfiler_PushFunction : public ICStub
  1245     friend class ICStubSpace;
  1247   protected:
  1248     const char *str_;
  1249     HeapPtrScript script_;
  1251     ICProfiler_PushFunction(JitCode *stubCode, const char *str, HandleScript script);
  1253   public:
  1254     static inline ICProfiler_PushFunction *New(ICStubSpace *space, JitCode *code,
  1255                                                const char *str, HandleScript script)
  1257         if (!code)
  1258             return nullptr;
  1259         return space->allocate<ICProfiler_PushFunction>(code, str, script);
  1262     HeapPtrScript &script() {
  1263         return script_;
  1266     static size_t offsetOfStr() {
  1267         return offsetof(ICProfiler_PushFunction, str_);
  1269     static size_t offsetOfScript() {
  1270         return offsetof(ICProfiler_PushFunction, script_);
  1273     // Compiler for this stub kind.
  1274     class Compiler : public ICStubCompiler {
  1275       protected:
  1276         const char *str_;
  1277         RootedScript script_;
  1278         bool generateStubCode(MacroAssembler &masm);
  1280       public:
  1281         Compiler(JSContext *cx, const char *str, HandleScript script)
  1282           : ICStubCompiler(cx, ICStub::Profiler_PushFunction),
  1283             str_(str),
  1284             script_(cx, script)
  1285         { }
  1287         ICProfiler_PushFunction *getStub(ICStubSpace *space) {
  1288             return ICProfiler_PushFunction::New(space, getStubCode(), str_, script_);
  1290     };
  1291 };
  1294 // TypeCheckPrimitiveSetStub
  1295 //   Base class for IC stubs (TypeUpdate or TypeMonitor) that check that a given
  1296 //   value's type falls within a set of primitive types.
  1298 class TypeCheckPrimitiveSetStub : public ICStub
  1300     friend class ICStubSpace;
  1301   protected:
  1302     inline static uint16_t TypeToFlag(JSValueType type) {
  1303         return 1u << static_cast<unsigned>(type);
  1306     inline static uint16_t ValidFlags() {
  1307         return ((TypeToFlag(JSVAL_TYPE_OBJECT) << 1) - 1) & ~TypeToFlag(JSVAL_TYPE_MAGIC);
  1310     TypeCheckPrimitiveSetStub(Kind kind, JitCode *stubCode, uint16_t flags)
  1311         : ICStub(kind, stubCode)
  1313         JS_ASSERT(kind == TypeMonitor_PrimitiveSet || kind == TypeUpdate_PrimitiveSet);
  1314         JS_ASSERT(flags && !(flags & ~ValidFlags()));
  1315         extra_ = flags;
  1318     TypeCheckPrimitiveSetStub *updateTypesAndCode(uint16_t flags, JitCode *code) {
  1319         JS_ASSERT(flags && !(flags & ~ValidFlags()));
  1320         if (!code)
  1321             return nullptr;
  1322         extra_ = flags;
  1323         updateCode(code);
  1324         return this;
  1327   public:
  1328     uint16_t typeFlags() const {
  1329         return extra_;
  1332     bool containsType(JSValueType type) const {
  1333         JS_ASSERT(type <= JSVAL_TYPE_OBJECT);
  1334         JS_ASSERT(type != JSVAL_TYPE_MAGIC);
  1335         return extra_ & TypeToFlag(type);
  1338     ICTypeMonitor_PrimitiveSet *toMonitorStub() {
  1339         return toTypeMonitor_PrimitiveSet();
  1342     ICTypeUpdate_PrimitiveSet *toUpdateStub() {
  1343         return toTypeUpdate_PrimitiveSet();
  1346     class Compiler : public ICStubCompiler {
  1347       protected:
  1348         TypeCheckPrimitiveSetStub *existingStub_;
  1349         uint16_t flags_;
  1351         virtual int32_t getKey() const {
  1352             return static_cast<int32_t>(kind) | (static_cast<int32_t>(flags_) << 16);
  1355       public:
  1356         Compiler(JSContext *cx, Kind kind, TypeCheckPrimitiveSetStub *existingStub,
  1357                  JSValueType type)
  1358           : ICStubCompiler(cx, kind),
  1359             existingStub_(existingStub),
  1360             flags_((existingStub ? existingStub->typeFlags() : 0) | TypeToFlag(type))
  1362             JS_ASSERT_IF(existingStub_, flags_ != existingStub_->typeFlags());
  1365         TypeCheckPrimitiveSetStub *updateStub() {
  1366             JS_ASSERT(existingStub_);
  1367             return existingStub_->updateTypesAndCode(flags_, getStubCode());
  1369     };
  1370 };
  1372 // TypeMonitor
  1374 // The TypeMonitor fallback stub is not always a regular fallback stub. When
  1375 // used for monitoring the values pushed by a bytecode it doesn't hold a
  1376 // pointer to the IC entry, but rather back to the main fallback stub for the
  1377 // IC (from which a pointer to the IC entry can be retrieved). When monitoring
  1378 // the types of 'this', arguments or other values with no associated IC, there
  1379 // is no main fallback stub, and the IC entry is referenced directly.
  1380 class ICTypeMonitor_Fallback : public ICStub
  1382     friend class ICStubSpace;
  1384     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1386     // Pointer to the main fallback stub for the IC or to the main IC entry,
  1387     // depending on hasFallbackStub.
  1388     union {
  1389         ICMonitoredFallbackStub *mainFallbackStub_;
  1390         ICEntry *icEntry_;
  1391     };
  1393     // Pointer to the first monitor stub.
  1394     ICStub *firstMonitorStub_;
  1396     // Address of the last monitor stub's field pointing to this
  1397     // fallback monitor stub.  This will get updated when new
  1398     // monitor stubs are created and added.
  1399     ICStub **lastMonitorStubPtrAddr_;
  1401     // Count of optimized type monitor stubs in this chain.
  1402     uint32_t numOptimizedMonitorStubs_ : 8;
  1404     // Whether this has a fallback stub referring to the IC entry.
  1405     bool hasFallbackStub_ : 1;
  1407     // Index of 'this' or argument which is being monitored, or BYTECODE_INDEX
  1408     // if this is monitoring the types of values pushed at some bytecode.
  1409     uint32_t argumentIndex_ : 23;
  1411     static const uint32_t BYTECODE_INDEX = (1 << 23) - 1;
  1413     ICTypeMonitor_Fallback(JitCode *stubCode, ICMonitoredFallbackStub *mainFallbackStub,
  1414                            uint32_t argumentIndex)
  1415       : ICStub(ICStub::TypeMonitor_Fallback, stubCode),
  1416         mainFallbackStub_(mainFallbackStub),
  1417         firstMonitorStub_(thisFromCtor()),
  1418         lastMonitorStubPtrAddr_(nullptr),
  1419         numOptimizedMonitorStubs_(0),
  1420         hasFallbackStub_(mainFallbackStub != nullptr),
  1421         argumentIndex_(argumentIndex)
  1422     { }
  1424     ICTypeMonitor_Fallback *thisFromCtor() {
  1425         return this;
  1428     void addOptimizedMonitorStub(ICStub *stub) {
  1429         stub->setNext(this);
  1431         JS_ASSERT((lastMonitorStubPtrAddr_ != nullptr) ==
  1432                   (numOptimizedMonitorStubs_ || !hasFallbackStub_));
  1434         if (lastMonitorStubPtrAddr_)
  1435             *lastMonitorStubPtrAddr_ = stub;
  1437         if (numOptimizedMonitorStubs_ == 0) {
  1438             JS_ASSERT(firstMonitorStub_ == this);
  1439             firstMonitorStub_ = stub;
  1440         } else {
  1441             JS_ASSERT(firstMonitorStub_ != nullptr);
  1444         lastMonitorStubPtrAddr_ = stub->addressOfNext();
  1445         numOptimizedMonitorStubs_++;
  1448   public:
  1449     static inline ICTypeMonitor_Fallback *New(
  1450         ICStubSpace *space, JitCode *code, ICMonitoredFallbackStub *mainFbStub,
  1451         uint32_t argumentIndex)
  1453         if (!code)
  1454             return nullptr;
  1455         return space->allocate<ICTypeMonitor_Fallback>(code, mainFbStub, argumentIndex);
  1458     bool hasStub(ICStub::Kind kind) {
  1459         ICStub *stub = firstMonitorStub_;
  1460         do {
  1461             if (stub->kind() == kind)
  1462                 return true;
  1464             stub = stub->next();
  1465         } while (stub);
  1467         return false;
  1470     inline ICFallbackStub *mainFallbackStub() const {
  1471         JS_ASSERT(hasFallbackStub_);
  1472         return mainFallbackStub_;
  1475     inline ICEntry *icEntry() const {
  1476         return hasFallbackStub_ ? mainFallbackStub()->icEntry() : icEntry_;
  1479     inline ICStub *firstMonitorStub() const {
  1480         return firstMonitorStub_;
  1483     static inline size_t offsetOfFirstMonitorStub() {
  1484         return offsetof(ICTypeMonitor_Fallback, firstMonitorStub_);
  1487     inline uint32_t numOptimizedMonitorStubs() const {
  1488         return numOptimizedMonitorStubs_;
  1491     inline bool monitorsThis() const {
  1492         return argumentIndex_ == 0;
  1495     inline bool monitorsArgument(uint32_t *pargument) const {
  1496         if (argumentIndex_ > 0 && argumentIndex_ < BYTECODE_INDEX) {
  1497             *pargument = argumentIndex_ - 1;
  1498             return true;
  1500         return false;
  1503     inline bool monitorsBytecode() const {
  1504         return argumentIndex_ == BYTECODE_INDEX;
  1507     // Fixup the IC entry as for a normal fallback stub, for this/arguments.
  1508     void fixupICEntry(ICEntry *icEntry) {
  1509         JS_ASSERT(!hasFallbackStub_);
  1510         JS_ASSERT(icEntry_ == nullptr);
  1511         JS_ASSERT(lastMonitorStubPtrAddr_ == nullptr);
  1512         icEntry_ = icEntry;
  1513         lastMonitorStubPtrAddr_ = icEntry_->addressOfFirstStub();
  1516     // Create a new monitor stub for the type of the given value, and
  1517     // add it to this chain.
  1518     bool addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val);
  1520     void resetMonitorStubChain(Zone *zone);
  1522     // Compiler for this stub kind.
  1523     class Compiler : public ICStubCompiler {
  1524         ICMonitoredFallbackStub *mainFallbackStub_;
  1525         uint32_t argumentIndex_;
  1527       protected:
  1528         bool generateStubCode(MacroAssembler &masm);
  1530       public:
  1531         Compiler(JSContext *cx, ICMonitoredFallbackStub *mainFallbackStub)
  1532           : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
  1533             mainFallbackStub_(mainFallbackStub),
  1534             argumentIndex_(BYTECODE_INDEX)
  1535         { }
  1537         Compiler(JSContext *cx, uint32_t argumentIndex)
  1538           : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
  1539             mainFallbackStub_(nullptr),
  1540             argumentIndex_(argumentIndex)
  1541         { }
  1543         ICTypeMonitor_Fallback *getStub(ICStubSpace *space) {
  1544             return ICTypeMonitor_Fallback::New(space, getStubCode(), mainFallbackStub_,
  1545                                                argumentIndex_);
  1547     };
  1548 };
  1550 class ICTypeMonitor_PrimitiveSet : public TypeCheckPrimitiveSetStub
  1552     friend class ICStubSpace;
  1554     ICTypeMonitor_PrimitiveSet(JitCode *stubCode, uint16_t flags)
  1555         : TypeCheckPrimitiveSetStub(TypeMonitor_PrimitiveSet, stubCode, flags)
  1556     {}
  1558   public:
  1559     static inline ICTypeMonitor_PrimitiveSet *New(ICStubSpace *space, JitCode *code,
  1560                                                   uint16_t flags)
  1562         if (!code)
  1563             return nullptr;
  1564         return space->allocate<ICTypeMonitor_PrimitiveSet>(code, flags);
  1567     class Compiler : public TypeCheckPrimitiveSetStub::Compiler {
  1568       protected:
  1569         bool generateStubCode(MacroAssembler &masm);
  1571       public:
  1572         Compiler(JSContext *cx, ICTypeMonitor_PrimitiveSet *existingStub, JSValueType type)
  1573           : TypeCheckPrimitiveSetStub::Compiler(cx, TypeMonitor_PrimitiveSet, existingStub, type)
  1574         {}
  1576         ICTypeMonitor_PrimitiveSet *updateStub() {
  1577             TypeCheckPrimitiveSetStub *stub =
  1578                 this->TypeCheckPrimitiveSetStub::Compiler::updateStub();
  1579             if (!stub)
  1580                 return nullptr;
  1581             return stub->toMonitorStub();
  1584         ICTypeMonitor_PrimitiveSet *getStub(ICStubSpace *space) {
  1585             JS_ASSERT(!existingStub_);
  1586             return ICTypeMonitor_PrimitiveSet::New(space, getStubCode(), flags_);
  1588     };
  1589 };
  1591 class ICTypeMonitor_SingleObject : public ICStub
  1593     friend class ICStubSpace;
  1595     HeapPtrObject obj_;
  1597     ICTypeMonitor_SingleObject(JitCode *stubCode, HandleObject obj);
  1599   public:
  1600     static inline ICTypeMonitor_SingleObject *New(
  1601             ICStubSpace *space, JitCode *code, HandleObject obj)
  1603         if (!code)
  1604             return nullptr;
  1605         return space->allocate<ICTypeMonitor_SingleObject>(code, obj);
  1608     HeapPtrObject &object() {
  1609         return obj_;
  1612     static size_t offsetOfObject() {
  1613         return offsetof(ICTypeMonitor_SingleObject, obj_);
  1616     class Compiler : public ICStubCompiler {
  1617       protected:
  1618         HandleObject obj_;
  1619         bool generateStubCode(MacroAssembler &masm);
  1621       public:
  1622         Compiler(JSContext *cx, HandleObject obj)
  1623           : ICStubCompiler(cx, TypeMonitor_SingleObject),
  1624             obj_(obj)
  1625         { }
  1627         ICTypeMonitor_SingleObject *getStub(ICStubSpace *space) {
  1628             return ICTypeMonitor_SingleObject::New(space, getStubCode(), obj_);
  1630     };
  1631 };
  1633 class ICTypeMonitor_TypeObject : public ICStub
  1635     friend class ICStubSpace;
  1637     HeapPtrTypeObject type_;
  1639     ICTypeMonitor_TypeObject(JitCode *stubCode, HandleTypeObject type);
  1641   public:
  1642     static inline ICTypeMonitor_TypeObject *New(
  1643             ICStubSpace *space, JitCode *code, HandleTypeObject type)
  1645         if (!code)
  1646             return nullptr;
  1647         return space->allocate<ICTypeMonitor_TypeObject>(code, type);
  1650     HeapPtrTypeObject &type() {
  1651         return type_;
  1654     static size_t offsetOfType() {
  1655         return offsetof(ICTypeMonitor_TypeObject, type_);
  1658     class Compiler : public ICStubCompiler {
  1659       protected:
  1660         HandleTypeObject type_;
  1661         bool generateStubCode(MacroAssembler &masm);
  1663       public:
  1664         Compiler(JSContext *cx, HandleTypeObject type)
  1665           : ICStubCompiler(cx, TypeMonitor_TypeObject),
  1666             type_(type)
  1667         { }
  1669         ICTypeMonitor_TypeObject *getStub(ICStubSpace *space) {
  1670             return ICTypeMonitor_TypeObject::New(space, getStubCode(), type_);
  1672     };
  1673 };
  1675 // TypeUpdate
  1677 extern const VMFunction DoTypeUpdateFallbackInfo;
  1679 // The TypeUpdate fallback is not a regular fallback, since it just
  1680 // forwards to a different entry point in the main fallback stub.
  1681 class ICTypeUpdate_Fallback : public ICStub
  1683     friend class ICStubSpace;
  1685     ICTypeUpdate_Fallback(JitCode *stubCode)
  1686       : ICStub(ICStub::TypeUpdate_Fallback, stubCode)
  1687     {}
  1689   public:
  1690     static inline ICTypeUpdate_Fallback *New(ICStubSpace *space, JitCode *code) {
  1691         if (!code)
  1692             return nullptr;
  1693         return space->allocate<ICTypeUpdate_Fallback>(code);
  1696     // Compiler for this stub kind.
  1697     class Compiler : public ICStubCompiler {
  1698       protected:
  1699         bool generateStubCode(MacroAssembler &masm);
  1701       public:
  1702         Compiler(JSContext *cx)
  1703           : ICStubCompiler(cx, ICStub::TypeUpdate_Fallback)
  1704         { }
  1706         ICTypeUpdate_Fallback *getStub(ICStubSpace *space) {
  1707             return ICTypeUpdate_Fallback::New(space, getStubCode());
  1709     };
  1710 };
  1712 class ICTypeUpdate_PrimitiveSet : public TypeCheckPrimitiveSetStub
  1714     friend class ICStubSpace;
  1716     ICTypeUpdate_PrimitiveSet(JitCode *stubCode, uint16_t flags)
  1717         : TypeCheckPrimitiveSetStub(TypeUpdate_PrimitiveSet, stubCode, flags)
  1718     {}
  1720   public:
  1721     static inline ICTypeUpdate_PrimitiveSet *New(ICStubSpace *space, JitCode *code,
  1722                                                  uint16_t flags)
  1724         if (!code)
  1725             return nullptr;
  1726         return space->allocate<ICTypeUpdate_PrimitiveSet>(code, flags);
  1729     class Compiler : public TypeCheckPrimitiveSetStub::Compiler {
  1730       protected:
  1731         bool generateStubCode(MacroAssembler &masm);
  1733       public:
  1734         Compiler(JSContext *cx, ICTypeUpdate_PrimitiveSet *existingStub, JSValueType type)
  1735           : TypeCheckPrimitiveSetStub::Compiler(cx, TypeUpdate_PrimitiveSet, existingStub, type)
  1736         {}
  1738         ICTypeUpdate_PrimitiveSet *updateStub() {
  1739             TypeCheckPrimitiveSetStub *stub =
  1740                 this->TypeCheckPrimitiveSetStub::Compiler::updateStub();
  1741             if (!stub)
  1742                 return nullptr;
  1743             return stub->toUpdateStub();
  1746         ICTypeUpdate_PrimitiveSet *getStub(ICStubSpace *space) {
  1747             JS_ASSERT(!existingStub_);
  1748             return ICTypeUpdate_PrimitiveSet::New(space, getStubCode(), flags_);
  1750     };
  1751 };
  1753 // Type update stub to handle a singleton object.
  1754 class ICTypeUpdate_SingleObject : public ICStub
  1756     friend class ICStubSpace;
  1758     HeapPtrObject obj_;
  1760     ICTypeUpdate_SingleObject(JitCode *stubCode, HandleObject obj);
  1762   public:
  1763     static inline ICTypeUpdate_SingleObject *New(ICStubSpace *space, JitCode *code,
  1764                                                  HandleObject obj)
  1766         if (!code)
  1767             return nullptr;
  1768         return space->allocate<ICTypeUpdate_SingleObject>(code, obj);
  1771     HeapPtrObject &object() {
  1772         return obj_;
  1775     static size_t offsetOfObject() {
  1776         return offsetof(ICTypeUpdate_SingleObject, obj_);
  1779     class Compiler : public ICStubCompiler {
  1780       protected:
  1781         HandleObject obj_;
  1782         bool generateStubCode(MacroAssembler &masm);
  1784       public:
  1785         Compiler(JSContext *cx, HandleObject obj)
  1786           : ICStubCompiler(cx, TypeUpdate_SingleObject),
  1787             obj_(obj)
  1788         { }
  1790         ICTypeUpdate_SingleObject *getStub(ICStubSpace *space) {
  1791             return ICTypeUpdate_SingleObject::New(space, getStubCode(), obj_);
  1793     };
  1794 };
  1796 // Type update stub to handle a single TypeObject.
  1797 class ICTypeUpdate_TypeObject : public ICStub
  1799     friend class ICStubSpace;
  1801     HeapPtrTypeObject type_;
  1803     ICTypeUpdate_TypeObject(JitCode *stubCode, HandleTypeObject type);
  1805   public:
  1806     static inline ICTypeUpdate_TypeObject *New(ICStubSpace *space, JitCode *code,
  1807                                                HandleTypeObject type)
  1809         if (!code)
  1810             return nullptr;
  1811         return space->allocate<ICTypeUpdate_TypeObject>(code, type);
  1814     HeapPtrTypeObject &type() {
  1815         return type_;
  1818     static size_t offsetOfType() {
  1819         return offsetof(ICTypeUpdate_TypeObject, type_);
  1822     class Compiler : public ICStubCompiler {
  1823       protected:
  1824         HandleTypeObject type_;
  1825         bool generateStubCode(MacroAssembler &masm);
  1827       public:
  1828         Compiler(JSContext *cx, HandleTypeObject type)
  1829           : ICStubCompiler(cx, TypeUpdate_TypeObject),
  1830             type_(type)
  1831         { }
  1833         ICTypeUpdate_TypeObject *getStub(ICStubSpace *space) {
  1834             return ICTypeUpdate_TypeObject::New(space, getStubCode(), type_);
  1836     };
  1837 };
  1839 // This
  1840 //      JSOP_THIS
  1842 class ICThis_Fallback : public ICFallbackStub
  1844     friend class ICStubSpace;
  1846     ICThis_Fallback(JitCode *stubCode)
  1847       : ICFallbackStub(ICStub::This_Fallback, stubCode) {}
  1849   public:
  1850     static inline ICThis_Fallback *New(ICStubSpace *space, JitCode *code) {
  1851         if (!code)
  1852             return nullptr;
  1853         return space->allocate<ICThis_Fallback>(code);
  1856     // Compiler for this stub kind.
  1857     class Compiler : public ICStubCompiler {
  1858       protected:
  1859         bool generateStubCode(MacroAssembler &masm);
  1861       public:
  1862         Compiler(JSContext *cx)
  1863           : ICStubCompiler(cx, ICStub::This_Fallback) {}
  1865         ICStub *getStub(ICStubSpace *space) {
  1866             return ICThis_Fallback::New(space, getStubCode());
  1868     };
  1869 };
  1871 class ICNewArray_Fallback : public ICFallbackStub
  1873     friend class ICStubSpace;
  1875     HeapPtrObject templateObject_;
  1877     ICNewArray_Fallback(JitCode *stubCode, JSObject *templateObject)
  1878       : ICFallbackStub(ICStub::NewArray_Fallback, stubCode), templateObject_(templateObject)
  1879     {}
  1881   public:
  1882     static inline ICNewArray_Fallback *New(ICStubSpace *space, JitCode *code,
  1883                                            JSObject *templateObject) {
  1884         if (!code)
  1885             return nullptr;
  1886         return space->allocate<ICNewArray_Fallback>(code, templateObject);
  1889     class Compiler : public ICStubCompiler {
  1890         RootedObject templateObject;
  1891         bool generateStubCode(MacroAssembler &masm);
  1893       public:
  1894         Compiler(JSContext *cx, JSObject *templateObject)
  1895           : ICStubCompiler(cx, ICStub::NewArray_Fallback),
  1896             templateObject(cx, templateObject)
  1897         {}
  1899         ICStub *getStub(ICStubSpace *space) {
  1900             return ICNewArray_Fallback::New(space, getStubCode(), templateObject);
  1902     };
  1904     HeapPtrObject &templateObject() {
  1905         return templateObject_;
  1907 };
  1909 class ICNewObject_Fallback : public ICFallbackStub
  1911     friend class ICStubSpace;
  1913     HeapPtrObject templateObject_;
  1915     ICNewObject_Fallback(JitCode *stubCode, JSObject *templateObject)
  1916       : ICFallbackStub(ICStub::NewObject_Fallback, stubCode), templateObject_(templateObject)
  1917     {}
  1919   public:
  1920     static inline ICNewObject_Fallback *New(ICStubSpace *space, JitCode *code,
  1921                                             JSObject *templateObject) {
  1922         if (!code)
  1923             return nullptr;
  1924         return space->allocate<ICNewObject_Fallback>(code, templateObject);
  1927     class Compiler : public ICStubCompiler {
  1928         RootedObject templateObject;
  1929         bool generateStubCode(MacroAssembler &masm);
  1931       public:
  1932         Compiler(JSContext *cx, JSObject *templateObject)
  1933           : ICStubCompiler(cx, ICStub::NewObject_Fallback),
  1934             templateObject(cx, templateObject)
  1935         {}
  1937         ICStub *getStub(ICStubSpace *space) {
  1938             return ICNewObject_Fallback::New(space, getStubCode(), templateObject);
  1940     };
  1942     HeapPtrObject &templateObject() {
  1943         return templateObject_;
  1945 };
  1947 // Compare
  1948 //      JSOP_LT
  1949 //      JSOP_GT
  1951 class ICCompare_Fallback : public ICFallbackStub
  1953     friend class ICStubSpace;
  1955     ICCompare_Fallback(JitCode *stubCode)
  1956       : ICFallbackStub(ICStub::Compare_Fallback, stubCode) {}
  1958   public:
  1959     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1961     static inline ICCompare_Fallback *New(ICStubSpace *space, JitCode *code) {
  1962         if (!code)
  1963             return nullptr;
  1964         return space->allocate<ICCompare_Fallback>(code);
  1967     // Compiler for this stub kind.
  1968     class Compiler : public ICStubCompiler {
  1969       protected:
  1970         bool generateStubCode(MacroAssembler &masm);
  1972       public:
  1973         Compiler(JSContext *cx)
  1974           : ICStubCompiler(cx, ICStub::Compare_Fallback) {}
  1976         ICStub *getStub(ICStubSpace *space) {
  1977             return ICCompare_Fallback::New(space, getStubCode());
  1979     };
  1980 };
  1982 class ICCompare_Int32 : public ICStub
  1984     friend class ICStubSpace;
  1986     ICCompare_Int32(JitCode *stubCode)
  1987       : ICStub(ICStub::Compare_Int32, stubCode) {}
  1989   public:
  1990     static inline ICCompare_Int32 *New(ICStubSpace *space, JitCode *code) {
  1991         if (!code)
  1992             return nullptr;
  1993         return space->allocate<ICCompare_Int32>(code);
  1996     // Compiler for this stub kind.
  1997     class Compiler : public ICMultiStubCompiler {
  1998       protected:
  1999         bool generateStubCode(MacroAssembler &masm);
  2001       public:
  2002         Compiler(JSContext *cx, JSOp op)
  2003           : ICMultiStubCompiler(cx, ICStub::Compare_Int32, op) {}
  2005         ICStub *getStub(ICStubSpace *space) {
  2006             return ICCompare_Int32::New(space, getStubCode());
  2008     };
  2009 };
  2011 class ICCompare_Double : public ICStub
  2013     friend class ICStubSpace;
  2015     ICCompare_Double(JitCode *stubCode)
  2016       : ICStub(ICStub::Compare_Double, stubCode)
  2017     {}
  2019   public:
  2020     static inline ICCompare_Double *New(ICStubSpace *space, JitCode *code) {
  2021         if (!code)
  2022             return nullptr;
  2023         return space->allocate<ICCompare_Double>(code);
  2026     class Compiler : public ICMultiStubCompiler {
  2027       protected:
  2028         bool generateStubCode(MacroAssembler &masm);
  2030       public:
  2031         Compiler(JSContext *cx, JSOp op)
  2032           : ICMultiStubCompiler(cx, ICStub::Compare_Double, op)
  2033         {}
  2035         ICStub *getStub(ICStubSpace *space) {
  2036             return ICCompare_Double::New(space, getStubCode());
  2038     };
  2039 };
  2041 class ICCompare_NumberWithUndefined : public ICStub
  2043     friend class ICStubSpace;
  2045     ICCompare_NumberWithUndefined(JitCode *stubCode, bool lhsIsUndefined)
  2046       : ICStub(ICStub::Compare_NumberWithUndefined, stubCode)
  2048         extra_ = lhsIsUndefined;
  2051   public:
  2052     static inline ICCompare_NumberWithUndefined *New(ICStubSpace *space, JitCode *code, bool lhsIsUndefined) {
  2053         if (!code)
  2054             return nullptr;
  2055         return space->allocate<ICCompare_NumberWithUndefined>(code, lhsIsUndefined);
  2058     bool lhsIsUndefined() {
  2059         return extra_;
  2062     class Compiler : public ICMultiStubCompiler {
  2063       protected:
  2064         bool generateStubCode(MacroAssembler &masm);
  2066         bool lhsIsUndefined;
  2068       public:
  2069         Compiler(JSContext *cx, JSOp op, bool lhsIsUndefined)
  2070           : ICMultiStubCompiler(cx, ICStub::Compare_NumberWithUndefined, op),
  2071             lhsIsUndefined(lhsIsUndefined)
  2072         {}
  2074         virtual int32_t getKey() const {
  2075             return static_cast<int32_t>(kind)
  2076                  | (static_cast<int32_t>(op) << 16)
  2077                  | (static_cast<int32_t>(lhsIsUndefined) << 24);
  2080         ICStub *getStub(ICStubSpace *space) {
  2081             return ICCompare_NumberWithUndefined::New(space, getStubCode(), lhsIsUndefined);
  2083     };
  2084 };
  2086 class ICCompare_String : public ICStub
  2088     friend class ICStubSpace;
  2090     ICCompare_String(JitCode *stubCode)
  2091       : ICStub(ICStub::Compare_String, stubCode)
  2092     {}
  2094   public:
  2095     static inline ICCompare_String *New(ICStubSpace *space, JitCode *code) {
  2096         if (!code)
  2097             return nullptr;
  2098         return space->allocate<ICCompare_String>(code);
  2101     class Compiler : public ICMultiStubCompiler {
  2102       protected:
  2103         bool generateStubCode(MacroAssembler &masm);
  2105       public:
  2106         Compiler(JSContext *cx, JSOp op)
  2107           : ICMultiStubCompiler(cx, ICStub::Compare_String, op)
  2108         {}
  2110         ICStub *getStub(ICStubSpace *space) {
  2111             return ICCompare_String::New(space, getStubCode());
  2113     };
  2114 };
  2116 class ICCompare_Boolean : public ICStub
  2118     friend class ICStubSpace;
  2120     ICCompare_Boolean(JitCode *stubCode)
  2121       : ICStub(ICStub::Compare_Boolean, stubCode)
  2122     {}
  2124   public:
  2125     static inline ICCompare_Boolean *New(ICStubSpace *space, JitCode *code) {
  2126         if (!code)
  2127             return nullptr;
  2128         return space->allocate<ICCompare_Boolean>(code);
  2131     class Compiler : public ICMultiStubCompiler {
  2132       protected:
  2133         bool generateStubCode(MacroAssembler &masm);
  2135       public:
  2136         Compiler(JSContext *cx, JSOp op)
  2137           : ICMultiStubCompiler(cx, ICStub::Compare_Boolean, op)
  2138         {}
  2140         ICStub *getStub(ICStubSpace *space) {
  2141             return ICCompare_Boolean::New(space, getStubCode());
  2143     };
  2144 };
  2146 class ICCompare_Object : public ICStub
  2148     friend class ICStubSpace;
  2150     ICCompare_Object(JitCode *stubCode)
  2151       : ICStub(ICStub::Compare_Object, stubCode)
  2152     {}
  2154   public:
  2155     static inline ICCompare_Object *New(ICStubSpace *space, JitCode *code) {
  2156         if (!code)
  2157             return nullptr;
  2158         return space->allocate<ICCompare_Object>(code);
  2161     class Compiler : public ICMultiStubCompiler {
  2162       protected:
  2163         bool generateStubCode(MacroAssembler &masm);
  2165       public:
  2166         Compiler(JSContext *cx, JSOp op)
  2167           : ICMultiStubCompiler(cx, ICStub::Compare_Object, op)
  2168         {}
  2170         ICStub *getStub(ICStubSpace *space) {
  2171             return ICCompare_Object::New(space, getStubCode());
  2173     };
  2174 };
  2176 class ICCompare_ObjectWithUndefined : public ICStub
  2178     friend class ICStubSpace;
  2180     ICCompare_ObjectWithUndefined(JitCode *stubCode)
  2181       : ICStub(ICStub::Compare_ObjectWithUndefined, stubCode)
  2182     {}
  2184   public:
  2185     static inline ICCompare_ObjectWithUndefined *New(ICStubSpace *space, JitCode *code) {
  2186         if (!code)
  2187             return nullptr;
  2188         return space->allocate<ICCompare_ObjectWithUndefined>(code);
  2191     class Compiler : public ICMultiStubCompiler {
  2192       protected:
  2193         bool generateStubCode(MacroAssembler &masm);
  2195         bool lhsIsUndefined;
  2196         bool compareWithNull;
  2198       public:
  2199         Compiler(JSContext *cx, JSOp op, bool lhsIsUndefined, bool compareWithNull)
  2200           : ICMultiStubCompiler(cx, ICStub::Compare_ObjectWithUndefined, op),
  2201             lhsIsUndefined(lhsIsUndefined),
  2202             compareWithNull(compareWithNull)
  2203         {}
  2205         virtual int32_t getKey() const {
  2206             return static_cast<int32_t>(kind)
  2207                  | (static_cast<int32_t>(op) << 16)
  2208                  | (static_cast<int32_t>(lhsIsUndefined) << 24)
  2209                  | (static_cast<int32_t>(compareWithNull) << 25);
  2212         ICStub *getStub(ICStubSpace *space) {
  2213             return ICCompare_ObjectWithUndefined::New(space, getStubCode());
  2215     };
  2216 };
  2218 class ICCompare_Int32WithBoolean : public ICStub
  2220     friend class ICStubSpace;
  2222     ICCompare_Int32WithBoolean(JitCode *stubCode, bool lhsIsInt32)
  2223       : ICStub(ICStub::Compare_Int32WithBoolean, stubCode)
  2225         extra_ = lhsIsInt32;
  2228   public:
  2229     static inline ICCompare_Int32WithBoolean *New(ICStubSpace *space, JitCode *code,
  2230                                                   bool lhsIsInt32)
  2232         if (!code)
  2233             return nullptr;
  2234         return space->allocate<ICCompare_Int32WithBoolean>(code, lhsIsInt32);
  2237     bool lhsIsInt32() const {
  2238         return extra_;
  2241     // Compiler for this stub kind.
  2242     class Compiler : public ICStubCompiler {
  2243       protected:
  2244         JSOp op_;
  2245         bool lhsIsInt32_;
  2246         bool generateStubCode(MacroAssembler &masm);
  2248         virtual int32_t getKey() const {
  2249             return (static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) |
  2250                     (static_cast<int32_t>(lhsIsInt32_) << 24));
  2253       public:
  2254         Compiler(JSContext *cx, JSOp op, bool lhsIsInt32)
  2255           : ICStubCompiler(cx, ICStub::Compare_Int32WithBoolean),
  2256             op_(op),
  2257             lhsIsInt32_(lhsIsInt32)
  2258         {}
  2260         ICStub *getStub(ICStubSpace *space) {
  2261             return ICCompare_Int32WithBoolean::New(space, getStubCode(), lhsIsInt32_);
  2263     };
  2264 };
  2266 // ToBool
  2267 //      JSOP_IFNE
  2269 class ICToBool_Fallback : public ICFallbackStub
  2271     friend class ICStubSpace;
  2273     ICToBool_Fallback(JitCode *stubCode)
  2274       : ICFallbackStub(ICStub::ToBool_Fallback, stubCode) {}
  2276   public:
  2277     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  2279     static inline ICToBool_Fallback *New(ICStubSpace *space, JitCode *code) {
  2280         if (!code)
  2281             return nullptr;
  2282         return space->allocate<ICToBool_Fallback>(code);
  2285     // Compiler for this stub kind.
  2286     class Compiler : public ICStubCompiler {
  2287       protected:
  2288         bool generateStubCode(MacroAssembler &masm);
  2290       public:
  2291         Compiler(JSContext *cx)
  2292           : ICStubCompiler(cx, ICStub::ToBool_Fallback) {}
  2294         ICStub *getStub(ICStubSpace *space) {
  2295             return ICToBool_Fallback::New(space, getStubCode());
  2297     };
  2298 };
  2300 class ICToBool_Int32 : public ICStub
  2302     friend class ICStubSpace;
  2304     ICToBool_Int32(JitCode *stubCode)
  2305       : ICStub(ICStub::ToBool_Int32, stubCode) {}
  2307   public:
  2308     static inline ICToBool_Int32 *New(ICStubSpace *space, JitCode *code) {
  2309         if (!code)
  2310             return nullptr;
  2311         return space->allocate<ICToBool_Int32>(code);
  2314     // Compiler for this stub kind.
  2315     class Compiler : public ICStubCompiler {
  2316       protected:
  2317         bool generateStubCode(MacroAssembler &masm);
  2319       public:
  2320         Compiler(JSContext *cx)
  2321           : ICStubCompiler(cx, ICStub::ToBool_Int32) {}
  2323         ICStub *getStub(ICStubSpace *space) {
  2324             return ICToBool_Int32::New(space, getStubCode());
  2326     };
  2327 };
  2329 class ICToBool_String : public ICStub
  2331     friend class ICStubSpace;
  2333     ICToBool_String(JitCode *stubCode)
  2334       : ICStub(ICStub::ToBool_String, stubCode) {}
  2336   public:
  2337     static inline ICToBool_String *New(ICStubSpace *space, JitCode *code) {
  2338         if (!code)
  2339             return nullptr;
  2340         return space->allocate<ICToBool_String>(code);
  2343     // Compiler for this stub kind.
  2344     class Compiler : public ICStubCompiler {
  2345       protected:
  2346         bool generateStubCode(MacroAssembler &masm);
  2348       public:
  2349         Compiler(JSContext *cx)
  2350           : ICStubCompiler(cx, ICStub::ToBool_String) {}
  2352         ICStub *getStub(ICStubSpace *space) {
  2353             return ICToBool_String::New(space, getStubCode());
  2355     };
  2356 };
  2358 class ICToBool_NullUndefined : public ICStub
  2360     friend class ICStubSpace;
  2362     ICToBool_NullUndefined(JitCode *stubCode)
  2363       : ICStub(ICStub::ToBool_NullUndefined, stubCode) {}
  2365   public:
  2366     static inline ICToBool_NullUndefined *New(ICStubSpace *space, JitCode *code) {
  2367         if (!code)
  2368             return nullptr;
  2369         return space->allocate<ICToBool_NullUndefined>(code);
  2372     // Compiler for this stub kind.
  2373     class Compiler : public ICStubCompiler {
  2374       protected:
  2375         bool generateStubCode(MacroAssembler &masm);
  2377       public:
  2378         Compiler(JSContext *cx)
  2379           : ICStubCompiler(cx, ICStub::ToBool_NullUndefined) {}
  2381         ICStub *getStub(ICStubSpace *space) {
  2382             return ICToBool_NullUndefined::New(space, getStubCode());
  2384     };
  2385 };
  2387 class ICToBool_Double : public ICStub
  2389     friend class ICStubSpace;
  2391     ICToBool_Double(JitCode *stubCode)
  2392       : ICStub(ICStub::ToBool_Double, stubCode) {}
  2394   public:
  2395     static inline ICToBool_Double *New(ICStubSpace *space, JitCode *code) {
  2396         if (!code)
  2397             return nullptr;
  2398         return space->allocate<ICToBool_Double>(code);
  2401     // Compiler for this stub kind.
  2402     class Compiler : public ICStubCompiler {
  2403       protected:
  2404         bool generateStubCode(MacroAssembler &masm);
  2406       public:
  2407         Compiler(JSContext *cx)
  2408           : ICStubCompiler(cx, ICStub::ToBool_Double) {}
  2410         ICStub *getStub(ICStubSpace *space) {
  2411             return ICToBool_Double::New(space, getStubCode());
  2413     };
  2414 };
  2416 class ICToBool_Object : public ICStub
  2418     friend class ICStubSpace;
  2420     ICToBool_Object(JitCode *stubCode)
  2421       : ICStub(ICStub::ToBool_Object, stubCode) {}
  2423   public:
  2424     static inline ICToBool_Object *New(ICStubSpace *space, JitCode *code) {
  2425         if (!code)
  2426             return nullptr;
  2427         return space->allocate<ICToBool_Object>(code);
  2430     // Compiler for this stub kind.
  2431     class Compiler : public ICStubCompiler {
  2432       protected:
  2433         bool generateStubCode(MacroAssembler &masm);
  2435       public:
  2436         Compiler(JSContext *cx)
  2437           : ICStubCompiler(cx, ICStub::ToBool_Object) {}
  2439         ICStub *getStub(ICStubSpace *space) {
  2440             return ICToBool_Object::New(space, getStubCode());
  2442     };
  2443 };
  2445 // ToNumber
  2446 //     JSOP_POS
  2448 class ICToNumber_Fallback : public ICFallbackStub
  2450     friend class ICStubSpace;
  2452     ICToNumber_Fallback(JitCode *stubCode)
  2453       : ICFallbackStub(ICStub::ToNumber_Fallback, stubCode) {}
  2455   public:
  2456     static inline ICToNumber_Fallback *New(ICStubSpace *space, JitCode *code) {
  2457         if (!code)
  2458             return nullptr;
  2459         return space->allocate<ICToNumber_Fallback>(code);
  2462     // Compiler for this stub kind.
  2463     class Compiler : public ICStubCompiler {
  2464       protected:
  2465         bool generateStubCode(MacroAssembler &masm);
  2467       public:
  2468         Compiler(JSContext *cx)
  2469           : ICStubCompiler(cx, ICStub::ToNumber_Fallback) {}
  2471         ICStub *getStub(ICStubSpace *space) {
  2472             return ICToNumber_Fallback::New(space, getStubCode());
  2474     };
  2475 };
  2477 // BinaryArith
  2478 //      JSOP_ADD
  2479 //      JSOP_BITAND, JSOP_BITXOR, JSOP_BITOR
  2480 //      JSOP_LSH, JSOP_RSH, JSOP_URSH
  2482 class ICBinaryArith_Fallback : public ICFallbackStub
  2484     friend class ICStubSpace;
  2486     ICBinaryArith_Fallback(JitCode *stubCode)
  2487       : ICFallbackStub(BinaryArith_Fallback, stubCode)
  2489         extra_ = 0;
  2492     static const uint16_t SAW_DOUBLE_RESULT_BIT = 0x1;
  2493     static const uint16_t UNOPTIMIZABLE_OPERANDS_BIT = 0x2;
  2495   public:
  2496     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  2498     static inline ICBinaryArith_Fallback *New(ICStubSpace *space, JitCode *code) {
  2499         if (!code)
  2500             return nullptr;
  2501         return space->allocate<ICBinaryArith_Fallback>(code);
  2504     bool sawDoubleResult() const {
  2505         return extra_ & SAW_DOUBLE_RESULT_BIT;
  2507     void setSawDoubleResult() {
  2508         extra_ |= SAW_DOUBLE_RESULT_BIT;
  2510     bool hadUnoptimizableOperands() const {
  2511         return extra_ & UNOPTIMIZABLE_OPERANDS_BIT;
  2513     void noteUnoptimizableOperands() {
  2514         extra_ |= UNOPTIMIZABLE_OPERANDS_BIT;
  2517     // Compiler for this stub kind.
  2518     class Compiler : public ICStubCompiler {
  2519       protected:
  2520         bool generateStubCode(MacroAssembler &masm);
  2522       public:
  2523         Compiler(JSContext *cx)
  2524           : ICStubCompiler(cx, ICStub::BinaryArith_Fallback) {}
  2526         ICStub *getStub(ICStubSpace *space) {
  2527             return ICBinaryArith_Fallback::New(space, getStubCode());
  2529     };
  2530 };
  2532 class ICBinaryArith_Int32 : public ICStub
  2534     friend class ICStubSpace;
  2536     ICBinaryArith_Int32(JitCode *stubCode, bool allowDouble)
  2537       : ICStub(BinaryArith_Int32, stubCode)
  2539         extra_ = allowDouble;
  2542   public:
  2543     static inline ICBinaryArith_Int32 *New(ICStubSpace *space, JitCode *code, bool allowDouble) {
  2544         if (!code)
  2545             return nullptr;
  2546         return space->allocate<ICBinaryArith_Int32>(code, allowDouble);
  2548     bool allowDouble() const {
  2549         return extra_;
  2552     // Compiler for this stub kind.
  2553     class Compiler : public ICStubCompiler {
  2554       protected:
  2555         JSOp op_;
  2556         bool allowDouble_;
  2558         bool generateStubCode(MacroAssembler &masm);
  2560         // Stub keys shift-stubs need to encode the kind, the JSOp and if we allow doubles.
  2561         virtual int32_t getKey() const {
  2562             return (static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) |
  2563                     (static_cast<int32_t>(allowDouble_) << 24));
  2566       public:
  2567         Compiler(JSContext *cx, JSOp op, bool allowDouble)
  2568           : ICStubCompiler(cx, ICStub::BinaryArith_Int32),
  2569             op_(op), allowDouble_(allowDouble) {}
  2571         ICStub *getStub(ICStubSpace *space) {
  2572             return ICBinaryArith_Int32::New(space, getStubCode(), allowDouble_);
  2574     };
  2575 };
  2577 class ICBinaryArith_StringConcat : public ICStub
  2579     friend class ICStubSpace;
  2581     ICBinaryArith_StringConcat(JitCode *stubCode)
  2582       : ICStub(BinaryArith_StringConcat, stubCode)
  2583     {}
  2585   public:
  2586     static inline ICBinaryArith_StringConcat *New(ICStubSpace *space, JitCode *code) {
  2587         if (!code)
  2588             return nullptr;
  2589         return space->allocate<ICBinaryArith_StringConcat>(code);
  2592     class Compiler : public ICStubCompiler {
  2593       protected:
  2594         bool generateStubCode(MacroAssembler &masm);
  2596       public:
  2597         Compiler(JSContext *cx)
  2598           : ICStubCompiler(cx, ICStub::BinaryArith_StringConcat)
  2599         {}
  2601         ICStub *getStub(ICStubSpace *space) {
  2602             return ICBinaryArith_StringConcat::New(space, getStubCode());
  2604     };
  2605 };
  2607 class ICBinaryArith_StringObjectConcat : public ICStub
  2609     friend class ICStubSpace;
  2611     ICBinaryArith_StringObjectConcat(JitCode *stubCode, bool lhsIsString)
  2612       : ICStub(BinaryArith_StringObjectConcat, stubCode)
  2614         extra_ = lhsIsString;
  2617   public:
  2618     static inline ICBinaryArith_StringObjectConcat *New(ICStubSpace *space, JitCode *code,
  2619                                                         bool lhsIsString) {
  2620         if (!code)
  2621             return nullptr;
  2622         return space->allocate<ICBinaryArith_StringObjectConcat>(code, lhsIsString);
  2625     bool lhsIsString() const {
  2626         return extra_;
  2629     class Compiler : public ICStubCompiler {
  2630       protected:
  2631         bool lhsIsString_;
  2632         bool generateStubCode(MacroAssembler &masm);
  2634         virtual int32_t getKey() const {
  2635             return static_cast<int32_t>(kind) | (static_cast<int32_t>(lhsIsString_) << 16);
  2638       public:
  2639         Compiler(JSContext *cx, bool lhsIsString)
  2640           : ICStubCompiler(cx, ICStub::BinaryArith_StringObjectConcat),
  2641             lhsIsString_(lhsIsString)
  2642         {}
  2644         ICStub *getStub(ICStubSpace *space) {
  2645             return ICBinaryArith_StringObjectConcat::New(space, getStubCode(), lhsIsString_);
  2647     };
  2648 };
  2650 class ICBinaryArith_Double : public ICStub
  2652     friend class ICStubSpace;
  2654     ICBinaryArith_Double(JitCode *stubCode)
  2655       : ICStub(BinaryArith_Double, stubCode)
  2656     {}
  2658   public:
  2659     static inline ICBinaryArith_Double *New(ICStubSpace *space, JitCode *code) {
  2660         if (!code)
  2661             return nullptr;
  2662         return space->allocate<ICBinaryArith_Double>(code);
  2665     class Compiler : public ICMultiStubCompiler {
  2666       protected:
  2667         bool generateStubCode(MacroAssembler &masm);
  2669       public:
  2670         Compiler(JSContext *cx, JSOp op)
  2671           : ICMultiStubCompiler(cx, ICStub::BinaryArith_Double, op)
  2672         {}
  2674         ICStub *getStub(ICStubSpace *space) {
  2675             return ICBinaryArith_Double::New(space, getStubCode());
  2677     };
  2678 };
  2680 class ICBinaryArith_BooleanWithInt32 : public ICStub
  2682     friend class ICStubSpace;
  2684     ICBinaryArith_BooleanWithInt32(JitCode *stubCode, bool lhsIsBool, bool rhsIsBool)
  2685       : ICStub(BinaryArith_BooleanWithInt32, stubCode)
  2687         JS_ASSERT(lhsIsBool || rhsIsBool);
  2688         extra_ = 0;
  2689         if (lhsIsBool)
  2690             extra_ |= 1;
  2691         if (rhsIsBool)
  2692             extra_ |= 2;
  2695   public:
  2696     static inline ICBinaryArith_BooleanWithInt32 *New(ICStubSpace *space, JitCode *code,
  2697                                                       bool lhsIsBool, bool rhsIsBool) {
  2698         if (!code)
  2699             return nullptr;
  2700         return space->allocate<ICBinaryArith_BooleanWithInt32>(code, lhsIsBool, rhsIsBool);
  2703     bool lhsIsBoolean() const {
  2704         return extra_ & 1;
  2707     bool rhsIsBoolean() const {
  2708         return extra_ & 2;
  2711     class Compiler : public ICStubCompiler {
  2712       protected:
  2713         JSOp op_;
  2714         bool lhsIsBool_;
  2715         bool rhsIsBool_;
  2716         bool generateStubCode(MacroAssembler &masm);
  2718         virtual int32_t getKey() const {
  2719             return static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) |
  2720                    (static_cast<int32_t>(lhsIsBool_) << 24) |
  2721                    (static_cast<int32_t>(rhsIsBool_) << 25);
  2724       public:
  2725         Compiler(JSContext *cx, JSOp op, bool lhsIsBool, bool rhsIsBool)
  2726           : ICStubCompiler(cx, ICStub::BinaryArith_BooleanWithInt32),
  2727             op_(op), lhsIsBool_(lhsIsBool), rhsIsBool_(rhsIsBool)
  2729             JS_ASSERT(op_ == JSOP_ADD || op_ == JSOP_SUB || op_ == JSOP_BITOR ||
  2730                       op_ == JSOP_BITAND || op_ == JSOP_BITXOR);
  2731             JS_ASSERT(lhsIsBool_ || rhsIsBool_);
  2734         ICStub *getStub(ICStubSpace *space) {
  2735             return ICBinaryArith_BooleanWithInt32::New(space, getStubCode(),
  2736                                                        lhsIsBool_, rhsIsBool_);
  2738     };
  2739 };
  2741 class ICBinaryArith_DoubleWithInt32 : public ICStub
  2743     friend class ICStubSpace;
  2745     ICBinaryArith_DoubleWithInt32(JitCode *stubCode, bool lhsIsDouble)
  2746       : ICStub(BinaryArith_DoubleWithInt32, stubCode)
  2748         extra_ = lhsIsDouble;
  2751   public:
  2752     static inline ICBinaryArith_DoubleWithInt32 *New(ICStubSpace *space, JitCode *code,
  2753                                                      bool lhsIsDouble) {
  2754         if (!code)
  2755             return nullptr;
  2756         return space->allocate<ICBinaryArith_DoubleWithInt32>(code, lhsIsDouble);
  2759     bool lhsIsDouble() const {
  2760         return extra_;
  2763     class Compiler : public ICMultiStubCompiler {
  2764       protected:
  2765         bool lhsIsDouble_;
  2766         bool generateStubCode(MacroAssembler &masm);
  2768         virtual int32_t getKey() const {
  2769             return static_cast<int32_t>(kind) | (static_cast<int32_t>(op) << 16) |
  2770                    (static_cast<int32_t>(lhsIsDouble_) << 24);
  2773       public:
  2774         Compiler(JSContext *cx, JSOp op, bool lhsIsDouble)
  2775           : ICMultiStubCompiler(cx, ICStub::BinaryArith_DoubleWithInt32, op),
  2776             lhsIsDouble_(lhsIsDouble)
  2777         {}
  2779         ICStub *getStub(ICStubSpace *space) {
  2780             return ICBinaryArith_DoubleWithInt32::New(space, getStubCode(), lhsIsDouble_);
  2782     };
  2783 };
  2785 // UnaryArith
  2786 //     JSOP_BITNOT
  2787 //     JSOP_NEG
  2789 class ICUnaryArith_Fallback : public ICFallbackStub
  2791     friend class ICStubSpace;
  2793     ICUnaryArith_Fallback(JitCode *stubCode)
  2794       : ICFallbackStub(UnaryArith_Fallback, stubCode)
  2796         extra_ = 0;
  2799   public:
  2800     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  2802     static inline ICUnaryArith_Fallback *New(ICStubSpace *space, JitCode *code) {
  2803         if (!code)
  2804             return nullptr;
  2805         return space->allocate<ICUnaryArith_Fallback>(code);
  2808     bool sawDoubleResult() {
  2809         return extra_;
  2811     void setSawDoubleResult() {
  2812         extra_ = 1;
  2815     // Compiler for this stub kind.
  2816     class Compiler : public ICStubCompiler {
  2817       protected:
  2818         bool generateStubCode(MacroAssembler &masm);
  2820       public:
  2821         Compiler(JSContext *cx)
  2822           : ICStubCompiler(cx, ICStub::UnaryArith_Fallback)
  2823         {}
  2825         ICStub *getStub(ICStubSpace *space) {
  2826             return ICUnaryArith_Fallback::New(space, getStubCode());
  2828     };
  2829 };
  2831 class ICUnaryArith_Int32 : public ICStub
  2833     friend class ICStubSpace;
  2835     ICUnaryArith_Int32(JitCode *stubCode)
  2836       : ICStub(UnaryArith_Int32, stubCode)
  2837     {}
  2839   public:
  2840     static inline ICUnaryArith_Int32 *New(ICStubSpace *space, JitCode *code) {
  2841         if (!code)
  2842             return nullptr;
  2843         return space->allocate<ICUnaryArith_Int32>(code);
  2846     class Compiler : public ICMultiStubCompiler {
  2847       protected:
  2848         bool generateStubCode(MacroAssembler &masm);
  2850       public:
  2851         Compiler(JSContext *cx, JSOp op)
  2852           : ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op)
  2853         {}
  2855         ICStub *getStub(ICStubSpace *space) {
  2856             return ICUnaryArith_Int32::New(space, getStubCode());
  2858     };
  2859 };
  2861 class ICUnaryArith_Double : public ICStub
  2863     friend class ICStubSpace;
  2865     ICUnaryArith_Double(JitCode *stubCode)
  2866       : ICStub(UnaryArith_Double, stubCode)
  2867     {}
  2869   public:
  2870     static inline ICUnaryArith_Double *New(ICStubSpace *space, JitCode *code) {
  2871         if (!code)
  2872             return nullptr;
  2873         return space->allocate<ICUnaryArith_Double>(code);
  2876     class Compiler : public ICMultiStubCompiler {
  2877       protected:
  2878         bool generateStubCode(MacroAssembler &masm);
  2880       public:
  2881         Compiler(JSContext *cx, JSOp op)
  2882           : ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op)
  2883         {}
  2885         ICStub *getStub(ICStubSpace *space) {
  2886             return ICUnaryArith_Double::New(space, getStubCode());
  2888     };
  2889 };
  2891 // GetElem
  2892 //      JSOP_GETELEM
  2894 class ICGetElem_Fallback : public ICMonitoredFallbackStub
  2896     friend class ICStubSpace;
  2898     ICGetElem_Fallback(JitCode *stubCode)
  2899       : ICMonitoredFallbackStub(ICStub::GetElem_Fallback, stubCode)
  2900     { }
  2902     static const uint16_t EXTRA_NON_NATIVE = 0x1;
  2903     static const uint16_t EXTRA_NEGATIVE_INDEX = 0x2;
  2905   public:
  2906     static const uint32_t MAX_OPTIMIZED_STUBS = 16;
  2908     static inline ICGetElem_Fallback *New(ICStubSpace *space, JitCode *code) {
  2909         if (!code)
  2910             return nullptr;
  2911         return space->allocate<ICGetElem_Fallback>(code);
  2914     void noteNonNativeAccess() {
  2915         extra_ |= EXTRA_NON_NATIVE;
  2917     bool hasNonNativeAccess() const {
  2918         return extra_ & EXTRA_NON_NATIVE;
  2921     void noteNegativeIndex() {
  2922         extra_ |= EXTRA_NEGATIVE_INDEX;
  2924     bool hasNegativeIndex() const {
  2925         return extra_ & EXTRA_NEGATIVE_INDEX;
  2928     // Compiler for this stub kind.
  2929     class Compiler : public ICStubCompiler {
  2930       protected:
  2931         bool generateStubCode(MacroAssembler &masm);
  2933       public:
  2934         Compiler(JSContext *cx)
  2935           : ICStubCompiler(cx, ICStub::GetElem_Fallback)
  2936         { }
  2938         ICStub *getStub(ICStubSpace *space) {
  2939             ICGetElem_Fallback *stub = ICGetElem_Fallback::New(space, getStubCode());
  2940             if (!stub)
  2941                 return nullptr;
  2942             if (!stub->initMonitoringChain(cx, space))
  2943                 return nullptr;
  2944             return stub;
  2946     };
  2947 };
  2949 class ICGetElemNativeStub : public ICMonitoredStub
  2951   public:
  2952     enum AccessType { FixedSlot = 0, DynamicSlot, NativeGetter, ScriptedGetter };
  2954   protected:
  2955     HeapPtrShape shape_;
  2956     HeapPtrPropertyName name_;
  2958     static const unsigned NEEDS_ATOMIZE_SHIFT = 0;
  2959     static const uint16_t NEEDS_ATOMIZE_MASK = 0x1;
  2961     static const unsigned ACCESSTYPE_SHIFT = 1;
  2962     static const uint16_t ACCESSTYPE_MASK = 0x3;
  2964     ICGetElemNativeStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  2965                         HandleShape shape, HandlePropertyName name, AccessType acctype,
  2966                         bool needsAtomize);
  2968     ~ICGetElemNativeStub();
  2970   public:
  2971     HeapPtrShape &shape() {
  2972         return shape_;
  2974     static size_t offsetOfShape() {
  2975         return offsetof(ICGetElemNativeStub, shape_);
  2978     HeapPtrPropertyName &name() {
  2979         return name_;
  2981     static size_t offsetOfName() {
  2982         return offsetof(ICGetElemNativeStub, name_);
  2985     AccessType accessType() const {
  2986         return static_cast<AccessType>((extra_ >> ACCESSTYPE_SHIFT) & ACCESSTYPE_MASK);
  2989     bool needsAtomize() const {
  2990         return (extra_ >> NEEDS_ATOMIZE_SHIFT) & NEEDS_ATOMIZE_MASK;
  2992 };
  2994 class ICGetElemNativeSlotStub : public ICGetElemNativeStub
  2996   protected:
  2997     uint32_t offset_;
  2999     ICGetElemNativeSlotStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  3000                             HandleShape shape, HandlePropertyName name,
  3001                             AccessType acctype, bool needsAtomize, uint32_t offset)
  3002       : ICGetElemNativeStub(kind, stubCode, firstMonitorStub, shape, name, acctype, needsAtomize),
  3003         offset_(offset)
  3005         JS_ASSERT(kind == GetElem_NativeSlot || kind == GetElem_NativePrototypeSlot);
  3006         JS_ASSERT(acctype == FixedSlot || acctype == DynamicSlot);
  3009   public:
  3010     uint32_t offset() const {
  3011         return offset_;
  3014     static size_t offsetOfOffset() {
  3015         return offsetof(ICGetElemNativeSlotStub, offset_);
  3017 };
  3019 class ICGetElemNativeGetterStub : public ICGetElemNativeStub
  3021   protected:
  3022     HeapPtrFunction getter_;
  3023     uint32_t pcOffset_;
  3025     ICGetElemNativeGetterStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  3026                             HandleShape shape, HandlePropertyName name, AccessType acctype,
  3027                             bool needsAtomize, HandleFunction getter, uint32_t pcOffset);
  3029   public:
  3030     HeapPtrFunction &getter() {
  3031         return getter_;
  3033     static size_t offsetOfGetter() {
  3034         return offsetof(ICGetElemNativeGetterStub, getter_);
  3037     static size_t offsetOfPCOffset() {
  3038         return offsetof(ICGetElemNativeGetterStub, pcOffset_);
  3040 };
  3042 class ICGetElem_NativeSlot : public ICGetElemNativeSlotStub
  3044     friend class ICStubSpace;
  3045     ICGetElem_NativeSlot(JitCode *stubCode, ICStub *firstMonitorStub,
  3046                          HandleShape shape, HandlePropertyName name,
  3047                          AccessType acctype, bool needsAtomize, uint32_t offset)
  3048       : ICGetElemNativeSlotStub(ICStub::GetElem_NativeSlot, stubCode, firstMonitorStub, shape,
  3049                                 name, acctype, needsAtomize, offset)
  3050     {}
  3052   public:
  3053     static inline ICGetElem_NativeSlot *New(ICStubSpace *space, JitCode *code,
  3054                                             ICStub *firstMonitorStub,
  3055                                             HandleShape shape, HandlePropertyName name,
  3056                                             AccessType acctype, bool needsAtomize, uint32_t offset)
  3058         if (!code)
  3059             return nullptr;
  3060         return space->allocate<ICGetElem_NativeSlot>(code, firstMonitorStub, shape, name,
  3061                                                      acctype, needsAtomize, offset);
  3063 };
  3065 class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub
  3067     friend class ICStubSpace;
  3068     HeapPtrObject holder_;
  3069     HeapPtrShape holderShape_;
  3071     ICGetElem_NativePrototypeSlot(JitCode *stubCode, ICStub *firstMonitorStub,
  3072                                   HandleShape shape, HandlePropertyName name,
  3073                                   AccessType acctype, bool needsAtomize, uint32_t offset,
  3074                                   HandleObject holder, HandleShape holderShape);
  3076   public:
  3077     static inline ICGetElem_NativePrototypeSlot *New(ICStubSpace *space, JitCode *code,
  3078                                                      ICStub *firstMonitorStub,
  3079                                                      HandleShape shape, HandlePropertyName name,
  3080                                                      AccessType acctype, bool needsAtomize,
  3081                                                      uint32_t offset, HandleObject holder,
  3082                                                      HandleShape holderShape)
  3084         if (!code)
  3085             return nullptr;
  3086         return space->allocate<ICGetElem_NativePrototypeSlot>(
  3087                     code, firstMonitorStub, shape, name, acctype, needsAtomize, offset, holder,
  3088                     holderShape);
  3091     HeapPtrObject &holder() {
  3092         return holder_;
  3094     static size_t offsetOfHolder() {
  3095         return offsetof(ICGetElem_NativePrototypeSlot, holder_);
  3098     HeapPtrShape &holderShape() {
  3099         return holderShape_;
  3101     static size_t offsetOfHolderShape() {
  3102         return offsetof(ICGetElem_NativePrototypeSlot, holderShape_);
  3104 };
  3106 class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub
  3108     friend class ICStubSpace;
  3109     HeapPtrObject holder_;
  3110     HeapPtrShape holderShape_;
  3112   protected:
  3113     ICGetElemNativePrototypeCallStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  3114                                      HandleShape shape, HandlePropertyName name,
  3115                                      AccessType acctype, bool needsAtomize, HandleFunction getter,
  3116                                      uint32_t pcOffset, HandleObject holder,
  3117                                      HandleShape holderShape);
  3119   public:
  3120     HeapPtrObject &holder() {
  3121         return holder_;
  3123     static size_t offsetOfHolder() {
  3124         return offsetof(ICGetElemNativePrototypeCallStub, holder_);
  3127     HeapPtrShape &holderShape() {
  3128         return holderShape_;
  3130     static size_t offsetOfHolderShape() {
  3131         return offsetof(ICGetElemNativePrototypeCallStub, holderShape_);
  3133 };
  3135 class ICGetElem_NativePrototypeCallNative : public ICGetElemNativePrototypeCallStub
  3137     friend class ICStubSpace;
  3139     ICGetElem_NativePrototypeCallNative(JitCode *stubCode, ICStub *firstMonitorStub,
  3140                                         HandleShape shape, HandlePropertyName name,
  3141                                         AccessType acctype, bool needsAtomize,
  3142                                         HandleFunction getter, uint32_t pcOffset,
  3143                                         HandleObject holder, HandleShape holderShape)
  3144       : ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallNative,
  3145                                          stubCode, firstMonitorStub, shape, name,
  3146                                          acctype, needsAtomize, getter, pcOffset, holder,
  3147                                          holderShape)
  3148     {}
  3150   public:
  3151     static inline ICGetElem_NativePrototypeCallNative *New(
  3152                     ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  3153                     HandleShape shape, HandlePropertyName name, AccessType acctype,
  3154                     bool needsAtomize, HandleFunction getter, uint32_t pcOffset,
  3155                     HandleObject holder, HandleShape holderShape)
  3157         if (!code)
  3158             return nullptr;
  3159         return space->allocate<ICGetElem_NativePrototypeCallNative>(
  3160                         code, firstMonitorStub, shape, name, acctype, needsAtomize, getter,
  3161                         pcOffset, holder, holderShape);
  3163 };
  3165 class ICGetElem_NativePrototypeCallScripted : public ICGetElemNativePrototypeCallStub
  3167     friend class ICStubSpace;
  3169     ICGetElem_NativePrototypeCallScripted(JitCode *stubCode, ICStub *firstMonitorStub,
  3170                                         HandleShape shape, HandlePropertyName name,
  3171                                         AccessType acctype, bool needsAtomize,
  3172                                         HandleFunction getter, uint32_t pcOffset,
  3173                                         HandleObject holder, HandleShape holderShape)
  3174       : ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallScripted,
  3175                                          stubCode, firstMonitorStub, shape, name,
  3176                                          acctype, needsAtomize, getter, pcOffset, holder,
  3177                                          holderShape)
  3178     {}
  3180   public:
  3181     static inline ICGetElem_NativePrototypeCallScripted *New(
  3182                     ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  3183                     HandleShape shape, HandlePropertyName name, AccessType acctype,
  3184                     bool needsAtomize, HandleFunction getter, uint32_t pcOffset,
  3185                     HandleObject holder, HandleShape holderShape)
  3187         if (!code)
  3188             return nullptr;
  3189         return space->allocate<ICGetElem_NativePrototypeCallScripted>(
  3190                         code, firstMonitorStub, shape, name, acctype, needsAtomize, getter,
  3191                         pcOffset, holder, holderShape);
  3193 };
  3195 // Compiler for GetElem_NativeSlot and GetElem_NativePrototypeSlot stubs.
  3196 class ICGetElemNativeCompiler : public ICStubCompiler
  3198     bool isCallElem_;
  3199     ICStub *firstMonitorStub_;
  3200     HandleObject obj_;
  3201     HandleObject holder_;
  3202     HandlePropertyName name_;
  3203     ICGetElemNativeStub::AccessType acctype_;
  3204     bool needsAtomize_;
  3205     uint32_t offset_;
  3206     HandleFunction getter_;
  3207     uint32_t pcOffset_;
  3209     bool emitCallNative(MacroAssembler &masm, Register objReg);
  3210     bool emitCallScripted(MacroAssembler &masm, Register objReg);
  3211     bool generateStubCode(MacroAssembler &masm);
  3213   protected:
  3214     virtual int32_t getKey() const {
  3215 #if JS_HAS_NO_SUCH_METHOD
  3216         return static_cast<int32_t>(kind) |
  3217                (static_cast<int32_t>(isCallElem_) << 16) |
  3218                (static_cast<int32_t>(needsAtomize_) << 17) |
  3219                (static_cast<int32_t>(acctype_) << 18);
  3220 #else
  3221         return static_cast<int32_t>(kind) | (static_cast<int32_t>(needsAtomize_) << 16) |
  3222                (static_cast<int32_t>(acctype_) << 17);
  3223 #endif
  3226   public:
  3227     ICGetElemNativeCompiler(JSContext *cx, ICStub::Kind kind, bool isCallElem,
  3228                             ICStub *firstMonitorStub, HandleObject obj, HandleObject holder,
  3229                             HandlePropertyName name, ICGetElemNativeStub::AccessType acctype,
  3230                             bool needsAtomize, uint32_t offset)
  3231       : ICStubCompiler(cx, kind),
  3232         isCallElem_(isCallElem),
  3233         firstMonitorStub_(firstMonitorStub),
  3234         obj_(obj),
  3235         holder_(holder),
  3236         name_(name),
  3237         acctype_(acctype),
  3238         needsAtomize_(needsAtomize),
  3239         offset_(offset),
  3240         getter_(js::NullPtr()),
  3241         pcOffset_(0)
  3242     {}
  3244     ICGetElemNativeCompiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
  3245                             HandleObject obj, HandleObject holder, HandlePropertyName name,
  3246                             ICGetElemNativeStub::AccessType acctype, bool needsAtomize,
  3247                             HandleFunction getter, uint32_t pcOffset, bool isCallElem)
  3248       : ICStubCompiler(cx, kind),
  3249         isCallElem_(false),
  3250         firstMonitorStub_(firstMonitorStub),
  3251         obj_(obj),
  3252         holder_(holder),
  3253         name_(name),
  3254         acctype_(acctype),
  3255         needsAtomize_(needsAtomize),
  3256         offset_(0),
  3257         getter_(getter),
  3258         pcOffset_(pcOffset)
  3259     {}
  3261     ICStub *getStub(ICStubSpace *space) {
  3262         RootedShape shape(cx, obj_->lastProperty());
  3263         if (kind == ICStub::GetElem_NativeSlot) {
  3264             JS_ASSERT(obj_ == holder_);
  3265             return ICGetElem_NativeSlot::New(
  3266                     space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
  3267                     offset_);
  3270         JS_ASSERT(obj_ != holder_);
  3271         RootedShape holderShape(cx, holder_->lastProperty());
  3272         if (kind == ICStub::GetElem_NativePrototypeSlot) {
  3273             return ICGetElem_NativePrototypeSlot::New(
  3274                     space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
  3275                     offset_, holder_, holderShape);
  3278         if (kind == ICStub::GetElem_NativePrototypeCallNative) {
  3279             return ICGetElem_NativePrototypeCallNative::New(
  3280                     space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
  3281                     getter_, pcOffset_, holder_, holderShape);
  3284         JS_ASSERT(kind == ICStub::GetElem_NativePrototypeCallScripted);
  3285         if (kind == ICStub::GetElem_NativePrototypeCallScripted) {
  3286             return ICGetElem_NativePrototypeCallScripted::New(
  3287                     space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
  3288                     getter_, pcOffset_, holder_, holderShape);
  3291         MOZ_ASSUME_UNREACHABLE("Invalid kind.");
  3292         return nullptr;
  3294 };
  3296 class ICGetElem_String : public ICStub
  3298     friend class ICStubSpace;
  3300     ICGetElem_String(JitCode *stubCode)
  3301       : ICStub(ICStub::GetElem_String, stubCode) {}
  3303   public:
  3304     static inline ICGetElem_String *New(ICStubSpace *space, JitCode *code) {
  3305         if (!code)
  3306             return nullptr;
  3307         return space->allocate<ICGetElem_String>(code);
  3310     // Compiler for this stub kind.
  3311     class Compiler : public ICStubCompiler {
  3312       protected:
  3313         bool generateStubCode(MacroAssembler &masm);
  3315       public:
  3316         Compiler(JSContext *cx)
  3317           : ICStubCompiler(cx, ICStub::GetElem_String) {}
  3319         ICStub *getStub(ICStubSpace *space) {
  3320             return ICGetElem_String::New(space, getStubCode());
  3322     };
  3323 };
  3325 class ICGetElem_Dense : public ICMonitoredStub
  3327     friend class ICStubSpace;
  3329     HeapPtrShape shape_;
  3331     ICGetElem_Dense(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape);
  3333   public:
  3334     static inline ICGetElem_Dense *New(ICStubSpace *space, JitCode *code,
  3335                                        ICStub *firstMonitorStub, HandleShape shape)
  3337         if (!code)
  3338             return nullptr;
  3339         return space->allocate<ICGetElem_Dense>(code, firstMonitorStub, shape);
  3342     static size_t offsetOfShape() {
  3343         return offsetof(ICGetElem_Dense, shape_);
  3346     HeapPtrShape &shape() {
  3347         return shape_;
  3350     class Compiler : public ICStubCompiler {
  3351       ICStub *firstMonitorStub_;
  3352       RootedShape shape_;
  3353       bool isCallElem_;
  3355       protected:
  3356         bool generateStubCode(MacroAssembler &masm);
  3358         virtual int32_t getKey() const {
  3359 #if JS_HAS_NO_SUCH_METHOD
  3360             return static_cast<int32_t>(kind) | (static_cast<int32_t>(isCallElem_) << 16);
  3361 #else
  3362             return static_cast<int32_t>(kind);
  3363 #endif
  3366       public:
  3367         Compiler(JSContext *cx, ICStub *firstMonitorStub, Shape *shape, bool isCallElem)
  3368           : ICStubCompiler(cx, ICStub::GetElem_Dense),
  3369             firstMonitorStub_(firstMonitorStub),
  3370             shape_(cx, shape),
  3371             isCallElem_(isCallElem)
  3372         {}
  3374         ICStub *getStub(ICStubSpace *space) {
  3375             return ICGetElem_Dense::New(space, getStubCode(), firstMonitorStub_, shape_);
  3377     };
  3378 };
  3380 class ICGetElem_TypedArray : public ICStub
  3382     friend class ICStubSpace;
  3384   protected: // Protected to silence Clang warning.
  3385     HeapPtrShape shape_;
  3387     ICGetElem_TypedArray(JitCode *stubCode, HandleShape shape, uint32_t type);
  3389   public:
  3390     static inline ICGetElem_TypedArray *New(ICStubSpace *space, JitCode *code,
  3391                                             HandleShape shape, uint32_t type)
  3393         if (!code)
  3394             return nullptr;
  3395         return space->allocate<ICGetElem_TypedArray>(code, shape, type);
  3398     static size_t offsetOfShape() {
  3399         return offsetof(ICGetElem_TypedArray, shape_);
  3402     HeapPtrShape &shape() {
  3403         return shape_;
  3406     class Compiler : public ICStubCompiler {
  3407       RootedShape shape_;
  3408       uint32_t type_;
  3410       protected:
  3411         bool generateStubCode(MacroAssembler &masm);
  3413         virtual int32_t getKey() const {
  3414             return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16);
  3417       public:
  3418         Compiler(JSContext *cx, Shape *shape, uint32_t type)
  3419           : ICStubCompiler(cx, ICStub::GetElem_TypedArray),
  3420             shape_(cx, shape),
  3421             type_(type)
  3422         {}
  3424         ICStub *getStub(ICStubSpace *space) {
  3425             return ICGetElem_TypedArray::New(space, getStubCode(), shape_, type_);
  3427     };
  3428 };
  3430 class ICGetElem_Arguments : public ICMonitoredStub
  3432     friend class ICStubSpace;
  3433   public:
  3434     enum Which { Normal, Strict, Magic };
  3436   private:
  3437     ICGetElem_Arguments(JitCode *stubCode, ICStub *firstMonitorStub, Which which)
  3438       : ICMonitoredStub(ICStub::GetElem_Arguments, stubCode, firstMonitorStub)
  3440         extra_ = static_cast<uint16_t>(which);
  3443   public:
  3444     static inline ICGetElem_Arguments *New(ICStubSpace *space, JitCode *code,
  3445                                            ICStub *firstMonitorStub, Which which)
  3447         if (!code)
  3448             return nullptr;
  3449         return space->allocate<ICGetElem_Arguments>(code, firstMonitorStub, which);
  3452     Which which() const {
  3453         return static_cast<Which>(extra_);
  3456     class Compiler : public ICStubCompiler {
  3457       ICStub *firstMonitorStub_;
  3458       Which which_;
  3459       bool isCallElem_;
  3461       protected:
  3462         bool generateStubCode(MacroAssembler &masm);
  3464         virtual int32_t getKey() const {
  3465 #if JS_HAS_NO_SUCH_METHOD
  3466             return static_cast<int32_t>(kind) |
  3467                    static_cast<int32_t>(isCallElem_ << 16) |
  3468                    (static_cast<int32_t>(which_) << 17);
  3469 #else
  3470             return static_cast<int32_t>(kind) | (static_cast<int32_t>(which_) << 16);
  3471 #endif
  3474       public:
  3475         Compiler(JSContext *cx, ICStub *firstMonitorStub, Which which, bool isCallElem)
  3476           : ICStubCompiler(cx, ICStub::GetElem_Arguments),
  3477             firstMonitorStub_(firstMonitorStub),
  3478             which_(which),
  3479             isCallElem_(isCallElem)
  3480         {}
  3482         ICStub *getStub(ICStubSpace *space) {
  3483             return ICGetElem_Arguments::New(space, getStubCode(), firstMonitorStub_, which_);
  3485     };
  3486 };
  3488 // SetElem
  3489 //      JSOP_SETELEM
  3490 //      JSOP_INITELEM
  3492 class ICSetElem_Fallback : public ICFallbackStub
  3494     friend class ICStubSpace;
  3496     ICSetElem_Fallback(JitCode *stubCode)
  3497       : ICFallbackStub(ICStub::SetElem_Fallback, stubCode)
  3498     { }
  3500   public:
  3501     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  3503     static inline ICSetElem_Fallback *New(ICStubSpace *space, JitCode *code) {
  3504         if (!code)
  3505             return nullptr;
  3506         return space->allocate<ICSetElem_Fallback>(code);
  3509     void noteArrayWriteHole() {
  3510         extra_ = 1;
  3512     bool hasArrayWriteHole() const {
  3513         return extra_;
  3516     // Compiler for this stub kind.
  3517     class Compiler : public ICStubCompiler {
  3518       protected:
  3519         bool generateStubCode(MacroAssembler &masm);
  3521       public:
  3522         Compiler(JSContext *cx)
  3523           : ICStubCompiler(cx, ICStub::SetElem_Fallback)
  3524         { }
  3526         ICStub *getStub(ICStubSpace *space) {
  3527             return ICSetElem_Fallback::New(space, getStubCode());
  3529     };
  3530 };
  3532 class ICSetElem_Dense : public ICUpdatedStub
  3534     friend class ICStubSpace;
  3536     HeapPtrShape shape_;
  3537     HeapPtrTypeObject type_;
  3539     ICSetElem_Dense(JitCode *stubCode, HandleShape shape, HandleTypeObject type);
  3541   public:
  3542     static inline ICSetElem_Dense *New(ICStubSpace *space, JitCode *code, HandleShape shape,
  3543                                        HandleTypeObject type) {
  3544         if (!code)
  3545             return nullptr;
  3546         return space->allocate<ICSetElem_Dense>(code, shape, type);
  3549     static size_t offsetOfShape() {
  3550         return offsetof(ICSetElem_Dense, shape_);
  3552     static size_t offsetOfType() {
  3553         return offsetof(ICSetElem_Dense, type_);
  3556     HeapPtrShape &shape() {
  3557         return shape_;
  3559     HeapPtrTypeObject &type() {
  3560         return type_;
  3563     class Compiler : public ICStubCompiler {
  3564         RootedShape shape_;
  3566         // Compiler is only live on stack during compilation, it should
  3567         // outlive any RootedTypeObject it's passed.  So it can just
  3568         // use the handle.
  3569         HandleTypeObject type_;
  3571         bool generateStubCode(MacroAssembler &masm);
  3573       public:
  3574         Compiler(JSContext *cx, Shape *shape, HandleTypeObject type)
  3575           : ICStubCompiler(cx, ICStub::SetElem_Dense),
  3576             shape_(cx, shape),
  3577             type_(type)
  3578         {}
  3580         ICUpdatedStub *getStub(ICStubSpace *space) {
  3581             ICSetElem_Dense *stub = ICSetElem_Dense::New(space, getStubCode(), shape_, type_);
  3582             if (!stub || !stub->initUpdatingChain(cx, space))
  3583                 return nullptr;
  3584             return stub;
  3586     };
  3587 };
  3589 template <size_t ProtoChainDepth> class ICSetElem_DenseAddImpl;
  3591 class ICSetElem_DenseAdd : public ICUpdatedStub
  3593     friend class ICStubSpace;
  3595   public:
  3596     static const size_t MAX_PROTO_CHAIN_DEPTH = 4;
  3598   protected:
  3599     HeapPtrTypeObject type_;
  3601     ICSetElem_DenseAdd(JitCode *stubCode, types::TypeObject *type, size_t protoChainDepth);
  3603   public:
  3604     static size_t offsetOfType() {
  3605         return offsetof(ICSetElem_DenseAdd, type_);
  3608     HeapPtrTypeObject &type() {
  3609         return type_;
  3611     size_t protoChainDepth() const {
  3612         MOZ_ASSERT(extra_ <= MAX_PROTO_CHAIN_DEPTH);
  3613         return extra_;
  3616     template <size_t ProtoChainDepth>
  3617     ICSetElem_DenseAddImpl<ProtoChainDepth> *toImplUnchecked() {
  3618         return static_cast<ICSetElem_DenseAddImpl<ProtoChainDepth> *>(this);
  3621     template <size_t ProtoChainDepth>
  3622     ICSetElem_DenseAddImpl<ProtoChainDepth> *toImpl() {
  3623         JS_ASSERT(ProtoChainDepth == protoChainDepth());
  3624         return toImplUnchecked<ProtoChainDepth>();
  3626 };
  3628 template <size_t ProtoChainDepth>
  3629 class ICSetElem_DenseAddImpl : public ICSetElem_DenseAdd
  3631     friend class ICStubSpace;
  3633     static const size_t NumShapes = ProtoChainDepth + 1;
  3634     mozilla::Array<HeapPtrShape, NumShapes> shapes_;
  3636     ICSetElem_DenseAddImpl(JitCode *stubCode, types::TypeObject *type,
  3637                            const AutoShapeVector *shapes)
  3638       : ICSetElem_DenseAdd(stubCode, type, ProtoChainDepth)
  3640         JS_ASSERT(shapes->length() == NumShapes);
  3641         for (size_t i = 0; i < NumShapes; i++)
  3642             shapes_[i].init((*shapes)[i]);
  3645   public:
  3646     static inline ICSetElem_DenseAddImpl *New(ICStubSpace *space, JitCode *code,
  3647                                               types::TypeObject *type,
  3648                                               const AutoShapeVector *shapes)
  3650         if (!code)
  3651             return nullptr;
  3652         return space->allocate<ICSetElem_DenseAddImpl<ProtoChainDepth> >(code, type, shapes);
  3655     void traceShapes(JSTracer *trc) {
  3656         for (size_t i = 0; i < NumShapes; i++)
  3657             MarkShape(trc, &shapes_[i], "baseline-setelem-denseadd-stub-shape");
  3659     Shape *shape(size_t i) const {
  3660         JS_ASSERT(i < NumShapes);
  3661         return shapes_[i];
  3663     static size_t offsetOfShape(size_t idx) {
  3664         return offsetof(ICSetElem_DenseAddImpl, shapes_) + idx * sizeof(HeapPtrShape);
  3666 };
  3668 class ICSetElemDenseAddCompiler : public ICStubCompiler {
  3669     RootedObject obj_;
  3670     size_t protoChainDepth_;
  3672     bool generateStubCode(MacroAssembler &masm);
  3674   protected:
  3675     virtual int32_t getKey() const {
  3676         return static_cast<int32_t>(kind) | (static_cast<int32_t>(protoChainDepth_) << 16);
  3679   public:
  3680     ICSetElemDenseAddCompiler(JSContext *cx, HandleObject obj, size_t protoChainDepth)
  3681         : ICStubCompiler(cx, ICStub::SetElem_DenseAdd),
  3682           obj_(cx, obj),
  3683           protoChainDepth_(protoChainDepth)
  3684     {}
  3686     template <size_t ProtoChainDepth>
  3687     ICUpdatedStub *getStubSpecific(ICStubSpace *space, const AutoShapeVector *shapes);
  3689     ICUpdatedStub *getStub(ICStubSpace *space);
  3690 };
  3692 class ICSetElem_TypedArray : public ICStub
  3694     friend class ICStubSpace;
  3696   protected: // Protected to silence Clang warning.
  3697     HeapPtrShape shape_;
  3699     ICSetElem_TypedArray(JitCode *stubCode, HandleShape shape, uint32_t type,
  3700                          bool expectOutOfBounds);
  3702   public:
  3703     static inline ICSetElem_TypedArray *New(ICStubSpace *space, JitCode *code,
  3704                                             HandleShape shape, uint32_t type,
  3705                                             bool expectOutOfBounds)
  3707         if (!code)
  3708             return nullptr;
  3709         return space->allocate<ICSetElem_TypedArray>(code, shape, type, expectOutOfBounds);
  3712     uint32_t type() const {
  3713         return extra_ & 0xff;
  3716     bool expectOutOfBounds() const {
  3717         return (extra_ >> 8) & 1;
  3720     static size_t offsetOfShape() {
  3721         return offsetof(ICSetElem_TypedArray, shape_);
  3724     HeapPtrShape &shape() {
  3725         return shape_;
  3728     class Compiler : public ICStubCompiler {
  3729         RootedShape shape_;
  3730         uint32_t type_;
  3731         bool expectOutOfBounds_;
  3733       protected:
  3734         bool generateStubCode(MacroAssembler &masm);
  3736         virtual int32_t getKey() const {
  3737             return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16) |
  3738                    (static_cast<int32_t>(expectOutOfBounds_) << 24);
  3741       public:
  3742         Compiler(JSContext *cx, Shape *shape, uint32_t type, bool expectOutOfBounds)
  3743           : ICStubCompiler(cx, ICStub::SetElem_TypedArray),
  3744             shape_(cx, shape),
  3745             type_(type),
  3746             expectOutOfBounds_(expectOutOfBounds)
  3747         {}
  3749         ICStub *getStub(ICStubSpace *space) {
  3750             return ICSetElem_TypedArray::New(space, getStubCode(), shape_, type_,
  3751                                              expectOutOfBounds_);
  3753     };
  3754 };
  3756 // In
  3757 //      JSOP_IN
  3758 class ICIn_Fallback : public ICFallbackStub
  3760     friend class ICStubSpace;
  3762     ICIn_Fallback(JitCode *stubCode)
  3763       : ICFallbackStub(ICStub::In_Fallback, stubCode)
  3764     { }
  3766   public:
  3767     static inline ICIn_Fallback *New(ICStubSpace *space, JitCode *code) {
  3768         if (!code)
  3769             return nullptr;
  3770         return space->allocate<ICIn_Fallback>(code);
  3773     class Compiler : public ICStubCompiler {
  3774       protected:
  3775         bool generateStubCode(MacroAssembler &masm);
  3777       public:
  3778         Compiler(JSContext *cx)
  3779           : ICStubCompiler(cx, ICStub::In_Fallback)
  3780         { }
  3782         ICStub *getStub(ICStubSpace *space) {
  3783             return ICIn_Fallback::New(space, getStubCode());
  3785     };
  3786 };
  3788 // GetName
  3789 //      JSOP_NAME
  3790 //      JSOP_GETGNAME
  3791 class ICGetName_Fallback : public ICMonitoredFallbackStub
  3793     friend class ICStubSpace;
  3795     ICGetName_Fallback(JitCode *stubCode)
  3796       : ICMonitoredFallbackStub(ICStub::GetName_Fallback, stubCode)
  3797     { }
  3799   public:
  3800     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  3802     static inline ICGetName_Fallback *New(ICStubSpace *space, JitCode *code) {
  3803         if (!code)
  3804             return nullptr;
  3805         return space->allocate<ICGetName_Fallback>(code);
  3808     class Compiler : public ICStubCompiler {
  3809       protected:
  3810         bool generateStubCode(MacroAssembler &masm);
  3812       public:
  3813         Compiler(JSContext *cx)
  3814           : ICStubCompiler(cx, ICStub::GetName_Fallback)
  3815         { }
  3817         ICStub *getStub(ICStubSpace *space) {
  3818             ICGetName_Fallback *stub = ICGetName_Fallback::New(space, getStubCode());
  3819             if (!stub || !stub->initMonitoringChain(cx, space))
  3820                 return nullptr;
  3821             return stub;
  3823     };
  3824 };
  3826 // Optimized GETGNAME/CALLGNAME stub.
  3827 class ICGetName_Global : public ICMonitoredStub
  3829     friend class ICStubSpace;
  3831   protected: // Protected to silence Clang warning.
  3832     HeapPtrShape shape_;
  3833     uint32_t slot_;
  3835     ICGetName_Global(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape, uint32_t slot);
  3837   public:
  3838     static inline ICGetName_Global *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  3839                                         HandleShape shape, uint32_t slot)
  3841         if (!code)
  3842             return nullptr;
  3843         return space->allocate<ICGetName_Global>(code, firstMonitorStub, shape, slot);
  3846     HeapPtrShape &shape() {
  3847         return shape_;
  3849     static size_t offsetOfShape() {
  3850         return offsetof(ICGetName_Global, shape_);
  3852     static size_t offsetOfSlot() {
  3853         return offsetof(ICGetName_Global, slot_);
  3856     class Compiler : public ICStubCompiler {
  3857         ICStub *firstMonitorStub_;
  3858         RootedShape shape_;
  3859         uint32_t slot_;
  3861       protected:
  3862         bool generateStubCode(MacroAssembler &masm);
  3864       public:
  3865         Compiler(JSContext *cx, ICStub *firstMonitorStub, Shape *shape, uint32_t slot)
  3866           : ICStubCompiler(cx, ICStub::GetName_Global),
  3867             firstMonitorStub_(firstMonitorStub),
  3868             shape_(cx, shape),
  3869             slot_(slot)
  3870         {}
  3872         ICStub *getStub(ICStubSpace *space) {
  3873             return ICGetName_Global::New(space, getStubCode(), firstMonitorStub_, shape_, slot_);
  3875     };
  3876 };
  3878 // Optimized GETNAME/CALLNAME stub, making a variable number of hops to get an
  3879 // 'own' property off some scope object. Unlike GETPROP on an object's
  3880 // prototype, there is no teleporting optimization to take advantage of and
  3881 // shape checks are required all along the scope chain.
  3882 template <size_t NumHops>
  3883 class ICGetName_Scope : public ICMonitoredStub
  3885     friend class ICStubSpace;
  3887     static const size_t MAX_HOPS = 6;
  3889     mozilla::Array<HeapPtrShape, NumHops + 1> shapes_;
  3890     uint32_t offset_;
  3892     ICGetName_Scope(JitCode *stubCode, ICStub *firstMonitorStub,
  3893                     AutoShapeVector *shapes, uint32_t offset);
  3895     static Kind GetStubKind() {
  3896         return (Kind) (GetName_Scope0 + NumHops);
  3899   public:
  3900     static inline ICGetName_Scope *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  3901                                        AutoShapeVector *shapes, uint32_t offset)
  3903         if (!code)
  3904             return nullptr;
  3905         return space->allocate<ICGetName_Scope<NumHops> >(code, firstMonitorStub, shapes, offset);
  3908     void traceScopes(JSTracer *trc) {
  3909         for (size_t i = 0; i < NumHops + 1; i++)
  3910             MarkShape(trc, &shapes_[i], "baseline-scope-stub-shape");
  3913     static size_t offsetOfShape(size_t index) {
  3914         JS_ASSERT(index <= NumHops);
  3915         return offsetof(ICGetName_Scope, shapes_) + (index * sizeof(HeapPtrShape));
  3917     static size_t offsetOfOffset() {
  3918         return offsetof(ICGetName_Scope, offset_);
  3921     class Compiler : public ICStubCompiler {
  3922         ICStub *firstMonitorStub_;
  3923         AutoShapeVector *shapes_;
  3924         bool isFixedSlot_;
  3925         uint32_t offset_;
  3927       protected:
  3928         bool generateStubCode(MacroAssembler &masm);
  3930       protected:
  3931         virtual int32_t getKey() const {
  3932             return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16);
  3935       public:
  3936         Compiler(JSContext *cx, ICStub *firstMonitorStub,
  3937                  AutoShapeVector *shapes, bool isFixedSlot, uint32_t offset)
  3938           : ICStubCompiler(cx, GetStubKind()),
  3939             firstMonitorStub_(firstMonitorStub),
  3940             shapes_(shapes),
  3941             isFixedSlot_(isFixedSlot),
  3942             offset_(offset)
  3946         ICStub *getStub(ICStubSpace *space) {
  3947             return ICGetName_Scope::New(space, getStubCode(), firstMonitorStub_, shapes_, offset_);
  3949     };
  3950 };
  3952 // BindName
  3953 //      JSOP_BINDNAME
  3954 class ICBindName_Fallback : public ICFallbackStub
  3956     friend class ICStubSpace;
  3958     ICBindName_Fallback(JitCode *stubCode)
  3959       : ICFallbackStub(ICStub::BindName_Fallback, stubCode)
  3960     { }
  3962   public:
  3963     static inline ICBindName_Fallback *New(ICStubSpace *space, JitCode *code) {
  3964         if (!code)
  3965             return nullptr;
  3966         return space->allocate<ICBindName_Fallback>(code);
  3969     class Compiler : public ICStubCompiler {
  3970       protected:
  3971         bool generateStubCode(MacroAssembler &masm);
  3973       public:
  3974         Compiler(JSContext *cx)
  3975           : ICStubCompiler(cx, ICStub::BindName_Fallback)
  3976         { }
  3978         ICStub *getStub(ICStubSpace *space) {
  3979             return ICBindName_Fallback::New(space, getStubCode());
  3981     };
  3982 };
  3984 // GetIntrinsic
  3985 //      JSOP_GETINTRINSIC
  3986 class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub
  3988     friend class ICStubSpace;
  3990     ICGetIntrinsic_Fallback(JitCode *stubCode)
  3991       : ICMonitoredFallbackStub(ICStub::GetIntrinsic_Fallback, stubCode)
  3992     { }
  3994   public:
  3995     static inline ICGetIntrinsic_Fallback *New(ICStubSpace *space, JitCode *code) {
  3996         if (!code)
  3997             return nullptr;
  3998         return space->allocate<ICGetIntrinsic_Fallback>(code);
  4001     class Compiler : public ICStubCompiler {
  4002       protected:
  4003         bool generateStubCode(MacroAssembler &masm);
  4005       public:
  4006         Compiler(JSContext *cx)
  4007           : ICStubCompiler(cx, ICStub::GetIntrinsic_Fallback)
  4008         { }
  4010         ICStub *getStub(ICStubSpace *space) {
  4011             ICGetIntrinsic_Fallback *stub = ICGetIntrinsic_Fallback::New(space, getStubCode());
  4012             if (!stub || !stub->initMonitoringChain(cx, space))
  4013                 return nullptr;
  4014             return stub;
  4016     };
  4017 };
  4019 // Stub that loads the constant result of a GETINTRINSIC operation.
  4020 class ICGetIntrinsic_Constant : public ICStub
  4022     friend class ICStubSpace;
  4024     HeapValue value_;
  4026     ICGetIntrinsic_Constant(JitCode *stubCode, HandleValue value);
  4027     ~ICGetIntrinsic_Constant();
  4029   public:
  4030     static inline ICGetIntrinsic_Constant *New(ICStubSpace *space, JitCode *code,
  4031                                                HandleValue value)
  4033         if (!code)
  4034             return nullptr;
  4035         return space->allocate<ICGetIntrinsic_Constant>(code, value);
  4038     HeapValue &value() {
  4039         return value_;
  4041     static size_t offsetOfValue() {
  4042         return offsetof(ICGetIntrinsic_Constant, value_);
  4045     class Compiler : public ICStubCompiler {
  4046         bool generateStubCode(MacroAssembler &masm);
  4048         HandleValue value_;
  4050       public:
  4051         Compiler(JSContext *cx, HandleValue value)
  4052           : ICStubCompiler(cx, ICStub::GetIntrinsic_Constant),
  4053             value_(value)
  4054         {}
  4056         ICStub *getStub(ICStubSpace *space) {
  4057             return ICGetIntrinsic_Constant::New(space, getStubCode(), value_);
  4059     };
  4060 };
  4062 class ICGetProp_Fallback : public ICMonitoredFallbackStub
  4064     friend class ICStubSpace;
  4066     ICGetProp_Fallback(JitCode *stubCode)
  4067       : ICMonitoredFallbackStub(ICStub::GetProp_Fallback, stubCode)
  4068     { }
  4070   public:
  4071     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  4073     static inline ICGetProp_Fallback *New(ICStubSpace *space, JitCode *code) {
  4074         if (!code)
  4075             return nullptr;
  4076         return space->allocate<ICGetProp_Fallback>(code);
  4079     static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
  4080     static const size_t ACCESSED_GETTER_BIT = 1;
  4082     void noteUnoptimizableAccess() {
  4083         extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
  4085     bool hadUnoptimizableAccess() const {
  4086         return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
  4089     void noteAccessedGetter() {
  4090         extra_ |= (1u << ACCESSED_GETTER_BIT);
  4092     bool hasAccessedGetter() const {
  4093         return extra_ & (1u << ACCESSED_GETTER_BIT);
  4096     class Compiler : public ICStubCompiler {
  4097       protected:
  4098         uint32_t returnFromIonOffset_;
  4099         uint32_t returnFromStubOffset_;
  4100         bool generateStubCode(MacroAssembler &masm);
  4101         bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> code);
  4103       public:
  4104         Compiler(JSContext *cx)
  4105           : ICStubCompiler(cx, ICStub::GetProp_Fallback)
  4106         { }
  4108         ICStub *getStub(ICStubSpace *space) {
  4109             ICGetProp_Fallback *stub = ICGetProp_Fallback::New(space, getStubCode());
  4110             if (!stub || !stub->initMonitoringChain(cx, space))
  4111                 return nullptr;
  4112             return stub;
  4114     };
  4115 };
  4117 // Stub for accessing a dense array's length.
  4118 class ICGetProp_ArrayLength : public ICStub
  4120     friend class ICStubSpace;
  4122     ICGetProp_ArrayLength(JitCode *stubCode)
  4123       : ICStub(GetProp_ArrayLength, stubCode)
  4124     {}
  4126   public:
  4127     static inline ICGetProp_ArrayLength *New(ICStubSpace *space, JitCode *code) {
  4128         if (!code)
  4129             return nullptr;
  4130         return space->allocate<ICGetProp_ArrayLength>(code);
  4133     class Compiler : public ICStubCompiler {
  4134         bool generateStubCode(MacroAssembler &masm);
  4136       public:
  4137         Compiler(JSContext *cx)
  4138           : ICStubCompiler(cx, ICStub::GetProp_ArrayLength)
  4139         {}
  4141         ICStub *getStub(ICStubSpace *space) {
  4142             return ICGetProp_ArrayLength::New(space, getStubCode());
  4144     };
  4145 };
  4147 // Stub for accessing a typed array's length.
  4148 class ICGetProp_TypedArrayLength : public ICStub
  4150     friend class ICStubSpace;
  4152     ICGetProp_TypedArrayLength(JitCode *stubCode)
  4153       : ICStub(GetProp_TypedArrayLength, stubCode)
  4154     {}
  4156   public:
  4157     static inline ICGetProp_TypedArrayLength *New(ICStubSpace *space, JitCode *code) {
  4158         if (!code)
  4159             return nullptr;
  4160         return space->allocate<ICGetProp_TypedArrayLength>(code);
  4163     class Compiler : public ICStubCompiler {
  4164         bool generateStubCode(MacroAssembler &masm);
  4166       public:
  4167         Compiler(JSContext *cx)
  4168           : ICStubCompiler(cx, ICStub::GetProp_TypedArrayLength)
  4169         {}
  4171         ICStub *getStub(ICStubSpace *space) {
  4172             return ICGetProp_TypedArrayLength::New(space, getStubCode());
  4174     };
  4175 };
  4177 // Stub for accessing a property on a primitive's prototype.
  4178 class ICGetProp_Primitive : public ICMonitoredStub
  4180     friend class ICStubSpace;
  4182   protected: // Protected to silence Clang warning.
  4183     // Shape of String.prototype/Number.prototype to check for.
  4184     HeapPtrShape protoShape_;
  4186     // Fixed or dynamic slot offset.
  4187     uint32_t offset_;
  4189     ICGetProp_Primitive(JitCode *stubCode, ICStub *firstMonitorStub,
  4190                         HandleShape protoShape, uint32_t offset);
  4192   public:
  4193     static inline ICGetProp_Primitive *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  4194                                            HandleShape protoShape, uint32_t offset)
  4196         if (!code)
  4197             return nullptr;
  4198         return space->allocate<ICGetProp_Primitive>(code, firstMonitorStub, protoShape, offset);
  4201     HeapPtrShape &protoShape() {
  4202         return protoShape_;
  4204     static size_t offsetOfProtoShape() {
  4205         return offsetof(ICGetProp_Primitive, protoShape_);
  4208     static size_t offsetOfOffset() {
  4209         return offsetof(ICGetProp_Primitive, offset_);
  4212     class Compiler : public ICStubCompiler {
  4213         ICStub *firstMonitorStub_;
  4214         JSValueType primitiveType_;
  4215         RootedObject prototype_;
  4216         bool isFixedSlot_;
  4217         uint32_t offset_;
  4219         bool generateStubCode(MacroAssembler &masm);
  4221       protected:
  4222         virtual int32_t getKey() const {
  4223             static_assert(sizeof(JSValueType) == 1, "JSValueType should fit in one byte");
  4224             return static_cast<int32_t>(kind)
  4225                 | (static_cast<int32_t>(isFixedSlot_) << 16)
  4226                 | (static_cast<int32_t>(primitiveType_) << 24);
  4229       public:
  4230         Compiler(JSContext *cx, ICStub *firstMonitorStub, JSValueType primitiveType,
  4231                  HandleObject prototype, bool isFixedSlot, uint32_t offset)
  4232           : ICStubCompiler(cx, ICStub::GetProp_Primitive),
  4233             firstMonitorStub_(firstMonitorStub),
  4234             primitiveType_(primitiveType),
  4235             prototype_(cx, prototype),
  4236             isFixedSlot_(isFixedSlot),
  4237             offset_(offset)
  4238         {}
  4240         ICStub *getStub(ICStubSpace *space) {
  4241             RootedShape protoShape(cx, prototype_->lastProperty());
  4242             return ICGetProp_Primitive::New(space, getStubCode(), firstMonitorStub_,
  4243                                             protoShape, offset_);
  4245     };
  4246 };
  4248 // Stub for accessing a string's length.
  4249 class ICGetProp_StringLength : public ICStub
  4251     friend class ICStubSpace;
  4253     ICGetProp_StringLength(JitCode *stubCode)
  4254       : ICStub(GetProp_StringLength, stubCode)
  4255     {}
  4257   public:
  4258     static inline ICGetProp_StringLength *New(ICStubSpace *space, JitCode *code) {
  4259         if (!code)
  4260             return nullptr;
  4261         return space->allocate<ICGetProp_StringLength>(code);
  4264     class Compiler : public ICStubCompiler {
  4265         bool generateStubCode(MacroAssembler &masm);
  4267       public:
  4268         Compiler(JSContext *cx)
  4269           : ICStubCompiler(cx, ICStub::GetProp_StringLength)
  4270         {}
  4272         ICStub *getStub(ICStubSpace *space) {
  4273             return ICGetProp_StringLength::New(space, getStubCode());
  4275     };
  4276 };
  4278 // Base class for GetProp_Native and GetProp_NativePrototype stubs.
  4279 class ICGetPropNativeStub : public ICMonitoredStub
  4281     // Object shape (lastProperty).
  4282     HeapPtrShape shape_;
  4284     // Fixed or dynamic slot offset.
  4285     uint32_t offset_;
  4287   protected:
  4288     ICGetPropNativeStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  4289                         HandleShape shape, uint32_t offset);
  4291   public:
  4292     HeapPtrShape &shape() {
  4293         return shape_;
  4295     uint32_t offset() const {
  4296         return offset_;
  4298     static size_t offsetOfShape() {
  4299         return offsetof(ICGetPropNativeStub, shape_);
  4301     static size_t offsetOfOffset() {
  4302         return offsetof(ICGetPropNativeStub, offset_);
  4304 };
  4306 // Stub for accessing an own property on a native object.
  4307 class ICGetProp_Native : public ICGetPropNativeStub
  4309     friend class ICStubSpace;
  4311     ICGetProp_Native(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape,
  4312                      uint32_t offset)
  4313       : ICGetPropNativeStub(GetProp_Native, stubCode, firstMonitorStub, shape, offset)
  4314     {}
  4316   public:
  4317     static inline ICGetProp_Native *New(ICStubSpace *space, JitCode *code,
  4318                                         ICStub *firstMonitorStub, HandleShape shape,
  4319                                         uint32_t offset)
  4321         if (!code)
  4322             return nullptr;
  4323         return space->allocate<ICGetProp_Native>(code, firstMonitorStub, shape, offset);
  4325 };
  4327 // Stub for accessing a property on a native object's prototype. Note that due to
  4328 // the shape teleporting optimization, we only have to guard on the object's shape
  4329 // and the holder's shape.
  4330 class ICGetProp_NativePrototype : public ICGetPropNativeStub
  4332     friend class ICStubSpace;
  4334   protected:
  4335     // Holder and its shape.
  4336     HeapPtrObject holder_;
  4337     HeapPtrShape holderShape_;
  4339     ICGetProp_NativePrototype(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape,
  4340                               uint32_t offset, HandleObject holder, HandleShape holderShape);
  4342   public:
  4343     static inline ICGetProp_NativePrototype *New(ICStubSpace *space, JitCode *code,
  4344                                                  ICStub *firstMonitorStub, HandleShape shape,
  4345                                                  uint32_t offset, HandleObject holder,
  4346                                                  HandleShape holderShape)
  4348         if (!code)
  4349             return nullptr;
  4350         return space->allocate<ICGetProp_NativePrototype>(code, firstMonitorStub, shape, offset,
  4351                                                           holder, holderShape);
  4354   public:
  4355     HeapPtrObject &holder() {
  4356         return holder_;
  4358     HeapPtrShape &holderShape() {
  4359         return holderShape_;
  4361     static size_t offsetOfHolder() {
  4362         return offsetof(ICGetProp_NativePrototype, holder_);
  4364     static size_t offsetOfHolderShape() {
  4365         return offsetof(ICGetProp_NativePrototype, holderShape_);
  4367 };
  4370 // Compiler for GetProp_Native and GetProp_NativePrototype stubs.
  4371 class ICGetPropNativeCompiler : public ICStubCompiler
  4373     bool isCallProp_;
  4374     ICStub *firstMonitorStub_;
  4375     HandleObject obj_;
  4376     HandleObject holder_;
  4377     HandlePropertyName propName_;
  4378     bool isFixedSlot_;
  4379     uint32_t offset_;
  4381     bool generateStubCode(MacroAssembler &masm);
  4383   protected:
  4384     virtual int32_t getKey() const {
  4385 #if JS_HAS_NO_SUCH_METHOD
  4386         return static_cast<int32_t>(kind) |
  4387                (static_cast<int32_t>(isCallProp_) << 16) |
  4388                (static_cast<int32_t>(isFixedSlot_) << 17);
  4389 #else
  4390         return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16);
  4391 #endif
  4394   public:
  4395     ICGetPropNativeCompiler(JSContext *cx, ICStub::Kind kind, bool isCallProp,
  4396                             ICStub *firstMonitorStub, HandleObject obj, HandleObject holder,
  4397                             HandlePropertyName propName, bool isFixedSlot, uint32_t offset)
  4398       : ICStubCompiler(cx, kind),
  4399         isCallProp_(isCallProp),
  4400         firstMonitorStub_(firstMonitorStub),
  4401         obj_(obj),
  4402         holder_(holder),
  4403         propName_(propName),
  4404         isFixedSlot_(isFixedSlot),
  4405         offset_(offset)
  4406     {}
  4408     ICStub *getStub(ICStubSpace *space) {
  4409         RootedShape shape(cx, obj_->lastProperty());
  4410         if (kind == ICStub::GetProp_Native) {
  4411             JS_ASSERT(obj_ == holder_);
  4412             return ICGetProp_Native::New(space, getStubCode(), firstMonitorStub_, shape, offset_);
  4415         JS_ASSERT(obj_ != holder_);
  4416         JS_ASSERT(kind == ICStub::GetProp_NativePrototype);
  4417         RootedShape holderShape(cx, holder_->lastProperty());
  4418         return ICGetProp_NativePrototype::New(space, getStubCode(), firstMonitorStub_, shape,
  4419                                               offset_, holder_, holderShape);
  4421 };
  4423 class ICGetPropCallGetter : public ICMonitoredStub
  4425     friend class ICStubSpace;
  4427   protected:
  4428     // We don't strictly need this for own property getters, but we need it to do
  4429     // Ion optimizations, so we should keep it around.
  4430     HeapPtrObject holder_;
  4432     HeapPtrShape holderShape_;
  4434     // Function to call.
  4435     HeapPtrFunction getter_;
  4437     // PC offset of call
  4438     uint32_t pcOffset_;
  4440     ICGetPropCallGetter(Kind kind, JitCode *stubCode, ICStub *firstMonitorStub, HandleObject holder,
  4441                         HandleShape holderShape, HandleFunction getter, uint32_t pcOffset);
  4443   public:
  4444     HeapPtrObject &holder() {
  4445         return holder_;
  4447     HeapPtrShape &holderShape() {
  4448         return holderShape_;
  4450     HeapPtrFunction &getter() {
  4451         return getter_;
  4454     static size_t offsetOfHolder() {
  4455         return offsetof(ICGetPropCallGetter, holder_);
  4457     static size_t offsetOfHolderShape() {
  4458         return offsetof(ICGetPropCallGetter, holderShape_);
  4460     static size_t offsetOfGetter() {
  4461         return offsetof(ICGetPropCallGetter, getter_);
  4463     static size_t offsetOfPCOffset() {
  4464         return offsetof(ICGetPropCallGetter, pcOffset_);
  4467     class Compiler : public ICStubCompiler {
  4468       protected:
  4469         ICStub *firstMonitorStub_;
  4470         RootedObject holder_;
  4471         RootedFunction getter_;
  4472         uint32_t pcOffset_;
  4474       public:
  4475         Compiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
  4476                  HandleObject holder, HandleFunction getter, uint32_t pcOffset)
  4477           : ICStubCompiler(cx, kind),
  4478             firstMonitorStub_(firstMonitorStub),
  4479             holder_(cx, holder),
  4480             getter_(cx, getter),
  4481             pcOffset_(pcOffset)
  4483             JS_ASSERT(kind == ICStub::GetProp_CallScripted ||
  4484                       kind == ICStub::GetProp_CallNative ||
  4485                       kind == ICStub::GetProp_CallNativePrototype);
  4487     };
  4488 };
  4490 // Stub for calling a getter (native or scripted) on a native object when the getter is kept on
  4491 // the proto-chain.
  4492 class ICGetPropCallPrototypeGetter : public ICGetPropCallGetter
  4494     friend class ICStubSpace;
  4496   protected:
  4497     // shape of receiver object.
  4498     HeapPtrShape receiverShape_;
  4500     ICGetPropCallPrototypeGetter(Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  4501                                  HandleShape receiverShape,
  4502                                  HandleObject holder, HandleShape holderShape,
  4503                                  HandleFunction getter, uint32_t pcOffset);
  4505   public:
  4506     HeapPtrShape &receiverShape() {
  4507         return receiverShape_;
  4510     static size_t offsetOfReceiverShape() {
  4511         return offsetof(ICGetPropCallPrototypeGetter, receiverShape_);
  4514     class Compiler : public ICGetPropCallGetter::Compiler {
  4515       protected:
  4516         RootedObject receiver_;
  4518       public:
  4519         Compiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
  4520                  HandleObject obj, HandleObject holder, HandleFunction getter, uint32_t pcOffset)
  4521           : ICGetPropCallGetter::Compiler(cx, kind, firstMonitorStub, holder, getter, pcOffset),
  4522             receiver_(cx, obj)
  4524             JS_ASSERT(kind == ICStub::GetProp_CallScripted ||
  4525                       kind == ICStub::GetProp_CallNativePrototype);
  4527     };
  4528 };
  4530 // Stub for calling a scripted getter on a native object when the getter is kept on the
  4531 // proto-chain.
  4532 class ICGetProp_CallScripted : public ICGetPropCallPrototypeGetter
  4534     friend class ICStubSpace;
  4536   protected:
  4537     ICGetProp_CallScripted(JitCode *stubCode, ICStub *firstMonitorStub,
  4538                            HandleShape receiverShape, HandleObject holder, HandleShape holderShape,
  4539                            HandleFunction getter, uint32_t pcOffset)
  4540       : ICGetPropCallPrototypeGetter(GetProp_CallScripted, stubCode, firstMonitorStub,
  4541                                      receiverShape, holder, holderShape, getter, pcOffset)
  4542     {}
  4544   public:
  4545     static inline ICGetProp_CallScripted *New(
  4546                 ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  4547                 HandleShape receiverShape, HandleObject holder, HandleShape holderShape,
  4548                 HandleFunction getter, uint32_t pcOffset)
  4550         if (!code)
  4551             return nullptr;
  4552         return space->allocate<ICGetProp_CallScripted>(code, firstMonitorStub,
  4553                                                        receiverShape, holder, holderShape, getter,
  4554                                                        pcOffset);
  4557     class Compiler : public ICGetPropCallPrototypeGetter::Compiler {
  4558       protected:
  4559         bool generateStubCode(MacroAssembler &masm);
  4561       public:
  4562         Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
  4563                  HandleObject holder, HandleFunction getter, uint32_t pcOffset)
  4564           : ICGetPropCallPrototypeGetter::Compiler(cx, ICStub::GetProp_CallScripted,
  4565                                                    firstMonitorStub, obj, holder,
  4566                                                    getter, pcOffset)
  4567         {}
  4569         ICStub *getStub(ICStubSpace *space) {
  4570             RootedShape receiverShape(cx, receiver_->lastProperty());
  4571             RootedShape holderShape(cx, holder_->lastProperty());
  4572             return ICGetProp_CallScripted::New(space, getStubCode(), firstMonitorStub_, receiverShape,
  4573                                                holder_, holderShape, getter_, pcOffset_);
  4575     };
  4576 };
  4578 // Stub for calling an own native getter on a native object.
  4579 class ICGetProp_CallNative : public ICGetPropCallGetter
  4581     friend class ICStubSpace;
  4583   protected:
  4585     ICGetProp_CallNative(JitCode *stubCode, ICStub *firstMonitorStub, HandleObject obj,
  4586                             HandleShape shape, HandleFunction getter, uint32_t pcOffset)
  4587       : ICGetPropCallGetter(GetProp_CallNative, stubCode, firstMonitorStub, obj, shape,
  4588                             getter, pcOffset)
  4589     { }
  4591   public:
  4592     static inline ICGetProp_CallNative *New(ICStubSpace *space, JitCode *code,
  4593                                             ICStub *firstMonitorStub, HandleObject obj,
  4594                                             HandleShape shape, HandleFunction getter,
  4595                                             uint32_t pcOffset)
  4597         if (!code)
  4598             return nullptr;
  4599         return space->allocate<ICGetProp_CallNative>(code, firstMonitorStub, obj, shape,
  4600                                                      getter, pcOffset);
  4603     class Compiler : public ICGetPropCallGetter::Compiler
  4605         bool inputDefinitelyObject_;
  4606       protected:
  4607         bool generateStubCode(MacroAssembler &masm);
  4609         virtual int32_t getKey() const {
  4610             return static_cast<int32_t>(kind) |
  4611                    (static_cast<int32_t>(inputDefinitelyObject_) << 16);
  4614       public:
  4615         Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
  4616                  HandleFunction getter, uint32_t pcOffset, bool inputDefinitelyObject = false)
  4617           : ICGetPropCallGetter::Compiler(cx, ICStub::GetProp_CallNative, firstMonitorStub,
  4618                                           obj, getter, pcOffset),
  4619             inputDefinitelyObject_(inputDefinitelyObject)
  4620         {}
  4622         ICStub *getStub(ICStubSpace *space) {
  4623             RootedShape shape(cx, holder_->lastProperty());
  4624             return ICGetProp_CallNative::New(space, getStubCode(), firstMonitorStub_, holder_,
  4625                                              shape, getter_, pcOffset_);
  4627     };
  4628 };
  4630 // Stub for calling an native getter on a native object when the getter is kept on the proto-chain.
  4631 class ICGetProp_CallNativePrototype : public ICGetPropCallPrototypeGetter
  4633     friend class ICStubSpace;
  4635   protected:
  4636     ICGetProp_CallNativePrototype(JitCode *stubCode, ICStub *firstMonitorStub,
  4637                          HandleShape receiverShape, HandleObject holder, HandleShape holderShape,
  4638                          HandleFunction getter, uint32_t pcOffset)
  4639       : ICGetPropCallPrototypeGetter(GetProp_CallNativePrototype, stubCode, firstMonitorStub,
  4640                                      receiverShape, holder, holderShape, getter, pcOffset)
  4641     {}
  4643   public:
  4644     static inline ICGetProp_CallNativePrototype *New(
  4645                 ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  4646                 HandleShape receiverShape, HandleObject holder, HandleShape holderShape,
  4647                 HandleFunction getter, uint32_t pcOffset)
  4649         if (!code)
  4650             return nullptr;
  4651         return space->allocate<ICGetProp_CallNativePrototype>(code, firstMonitorStub,
  4652                                                               receiverShape, holder, holderShape,
  4653                                                               getter, pcOffset);
  4656     class Compiler : public ICGetPropCallPrototypeGetter::Compiler {
  4657       protected:
  4658         bool generateStubCode(MacroAssembler &masm);
  4660       public:
  4661         Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
  4662                  HandleObject holder, HandleFunction getter, uint32_t pcOffset)
  4663           : ICGetPropCallPrototypeGetter::Compiler(cx, ICStub::GetProp_CallNativePrototype,
  4664                                                    firstMonitorStub, obj, holder,
  4665                                                    getter, pcOffset)
  4666         {}
  4668         ICStub *getStub(ICStubSpace *space) {
  4669             RootedShape receiverShape(cx, receiver_->lastProperty());
  4670             RootedShape holderShape(cx, holder_->lastProperty());
  4671             return ICGetProp_CallNativePrototype::New(space, getStubCode(), firstMonitorStub_, receiverShape,
  4672                                                       holder_, holderShape, getter_, pcOffset_);
  4674     };
  4675 };
  4677 class ICGetPropCallDOMProxyNativeStub : public ICMonitoredStub
  4679   friend class ICStubSpace;
  4680   protected:
  4681     // Shape of the DOMProxy
  4682     HeapPtrShape shape_;
  4684     // Proxy handler to check against.
  4685     BaseProxyHandler *proxyHandler_;
  4687     // Object shape of expected expando object. (nullptr if no expando object should be there)
  4688     HeapPtrShape expandoShape_;
  4690     // Holder and its shape.
  4691     HeapPtrObject holder_;
  4692     HeapPtrShape holderShape_;
  4694     // Function to call.
  4695     HeapPtrFunction getter_;
  4697     // PC offset of call
  4698     uint32_t pcOffset_;
  4700     ICGetPropCallDOMProxyNativeStub(ICStub::Kind kind, JitCode *stubCode,
  4701                                     ICStub *firstMonitorStub, HandleShape shape,
  4702                                     BaseProxyHandler *proxyHandler, HandleShape expandoShape,
  4703                                     HandleObject holder, HandleShape holderShape,
  4704                                     HandleFunction getter, uint32_t pcOffset);
  4706   public:
  4707     HeapPtrShape &shape() {
  4708         return shape_;
  4710     HeapPtrShape &expandoShape() {
  4711         return expandoShape_;
  4713     HeapPtrObject &holder() {
  4714         return holder_;
  4716     HeapPtrShape &holderShape() {
  4717         return holderShape_;
  4719     HeapPtrFunction &getter() {
  4720         return getter_;
  4722     uint32_t pcOffset() const {
  4723         return pcOffset_;
  4726     static size_t offsetOfShape() {
  4727         return offsetof(ICGetPropCallDOMProxyNativeStub, shape_);
  4729     static size_t offsetOfProxyHandler() {
  4730         return offsetof(ICGetPropCallDOMProxyNativeStub, proxyHandler_);
  4732     static size_t offsetOfExpandoShape() {
  4733         return offsetof(ICGetPropCallDOMProxyNativeStub, expandoShape_);
  4735     static size_t offsetOfHolder() {
  4736         return offsetof(ICGetPropCallDOMProxyNativeStub, holder_);
  4738     static size_t offsetOfHolderShape() {
  4739         return offsetof(ICGetPropCallDOMProxyNativeStub, holderShape_);
  4741     static size_t offsetOfGetter() {
  4742         return offsetof(ICGetPropCallDOMProxyNativeStub, getter_);
  4744     static size_t offsetOfPCOffset() {
  4745         return offsetof(ICGetPropCallDOMProxyNativeStub, pcOffset_);
  4747 };
  4749 class ICGetProp_CallDOMProxyNative : public ICGetPropCallDOMProxyNativeStub
  4751     friend class ICStubSpace;
  4752     ICGetProp_CallDOMProxyNative(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape,
  4753                                  BaseProxyHandler *proxyHandler, HandleShape expandoShape,
  4754                                  HandleObject holder, HandleShape holderShape,
  4755                                  HandleFunction getter, uint32_t pcOffset)
  4756       : ICGetPropCallDOMProxyNativeStub(ICStub::GetProp_CallDOMProxyNative, stubCode,
  4757                                         firstMonitorStub, shape, proxyHandler, expandoShape,
  4758                                         holder, holderShape, getter, pcOffset)
  4759     {}
  4761   public:
  4762     static inline ICGetProp_CallDOMProxyNative *New(
  4763             ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  4764             HandleShape shape, BaseProxyHandler *proxyHandler,
  4765             HandleShape expandoShape, HandleObject holder, HandleShape holderShape,
  4766             HandleFunction getter, uint32_t pcOffset)
  4768         if (!code)
  4769             return nullptr;
  4770         return space->allocate<ICGetProp_CallDOMProxyNative>(code, firstMonitorStub, shape,
  4771                                                    proxyHandler, expandoShape, holder,
  4772                                                    holderShape, getter, pcOffset);
  4774 };
  4776 class ICGetProp_CallDOMProxyWithGenerationNative : public ICGetPropCallDOMProxyNativeStub
  4778   protected:
  4779     ExpandoAndGeneration *expandoAndGeneration_;
  4780     uint32_t generation_;
  4782   public:
  4783     ICGetProp_CallDOMProxyWithGenerationNative(JitCode *stubCode, ICStub *firstMonitorStub,
  4784                                                HandleShape shape, BaseProxyHandler *proxyHandler,
  4785                                                ExpandoAndGeneration *expandoAndGeneration,
  4786                                                uint32_t generation, HandleShape expandoShape,
  4787                                                HandleObject holder, HandleShape holderShape,
  4788                                                HandleFunction getter, uint32_t pcOffset)
  4789       : ICGetPropCallDOMProxyNativeStub(ICStub::GetProp_CallDOMProxyWithGenerationNative,
  4790                                         stubCode, firstMonitorStub, shape, proxyHandler,
  4791                                         expandoShape, holder, holderShape, getter, pcOffset),
  4792         expandoAndGeneration_(expandoAndGeneration),
  4793         generation_(generation)
  4797     static inline ICGetProp_CallDOMProxyWithGenerationNative *New(
  4798             ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  4799             HandleShape shape, BaseProxyHandler *proxyHandler,
  4800             ExpandoAndGeneration *expandoAndGeneration, uint32_t generation,
  4801             HandleShape expandoShape, HandleObject holder, HandleShape holderShape,
  4802             HandleFunction getter, uint32_t pcOffset)
  4804         if (!code)
  4805             return nullptr;
  4806         return space->allocate<ICGetProp_CallDOMProxyWithGenerationNative>(code, firstMonitorStub,
  4807                                                    shape, proxyHandler, expandoAndGeneration,
  4808                                                    generation, expandoShape, holder, holderShape,
  4809                                                    getter, pcOffset);
  4812     void *expandoAndGeneration() const {
  4813         return expandoAndGeneration_;
  4815     uint32_t generation() const {
  4816         return generation_;
  4819     void setGeneration(uint32_t value) {
  4820         generation_ = value;
  4823     static size_t offsetOfInternalStruct() {
  4824         return offsetof(ICGetProp_CallDOMProxyWithGenerationNative, expandoAndGeneration_);
  4826     static size_t offsetOfGeneration() {
  4827         return offsetof(ICGetProp_CallDOMProxyWithGenerationNative, generation_);
  4829 };
  4831 class ICGetPropCallDOMProxyNativeCompiler : public ICStubCompiler {
  4832     ICStub *firstMonitorStub_;
  4833     Rooted<ProxyObject*> proxy_;
  4834     RootedObject holder_;
  4835     RootedFunction getter_;
  4836     uint32_t pcOffset_;
  4838     bool generateStubCode(MacroAssembler &masm, Address* internalStructAddr,
  4839                           Address* generationAddr);
  4840     bool generateStubCode(MacroAssembler &masm);
  4842   public:
  4843     ICGetPropCallDOMProxyNativeCompiler(JSContext *cx, ICStub::Kind kind,
  4844                                         ICStub *firstMonitorStub, Handle<ProxyObject*> proxy,
  4845                                         HandleObject holder, HandleFunction getter,
  4846                                         uint32_t pcOffset);
  4848     ICStub *getStub(ICStubSpace *space);
  4849 };
  4851 class ICGetProp_DOMProxyShadowed : public ICMonitoredStub
  4853   friend class ICStubSpace;
  4854   protected:
  4855     HeapPtrShape shape_;
  4856     BaseProxyHandler *proxyHandler_;
  4857     HeapPtrPropertyName name_;
  4858     uint32_t pcOffset_;
  4860     ICGetProp_DOMProxyShadowed(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape,
  4861                                BaseProxyHandler *proxyHandler, HandlePropertyName name,
  4862                                uint32_t pcOffset);
  4864   public:
  4865     static inline ICGetProp_DOMProxyShadowed *New(ICStubSpace *space, JitCode *code,
  4866                                                   ICStub *firstMonitorStub, HandleShape shape,
  4867                                                   BaseProxyHandler *proxyHandler,
  4868                                                   HandlePropertyName name, uint32_t pcOffset)
  4870         if (!code)
  4871             return nullptr;
  4872         return space->allocate<ICGetProp_DOMProxyShadowed>(code, firstMonitorStub, shape,
  4873                                                            proxyHandler, name, pcOffset);
  4876     HeapPtrShape &shape() {
  4877         return shape_;
  4879     HeapPtrPropertyName &name() {
  4880         return name_;
  4883     static size_t offsetOfShape() {
  4884         return offsetof(ICGetProp_DOMProxyShadowed, shape_);
  4886     static size_t offsetOfProxyHandler() {
  4887         return offsetof(ICGetProp_DOMProxyShadowed, proxyHandler_);
  4889     static size_t offsetOfName() {
  4890         return offsetof(ICGetProp_DOMProxyShadowed, name_);
  4892     static size_t offsetOfPCOffset() {
  4893         return offsetof(ICGetProp_DOMProxyShadowed, pcOffset_);
  4896     class Compiler : public ICStubCompiler {
  4897         ICStub *firstMonitorStub_;
  4898         Rooted<ProxyObject*> proxy_;
  4899         RootedPropertyName name_;
  4900         uint32_t pcOffset_;
  4902         bool generateStubCode(MacroAssembler &masm);
  4904       public:
  4905         Compiler(JSContext *cx, ICStub *firstMonitorStub, Handle<ProxyObject*> proxy,
  4906                  HandlePropertyName name, uint32_t pcOffset)
  4907           : ICStubCompiler(cx, ICStub::GetProp_CallNative),
  4908             firstMonitorStub_(firstMonitorStub),
  4909             proxy_(cx, proxy),
  4910             name_(cx, name),
  4911             pcOffset_(pcOffset)
  4912         {}
  4914         ICStub *getStub(ICStubSpace *space);
  4915     };
  4916 };
  4918 class ICGetProp_ArgumentsLength : public ICStub
  4920   friend class ICStubSpace;
  4921   public:
  4922     enum Which { Normal, Strict, Magic };
  4924   protected:
  4925     ICGetProp_ArgumentsLength(JitCode *stubCode)
  4926       : ICStub(ICStub::GetProp_ArgumentsLength, stubCode)
  4927     { }
  4929   public:
  4930     static inline ICGetProp_ArgumentsLength *New(ICStubSpace *space, JitCode *code)
  4932         if (!code)
  4933             return nullptr;
  4934         return space->allocate<ICGetProp_ArgumentsLength>(code);
  4937     class Compiler : public ICStubCompiler {
  4938       protected:
  4939         Which which_;
  4941         bool generateStubCode(MacroAssembler &masm);
  4943         virtual int32_t getKey() const {
  4944             return static_cast<int32_t>(kind) | (static_cast<int32_t>(which_) << 16);
  4947       public:
  4948         Compiler(JSContext *cx, Which which)
  4949           : ICStubCompiler(cx, ICStub::GetProp_ArgumentsLength),
  4950             which_(which)
  4951         {}
  4953         ICStub *getStub(ICStubSpace *space) {
  4954             return ICGetProp_ArgumentsLength::New(space, getStubCode());
  4956     };
  4957 };
  4959 // SetProp
  4960 //     JSOP_SETPROP
  4961 //     JSOP_SETNAME
  4962 //     JSOP_SETGNAME
  4963 //     JSOP_INITPROP
  4965 class ICSetProp_Fallback : public ICFallbackStub
  4967     friend class ICStubSpace;
  4969     ICSetProp_Fallback(JitCode *stubCode)
  4970       : ICFallbackStub(ICStub::SetProp_Fallback, stubCode)
  4971     { }
  4973   public:
  4974     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  4976     static inline ICSetProp_Fallback *New(ICStubSpace *space, JitCode *code) {
  4977         if (!code)
  4978             return nullptr;
  4979         return space->allocate<ICSetProp_Fallback>(code);
  4982     static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
  4983     void noteUnoptimizableAccess() {
  4984         extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
  4986     bool hadUnoptimizableAccess() const {
  4987         return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
  4990     class Compiler : public ICStubCompiler {
  4991       protected:
  4992         uint32_t returnFromIonOffset_;
  4993         uint32_t returnFromStubOffset_;
  4994         bool generateStubCode(MacroAssembler &masm);
  4995         bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> code);
  4997       public:
  4998         Compiler(JSContext *cx)
  4999           : ICStubCompiler(cx, ICStub::SetProp_Fallback)
  5000         { }
  5002         ICStub *getStub(ICStubSpace *space) {
  5003             return ICSetProp_Fallback::New(space, getStubCode());
  5005     };
  5006 };
  5008 // Optimized SETPROP/SETGNAME/SETNAME stub.
  5009 class ICSetProp_Native : public ICUpdatedStub
  5011     friend class ICStubSpace;
  5013   protected: // Protected to silence Clang warning.
  5014     HeapPtrTypeObject type_;
  5015     HeapPtrShape shape_;
  5016     uint32_t offset_;
  5018     ICSetProp_Native(JitCode *stubCode, HandleTypeObject type, HandleShape shape, uint32_t offset);
  5020   public:
  5021     static inline ICSetProp_Native *New(ICStubSpace *space, JitCode *code, HandleTypeObject type,
  5022                                         HandleShape shape, uint32_t offset)
  5024         if (!code)
  5025             return nullptr;
  5026         return space->allocate<ICSetProp_Native>(code, type, shape, offset);
  5028     HeapPtrTypeObject &type() {
  5029         return type_;
  5031     HeapPtrShape &shape() {
  5032         return shape_;
  5034     static size_t offsetOfType() {
  5035         return offsetof(ICSetProp_Native, type_);
  5037     static size_t offsetOfShape() {
  5038         return offsetof(ICSetProp_Native, shape_);
  5040     static size_t offsetOfOffset() {
  5041         return offsetof(ICSetProp_Native, offset_);
  5044     class Compiler : public ICStubCompiler {
  5045         RootedObject obj_;
  5046         bool isFixedSlot_;
  5047         uint32_t offset_;
  5049       protected:
  5050         virtual int32_t getKey() const {
  5051             return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16);
  5054         bool generateStubCode(MacroAssembler &masm);
  5056       public:
  5057         Compiler(JSContext *cx, HandleObject obj, bool isFixedSlot, uint32_t offset)
  5058           : ICStubCompiler(cx, ICStub::SetProp_Native),
  5059             obj_(cx, obj),
  5060             isFixedSlot_(isFixedSlot),
  5061             offset_(offset)
  5062         {}
  5064         ICUpdatedStub *getStub(ICStubSpace *space);
  5065     };
  5066 };
  5069 template <size_t ProtoChainDepth> class ICSetProp_NativeAddImpl;
  5071 class ICSetProp_NativeAdd : public ICUpdatedStub
  5073   public:
  5074     static const size_t MAX_PROTO_CHAIN_DEPTH = 4;
  5076   protected: // Protected to silence Clang warning.
  5077     HeapPtrTypeObject type_;
  5078     HeapPtrShape newShape_;
  5079     uint32_t offset_;
  5081     ICSetProp_NativeAdd(JitCode *stubCode, HandleTypeObject type, size_t protoChainDepth,
  5082                         HandleShape newShape, uint32_t offset);
  5084   public:
  5085     size_t protoChainDepth() const {
  5086         return extra_;
  5088     HeapPtrTypeObject &type() {
  5089         return type_;
  5091     HeapPtrShape &newShape() {
  5092         return newShape_;
  5095     template <size_t ProtoChainDepth>
  5096     ICSetProp_NativeAddImpl<ProtoChainDepth> *toImpl() {
  5097         JS_ASSERT(ProtoChainDepth == protoChainDepth());
  5098         return static_cast<ICSetProp_NativeAddImpl<ProtoChainDepth> *>(this);
  5101     static size_t offsetOfType() {
  5102         return offsetof(ICSetProp_NativeAdd, type_);
  5104     static size_t offsetOfNewShape() {
  5105         return offsetof(ICSetProp_NativeAdd, newShape_);
  5107     static size_t offsetOfOffset() {
  5108         return offsetof(ICSetProp_NativeAdd, offset_);
  5110 };
  5112 template <size_t ProtoChainDepth>
  5113 class ICSetProp_NativeAddImpl : public ICSetProp_NativeAdd
  5115     friend class ICStubSpace;
  5117     static const size_t NumShapes = ProtoChainDepth + 1;
  5118     mozilla::Array<HeapPtrShape, NumShapes> shapes_;
  5120     ICSetProp_NativeAddImpl(JitCode *stubCode, HandleTypeObject type,
  5121                             const AutoShapeVector *shapes,
  5122                             HandleShape newShape, uint32_t offset);
  5124   public:
  5125     static inline ICSetProp_NativeAddImpl *New(
  5126             ICStubSpace *space, JitCode *code, HandleTypeObject type,
  5127             const AutoShapeVector *shapes, HandleShape newShape, uint32_t offset)
  5129         if (!code)
  5130             return nullptr;
  5131         return space->allocate<ICSetProp_NativeAddImpl<ProtoChainDepth> >(
  5132                             code, type, shapes, newShape, offset);
  5135     void traceShapes(JSTracer *trc) {
  5136         for (size_t i = 0; i < NumShapes; i++)
  5137             MarkShape(trc, &shapes_[i], "baseline-setpropnativeadd-stub-shape");
  5140     static size_t offsetOfShape(size_t idx) {
  5141         return offsetof(ICSetProp_NativeAddImpl, shapes_) + (idx * sizeof(HeapPtrShape));
  5143 };
  5145 class ICSetPropNativeAddCompiler : public ICStubCompiler {
  5146     RootedObject obj_;
  5147     RootedShape oldShape_;
  5148     size_t protoChainDepth_;
  5149     bool isFixedSlot_;
  5150     uint32_t offset_;
  5152   protected:
  5153     virtual int32_t getKey() const {
  5154         return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16) |
  5155                (static_cast<int32_t>(protoChainDepth_) << 20);
  5158     bool generateStubCode(MacroAssembler &masm);
  5160   public:
  5161     ICSetPropNativeAddCompiler(JSContext *cx, HandleObject obj, HandleShape oldShape,
  5162                                size_t protoChainDepth, bool isFixedSlot, uint32_t offset);
  5164     template <size_t ProtoChainDepth>
  5165     ICUpdatedStub *getStubSpecific(ICStubSpace *space, const AutoShapeVector *shapes)
  5167         RootedTypeObject type(cx, obj_->getType(cx));
  5168         if (!type)
  5169             return nullptr;
  5171         RootedShape newShape(cx, obj_->lastProperty());
  5173         return ICSetProp_NativeAddImpl<ProtoChainDepth>::New(
  5174                     space, getStubCode(), type, shapes, newShape, offset_);
  5177     ICUpdatedStub *getStub(ICStubSpace *space);
  5178 };
  5180 // Base stub for calling a setters on a native object.
  5181 class ICSetPropCallSetter : public ICStub
  5183     friend class ICStubSpace;
  5185   protected:
  5186     // Object shape (lastProperty).
  5187     HeapPtrShape shape_;
  5189     // Holder and shape.
  5190     HeapPtrObject holder_;
  5191     HeapPtrShape holderShape_;
  5193     // Function to call.
  5194     HeapPtrFunction setter_;
  5196     // PC of call, for profiler
  5197     uint32_t pcOffset_;
  5199     ICSetPropCallSetter(Kind kind, JitCode *stubCode, HandleShape shape, HandleObject holder,
  5200                         HandleShape holderShape, HandleFunction setter, uint32_t pcOffset);
  5202   public:
  5203     HeapPtrShape &shape() {
  5204         return shape_;
  5206     HeapPtrObject &holder() {
  5207         return holder_;
  5209     HeapPtrShape &holderShape() {
  5210         return holderShape_;
  5212     HeapPtrFunction &setter() {
  5213         return setter_;
  5216     static size_t offsetOfShape() {
  5217         return offsetof(ICSetPropCallSetter, shape_);
  5219     static size_t offsetOfHolder() {
  5220         return offsetof(ICSetPropCallSetter, holder_);
  5222     static size_t offsetOfHolderShape() {
  5223         return offsetof(ICSetPropCallSetter, holderShape_);
  5225     static size_t offsetOfSetter() {
  5226         return offsetof(ICSetPropCallSetter, setter_);
  5228     static size_t offsetOfPCOffset() {
  5229         return offsetof(ICSetPropCallSetter, pcOffset_);
  5232     class Compiler : public ICStubCompiler {
  5233       protected:
  5234         RootedObject obj_;
  5235         RootedObject holder_;
  5236         RootedFunction setter_;
  5237         uint32_t pcOffset_;
  5239       public:
  5240         Compiler(JSContext *cx, ICStub::Kind kind, HandleObject obj, HandleObject holder,
  5241                  HandleFunction setter, uint32_t pcOffset)
  5242           : ICStubCompiler(cx, kind),
  5243             obj_(cx, obj),
  5244             holder_(cx, holder),
  5245             setter_(cx, setter),
  5246             pcOffset_(pcOffset)
  5248             JS_ASSERT(kind == ICStub::SetProp_CallScripted || kind == ICStub::SetProp_CallNative);
  5250     };
  5251 };
  5253 // Stub for calling a scripted setter on a native object.
  5254 class ICSetProp_CallScripted : public ICSetPropCallSetter
  5256     friend class ICStubSpace;
  5258   protected:
  5259     ICSetProp_CallScripted(JitCode *stubCode, HandleShape shape, HandleObject holder,
  5260                            HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
  5261       : ICSetPropCallSetter(SetProp_CallScripted, stubCode, shape, holder, holderShape,
  5262                             setter, pcOffset)
  5263     {}
  5265   public:
  5266     static inline ICSetProp_CallScripted *New(ICStubSpace *space, JitCode *code,
  5267                                               HandleShape shape, HandleObject holder,
  5268                                               HandleShape holderShape, HandleFunction setter,
  5269                                               uint32_t pcOffset)
  5271         if (!code)
  5272             return nullptr;
  5273         return space->allocate<ICSetProp_CallScripted>(code, shape, holder, holderShape, setter,
  5274                                                        pcOffset);
  5277     class Compiler : public ICSetPropCallSetter::Compiler {
  5278       protected:
  5279         bool generateStubCode(MacroAssembler &masm);
  5281       public:
  5282         Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter,
  5283                  uint32_t pcOffset)
  5284           : ICSetPropCallSetter::Compiler(cx, ICStub::SetProp_CallScripted,
  5285                                           obj, holder, setter, pcOffset)
  5286         {}
  5288         ICStub *getStub(ICStubSpace *space) {
  5289             RootedShape shape(cx, obj_->lastProperty());
  5290             RootedShape holderShape(cx, holder_->lastProperty());
  5291             return ICSetProp_CallScripted::New(space, getStubCode(), shape, holder_, holderShape,
  5292                                                setter_, pcOffset_);
  5294     };
  5295 };
  5297 // Stub for calling a native setter on a native object.
  5298 class ICSetProp_CallNative : public ICSetPropCallSetter
  5300     friend class ICStubSpace;
  5302   protected:
  5303     ICSetProp_CallNative(JitCode *stubCode, HandleShape shape, HandleObject holder,
  5304                            HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
  5305       : ICSetPropCallSetter(SetProp_CallNative, stubCode, shape, holder, holderShape,
  5306                             setter, pcOffset)
  5307     {}
  5309   public:
  5310     static inline ICSetProp_CallNative *New(ICStubSpace *space, JitCode *code,
  5311                                             HandleShape shape, HandleObject holder,
  5312                                             HandleShape holderShape, HandleFunction setter,
  5313                                             uint32_t pcOffset)
  5315         if (!code)
  5316             return nullptr;
  5317         return space->allocate<ICSetProp_CallNative>(code, shape, holder, holderShape, setter,
  5318                                                      pcOffset);
  5321     class Compiler : public ICSetPropCallSetter::Compiler {
  5322       protected:
  5323         bool generateStubCode(MacroAssembler &masm);
  5325       public:
  5326         Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter,
  5327                  uint32_t pcOffset)
  5328           : ICSetPropCallSetter::Compiler(cx, ICStub::SetProp_CallNative,
  5329                                           obj, holder, setter, pcOffset)
  5330         {}
  5332         ICStub *getStub(ICStubSpace *space) {
  5333             RootedShape shape(cx, obj_->lastProperty());
  5334             RootedShape holderShape(cx, holder_->lastProperty());
  5335             return ICSetProp_CallNative::New(space, getStubCode(), shape, holder_, holderShape,
  5336                                                setter_, pcOffset_);
  5338     };
  5339 };
  5341 // Call
  5342 //      JSOP_CALL
  5343 //      JSOP_FUNAPPLY
  5344 //      JSOP_FUNCALL
  5345 //      JSOP_NEW
  5347 class ICCallStubCompiler : public ICStubCompiler
  5349   protected:
  5350     ICCallStubCompiler(JSContext *cx, ICStub::Kind kind)
  5351       : ICStubCompiler(cx, kind)
  5352     { }
  5354     enum FunApplyThing {
  5355         FunApply_MagicArgs,
  5356         FunApply_Array
  5357     };
  5359     void pushCallArguments(MacroAssembler &masm, GeneralRegisterSet regs, Register argcReg);
  5360     Register guardFunApply(MacroAssembler &masm, GeneralRegisterSet regs, Register argcReg,
  5361                            bool checkNative, FunApplyThing applyThing, Label *failure);
  5362     void pushCallerArguments(MacroAssembler &masm, GeneralRegisterSet regs);
  5363     void pushArrayArguments(MacroAssembler &masm, Address arrayVal, GeneralRegisterSet regs);
  5364 };
  5366 class ICCall_Fallback : public ICMonitoredFallbackStub
  5368     friend class ICStubSpace;
  5369   public:
  5370     static const unsigned CONSTRUCTING_FLAG = 0x0001;
  5372     static const uint32_t MAX_OPTIMIZED_STUBS = 16;
  5373     static const uint32_t MAX_SCRIPTED_STUBS = 7;
  5374     static const uint32_t MAX_NATIVE_STUBS = 7;
  5375   private:
  5377     ICCall_Fallback(JitCode *stubCode, bool isConstructing)
  5378       : ICMonitoredFallbackStub(ICStub::Call_Fallback, stubCode)
  5380         extra_ = 0;
  5381         if (isConstructing)
  5382             extra_ |= CONSTRUCTING_FLAG;
  5385   public:
  5387     static inline ICCall_Fallback *New(ICStubSpace *space, JitCode *code, bool isConstructing)
  5389         if (!code)
  5390             return nullptr;
  5391         return space->allocate<ICCall_Fallback>(code, isConstructing);
  5394     bool isConstructing() const {
  5395         return extra_ & CONSTRUCTING_FLAG;
  5398     unsigned scriptedStubCount() const {
  5399         return numStubsWithKind(Call_Scripted);
  5401     bool scriptedStubsAreGeneralized() const {
  5402         return hasStub(Call_AnyScripted);
  5405     unsigned nativeStubCount() const {
  5406         return numStubsWithKind(Call_Native);
  5408     bool nativeStubsAreGeneralized() const {
  5409         // Return hasStub(Call_AnyNative) after Call_AnyNative stub is added.
  5410         return false;
  5413     // Compiler for this stub kind.
  5414     class Compiler : public ICCallStubCompiler {
  5415       protected:
  5416         bool isConstructing_;
  5417         uint32_t returnFromIonOffset_;
  5418         uint32_t returnFromStubOffset_;
  5419         bool generateStubCode(MacroAssembler &masm);
  5420         bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> code);
  5422       public:
  5423         Compiler(JSContext *cx, bool isConstructing)
  5424           : ICCallStubCompiler(cx, ICStub::Call_Fallback),
  5425             isConstructing_(isConstructing)
  5426         { }
  5428         ICStub *getStub(ICStubSpace *space) {
  5429             ICCall_Fallback *stub = ICCall_Fallback::New(space, getStubCode(), isConstructing_);
  5430             if (!stub || !stub->initMonitoringChain(cx, space))
  5431                 return nullptr;
  5432             return stub;
  5434     };
  5435 };
  5437 class ICCall_Scripted : public ICMonitoredStub
  5439     friend class ICStubSpace;
  5441   protected:
  5442     HeapPtrScript calleeScript_;
  5443     HeapPtrObject templateObject_;
  5444     uint32_t pcOffset_;
  5446     ICCall_Scripted(JitCode *stubCode, ICStub *firstMonitorStub,
  5447                     HandleScript calleeScript, HandleObject templateObject,
  5448                     uint32_t pcOffset);
  5450   public:
  5451     static inline ICCall_Scripted *New(
  5452             ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  5453             HandleScript calleeScript, HandleObject templateObject,
  5454             uint32_t pcOffset)
  5456         if (!code)
  5457             return nullptr;
  5458         return space->allocate<ICCall_Scripted>(code, firstMonitorStub,
  5459                                                 calleeScript, templateObject, pcOffset);
  5462     HeapPtrScript &calleeScript() {
  5463         return calleeScript_;
  5465     HeapPtrObject &templateObject() {
  5466         return templateObject_;
  5469     static size_t offsetOfCalleeScript() {
  5470         return offsetof(ICCall_Scripted, calleeScript_);
  5472     static size_t offsetOfPCOffset() {
  5473         return offsetof(ICCall_Scripted, pcOffset_);
  5475 };
  5477 class ICCall_AnyScripted : public ICMonitoredStub
  5479     friend class ICStubSpace;
  5481   protected:
  5482     uint32_t pcOffset_;
  5484     ICCall_AnyScripted(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset)
  5485       : ICMonitoredStub(ICStub::Call_AnyScripted, stubCode, firstMonitorStub),
  5486         pcOffset_(pcOffset)
  5487     { }
  5489   public:
  5490     static inline ICCall_AnyScripted *New(ICStubSpace *space, JitCode *code,
  5491                                           ICStub *firstMonitorStub, uint32_t pcOffset)
  5493         if (!code)
  5494             return nullptr;
  5495         return space->allocate<ICCall_AnyScripted>(code, firstMonitorStub, pcOffset);
  5498     static size_t offsetOfPCOffset() {
  5499         return offsetof(ICCall_AnyScripted, pcOffset_);
  5501 };
  5503 // Compiler for Call_Scripted and Call_AnyScripted stubs.
  5504 class ICCallScriptedCompiler : public ICCallStubCompiler {
  5505   protected:
  5506     ICStub *firstMonitorStub_;
  5507     bool isConstructing_;
  5508     RootedScript calleeScript_;
  5509     RootedObject templateObject_;
  5510     uint32_t pcOffset_;
  5511     bool generateStubCode(MacroAssembler &masm);
  5513     virtual int32_t getKey() const {
  5514         return static_cast<int32_t>(kind) | (static_cast<int32_t>(isConstructing_) << 16);
  5517   public:
  5518     ICCallScriptedCompiler(JSContext *cx, ICStub *firstMonitorStub,
  5519                            HandleScript calleeScript, HandleObject templateObject,
  5520                            bool isConstructing, uint32_t pcOffset)
  5521       : ICCallStubCompiler(cx, ICStub::Call_Scripted),
  5522         firstMonitorStub_(firstMonitorStub),
  5523         isConstructing_(isConstructing),
  5524         calleeScript_(cx, calleeScript),
  5525         templateObject_(cx, templateObject),
  5526         pcOffset_(pcOffset)
  5527     { }
  5529     ICCallScriptedCompiler(JSContext *cx, ICStub *firstMonitorStub, bool isConstructing,
  5530                            uint32_t pcOffset)
  5531       : ICCallStubCompiler(cx, ICStub::Call_AnyScripted),
  5532         firstMonitorStub_(firstMonitorStub),
  5533         isConstructing_(isConstructing),
  5534         calleeScript_(cx, nullptr),
  5535         templateObject_(cx, nullptr),
  5536         pcOffset_(pcOffset)
  5537     { }
  5539     ICStub *getStub(ICStubSpace *space) {
  5540         if (calleeScript_) {
  5541             return ICCall_Scripted::New(space, getStubCode(), firstMonitorStub_,
  5542                                         calleeScript_, templateObject_,
  5543                                         pcOffset_);
  5545         return ICCall_AnyScripted::New(space, getStubCode(), firstMonitorStub_, pcOffset_);
  5547 };
  5549 class ICCall_Native : public ICMonitoredStub
  5551     friend class ICStubSpace;
  5553   protected:
  5554     HeapPtrFunction callee_;
  5555     HeapPtrObject templateObject_;
  5556     uint32_t pcOffset_;
  5558 #ifdef JS_ARM_SIMULATOR
  5559     void *native_;
  5560 #endif
  5562     ICCall_Native(JitCode *stubCode, ICStub *firstMonitorStub,
  5563                   HandleFunction callee, HandleObject templateObject,
  5564                   uint32_t pcOffset);
  5566   public:
  5567     static inline ICCall_Native *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  5568                                      HandleFunction callee, HandleObject templateObject,
  5569                                      uint32_t pcOffset)
  5571         if (!code)
  5572             return nullptr;
  5573         return space->allocate<ICCall_Native>(code, firstMonitorStub,
  5574                                               callee, templateObject, pcOffset);
  5577     HeapPtrFunction &callee() {
  5578         return callee_;
  5580     HeapPtrObject &templateObject() {
  5581         return templateObject_;
  5584     static size_t offsetOfCallee() {
  5585         return offsetof(ICCall_Native, callee_);
  5587     static size_t offsetOfPCOffset() {
  5588         return offsetof(ICCall_Native, pcOffset_);
  5591 #ifdef JS_ARM_SIMULATOR
  5592     static size_t offsetOfNative() {
  5593         return offsetof(ICCall_Native, native_);
  5595 #endif
  5597     // Compiler for this stub kind.
  5598     class Compiler : public ICCallStubCompiler {
  5599       protected:
  5600         ICStub *firstMonitorStub_;
  5601         bool isConstructing_;
  5602         RootedFunction callee_;
  5603         RootedObject templateObject_;
  5604         uint32_t pcOffset_;
  5605         bool generateStubCode(MacroAssembler &masm);
  5607         virtual int32_t getKey() const {
  5608             return static_cast<int32_t>(kind) | (static_cast<int32_t>(isConstructing_) << 16);
  5611       public:
  5612         Compiler(JSContext *cx, ICStub *firstMonitorStub,
  5613                  HandleFunction callee, HandleObject templateObject,
  5614                  bool isConstructing, uint32_t pcOffset)
  5615           : ICCallStubCompiler(cx, ICStub::Call_Native),
  5616             firstMonitorStub_(firstMonitorStub),
  5617             isConstructing_(isConstructing),
  5618             callee_(cx, callee),
  5619             templateObject_(cx, templateObject),
  5620             pcOffset_(pcOffset)
  5621         { }
  5623         ICStub *getStub(ICStubSpace *space) {
  5624             return ICCall_Native::New(space, getStubCode(), firstMonitorStub_,
  5625                                       callee_, templateObject_, pcOffset_);
  5627     };
  5628 };
  5630 class ICCall_ScriptedApplyArray : public ICMonitoredStub
  5632     friend class ICStubSpace;
  5633   public:
  5634     // The maximum length of an inlineable funcall array.
  5635     // Keep this small to avoid controllable stack overflows by attackers passing large
  5636     // arrays to fun.apply.
  5637     static const uint32_t MAX_ARGS_ARRAY_LENGTH = 16;
  5639   protected:
  5640     uint32_t pcOffset_;
  5642     ICCall_ScriptedApplyArray(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset)
  5643       : ICMonitoredStub(ICStub::Call_ScriptedApplyArray, stubCode, firstMonitorStub),
  5644         pcOffset_(pcOffset)
  5645     {}
  5647   public:
  5648     static inline ICCall_ScriptedApplyArray *New(ICStubSpace *space, JitCode *code,
  5649                                                  ICStub *firstMonitorStub, uint32_t pcOffset)
  5651         if (!code)
  5652             return nullptr;
  5653         return space->allocate<ICCall_ScriptedApplyArray>(code, firstMonitorStub, pcOffset);
  5656     static size_t offsetOfPCOffset() {
  5657         return offsetof(ICCall_ScriptedApplyArray, pcOffset_);
  5660     // Compiler for this stub kind.
  5661     class Compiler : public ICCallStubCompiler {
  5662       protected:
  5663         ICStub *firstMonitorStub_;
  5664         uint32_t pcOffset_;
  5665         bool generateStubCode(MacroAssembler &masm);
  5667         virtual int32_t getKey() const {
  5668             return static_cast<int32_t>(kind);
  5671       public:
  5672         Compiler(JSContext *cx, ICStub *firstMonitorStub, uint32_t pcOffset)
  5673           : ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArray),
  5674             firstMonitorStub_(firstMonitorStub),
  5675             pcOffset_(pcOffset)
  5676         { }
  5678         ICStub *getStub(ICStubSpace *space) {
  5679             return ICCall_ScriptedApplyArray::New(space, getStubCode(), firstMonitorStub_,
  5680                                                       pcOffset_);
  5682     };
  5683 };
  5685 class ICCall_ScriptedApplyArguments : public ICMonitoredStub
  5687     friend class ICStubSpace;
  5689   protected:
  5690     uint32_t pcOffset_;
  5692     ICCall_ScriptedApplyArguments(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset)
  5693       : ICMonitoredStub(ICStub::Call_ScriptedApplyArguments, stubCode, firstMonitorStub),
  5694         pcOffset_(pcOffset)
  5695     {}
  5697   public:
  5698     static inline ICCall_ScriptedApplyArguments *New(ICStubSpace *space, JitCode *code,
  5699                                                      ICStub *firstMonitorStub, uint32_t pcOffset)
  5701         if (!code)
  5702             return nullptr;
  5703         return space->allocate<ICCall_ScriptedApplyArguments>(code, firstMonitorStub, pcOffset);
  5706     static size_t offsetOfPCOffset() {
  5707         return offsetof(ICCall_ScriptedApplyArguments, pcOffset_);
  5710     // Compiler for this stub kind.
  5711     class Compiler : public ICCallStubCompiler {
  5712       protected:
  5713         ICStub *firstMonitorStub_;
  5714         uint32_t pcOffset_;
  5715         bool generateStubCode(MacroAssembler &masm);
  5717         virtual int32_t getKey() const {
  5718             return static_cast<int32_t>(kind);
  5721       public:
  5722         Compiler(JSContext *cx, ICStub *firstMonitorStub, uint32_t pcOffset)
  5723           : ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArguments),
  5724             firstMonitorStub_(firstMonitorStub),
  5725             pcOffset_(pcOffset)
  5726         { }
  5728         ICStub *getStub(ICStubSpace *space) {
  5729             return ICCall_ScriptedApplyArguments::New(space, getStubCode(), firstMonitorStub_,
  5730                                                       pcOffset_);
  5732     };
  5733 };
  5735 // Handles calls of the form |fun.call(...)| where fun is a scripted function.
  5736 class ICCall_ScriptedFunCall : public ICMonitoredStub
  5738     friend class ICStubSpace;
  5740   protected:
  5741     uint32_t pcOffset_;
  5743     ICCall_ScriptedFunCall(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset)
  5744       : ICMonitoredStub(ICStub::Call_ScriptedFunCall, stubCode, firstMonitorStub),
  5745         pcOffset_(pcOffset)
  5746     {}
  5748   public:
  5749     static inline ICCall_ScriptedFunCall *New(ICStubSpace *space, JitCode *code,
  5750                                               ICStub *firstMonitorStub, uint32_t pcOffset)
  5752         if (!code)
  5753             return nullptr;
  5754         return space->allocate<ICCall_ScriptedFunCall>(code, firstMonitorStub, pcOffset);
  5757     static size_t offsetOfPCOffset() {
  5758         return offsetof(ICCall_ScriptedFunCall, pcOffset_);
  5761     // Compiler for this stub kind.
  5762     class Compiler : public ICCallStubCompiler {
  5763       protected:
  5764         ICStub *firstMonitorStub_;
  5765         uint32_t pcOffset_;
  5766         bool generateStubCode(MacroAssembler &masm);
  5768         virtual int32_t getKey() const {
  5769             return static_cast<int32_t>(kind);
  5772       public:
  5773         Compiler(JSContext *cx, ICStub *firstMonitorStub, uint32_t pcOffset)
  5774           : ICCallStubCompiler(cx, ICStub::Call_ScriptedFunCall),
  5775             firstMonitorStub_(firstMonitorStub),
  5776             pcOffset_(pcOffset)
  5777         { }
  5779         ICStub *getStub(ICStubSpace *space) {
  5780             return ICCall_ScriptedFunCall::New(space, getStubCode(), firstMonitorStub_,
  5781                                                pcOffset_);
  5783     };
  5784 };
  5786 // Stub for performing a TableSwitch, updating the IC's return address to jump
  5787 // to whatever point the switch is branching to.
  5788 class ICTableSwitch : public ICStub
  5790     friend class ICStubSpace;
  5792   protected: // Protected to silence Clang warning.
  5793     void **table_;
  5794     int32_t min_;
  5795     int32_t length_;
  5796     void *defaultTarget_;
  5798     ICTableSwitch(JitCode *stubCode, void **table,
  5799                   int32_t min, int32_t length, void *defaultTarget)
  5800       : ICStub(TableSwitch, stubCode), table_(table),
  5801         min_(min), length_(length), defaultTarget_(defaultTarget)
  5802     {}
  5804   public:
  5805     static inline ICTableSwitch *New(ICStubSpace *space, JitCode *code, void **table,
  5806                                      int32_t min, int32_t length, void *defaultTarget) {
  5807         if (!code)
  5808             return nullptr;
  5809         return space->allocate<ICTableSwitch>(code, table, min, length, defaultTarget);
  5812     void fixupJumpTable(JSScript *script, BaselineScript *baseline);
  5814     class Compiler : public ICStubCompiler {
  5815         bool generateStubCode(MacroAssembler &masm);
  5817         jsbytecode *pc_;
  5819       public:
  5820         Compiler(JSContext *cx, jsbytecode *pc)
  5821           : ICStubCompiler(cx, ICStub::TableSwitch), pc_(pc)
  5822         {}
  5824         ICStub *getStub(ICStubSpace *space);
  5825     };
  5826 };
  5828 // IC for constructing an iterator from an input value.
  5829 class ICIteratorNew_Fallback : public ICFallbackStub
  5831     friend class ICStubSpace;
  5833     ICIteratorNew_Fallback(JitCode *stubCode)
  5834       : ICFallbackStub(ICStub::IteratorNew_Fallback, stubCode)
  5835     { }
  5837   public:
  5838     static inline ICIteratorNew_Fallback *New(ICStubSpace *space, JitCode *code) {
  5839         if (!code)
  5840             return nullptr;
  5841         return space->allocate<ICIteratorNew_Fallback>(code);
  5844     class Compiler : public ICStubCompiler {
  5845       protected:
  5846         bool generateStubCode(MacroAssembler &masm);
  5848       public:
  5849         Compiler(JSContext *cx)
  5850           : ICStubCompiler(cx, ICStub::IteratorNew_Fallback)
  5851         { }
  5853         ICStub *getStub(ICStubSpace *space) {
  5854             return ICIteratorNew_Fallback::New(space, getStubCode());
  5856     };
  5857 };
  5859 // IC for testing if there are more values in an iterator.
  5860 class ICIteratorMore_Fallback : public ICFallbackStub
  5862     friend class ICStubSpace;
  5864     ICIteratorMore_Fallback(JitCode *stubCode)
  5865       : ICFallbackStub(ICStub::IteratorMore_Fallback, stubCode)
  5866     { }
  5868   public:
  5869     static inline ICIteratorMore_Fallback *New(ICStubSpace *space, JitCode *code) {
  5870         if (!code)
  5871             return nullptr;
  5872         return space->allocate<ICIteratorMore_Fallback>(code);
  5875     class Compiler : public ICStubCompiler {
  5876       protected:
  5877         bool generateStubCode(MacroAssembler &masm);
  5879       public:
  5880         Compiler(JSContext *cx)
  5881           : ICStubCompiler(cx, ICStub::IteratorMore_Fallback)
  5882         { }
  5884         ICStub *getStub(ICStubSpace *space) {
  5885             return ICIteratorMore_Fallback::New(space, getStubCode());
  5887     };
  5888 };
  5890 // IC for testing if there are more values in a native iterator.
  5891 class ICIteratorMore_Native : public ICStub
  5893     friend class ICStubSpace;
  5895     ICIteratorMore_Native(JitCode *stubCode)
  5896       : ICStub(ICStub::IteratorMore_Native, stubCode)
  5897     { }
  5899   public:
  5900     static inline ICIteratorMore_Native *New(ICStubSpace *space, JitCode *code) {
  5901         if (!code)
  5902             return nullptr;
  5903         return space->allocate<ICIteratorMore_Native>(code);
  5906     class Compiler : public ICStubCompiler {
  5907       protected:
  5908         bool generateStubCode(MacroAssembler &masm);
  5910       public:
  5911         Compiler(JSContext *cx)
  5912           : ICStubCompiler(cx, ICStub::IteratorMore_Native)
  5913         { }
  5915         ICStub *getStub(ICStubSpace *space) {
  5916             return ICIteratorMore_Native::New(space, getStubCode());
  5918     };
  5919 };
  5921 // IC for getting the next value in an iterator.
  5922 class ICIteratorNext_Fallback : public ICFallbackStub
  5924     friend class ICStubSpace;
  5926     ICIteratorNext_Fallback(JitCode *stubCode)
  5927       : ICFallbackStub(ICStub::IteratorNext_Fallback, stubCode)
  5928     { }
  5930   public:
  5931     static inline ICIteratorNext_Fallback *New(ICStubSpace *space, JitCode *code) {
  5932         if (!code)
  5933             return nullptr;
  5934         return space->allocate<ICIteratorNext_Fallback>(code);
  5937     void setHasNonStringResult() {
  5938         JS_ASSERT(extra_ == 0);
  5939         extra_ = 1;
  5941     bool hasNonStringResult() const {
  5942         return extra_;
  5945     class Compiler : public ICStubCompiler {
  5946       protected:
  5947         bool generateStubCode(MacroAssembler &masm);
  5949       public:
  5950         Compiler(JSContext *cx)
  5951           : ICStubCompiler(cx, ICStub::IteratorNext_Fallback)
  5952         { }
  5954         ICStub *getStub(ICStubSpace *space) {
  5955             return ICIteratorNext_Fallback::New(space, getStubCode());
  5957     };
  5958 };
  5960 // IC for getting the next value in a native iterator.
  5961 class ICIteratorNext_Native : public ICStub
  5963     friend class ICStubSpace;
  5965     ICIteratorNext_Native(JitCode *stubCode)
  5966       : ICStub(ICStub::IteratorNext_Native, stubCode)
  5967     { }
  5969   public:
  5970     static inline ICIteratorNext_Native *New(ICStubSpace *space, JitCode *code) {
  5971         if (!code)
  5972             return nullptr;
  5973         return space->allocate<ICIteratorNext_Native>(code);
  5976     class Compiler : public ICStubCompiler {
  5977       protected:
  5978         bool generateStubCode(MacroAssembler &masm);
  5980       public:
  5981         Compiler(JSContext *cx)
  5982           : ICStubCompiler(cx, ICStub::IteratorNext_Native)
  5983         { }
  5985         ICStub *getStub(ICStubSpace *space) {
  5986             return ICIteratorNext_Native::New(space, getStubCode());
  5988     };
  5989 };
  5991 // IC for closing an iterator.
  5992 class ICIteratorClose_Fallback : public ICFallbackStub
  5994     friend class ICStubSpace;
  5996     ICIteratorClose_Fallback(JitCode *stubCode)
  5997       : ICFallbackStub(ICStub::IteratorClose_Fallback, stubCode)
  5998     { }
  6000   public:
  6001     static inline ICIteratorClose_Fallback *New(ICStubSpace *space, JitCode *code) {
  6002         if (!code)
  6003             return nullptr;
  6004         return space->allocate<ICIteratorClose_Fallback>(code);
  6007     class Compiler : public ICStubCompiler {
  6008       protected:
  6009         bool generateStubCode(MacroAssembler &masm);
  6011       public:
  6012         Compiler(JSContext *cx)
  6013           : ICStubCompiler(cx, ICStub::IteratorClose_Fallback)
  6014         { }
  6016         ICStub *getStub(ICStubSpace *space) {
  6017             return ICIteratorClose_Fallback::New(space, getStubCode());
  6019     };
  6020 };
  6022 // InstanceOf
  6023 //      JSOP_INSTANCEOF
  6024 class ICInstanceOf_Fallback : public ICFallbackStub
  6026     friend class ICStubSpace;
  6028     ICInstanceOf_Fallback(JitCode *stubCode)
  6029       : ICFallbackStub(ICStub::InstanceOf_Fallback, stubCode)
  6030     { }
  6032   public:
  6033     static inline ICInstanceOf_Fallback *New(ICStubSpace *space, JitCode *code) {
  6034         if (!code)
  6035             return nullptr;
  6036         return space->allocate<ICInstanceOf_Fallback>(code);
  6039     class Compiler : public ICStubCompiler {
  6040       protected:
  6041         bool generateStubCode(MacroAssembler &masm);
  6043       public:
  6044         Compiler(JSContext *cx)
  6045           : ICStubCompiler(cx, ICStub::InstanceOf_Fallback)
  6046         { }
  6048         ICStub *getStub(ICStubSpace *space) {
  6049             return ICInstanceOf_Fallback::New(space, getStubCode());
  6051     };
  6052 };
  6054 // TypeOf
  6055 //      JSOP_TYPEOF
  6056 //      JSOP_TYPEOFEXPR
  6057 class ICTypeOf_Fallback : public ICFallbackStub
  6059     friend class ICStubSpace;
  6061     ICTypeOf_Fallback(JitCode *stubCode)
  6062       : ICFallbackStub(ICStub::TypeOf_Fallback, stubCode)
  6063     { }
  6065   public:
  6066     static inline ICTypeOf_Fallback *New(ICStubSpace *space, JitCode *code) {
  6067         if (!code)
  6068             return nullptr;
  6069         return space->allocate<ICTypeOf_Fallback>(code);
  6072     class Compiler : public ICStubCompiler {
  6073       protected:
  6074         bool generateStubCode(MacroAssembler &masm);
  6076       public:
  6077         Compiler(JSContext *cx)
  6078           : ICStubCompiler(cx, ICStub::TypeOf_Fallback)
  6079         { }
  6081         ICStub *getStub(ICStubSpace *space) {
  6082             return ICTypeOf_Fallback::New(space, getStubCode());
  6084     };
  6085 };
  6087 class ICTypeOf_Typed : public ICFallbackStub
  6089     friend class ICStubSpace;
  6091     ICTypeOf_Typed(JitCode *stubCode, JSType type)
  6092       : ICFallbackStub(ICStub::TypeOf_Typed, stubCode)
  6094         extra_ = uint16_t(type);
  6095         JS_ASSERT(JSType(extra_) == type);
  6098   public:
  6099     static inline ICTypeOf_Typed *New(ICStubSpace *space, JitCode *code, JSType type) {
  6100         if (!code)
  6101             return nullptr;
  6102         return space->allocate<ICTypeOf_Typed>(code, type);
  6105     JSType type() const {
  6106         return JSType(extra_);
  6109     class Compiler : public ICStubCompiler {
  6110       protected:
  6111         JSType type_;
  6112         RootedString typeString_;
  6113         bool generateStubCode(MacroAssembler &masm);
  6115         virtual int32_t getKey() const {
  6116             return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16);
  6119       public:
  6120         Compiler(JSContext *cx, JSType type, HandleString string)
  6121           : ICStubCompiler(cx, ICStub::TypeOf_Typed),
  6122             type_(type),
  6123             typeString_(cx, string)
  6124         { }
  6126         ICStub *getStub(ICStubSpace *space) {
  6127             return ICTypeOf_Typed::New(space, getStubCode(), type_);
  6129     };
  6130 };
  6132 class ICRest_Fallback : public ICFallbackStub
  6134     friend class ICStubSpace;
  6136     HeapPtrObject templateObject_;
  6138     ICRest_Fallback(JitCode *stubCode, JSObject *templateObject)
  6139       : ICFallbackStub(ICStub::Rest_Fallback, stubCode), templateObject_(templateObject)
  6140     { }
  6142   public:
  6143     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  6145     static inline ICRest_Fallback *New(ICStubSpace *space, JitCode *code,
  6146                                        JSObject *templateObject) {
  6147         if (!code)
  6148             return nullptr;
  6149         return space->allocate<ICRest_Fallback>(code, templateObject);
  6152     HeapPtrObject &templateObject() {
  6153         return templateObject_;
  6156     class Compiler : public ICStubCompiler {
  6157       protected:
  6158         RootedObject templateObject;
  6159         bool generateStubCode(MacroAssembler &masm);
  6161       public:
  6162         Compiler(JSContext *cx, JSObject *templateObject)
  6163           : ICStubCompiler(cx, ICStub::Rest_Fallback),
  6164             templateObject(cx, templateObject)
  6165         { }
  6167         ICStub *getStub(ICStubSpace *space) {
  6168             return ICRest_Fallback::New(space, getStubCode(), templateObject);
  6170     };
  6171 };
  6173 // Stub for JSOP_RETSUB ("returning" from a |finally| block).
  6174 class ICRetSub_Fallback : public ICFallbackStub
  6176     friend class ICStubSpace;
  6178     ICRetSub_Fallback(JitCode *stubCode)
  6179       : ICFallbackStub(ICStub::RetSub_Fallback, stubCode)
  6180     { }
  6182   public:
  6183     static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  6185     static inline ICRetSub_Fallback *New(ICStubSpace *space, JitCode *code) {
  6186         if (!code)
  6187             return nullptr;
  6188         return space->allocate<ICRetSub_Fallback>(code);
  6191     class Compiler : public ICStubCompiler {
  6192       protected:
  6193         bool generateStubCode(MacroAssembler &masm);
  6195       public:
  6196         Compiler(JSContext *cx)
  6197           : ICStubCompiler(cx, ICStub::RetSub_Fallback)
  6198         { }
  6200         ICStub *getStub(ICStubSpace *space) {
  6201             return ICRetSub_Fallback::New(space, getStubCode());
  6203     };
  6204 };
  6206 // Optimized JSOP_RETSUB stub. Every stub maps a single pc offset to its
  6207 // native code address.
  6208 class ICRetSub_Resume : public ICStub
  6210     friend class ICStubSpace;
  6212   protected:
  6213     uint32_t pcOffset_;
  6214     uint8_t *addr_;
  6216     ICRetSub_Resume(JitCode *stubCode, uint32_t pcOffset, uint8_t *addr)
  6217       : ICStub(ICStub::RetSub_Resume, stubCode),
  6218         pcOffset_(pcOffset),
  6219         addr_(addr)
  6220     { }
  6222   public:
  6223     static ICRetSub_Resume *New(ICStubSpace *space, JitCode *code, uint32_t pcOffset,
  6224                                 uint8_t *addr) {
  6225         if (!code)
  6226             return nullptr;
  6227         return space->allocate<ICRetSub_Resume>(code, pcOffset, addr);
  6230     static size_t offsetOfPCOffset() {
  6231         return offsetof(ICRetSub_Resume, pcOffset_);
  6233     static size_t offsetOfAddr() {
  6234         return offsetof(ICRetSub_Resume, addr_);
  6237     class Compiler : public ICStubCompiler {
  6238         uint32_t pcOffset_;
  6239         uint8_t *addr_;
  6241         bool generateStubCode(MacroAssembler &masm);
  6243       public:
  6244         Compiler(JSContext *cx, uint32_t pcOffset, uint8_t *addr)
  6245           : ICStubCompiler(cx, ICStub::RetSub_Resume),
  6246             pcOffset_(pcOffset),
  6247             addr_(addr)
  6248         { }
  6250         ICStub *getStub(ICStubSpace *space) {
  6251             return ICRetSub_Resume::New(space, getStubCode(), pcOffset_, addr_);
  6253     };
  6254 };
  6256 } // namespace jit
  6257 } // namespace js
  6259 #endif // JS_ION
  6261 #endif /* jit_BaselineIC_h */

mercurial