js/src/jit/BaselineIC.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/jit/BaselineIC.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,6261 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef jit_BaselineIC_h
    1.11 +#define jit_BaselineIC_h
    1.12 +
    1.13 +#ifdef JS_ION
    1.14 +
    1.15 +#include "mozilla/Assertions.h"
    1.16 +
    1.17 +#include "jscntxt.h"
    1.18 +#include "jscompartment.h"
    1.19 +#include "jsgc.h"
    1.20 +#include "jsopcode.h"
    1.21 +
    1.22 +#include "jit/BaselineJIT.h"
    1.23 +#include "jit/BaselineRegisters.h"
    1.24 +
    1.25 +namespace js {
    1.26 +namespace jit {
    1.27 +
    1.28 +//
    1.29 +// Baseline Inline Caches are polymorphic caches that aggressively
    1.30 +// share their stub code.
    1.31 +//
    1.32 +// Every polymorphic site contains a linked list of stubs which are
    1.33 +// specific to that site.  These stubs are composed of a |StubData|
    1.34 +// structure that stores parametrization information (e.g.
    1.35 +// the shape pointer for a shape-check-and-property-get stub), any
    1.36 +// dynamic information (e.g. use counts), a pointer to the stub code,
    1.37 +// and a pointer to the next stub state in the linked list.
    1.38 +//
    1.39 +// Every BaselineScript keeps an table of |CacheDescriptor| data
    1.40 +// structures, which store the following:
    1.41 +//      A pointer to the first StubData in the cache.
    1.42 +//      The bytecode PC of the relevant IC.
    1.43 +//      The machine-code PC where the call to the stubcode returns.
    1.44 +//
    1.45 +// A diagram:
    1.46 +//
    1.47 +//        Control flow                  Pointers
    1.48 +//      =======#                     ----.     .---->
    1.49 +//             #                         |     |
    1.50 +//             #======>                  \-----/
    1.51 +//
    1.52 +//
    1.53 +//                                   .---------------------------------------.
    1.54 +//                                   |         .-------------------------.   |
    1.55 +//                                   |         |         .----.          |   |
    1.56 +//         Baseline                  |         |         |    |          |   |
    1.57 +//         JIT Code              0   ^     1   ^     2   ^    |          |   |
    1.58 +//     +--------------+    .-->+-----+   +-----+   +-----+    |          |   |
    1.59 +//     |              |  #=|==>|     |==>|     |==>| FB  |    |          |   |
    1.60 +//     |              |  # |   +-----+   +-----+   +-----+    |          |   |
    1.61 +//     |              |  # |      #         #         #       |          |   |
    1.62 +//     |==============|==# |      #         #         #       |          |   |
    1.63 +//     |=== IC =======|    |      #         #         #       |          |   |
    1.64 +//  .->|==============|<===|======#=========#=========#       |          |   |
    1.65 +//  |  |              |    |                                  |          |   |
    1.66 +//  |  |              |    |                                  |          |   |
    1.67 +//  |  |              |    |                                  |          |   |
    1.68 +//  |  |              |    |                                  v          |   |
    1.69 +//  |  |              |    |                              +---------+    |   |
    1.70 +//  |  |              |    |                              | Fallback|    |   |
    1.71 +//  |  |              |    |                              | Stub    |    |   |
    1.72 +//  |  |              |    |                              | Code    |    |   |
    1.73 +//  |  |              |    |                              +---------+    |   |
    1.74 +//  |  +--------------+    |                                             |   |
    1.75 +//  |         |_______     |                              +---------+    |   |
    1.76 +//  |                |     |                              | Stub    |<---/   |
    1.77 +//  |        IC      |     \--.                           | Code    |        |
    1.78 +//  |    Descriptor  |        |                           +---------+        |
    1.79 +//  |      Table     v        |                                              |
    1.80 +//  |  +-----------------+    |                           +---------+        |
    1.81 +//  \--| Ins | PC | Stub |----/                           | Stub    |<-------/
    1.82 +//     +-----------------+                                | Code    |
    1.83 +//     |       ...       |                                +---------+
    1.84 +//     +-----------------+
    1.85 +//                                                          Shared
    1.86 +//                                                          Stub Code
    1.87 +//
    1.88 +//
    1.89 +// Type ICs
    1.90 +// ========
    1.91 +//
    1.92 +// Type ICs are otherwise regular ICs that are actually nested within
    1.93 +// other IC chains.  They serve to optimize locations in the code where the
    1.94 +// baseline compiler would have otherwise had to perform a type Monitor operation
    1.95 +// (e.g. the result of GetProp, GetElem, etc.), or locations where the baseline
    1.96 +// compiler would have had to modify a heap typeset using the type of an input
    1.97 +// value (e.g. SetProp, SetElem, etc.)
    1.98 +//
    1.99 +// There are two kinds of Type ICs: Monitor and Update.
   1.100 +//
   1.101 +// Note that type stub bodies are no-ops.  The stubs only exist for their
   1.102 +// guards, and their existence simply signifies that the typeset (implicit)
   1.103 +// that is being checked already contains that type.
   1.104 +//
   1.105 +// TypeMonitor ICs
   1.106 +// ---------------
   1.107 +// Monitor ICs are shared between stubs in the general IC, and monitor the resulting
   1.108 +// types of getter operations (call returns, getprop outputs, etc.)
   1.109 +//
   1.110 +//        +-----------+     +-----------+     +-----------+     +-----------+
   1.111 +//   ---->| Stub 1    |---->| Stub 2    |---->| Stub 3    |---->| FB Stub   |
   1.112 +//        +-----------+     +-----------+     +-----------+     +-----------+
   1.113 +//             |                  |                 |                  |
   1.114 +//             |------------------/-----------------/                  |
   1.115 +//             v                                                       |
   1.116 +//        +-----------+     +-----------+     +-----------+            |
   1.117 +//        | Type 1    |---->| Type 2    |---->| Type FB   |            |
   1.118 +//        +-----------+     +-----------+     +-----------+            |
   1.119 +//             |                 |                  |                  |
   1.120 +//  <----------/-----------------/------------------/------------------/
   1.121 +//                r e t u r n    p a t h
   1.122 +//
   1.123 +// After an optimized IC stub successfully executes, it passes control to the type stub
   1.124 +// chain to check the resulting type.  If no type stub succeeds, and the monitor fallback
   1.125 +// stub is reached, the monitor fallback stub performs a manual monitor, and also adds the
   1.126 +// appropriate type stub to the chain.
   1.127 +//
   1.128 +// The IC's main fallback, in addition to generating new mainline stubs, also generates
   1.129 +// type stubs as reflected by its returned value.
   1.130 +//
   1.131 +// NOTE: The type IC chain returns directly to the mainline code, not back to the
   1.132 +// stub it was entered from.  Thus, entering a type IC is a matter of a |jump|, not
   1.133 +// a |call|.  This allows us to safely call a VM Monitor function from within the monitor IC's
   1.134 +// fallback chain, since the return address (needed for stack inspection) is preserved.
   1.135 +//
   1.136 +//
   1.137 +// TypeUpdate ICs
   1.138 +// --------------
   1.139 +// Update ICs update heap typesets and monitor the input types of setter operations
   1.140 +// (setelem, setprop inputs, etc.).  Unlike monitor ICs, they are not shared
   1.141 +// between stubs on an IC, but instead are kept track of on a per-stub basis.
   1.142 +//
   1.143 +// This is because the main stubs for the operation will each identify a potentially
   1.144 +// different TypeObject to update.  New input types must be tracked on a typeobject-to-
   1.145 +// typeobject basis.
   1.146 +//
   1.147 +// Type-update ICs cannot be called in tail position (they must return to the
   1.148 +// the stub that called them so that the stub may continue to perform its original
   1.149 +// purpose).  This means that any VMCall to perform a manual type update from C++ must be
   1.150 +// done from within the main IC stub.  This necessitates that the stub enter a
   1.151 +// "BaselineStub" frame before making the call.
   1.152 +//
   1.153 +// If the type-update IC chain could itself make the VMCall, then the BaselineStub frame
   1.154 +// must be entered before calling the type-update chain, and exited afterward.  This
   1.155 +// is very expensive for a common case where we expect the type-update fallback to not
   1.156 +// be called.  To avoid the cost of entering and exiting a BaselineStub frame when
   1.157 +// using the type-update IC chain, we design the chain to not perform any VM-calls
   1.158 +// in its fallback.
   1.159 +//
   1.160 +// Instead, the type-update IC chain is responsible for returning 1 or 0, depending
   1.161 +// on if a type is represented in the chain or not.  The fallback stub simply returns
   1.162 +// 0, and all other optimized stubs return 1.
   1.163 +// If the chain returns 1, then the IC stub goes ahead and performs its operation.
   1.164 +// If the chain returns 0, then the IC stub performs a call to the fallback function
   1.165 +// inline (doing the requisite BaselineStub frame enter/exit).
   1.166 +// This allows us to avoid the expensive subfram enter/exit in the common case.
   1.167 +//
   1.168 +//                                 r e t u r n    p a t h
   1.169 +//   <--------------.-----------------.-----------------.-----------------.
   1.170 +//                  |                 |                 |                 |
   1.171 +//        +-----------+     +-----------+     +-----------+     +-----------+
   1.172 +//   ---->| Stub 1    |---->| Stub 2    |---->| Stub 3    |---->| FB Stub   |
   1.173 +//        +-----------+     +-----------+     +-----------+     +-----------+
   1.174 +//          |   ^             |   ^             |   ^
   1.175 +//          |   |             |   |             |   |
   1.176 +//          |   |             |   |             |   |----------------.
   1.177 +//          |   |             |   |             v   |1               |0
   1.178 +//          |   |             |   |         +-----------+    +-----------+
   1.179 +//          |   |             |   |         | Type 3.1  |--->|    FB 3   |
   1.180 +//          |   |             |   |         +-----------+    +-----------+
   1.181 +//          |   |             |   |
   1.182 +//          |   |             |   \-------------.-----------------.
   1.183 +//          |   |             |   |             |                 |
   1.184 +//          |   |             v   |1            |1                |0
   1.185 +//          |   |         +-----------+     +-----------+     +-----------+
   1.186 +//          |   |         | Type 2.1  |---->| Type 2.2  |---->|    FB 2   |
   1.187 +//          |   |         +-----------+     +-----------+     +-----------+
   1.188 +//          |   |
   1.189 +//          |   \-------------.-----------------.
   1.190 +//          |   |             |                 |
   1.191 +//          v   |1            |1                |0
   1.192 +//     +-----------+     +-----------+     +-----------+
   1.193 +//     | Type 1.1  |---->| Type 1.2  |---->|   FB 1    |
   1.194 +//     +-----------+     +-----------+     +-----------+
   1.195 +//
   1.196 +
   1.197 +class ICStub;
   1.198 +class ICFallbackStub;
   1.199 +
   1.200 +//
   1.201 +// An entry in the Baseline IC descriptor table.
   1.202 +//
   1.203 +class ICEntry
   1.204 +{
   1.205 +  private:
   1.206 +    // A pointer to the baseline IC stub for this instruction.
   1.207 +    ICStub *firstStub_;
   1.208 +
   1.209 +    // Offset from the start of the JIT code where the IC
   1.210 +    // load and call instructions are.
   1.211 +    uint32_t returnOffset_;
   1.212 +
   1.213 +    // The PC of this IC's bytecode op within the JSScript.
   1.214 +    uint32_t pcOffset_ : 29;
   1.215 +
   1.216 +  public:
   1.217 +    enum Kind {
   1.218 +        // A for-op IC entry.
   1.219 +        Kind_Op = 0,
   1.220 +
   1.221 +        // A non-op IC entry.
   1.222 +        Kind_NonOp,
   1.223 +
   1.224 +        // A fake IC entry for returning from a callVM.
   1.225 +        Kind_CallVM,
   1.226 +
   1.227 +        // A fake IC entry for returning from DebugTrapHandler.
   1.228 +        Kind_DebugTrap,
   1.229 +
   1.230 +        // A fake IC entry for returning from a callVM to
   1.231 +        // Debug{Prologue,Epilogue}.
   1.232 +        Kind_DebugPrologue,
   1.233 +        Kind_DebugEpilogue
   1.234 +    };
   1.235 +
   1.236 +  private:
   1.237 +    // What this IC is for.
   1.238 +    Kind kind_ : 3;
   1.239 +
   1.240 +    // Set the kind and asserts that it's sane.
   1.241 +    void setKind(Kind kind) {
   1.242 +        kind_ = kind;
   1.243 +        MOZ_ASSERT(this->kind() == kind);
   1.244 +    }
   1.245 +
   1.246 +  public:
   1.247 +    ICEntry(uint32_t pcOffset, Kind kind)
   1.248 +      : firstStub_(nullptr), returnOffset_(), pcOffset_(pcOffset)
   1.249 +    {
   1.250 +        // The offset must fit in at least 29 bits, since we shave off 3 for
   1.251 +        // the Kind enum.
   1.252 +        MOZ_ASSERT(pcOffset_ == pcOffset);
   1.253 +        JS_STATIC_ASSERT(BaselineScript::MAX_JSSCRIPT_LENGTH < 0x1fffffffu);
   1.254 +        MOZ_ASSERT(pcOffset <= BaselineScript::MAX_JSSCRIPT_LENGTH);
   1.255 +        setKind(kind);
   1.256 +    }
   1.257 +
   1.258 +    CodeOffsetLabel returnOffset() const {
   1.259 +        return CodeOffsetLabel(returnOffset_);
   1.260 +    }
   1.261 +
   1.262 +    void setReturnOffset(CodeOffsetLabel offset) {
   1.263 +        JS_ASSERT(offset.offset() <= (size_t) UINT32_MAX);
   1.264 +        returnOffset_ = (uint32_t) offset.offset();
   1.265 +    }
   1.266 +
   1.267 +    void fixupReturnOffset(MacroAssembler &masm) {
   1.268 +        CodeOffsetLabel offset = returnOffset();
   1.269 +        offset.fixup(&masm);
   1.270 +        JS_ASSERT(offset.offset() <= UINT32_MAX);
   1.271 +        returnOffset_ = (uint32_t) offset.offset();
   1.272 +    }
   1.273 +
   1.274 +    uint32_t pcOffset() const {
   1.275 +        return pcOffset_;
   1.276 +    }
   1.277 +
   1.278 +    jsbytecode *pc(JSScript *script) const {
   1.279 +        return script->offsetToPC(pcOffset_);
   1.280 +    }
   1.281 +
   1.282 +    Kind kind() const {
   1.283 +        // MSVC compiles enums as signed.
   1.284 +        return (Kind)(kind_ & 0x7);
   1.285 +    }
   1.286 +    bool isForOp() const {
   1.287 +        return kind() == Kind_Op;
   1.288 +    }
   1.289 +
   1.290 +    void setForDebugPrologue() {
   1.291 +        MOZ_ASSERT(kind() == Kind_CallVM);
   1.292 +        setKind(Kind_DebugPrologue);
   1.293 +    }
   1.294 +    void setForDebugEpilogue() {
   1.295 +        MOZ_ASSERT(kind() == Kind_CallVM);
   1.296 +        setKind(Kind_DebugEpilogue);
   1.297 +    }
   1.298 +
   1.299 +    bool hasStub() const {
   1.300 +        return firstStub_ != nullptr;
   1.301 +    }
   1.302 +    ICStub *firstStub() const {
   1.303 +        JS_ASSERT(hasStub());
   1.304 +        return firstStub_;
   1.305 +    }
   1.306 +
   1.307 +    ICFallbackStub *fallbackStub() const;
   1.308 +
   1.309 +    void setFirstStub(ICStub *stub) {
   1.310 +        firstStub_ = stub;
   1.311 +    }
   1.312 +
   1.313 +    static inline size_t offsetOfFirstStub() {
   1.314 +        return offsetof(ICEntry, firstStub_);
   1.315 +    }
   1.316 +
   1.317 +    inline ICStub **addressOfFirstStub() {
   1.318 +        return &firstStub_;
   1.319 +    }
   1.320 +};
   1.321 +
   1.322 +// List of baseline IC stub kinds.
   1.323 +#define IC_STUB_KIND_LIST(_)    \
   1.324 +    _(UseCount_Fallback)        \
   1.325 +                                \
   1.326 +    _(Profiler_Fallback)        \
   1.327 +    _(Profiler_PushFunction)    \
   1.328 +                                \
   1.329 +    _(TypeMonitor_Fallback)     \
   1.330 +    _(TypeMonitor_SingleObject) \
   1.331 +    _(TypeMonitor_TypeObject)   \
   1.332 +    _(TypeMonitor_PrimitiveSet) \
   1.333 +                                \
   1.334 +    _(TypeUpdate_Fallback)      \
   1.335 +    _(TypeUpdate_SingleObject)  \
   1.336 +    _(TypeUpdate_TypeObject)    \
   1.337 +    _(TypeUpdate_PrimitiveSet)  \
   1.338 +                                \
   1.339 +    _(This_Fallback)            \
   1.340 +                                \
   1.341 +    _(NewArray_Fallback)        \
   1.342 +    _(NewObject_Fallback)       \
   1.343 +                                \
   1.344 +    _(Compare_Fallback)         \
   1.345 +    _(Compare_Int32)            \
   1.346 +    _(Compare_Double)           \
   1.347 +    _(Compare_NumberWithUndefined) \
   1.348 +    _(Compare_String)           \
   1.349 +    _(Compare_Boolean)          \
   1.350 +    _(Compare_Object)           \
   1.351 +    _(Compare_ObjectWithUndefined) \
   1.352 +    _(Compare_Int32WithBoolean) \
   1.353 +                                \
   1.354 +    _(ToBool_Fallback)          \
   1.355 +    _(ToBool_Int32)             \
   1.356 +    _(ToBool_String)            \
   1.357 +    _(ToBool_NullUndefined)     \
   1.358 +    _(ToBool_Double)            \
   1.359 +    _(ToBool_Object)            \
   1.360 +                                \
   1.361 +    _(ToNumber_Fallback)        \
   1.362 +                                \
   1.363 +    _(BinaryArith_Fallback)     \
   1.364 +    _(BinaryArith_Int32)        \
   1.365 +    _(BinaryArith_Double)       \
   1.366 +    _(BinaryArith_StringConcat) \
   1.367 +    _(BinaryArith_StringObjectConcat) \
   1.368 +    _(BinaryArith_BooleanWithInt32) \
   1.369 +    _(BinaryArith_DoubleWithInt32) \
   1.370 +                                \
   1.371 +    _(UnaryArith_Fallback)      \
   1.372 +    _(UnaryArith_Int32)         \
   1.373 +    _(UnaryArith_Double)        \
   1.374 +                                \
   1.375 +    _(Call_Fallback)            \
   1.376 +    _(Call_Scripted)            \
   1.377 +    _(Call_AnyScripted)         \
   1.378 +    _(Call_Native)              \
   1.379 +    _(Call_ScriptedApplyArray)  \
   1.380 +    _(Call_ScriptedApplyArguments) \
   1.381 +    _(Call_ScriptedFunCall)     \
   1.382 +                                \
   1.383 +    _(GetElem_Fallback)         \
   1.384 +    _(GetElem_NativeSlot)       \
   1.385 +    _(GetElem_NativePrototypeSlot) \
   1.386 +    _(GetElem_NativePrototypeCallNative) \
   1.387 +    _(GetElem_NativePrototypeCallScripted) \
   1.388 +    _(GetElem_String)           \
   1.389 +    _(GetElem_Dense)            \
   1.390 +    _(GetElem_TypedArray)       \
   1.391 +    _(GetElem_Arguments)        \
   1.392 +                                \
   1.393 +    _(SetElem_Fallback)         \
   1.394 +    _(SetElem_Dense)            \
   1.395 +    _(SetElem_DenseAdd)         \
   1.396 +    _(SetElem_TypedArray)       \
   1.397 +                                \
   1.398 +    _(In_Fallback)              \
   1.399 +                                \
   1.400 +    _(GetName_Fallback)         \
   1.401 +    _(GetName_Global)           \
   1.402 +    _(GetName_Scope0)           \
   1.403 +    _(GetName_Scope1)           \
   1.404 +    _(GetName_Scope2)           \
   1.405 +    _(GetName_Scope3)           \
   1.406 +    _(GetName_Scope4)           \
   1.407 +    _(GetName_Scope5)           \
   1.408 +    _(GetName_Scope6)           \
   1.409 +                                \
   1.410 +    _(BindName_Fallback)        \
   1.411 +                                \
   1.412 +    _(GetIntrinsic_Fallback)    \
   1.413 +    _(GetIntrinsic_Constant)    \
   1.414 +                                \
   1.415 +    _(GetProp_Fallback)         \
   1.416 +    _(GetProp_ArrayLength)      \
   1.417 +    _(GetProp_TypedArrayLength) \
   1.418 +    _(GetProp_Primitive)        \
   1.419 +    _(GetProp_StringLength)     \
   1.420 +    _(GetProp_Native)           \
   1.421 +    _(GetProp_NativePrototype)  \
   1.422 +    _(GetProp_CallScripted)     \
   1.423 +    _(GetProp_CallNative)       \
   1.424 +    _(GetProp_CallNativePrototype)\
   1.425 +    _(GetProp_CallDOMProxyNative)\
   1.426 +    _(GetProp_CallDOMProxyWithGenerationNative)\
   1.427 +    _(GetProp_DOMProxyShadowed) \
   1.428 +    _(GetProp_ArgumentsLength)  \
   1.429 +                                \
   1.430 +    _(SetProp_Fallback)         \
   1.431 +    _(SetProp_Native)           \
   1.432 +    _(SetProp_NativeAdd)        \
   1.433 +    _(SetProp_CallScripted)     \
   1.434 +    _(SetProp_CallNative)       \
   1.435 +                                \
   1.436 +    _(TableSwitch)              \
   1.437 +                                \
   1.438 +    _(IteratorNew_Fallback)     \
   1.439 +    _(IteratorMore_Fallback)    \
   1.440 +    _(IteratorMore_Native)      \
   1.441 +    _(IteratorNext_Fallback)    \
   1.442 +    _(IteratorNext_Native)      \
   1.443 +    _(IteratorClose_Fallback)   \
   1.444 +                                \
   1.445 +    _(InstanceOf_Fallback)      \
   1.446 +                                \
   1.447 +    _(TypeOf_Fallback)          \
   1.448 +    _(TypeOf_Typed)             \
   1.449 +                                \
   1.450 +    _(Rest_Fallback)            \
   1.451 +                                \
   1.452 +    _(RetSub_Fallback)          \
   1.453 +    _(RetSub_Resume)
   1.454 +
   1.455 +#define FORWARD_DECLARE_STUBS(kindName) class IC##kindName;
   1.456 +    IC_STUB_KIND_LIST(FORWARD_DECLARE_STUBS)
   1.457 +#undef FORWARD_DECLARE_STUBS
   1.458 +
   1.459 +class ICMonitoredStub;
   1.460 +class ICMonitoredFallbackStub;
   1.461 +class ICUpdatedStub;
   1.462 +
   1.463 +// Constant iterator that traverses arbitrary chains of ICStubs.
   1.464 +// No requirements are made of the ICStub used to construct this
   1.465 +// iterator, aside from that the stub be part of a nullptr-terminated
   1.466 +// chain.
   1.467 +// The iterator is considered to be at its end once it has been
   1.468 +// incremented _past_ the last stub.  Thus, if 'atEnd()' returns
   1.469 +// true, the '*' and '->' operations are not valid.
   1.470 +class ICStubConstIterator
   1.471 +{
   1.472 +    friend class ICStub;
   1.473 +    friend class ICFallbackStub;
   1.474 +
   1.475 +  private:
   1.476 +    ICStub *currentStub_;
   1.477 +
   1.478 +  public:
   1.479 +    ICStubConstIterator(ICStub *currentStub) : currentStub_(currentStub) {}
   1.480 +
   1.481 +    static ICStubConstIterator StartingAt(ICStub *stub) {
   1.482 +        return ICStubConstIterator(stub);
   1.483 +    }
   1.484 +    static ICStubConstIterator End(ICStub *stub) {
   1.485 +        return ICStubConstIterator(nullptr);
   1.486 +    }
   1.487 +
   1.488 +    bool operator ==(const ICStubConstIterator &other) const {
   1.489 +        return currentStub_ == other.currentStub_;
   1.490 +    }
   1.491 +    bool operator !=(const ICStubConstIterator &other) const {
   1.492 +        return !(*this == other);
   1.493 +    }
   1.494 +
   1.495 +    ICStubConstIterator &operator++();
   1.496 +
   1.497 +    ICStubConstIterator operator++(int) {
   1.498 +        ICStubConstIterator oldThis(*this);
   1.499 +        ++(*this);
   1.500 +        return oldThis;
   1.501 +    }
   1.502 +
   1.503 +    ICStub *operator *() const {
   1.504 +        JS_ASSERT(currentStub_);
   1.505 +        return currentStub_;
   1.506 +    }
   1.507 +
   1.508 +    ICStub *operator ->() const {
   1.509 +        JS_ASSERT(currentStub_);
   1.510 +        return currentStub_;
   1.511 +    }
   1.512 +
   1.513 +    bool atEnd() const {
   1.514 +        return currentStub_ == nullptr;
   1.515 +    }
   1.516 +};
   1.517 +
   1.518 +// Iterator that traverses "regular" IC chains that start at an ICEntry
   1.519 +// and are terminated with an ICFallbackStub.
   1.520 +//
   1.521 +// The iterator is considered to be at its end once it is _at_ the
   1.522 +// fallback stub.  Thus, unlike the ICStubConstIterator, operators
   1.523 +// '*' and '->' are valid even if 'atEnd()' returns true - they
   1.524 +// will act on the fallback stub.
   1.525 +//
   1.526 +// This iterator also allows unlinking of stubs being traversed.
   1.527 +// Note that 'unlink' does not implicitly advance the iterator -
   1.528 +// it must be advanced explicitly using '++'.
   1.529 +class ICStubIterator
   1.530 +{
   1.531 +    friend class ICFallbackStub;
   1.532 +
   1.533 +  private:
   1.534 +    ICEntry *icEntry_;
   1.535 +    ICFallbackStub *fallbackStub_;
   1.536 +    ICStub *previousStub_;
   1.537 +    ICStub *currentStub_;
   1.538 +    bool unlinked_;
   1.539 +
   1.540 +    ICStubIterator(ICFallbackStub *fallbackStub, bool end=false);
   1.541 +  public:
   1.542 +
   1.543 +    bool operator ==(const ICStubIterator &other) const {
   1.544 +        // == should only ever be called on stubs from the same chain.
   1.545 +        JS_ASSERT(icEntry_ == other.icEntry_);
   1.546 +        JS_ASSERT(fallbackStub_ == other.fallbackStub_);
   1.547 +        return currentStub_ == other.currentStub_;
   1.548 +    }
   1.549 +    bool operator !=(const ICStubIterator &other) const {
   1.550 +        return !(*this == other);
   1.551 +    }
   1.552 +
   1.553 +    ICStubIterator &operator++();
   1.554 +
   1.555 +    ICStubIterator operator++(int) {
   1.556 +        ICStubIterator oldThis(*this);
   1.557 +        ++(*this);
   1.558 +        return oldThis;
   1.559 +    }
   1.560 +
   1.561 +    ICStub *operator *() const {
   1.562 +        return currentStub_;
   1.563 +    }
   1.564 +
   1.565 +    ICStub *operator ->() const {
   1.566 +        return currentStub_;
   1.567 +    }
   1.568 +
   1.569 +    bool atEnd() const {
   1.570 +        return currentStub_ == (ICStub *) fallbackStub_;
   1.571 +    }
   1.572 +
   1.573 +    void unlink(JSContext *cx);
   1.574 +};
   1.575 +
   1.576 +//
   1.577 +// Base class for all IC stubs.
   1.578 +//
   1.579 +class ICStub
   1.580 +{
   1.581 +    friend class ICFallbackStub;
   1.582 +
   1.583 +  public:
   1.584 +    enum Kind {
   1.585 +        INVALID = 0,
   1.586 +#define DEF_ENUM_KIND(kindName) kindName,
   1.587 +        IC_STUB_KIND_LIST(DEF_ENUM_KIND)
   1.588 +#undef DEF_ENUM_KIND
   1.589 +        LIMIT
   1.590 +    };
   1.591 +
   1.592 +    static inline bool IsValidKind(Kind k) {
   1.593 +        return (k > INVALID) && (k < LIMIT);
   1.594 +    }
   1.595 +
   1.596 +    static const char *KindString(Kind k) {
   1.597 +        switch(k) {
   1.598 +#define DEF_KIND_STR(kindName) case kindName: return #kindName;
   1.599 +            IC_STUB_KIND_LIST(DEF_KIND_STR)
   1.600 +#undef DEF_KIND_STR
   1.601 +          default:
   1.602 +            MOZ_ASSUME_UNREACHABLE("Invalid kind.");
   1.603 +        }
   1.604 +    }
   1.605 +
   1.606 +    enum Trait {
   1.607 +        Regular             = 0x0,
   1.608 +        Fallback            = 0x1,
   1.609 +        Monitored           = 0x2,
   1.610 +        MonitoredFallback   = 0x3,
   1.611 +        Updated             = 0x4
   1.612 +    };
   1.613 +
   1.614 +    void markCode(JSTracer *trc, const char *name);
   1.615 +    void updateCode(JitCode *stubCode);
   1.616 +    void trace(JSTracer *trc);
   1.617 +
   1.618 +  protected:
   1.619 +    // The raw jitcode to call for this stub.
   1.620 +    uint8_t *stubCode_;
   1.621 +
   1.622 +    // Pointer to next IC stub.  This is null for the last IC stub, which should
   1.623 +    // either be a fallback or inert IC stub.
   1.624 +    ICStub *next_;
   1.625 +
   1.626 +    // A 16-bit field usable by subtypes of ICStub for subtype-specific small-info
   1.627 +    uint16_t extra_;
   1.628 +
   1.629 +    // The kind of the stub.
   1.630 +    //  High bit is 'isFallback' flag.
   1.631 +    //  Second high bit is 'isMonitored' flag.
   1.632 +    Trait trait_ : 3;
   1.633 +    Kind kind_ : 13;
   1.634 +
   1.635 +    inline ICStub(Kind kind, JitCode *stubCode)
   1.636 +      : stubCode_(stubCode->raw()),
   1.637 +        next_(nullptr),
   1.638 +        extra_(0),
   1.639 +        trait_(Regular),
   1.640 +        kind_(kind)
   1.641 +    {
   1.642 +        JS_ASSERT(stubCode != nullptr);
   1.643 +    }
   1.644 +
   1.645 +    inline ICStub(Kind kind, Trait trait, JitCode *stubCode)
   1.646 +      : stubCode_(stubCode->raw()),
   1.647 +        next_(nullptr),
   1.648 +        extra_(0),
   1.649 +        trait_(trait),
   1.650 +        kind_(kind)
   1.651 +    {
   1.652 +        JS_ASSERT(stubCode != nullptr);
   1.653 +    }
   1.654 +
   1.655 +    inline Trait trait() const {
   1.656 +        // Workaround for MSVC reading trait_ as signed value.
   1.657 +        return (Trait)(trait_ & 0x7);
   1.658 +    }
   1.659 +
   1.660 +  public:
   1.661 +
   1.662 +    inline Kind kind() const {
   1.663 +        return static_cast<Kind>(kind_);
   1.664 +    }
   1.665 +
   1.666 +    inline bool isFallback() const {
   1.667 +        return trait() == Fallback || trait() == MonitoredFallback;
   1.668 +    }
   1.669 +
   1.670 +    inline bool isMonitored() const {
   1.671 +        return trait() == Monitored;
   1.672 +    }
   1.673 +
   1.674 +    inline bool isUpdated() const {
   1.675 +        return trait() == Updated;
   1.676 +    }
   1.677 +
   1.678 +    inline bool isMonitoredFallback() const {
   1.679 +        return trait() == MonitoredFallback;
   1.680 +    }
   1.681 +
   1.682 +    inline const ICFallbackStub *toFallbackStub() const {
   1.683 +        JS_ASSERT(isFallback());
   1.684 +        return reinterpret_cast<const ICFallbackStub *>(this);
   1.685 +    }
   1.686 +
   1.687 +    inline ICFallbackStub *toFallbackStub() {
   1.688 +        JS_ASSERT(isFallback());
   1.689 +        return reinterpret_cast<ICFallbackStub *>(this);
   1.690 +    }
   1.691 +
   1.692 +    inline const ICMonitoredStub *toMonitoredStub() const {
   1.693 +        JS_ASSERT(isMonitored());
   1.694 +        return reinterpret_cast<const ICMonitoredStub *>(this);
   1.695 +    }
   1.696 +
   1.697 +    inline ICMonitoredStub *toMonitoredStub() {
   1.698 +        JS_ASSERT(isMonitored());
   1.699 +        return reinterpret_cast<ICMonitoredStub *>(this);
   1.700 +    }
   1.701 +
   1.702 +    inline const ICMonitoredFallbackStub *toMonitoredFallbackStub() const {
   1.703 +        JS_ASSERT(isMonitoredFallback());
   1.704 +        return reinterpret_cast<const ICMonitoredFallbackStub *>(this);
   1.705 +    }
   1.706 +
   1.707 +    inline ICMonitoredFallbackStub *toMonitoredFallbackStub() {
   1.708 +        JS_ASSERT(isMonitoredFallback());
   1.709 +        return reinterpret_cast<ICMonitoredFallbackStub *>(this);
   1.710 +    }
   1.711 +
   1.712 +    inline const ICUpdatedStub *toUpdatedStub() const {
   1.713 +        JS_ASSERT(isUpdated());
   1.714 +        return reinterpret_cast<const ICUpdatedStub *>(this);
   1.715 +    }
   1.716 +
   1.717 +    inline ICUpdatedStub *toUpdatedStub() {
   1.718 +        JS_ASSERT(isUpdated());
   1.719 +        return reinterpret_cast<ICUpdatedStub *>(this);
   1.720 +    }
   1.721 +
   1.722 +#define KIND_METHODS(kindName)   \
   1.723 +    inline bool is##kindName() const { return kind() == kindName; } \
   1.724 +    inline const IC##kindName *to##kindName() const { \
   1.725 +        JS_ASSERT(is##kindName()); \
   1.726 +        return reinterpret_cast<const IC##kindName *>(this); \
   1.727 +    } \
   1.728 +    inline IC##kindName *to##kindName() { \
   1.729 +        JS_ASSERT(is##kindName()); \
   1.730 +        return reinterpret_cast<IC##kindName *>(this); \
   1.731 +    }
   1.732 +    IC_STUB_KIND_LIST(KIND_METHODS)
   1.733 +#undef KIND_METHODS
   1.734 +
   1.735 +    inline ICStub *next() const {
   1.736 +        return next_;
   1.737 +    }
   1.738 +
   1.739 +    inline bool hasNext() const {
   1.740 +        return next_ != nullptr;
   1.741 +    }
   1.742 +
   1.743 +    inline void setNext(ICStub *stub) {
   1.744 +        // Note: next_ only needs to be changed under the compilation lock for
   1.745 +        // non-type-monitor/update ICs.
   1.746 +        next_ = stub;
   1.747 +    }
   1.748 +
   1.749 +    inline ICStub **addressOfNext() {
   1.750 +        return &next_;
   1.751 +    }
   1.752 +
   1.753 +    inline JitCode *jitCode() {
   1.754 +        return JitCode::FromExecutable(stubCode_);
   1.755 +    }
   1.756 +
   1.757 +    inline uint8_t *rawStubCode() const {
   1.758 +        return stubCode_;
   1.759 +    }
   1.760 +
   1.761 +    // This method is not valid on TypeUpdate stub chains!
   1.762 +    inline ICFallbackStub *getChainFallback() {
   1.763 +        ICStub *lastStub = this;
   1.764 +        while (lastStub->next_)
   1.765 +            lastStub = lastStub->next_;
   1.766 +        JS_ASSERT(lastStub->isFallback());
   1.767 +        return lastStub->toFallbackStub();
   1.768 +    }
   1.769 +
   1.770 +    inline ICStubConstIterator beginHere() {
   1.771 +        return ICStubConstIterator::StartingAt(this);
   1.772 +    }
   1.773 +
   1.774 +    static inline size_t offsetOfNext() {
   1.775 +        return offsetof(ICStub, next_);
   1.776 +    }
   1.777 +
   1.778 +    static inline size_t offsetOfStubCode() {
   1.779 +        return offsetof(ICStub, stubCode_);
   1.780 +    }
   1.781 +
   1.782 +    static inline size_t offsetOfExtra() {
   1.783 +        return offsetof(ICStub, extra_);
   1.784 +    }
   1.785 +
   1.786 +    static bool CanMakeCalls(ICStub::Kind kind) {
   1.787 +        JS_ASSERT(IsValidKind(kind));
   1.788 +        switch (kind) {
   1.789 +          case Call_Fallback:
   1.790 +          case Call_Scripted:
   1.791 +          case Call_AnyScripted:
   1.792 +          case Call_Native:
   1.793 +          case Call_ScriptedApplyArray:
   1.794 +          case Call_ScriptedApplyArguments:
   1.795 +          case Call_ScriptedFunCall:
   1.796 +          case UseCount_Fallback:
   1.797 +          case GetElem_NativeSlot:
   1.798 +          case GetElem_NativePrototypeSlot:
   1.799 +          case GetElem_NativePrototypeCallNative:
   1.800 +          case GetElem_NativePrototypeCallScripted:
   1.801 +          case GetProp_CallScripted:
   1.802 +          case GetProp_CallNative:
   1.803 +          case GetProp_CallNativePrototype:
   1.804 +          case GetProp_CallDOMProxyNative:
   1.805 +          case GetProp_CallDOMProxyWithGenerationNative:
   1.806 +          case GetProp_DOMProxyShadowed:
   1.807 +          case SetProp_CallScripted:
   1.808 +          case SetProp_CallNative:
   1.809 +          case RetSub_Fallback:
   1.810 +          // These two fallback stubs don't actually make non-tail calls,
   1.811 +          // but the fallback code for the bailout path needs to pop the stub frame
   1.812 +          // pushed during the bailout.
   1.813 +          case GetProp_Fallback:
   1.814 +          case SetProp_Fallback:
   1.815 +#if JS_HAS_NO_SUCH_METHOD
   1.816 +          case GetElem_Dense:
   1.817 +          case GetElem_Arguments:
   1.818 +          case GetProp_NativePrototype:
   1.819 +          case GetProp_Native:
   1.820 +#endif
   1.821 +            return true;
   1.822 +          default:
   1.823 +            return false;
   1.824 +        }
   1.825 +    }
   1.826 +
   1.827 +    // Optimized stubs get purged on GC.  But some stubs can be active on the
   1.828 +    // stack during GC - specifically the ones that can make calls.  To ensure
   1.829 +    // that these do not get purged, all stubs that can make calls are allocated
   1.830 +    // in the fallback stub space.
   1.831 +    bool allocatedInFallbackSpace() const {
   1.832 +        JS_ASSERT(next());
   1.833 +        return CanMakeCalls(kind());
   1.834 +    }
   1.835 +};
   1.836 +
   1.837 +class ICFallbackStub : public ICStub
   1.838 +{
   1.839 +    friend class ICStubConstIterator;
   1.840 +  protected:
   1.841 +    // Fallback stubs need these fields to easily add new stubs to
   1.842 +    // the linked list of stubs for an IC.
   1.843 +
   1.844 +    // The IC entry for this linked list of stubs.
   1.845 +    ICEntry *icEntry_;
   1.846 +
   1.847 +    // The number of stubs kept in the IC entry.
   1.848 +    uint32_t numOptimizedStubs_;
   1.849 +
   1.850 +    // A pointer to the location stub pointer that needs to be
   1.851 +    // changed to add a new "last" stub immediately before the fallback
   1.852 +    // stub.  This'll start out pointing to the icEntry's "firstStub_"
   1.853 +    // field, and as new stubs are addd, it'll point to the current
   1.854 +    // last stub's "next_" field.
   1.855 +    ICStub **lastStubPtrAddr_;
   1.856 +
   1.857 +    ICFallbackStub(Kind kind, JitCode *stubCode)
   1.858 +      : ICStub(kind, ICStub::Fallback, stubCode),
   1.859 +        icEntry_(nullptr),
   1.860 +        numOptimizedStubs_(0),
   1.861 +        lastStubPtrAddr_(nullptr) {}
   1.862 +
   1.863 +    ICFallbackStub(Kind kind, Trait trait, JitCode *stubCode)
   1.864 +      : ICStub(kind, trait, stubCode),
   1.865 +        icEntry_(nullptr),
   1.866 +        numOptimizedStubs_(0),
   1.867 +        lastStubPtrAddr_(nullptr)
   1.868 +    {
   1.869 +        JS_ASSERT(trait == ICStub::Fallback ||
   1.870 +                  trait == ICStub::MonitoredFallback);
   1.871 +    }
   1.872 +
   1.873 +  public:
   1.874 +    inline ICEntry *icEntry() const {
   1.875 +        return icEntry_;
   1.876 +    }
   1.877 +
   1.878 +    inline size_t numOptimizedStubs() const {
   1.879 +        return (size_t) numOptimizedStubs_;
   1.880 +    }
   1.881 +
   1.882 +    // The icEntry and lastStubPtrAddr_ fields can't be initialized when the stub is
   1.883 +    // created since the stub is created at compile time, and we won't know the IC entry
   1.884 +    // address until after compile when the BaselineScript is created.  This method
   1.885 +    // allows these fields to be fixed up at that point.
   1.886 +    void fixupICEntry(ICEntry *icEntry) {
   1.887 +        JS_ASSERT(icEntry_ == nullptr);
   1.888 +        JS_ASSERT(lastStubPtrAddr_ == nullptr);
   1.889 +        icEntry_ = icEntry;
   1.890 +        lastStubPtrAddr_ = icEntry_->addressOfFirstStub();
   1.891 +    }
   1.892 +
   1.893 +    // Add a new stub to the IC chain terminated by this fallback stub.
   1.894 +    void addNewStub(ICStub *stub) {
   1.895 +        JS_ASSERT(*lastStubPtrAddr_ == this);
   1.896 +        JS_ASSERT(stub->next() == nullptr);
   1.897 +        stub->setNext(this);
   1.898 +        *lastStubPtrAddr_ = stub;
   1.899 +        lastStubPtrAddr_ = stub->addressOfNext();
   1.900 +        numOptimizedStubs_++;
   1.901 +    }
   1.902 +
   1.903 +    ICStubConstIterator beginChainConst() const {
   1.904 +        return ICStubConstIterator(icEntry_->firstStub());
   1.905 +    }
   1.906 +
   1.907 +    ICStubIterator beginChain() {
   1.908 +        return ICStubIterator(this);
   1.909 +    }
   1.910 +
   1.911 +    bool hasStub(ICStub::Kind kind) const {
   1.912 +        for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
   1.913 +            if (iter->kind() == kind)
   1.914 +                return true;
   1.915 +        }
   1.916 +        return false;
   1.917 +    }
   1.918 +
   1.919 +    unsigned numStubsWithKind(ICStub::Kind kind) const {
   1.920 +        unsigned count = 0;
   1.921 +        for (ICStubConstIterator iter = beginChainConst(); !iter.atEnd(); iter++) {
   1.922 +            if (iter->kind() == kind)
   1.923 +                count++;
   1.924 +        }
   1.925 +        return count;
   1.926 +    }
   1.927 +
   1.928 +    void unlinkStub(Zone *zone, ICStub *prev, ICStub *stub);
   1.929 +    void unlinkStubsWithKind(JSContext *cx, ICStub::Kind kind);
   1.930 +};
   1.931 +
   1.932 +// Monitored stubs are IC stubs that feed a single resulting value out to a
   1.933 +// type monitor operation.
   1.934 +class ICMonitoredStub : public ICStub
   1.935 +{
   1.936 +  protected:
   1.937 +    // Pointer to the start of the type monitoring stub chain.
   1.938 +    ICStub *firstMonitorStub_;
   1.939 +
   1.940 +    ICMonitoredStub(Kind kind, JitCode *stubCode, ICStub *firstMonitorStub);
   1.941 +
   1.942 +  public:
   1.943 +    inline void updateFirstMonitorStub(ICStub *monitorStub) {
   1.944 +        // This should only be called once: when the first optimized monitor stub
   1.945 +        // is added to the type monitor IC chain.
   1.946 +        JS_ASSERT(firstMonitorStub_ && firstMonitorStub_->isTypeMonitor_Fallback());
   1.947 +        firstMonitorStub_ = monitorStub;
   1.948 +    }
   1.949 +    inline void resetFirstMonitorStub(ICStub *monitorFallback) {
   1.950 +        JS_ASSERT(monitorFallback->isTypeMonitor_Fallback());
   1.951 +        firstMonitorStub_ = monitorFallback;
   1.952 +    }
   1.953 +    inline ICStub *firstMonitorStub() const {
   1.954 +        return firstMonitorStub_;
   1.955 +    }
   1.956 +
   1.957 +    static inline size_t offsetOfFirstMonitorStub() {
   1.958 +        return offsetof(ICMonitoredStub, firstMonitorStub_);
   1.959 +    }
   1.960 +};
   1.961 +
   1.962 +// Monitored fallback stubs - as the name implies.
   1.963 +class ICMonitoredFallbackStub : public ICFallbackStub
   1.964 +{
   1.965 +  protected:
   1.966 +    // Pointer to the fallback monitor stub.
   1.967 +    ICTypeMonitor_Fallback *fallbackMonitorStub_;
   1.968 +
   1.969 +    ICMonitoredFallbackStub(Kind kind, JitCode *stubCode)
   1.970 +      : ICFallbackStub(kind, ICStub::MonitoredFallback, stubCode),
   1.971 +        fallbackMonitorStub_(nullptr) {}
   1.972 +
   1.973 +  public:
   1.974 +    bool initMonitoringChain(JSContext *cx, ICStubSpace *space);
   1.975 +    bool addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val);
   1.976 +
   1.977 +    inline ICTypeMonitor_Fallback *fallbackMonitorStub() const {
   1.978 +        return fallbackMonitorStub_;
   1.979 +    }
   1.980 +
   1.981 +    static inline size_t offsetOfFallbackMonitorStub() {
   1.982 +        return offsetof(ICMonitoredFallbackStub, fallbackMonitorStub_);
   1.983 +    }
   1.984 +};
   1.985 +
   1.986 +// Updated stubs are IC stubs that use a TypeUpdate IC to track
   1.987 +// the status of heap typesets that need to be updated.
   1.988 +class ICUpdatedStub : public ICStub
   1.989 +{
   1.990 +  protected:
   1.991 +    // Pointer to the start of the type updating stub chain.
   1.992 +    ICStub *firstUpdateStub_;
   1.993 +
   1.994 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
   1.995 +    uint32_t numOptimizedStubs_;
   1.996 +
   1.997 +    ICUpdatedStub(Kind kind, JitCode *stubCode)
   1.998 +      : ICStub(kind, ICStub::Updated, stubCode),
   1.999 +        firstUpdateStub_(nullptr),
  1.1000 +        numOptimizedStubs_(0)
  1.1001 +    {}
  1.1002 +
  1.1003 +  public:
  1.1004 +    bool initUpdatingChain(JSContext *cx, ICStubSpace *space);
  1.1005 +
  1.1006 +    bool addUpdateStubForValue(JSContext *cx, HandleScript script, HandleObject obj, HandleId id,
  1.1007 +                               HandleValue val);
  1.1008 +
  1.1009 +    void addOptimizedUpdateStub(ICStub *stub) {
  1.1010 +        if (firstUpdateStub_->isTypeUpdate_Fallback()) {
  1.1011 +            stub->setNext(firstUpdateStub_);
  1.1012 +            firstUpdateStub_ = stub;
  1.1013 +        } else {
  1.1014 +            ICStub *iter = firstUpdateStub_;
  1.1015 +            JS_ASSERT(iter->next() != nullptr);
  1.1016 +            while (!iter->next()->isTypeUpdate_Fallback())
  1.1017 +                iter = iter->next();
  1.1018 +            JS_ASSERT(iter->next()->next() == nullptr);
  1.1019 +            stub->setNext(iter->next());
  1.1020 +            iter->setNext(stub);
  1.1021 +        }
  1.1022 +
  1.1023 +        numOptimizedStubs_++;
  1.1024 +    }
  1.1025 +
  1.1026 +    inline ICStub *firstUpdateStub() const {
  1.1027 +        return firstUpdateStub_;
  1.1028 +    }
  1.1029 +
  1.1030 +    bool hasTypeUpdateStub(ICStub::Kind kind) {
  1.1031 +        ICStub *stub = firstUpdateStub_;
  1.1032 +        do {
  1.1033 +            if (stub->kind() == kind)
  1.1034 +                return true;
  1.1035 +
  1.1036 +            stub = stub->next();
  1.1037 +        } while (stub);
  1.1038 +
  1.1039 +        return false;
  1.1040 +    }
  1.1041 +
  1.1042 +    inline uint32_t numOptimizedStubs() const {
  1.1043 +        return numOptimizedStubs_;
  1.1044 +    }
  1.1045 +
  1.1046 +    static inline size_t offsetOfFirstUpdateStub() {
  1.1047 +        return offsetof(ICUpdatedStub, firstUpdateStub_);
  1.1048 +    }
  1.1049 +};
  1.1050 +
  1.1051 +// Base class for stubcode compilers.
  1.1052 +class ICStubCompiler
  1.1053 +{
  1.1054 +    // Prevent GC in the middle of stub compilation.
  1.1055 +    js::gc::AutoSuppressGC suppressGC;
  1.1056 +
  1.1057 +
  1.1058 +  protected:
  1.1059 +    JSContext *cx;
  1.1060 +    ICStub::Kind kind;
  1.1061 +#ifdef DEBUG
  1.1062 +    bool entersStubFrame_;
  1.1063 +#endif
  1.1064 +
  1.1065 +    // By default the stubcode key is just the kind.
  1.1066 +    virtual int32_t getKey() const {
  1.1067 +        return static_cast<int32_t>(kind);
  1.1068 +    }
  1.1069 +
  1.1070 +    virtual bool generateStubCode(MacroAssembler &masm) = 0;
  1.1071 +    virtual bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> genCode) {
  1.1072 +        return true;
  1.1073 +    }
  1.1074 +    JitCode *getStubCode();
  1.1075 +
  1.1076 +    ICStubCompiler(JSContext *cx, ICStub::Kind kind)
  1.1077 +      : suppressGC(cx), cx(cx), kind(kind)
  1.1078 +#ifdef DEBUG
  1.1079 +      , entersStubFrame_(false)
  1.1080 +#endif
  1.1081 +    {}
  1.1082 +
  1.1083 +    // Emits a tail call to a VMFunction wrapper.
  1.1084 +    bool tailCallVM(const VMFunction &fun, MacroAssembler &masm);
  1.1085 +
  1.1086 +    // Emits a normal (non-tail) call to a VMFunction wrapper.
  1.1087 +    bool callVM(const VMFunction &fun, MacroAssembler &masm);
  1.1088 +
  1.1089 +    // Emits a call to a type-update IC, assuming that the value to be
  1.1090 +    // checked is already in R0.
  1.1091 +    bool callTypeUpdateIC(MacroAssembler &masm, uint32_t objectOffset);
  1.1092 +
  1.1093 +    // A stub frame is used when a stub wants to call into the VM without
  1.1094 +    // performing a tail call. This is required for the return address
  1.1095 +    // to pc mapping to work.
  1.1096 +    void enterStubFrame(MacroAssembler &masm, Register scratch);
  1.1097 +    void leaveStubFrame(MacroAssembler &masm, bool calledIntoIon = false);
  1.1098 +    void leaveStubFrameHead(MacroAssembler &masm, bool calledIntoIon = false);
  1.1099 +    void leaveStubFrameCommonTail(MacroAssembler &masm);
  1.1100 +
  1.1101 +    // Some stubs need to emit SPS profiler updates.  This emits the guarding
  1.1102 +    // jitcode for those stubs.  If profiling is not enabled, jumps to the
  1.1103 +    // given label.
  1.1104 +    void guardProfilingEnabled(MacroAssembler &masm, Register scratch, Label *skip);
  1.1105 +
  1.1106 +    // Higher-level helper to emit an update to the profiler pseudo-stack.
  1.1107 +    void emitProfilingUpdate(MacroAssembler &masm, Register pcIdx, Register scratch,
  1.1108 +                             uint32_t stubPcOffset);
  1.1109 +    void emitProfilingUpdate(MacroAssembler &masm, GeneralRegisterSet regs, uint32_t stubPcOffset);
  1.1110 +
  1.1111 +    inline GeneralRegisterSet availableGeneralRegs(size_t numInputs) const {
  1.1112 +        GeneralRegisterSet regs(GeneralRegisterSet::All());
  1.1113 +        JS_ASSERT(!regs.has(BaselineStackReg));
  1.1114 +#if defined(JS_CODEGEN_ARM)
  1.1115 +        JS_ASSERT(!regs.has(BaselineTailCallReg));
  1.1116 +        regs.take(BaselineSecondScratchReg);
  1.1117 +#elif defined(JS_CODEGEN_MIPS)
  1.1118 +        JS_ASSERT(!regs.has(BaselineTailCallReg));
  1.1119 +        JS_ASSERT(!regs.has(BaselineSecondScratchReg));
  1.1120 +#endif
  1.1121 +        regs.take(BaselineFrameReg);
  1.1122 +        regs.take(BaselineStubReg);
  1.1123 +#ifdef JS_CODEGEN_X64
  1.1124 +        regs.take(ExtractTemp0);
  1.1125 +        regs.take(ExtractTemp1);
  1.1126 +#endif
  1.1127 +
  1.1128 +        switch (numInputs) {
  1.1129 +          case 0:
  1.1130 +            break;
  1.1131 +          case 1:
  1.1132 +            regs.take(R0);
  1.1133 +            break;
  1.1134 +          case 2:
  1.1135 +            regs.take(R0);
  1.1136 +            regs.take(R1);
  1.1137 +            break;
  1.1138 +          default:
  1.1139 +            MOZ_ASSUME_UNREACHABLE("Invalid numInputs");
  1.1140 +        }
  1.1141 +
  1.1142 +        return regs;
  1.1143 +    }
  1.1144 +
  1.1145 +#ifdef JSGC_GENERATIONAL
  1.1146 +    inline bool emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, ValueOperand val,
  1.1147 +                                         Register scratch, GeneralRegisterSet saveRegs);
  1.1148 +#endif
  1.1149 +
  1.1150 +  public:
  1.1151 +    virtual ICStub *getStub(ICStubSpace *space) = 0;
  1.1152 +
  1.1153 +    ICStubSpace *getStubSpace(JSScript *script) {
  1.1154 +        if (ICStub::CanMakeCalls(kind))
  1.1155 +            return script->baselineScript()->fallbackStubSpace();
  1.1156 +        return script->zone()->jitZone()->optimizedStubSpace();
  1.1157 +    }
  1.1158 +};
  1.1159 +
  1.1160 +// Base class for stub compilers that can generate multiple stubcodes.
  1.1161 +// These compilers need access to the JSOp they are compiling for.
  1.1162 +class ICMultiStubCompiler : public ICStubCompiler
  1.1163 +{
  1.1164 +  protected:
  1.1165 +    JSOp op;
  1.1166 +
  1.1167 +    // Stub keys for multi-stub kinds are composed of both the kind
  1.1168 +    // and the op they are compiled for.
  1.1169 +    virtual int32_t getKey() const {
  1.1170 +        return static_cast<int32_t>(kind) | (static_cast<int32_t>(op) << 16);
  1.1171 +    }
  1.1172 +
  1.1173 +    ICMultiStubCompiler(JSContext *cx, ICStub::Kind kind, JSOp op)
  1.1174 +      : ICStubCompiler(cx, kind), op(op) {}
  1.1175 +};
  1.1176 +
  1.1177 +// UseCount_Fallback
  1.1178 +
  1.1179 +// A UseCount IC chain has only the fallback stub.
  1.1180 +class ICUseCount_Fallback : public ICFallbackStub
  1.1181 +{
  1.1182 +    friend class ICStubSpace;
  1.1183 +
  1.1184 +    ICUseCount_Fallback(JitCode *stubCode)
  1.1185 +      : ICFallbackStub(ICStub::UseCount_Fallback, stubCode)
  1.1186 +    { }
  1.1187 +
  1.1188 +  public:
  1.1189 +    static inline ICUseCount_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.1190 +        if (!code)
  1.1191 +            return nullptr;
  1.1192 +        return space->allocate<ICUseCount_Fallback>(code);
  1.1193 +    }
  1.1194 +
  1.1195 +    // Compiler for this stub kind.
  1.1196 +    class Compiler : public ICStubCompiler {
  1.1197 +      protected:
  1.1198 +        bool generateStubCode(MacroAssembler &masm);
  1.1199 +
  1.1200 +      public:
  1.1201 +        Compiler(JSContext *cx)
  1.1202 +          : ICStubCompiler(cx, ICStub::UseCount_Fallback)
  1.1203 +        { }
  1.1204 +
  1.1205 +        ICUseCount_Fallback *getStub(ICStubSpace *space) {
  1.1206 +            return ICUseCount_Fallback::New(space, getStubCode());
  1.1207 +        }
  1.1208 +    };
  1.1209 +};
  1.1210 +
  1.1211 +// Profiler_Fallback
  1.1212 +
  1.1213 +class ICProfiler_Fallback : public ICFallbackStub
  1.1214 +{
  1.1215 +    friend class ICStubSpace;
  1.1216 +
  1.1217 +    ICProfiler_Fallback(JitCode *stubCode)
  1.1218 +      : ICFallbackStub(ICStub::Profiler_Fallback, stubCode)
  1.1219 +    { }
  1.1220 +
  1.1221 +  public:
  1.1222 +    static inline ICProfiler_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.1223 +        if (!code)
  1.1224 +            return nullptr;
  1.1225 +        return space->allocate<ICProfiler_Fallback>(code);
  1.1226 +    }
  1.1227 +
  1.1228 +    // Compiler for this stub kind.
  1.1229 +    class Compiler : public ICStubCompiler {
  1.1230 +      protected:
  1.1231 +        bool generateStubCode(MacroAssembler &masm);
  1.1232 +
  1.1233 +      public:
  1.1234 +        Compiler(JSContext *cx)
  1.1235 +          : ICStubCompiler(cx, ICStub::Profiler_Fallback)
  1.1236 +        { }
  1.1237 +
  1.1238 +        ICProfiler_Fallback *getStub(ICStubSpace *space) {
  1.1239 +            return ICProfiler_Fallback::New(space, getStubCode());
  1.1240 +        }
  1.1241 +    };
  1.1242 +};
  1.1243 +
  1.1244 +// Profiler_PushFunction
  1.1245 +
  1.1246 +class ICProfiler_PushFunction : public ICStub
  1.1247 +{
  1.1248 +    friend class ICStubSpace;
  1.1249 +
  1.1250 +  protected:
  1.1251 +    const char *str_;
  1.1252 +    HeapPtrScript script_;
  1.1253 +
  1.1254 +    ICProfiler_PushFunction(JitCode *stubCode, const char *str, HandleScript script);
  1.1255 +
  1.1256 +  public:
  1.1257 +    static inline ICProfiler_PushFunction *New(ICStubSpace *space, JitCode *code,
  1.1258 +                                               const char *str, HandleScript script)
  1.1259 +    {
  1.1260 +        if (!code)
  1.1261 +            return nullptr;
  1.1262 +        return space->allocate<ICProfiler_PushFunction>(code, str, script);
  1.1263 +    }
  1.1264 +
  1.1265 +    HeapPtrScript &script() {
  1.1266 +        return script_;
  1.1267 +    }
  1.1268 +
  1.1269 +    static size_t offsetOfStr() {
  1.1270 +        return offsetof(ICProfiler_PushFunction, str_);
  1.1271 +    }
  1.1272 +    static size_t offsetOfScript() {
  1.1273 +        return offsetof(ICProfiler_PushFunction, script_);
  1.1274 +    }
  1.1275 +
  1.1276 +    // Compiler for this stub kind.
  1.1277 +    class Compiler : public ICStubCompiler {
  1.1278 +      protected:
  1.1279 +        const char *str_;
  1.1280 +        RootedScript script_;
  1.1281 +        bool generateStubCode(MacroAssembler &masm);
  1.1282 +
  1.1283 +      public:
  1.1284 +        Compiler(JSContext *cx, const char *str, HandleScript script)
  1.1285 +          : ICStubCompiler(cx, ICStub::Profiler_PushFunction),
  1.1286 +            str_(str),
  1.1287 +            script_(cx, script)
  1.1288 +        { }
  1.1289 +
  1.1290 +        ICProfiler_PushFunction *getStub(ICStubSpace *space) {
  1.1291 +            return ICProfiler_PushFunction::New(space, getStubCode(), str_, script_);
  1.1292 +        }
  1.1293 +    };
  1.1294 +};
  1.1295 +
  1.1296 +
  1.1297 +// TypeCheckPrimitiveSetStub
  1.1298 +//   Base class for IC stubs (TypeUpdate or TypeMonitor) that check that a given
  1.1299 +//   value's type falls within a set of primitive types.
  1.1300 +
  1.1301 +class TypeCheckPrimitiveSetStub : public ICStub
  1.1302 +{
  1.1303 +    friend class ICStubSpace;
  1.1304 +  protected:
  1.1305 +    inline static uint16_t TypeToFlag(JSValueType type) {
  1.1306 +        return 1u << static_cast<unsigned>(type);
  1.1307 +    }
  1.1308 +
  1.1309 +    inline static uint16_t ValidFlags() {
  1.1310 +        return ((TypeToFlag(JSVAL_TYPE_OBJECT) << 1) - 1) & ~TypeToFlag(JSVAL_TYPE_MAGIC);
  1.1311 +    }
  1.1312 +
  1.1313 +    TypeCheckPrimitiveSetStub(Kind kind, JitCode *stubCode, uint16_t flags)
  1.1314 +        : ICStub(kind, stubCode)
  1.1315 +    {
  1.1316 +        JS_ASSERT(kind == TypeMonitor_PrimitiveSet || kind == TypeUpdate_PrimitiveSet);
  1.1317 +        JS_ASSERT(flags && !(flags & ~ValidFlags()));
  1.1318 +        extra_ = flags;
  1.1319 +    }
  1.1320 +
  1.1321 +    TypeCheckPrimitiveSetStub *updateTypesAndCode(uint16_t flags, JitCode *code) {
  1.1322 +        JS_ASSERT(flags && !(flags & ~ValidFlags()));
  1.1323 +        if (!code)
  1.1324 +            return nullptr;
  1.1325 +        extra_ = flags;
  1.1326 +        updateCode(code);
  1.1327 +        return this;
  1.1328 +    }
  1.1329 +
  1.1330 +  public:
  1.1331 +    uint16_t typeFlags() const {
  1.1332 +        return extra_;
  1.1333 +    }
  1.1334 +
  1.1335 +    bool containsType(JSValueType type) const {
  1.1336 +        JS_ASSERT(type <= JSVAL_TYPE_OBJECT);
  1.1337 +        JS_ASSERT(type != JSVAL_TYPE_MAGIC);
  1.1338 +        return extra_ & TypeToFlag(type);
  1.1339 +    }
  1.1340 +
  1.1341 +    ICTypeMonitor_PrimitiveSet *toMonitorStub() {
  1.1342 +        return toTypeMonitor_PrimitiveSet();
  1.1343 +    }
  1.1344 +
  1.1345 +    ICTypeUpdate_PrimitiveSet *toUpdateStub() {
  1.1346 +        return toTypeUpdate_PrimitiveSet();
  1.1347 +    }
  1.1348 +
  1.1349 +    class Compiler : public ICStubCompiler {
  1.1350 +      protected:
  1.1351 +        TypeCheckPrimitiveSetStub *existingStub_;
  1.1352 +        uint16_t flags_;
  1.1353 +
  1.1354 +        virtual int32_t getKey() const {
  1.1355 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(flags_) << 16);
  1.1356 +        }
  1.1357 +
  1.1358 +      public:
  1.1359 +        Compiler(JSContext *cx, Kind kind, TypeCheckPrimitiveSetStub *existingStub,
  1.1360 +                 JSValueType type)
  1.1361 +          : ICStubCompiler(cx, kind),
  1.1362 +            existingStub_(existingStub),
  1.1363 +            flags_((existingStub ? existingStub->typeFlags() : 0) | TypeToFlag(type))
  1.1364 +        {
  1.1365 +            JS_ASSERT_IF(existingStub_, flags_ != existingStub_->typeFlags());
  1.1366 +        }
  1.1367 +
  1.1368 +        TypeCheckPrimitiveSetStub *updateStub() {
  1.1369 +            JS_ASSERT(existingStub_);
  1.1370 +            return existingStub_->updateTypesAndCode(flags_, getStubCode());
  1.1371 +        }
  1.1372 +    };
  1.1373 +};
  1.1374 +
  1.1375 +// TypeMonitor
  1.1376 +
  1.1377 +// The TypeMonitor fallback stub is not always a regular fallback stub. When
  1.1378 +// used for monitoring the values pushed by a bytecode it doesn't hold a
  1.1379 +// pointer to the IC entry, but rather back to the main fallback stub for the
  1.1380 +// IC (from which a pointer to the IC entry can be retrieved). When monitoring
  1.1381 +// the types of 'this', arguments or other values with no associated IC, there
  1.1382 +// is no main fallback stub, and the IC entry is referenced directly.
  1.1383 +class ICTypeMonitor_Fallback : public ICStub
  1.1384 +{
  1.1385 +    friend class ICStubSpace;
  1.1386 +
  1.1387 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.1388 +
  1.1389 +    // Pointer to the main fallback stub for the IC or to the main IC entry,
  1.1390 +    // depending on hasFallbackStub.
  1.1391 +    union {
  1.1392 +        ICMonitoredFallbackStub *mainFallbackStub_;
  1.1393 +        ICEntry *icEntry_;
  1.1394 +    };
  1.1395 +
  1.1396 +    // Pointer to the first monitor stub.
  1.1397 +    ICStub *firstMonitorStub_;
  1.1398 +
  1.1399 +    // Address of the last monitor stub's field pointing to this
  1.1400 +    // fallback monitor stub.  This will get updated when new
  1.1401 +    // monitor stubs are created and added.
  1.1402 +    ICStub **lastMonitorStubPtrAddr_;
  1.1403 +
  1.1404 +    // Count of optimized type monitor stubs in this chain.
  1.1405 +    uint32_t numOptimizedMonitorStubs_ : 8;
  1.1406 +
  1.1407 +    // Whether this has a fallback stub referring to the IC entry.
  1.1408 +    bool hasFallbackStub_ : 1;
  1.1409 +
  1.1410 +    // Index of 'this' or argument which is being monitored, or BYTECODE_INDEX
  1.1411 +    // if this is monitoring the types of values pushed at some bytecode.
  1.1412 +    uint32_t argumentIndex_ : 23;
  1.1413 +
  1.1414 +    static const uint32_t BYTECODE_INDEX = (1 << 23) - 1;
  1.1415 +
  1.1416 +    ICTypeMonitor_Fallback(JitCode *stubCode, ICMonitoredFallbackStub *mainFallbackStub,
  1.1417 +                           uint32_t argumentIndex)
  1.1418 +      : ICStub(ICStub::TypeMonitor_Fallback, stubCode),
  1.1419 +        mainFallbackStub_(mainFallbackStub),
  1.1420 +        firstMonitorStub_(thisFromCtor()),
  1.1421 +        lastMonitorStubPtrAddr_(nullptr),
  1.1422 +        numOptimizedMonitorStubs_(0),
  1.1423 +        hasFallbackStub_(mainFallbackStub != nullptr),
  1.1424 +        argumentIndex_(argumentIndex)
  1.1425 +    { }
  1.1426 +
  1.1427 +    ICTypeMonitor_Fallback *thisFromCtor() {
  1.1428 +        return this;
  1.1429 +    }
  1.1430 +
  1.1431 +    void addOptimizedMonitorStub(ICStub *stub) {
  1.1432 +        stub->setNext(this);
  1.1433 +
  1.1434 +        JS_ASSERT((lastMonitorStubPtrAddr_ != nullptr) ==
  1.1435 +                  (numOptimizedMonitorStubs_ || !hasFallbackStub_));
  1.1436 +
  1.1437 +        if (lastMonitorStubPtrAddr_)
  1.1438 +            *lastMonitorStubPtrAddr_ = stub;
  1.1439 +
  1.1440 +        if (numOptimizedMonitorStubs_ == 0) {
  1.1441 +            JS_ASSERT(firstMonitorStub_ == this);
  1.1442 +            firstMonitorStub_ = stub;
  1.1443 +        } else {
  1.1444 +            JS_ASSERT(firstMonitorStub_ != nullptr);
  1.1445 +        }
  1.1446 +
  1.1447 +        lastMonitorStubPtrAddr_ = stub->addressOfNext();
  1.1448 +        numOptimizedMonitorStubs_++;
  1.1449 +    }
  1.1450 +
  1.1451 +  public:
  1.1452 +    static inline ICTypeMonitor_Fallback *New(
  1.1453 +        ICStubSpace *space, JitCode *code, ICMonitoredFallbackStub *mainFbStub,
  1.1454 +        uint32_t argumentIndex)
  1.1455 +    {
  1.1456 +        if (!code)
  1.1457 +            return nullptr;
  1.1458 +        return space->allocate<ICTypeMonitor_Fallback>(code, mainFbStub, argumentIndex);
  1.1459 +    }
  1.1460 +
  1.1461 +    bool hasStub(ICStub::Kind kind) {
  1.1462 +        ICStub *stub = firstMonitorStub_;
  1.1463 +        do {
  1.1464 +            if (stub->kind() == kind)
  1.1465 +                return true;
  1.1466 +
  1.1467 +            stub = stub->next();
  1.1468 +        } while (stub);
  1.1469 +
  1.1470 +        return false;
  1.1471 +    }
  1.1472 +
  1.1473 +    inline ICFallbackStub *mainFallbackStub() const {
  1.1474 +        JS_ASSERT(hasFallbackStub_);
  1.1475 +        return mainFallbackStub_;
  1.1476 +    }
  1.1477 +
  1.1478 +    inline ICEntry *icEntry() const {
  1.1479 +        return hasFallbackStub_ ? mainFallbackStub()->icEntry() : icEntry_;
  1.1480 +    }
  1.1481 +
  1.1482 +    inline ICStub *firstMonitorStub() const {
  1.1483 +        return firstMonitorStub_;
  1.1484 +    }
  1.1485 +
  1.1486 +    static inline size_t offsetOfFirstMonitorStub() {
  1.1487 +        return offsetof(ICTypeMonitor_Fallback, firstMonitorStub_);
  1.1488 +    }
  1.1489 +
  1.1490 +    inline uint32_t numOptimizedMonitorStubs() const {
  1.1491 +        return numOptimizedMonitorStubs_;
  1.1492 +    }
  1.1493 +
  1.1494 +    inline bool monitorsThis() const {
  1.1495 +        return argumentIndex_ == 0;
  1.1496 +    }
  1.1497 +
  1.1498 +    inline bool monitorsArgument(uint32_t *pargument) const {
  1.1499 +        if (argumentIndex_ > 0 && argumentIndex_ < BYTECODE_INDEX) {
  1.1500 +            *pargument = argumentIndex_ - 1;
  1.1501 +            return true;
  1.1502 +        }
  1.1503 +        return false;
  1.1504 +    }
  1.1505 +
  1.1506 +    inline bool monitorsBytecode() const {
  1.1507 +        return argumentIndex_ == BYTECODE_INDEX;
  1.1508 +    }
  1.1509 +
  1.1510 +    // Fixup the IC entry as for a normal fallback stub, for this/arguments.
  1.1511 +    void fixupICEntry(ICEntry *icEntry) {
  1.1512 +        JS_ASSERT(!hasFallbackStub_);
  1.1513 +        JS_ASSERT(icEntry_ == nullptr);
  1.1514 +        JS_ASSERT(lastMonitorStubPtrAddr_ == nullptr);
  1.1515 +        icEntry_ = icEntry;
  1.1516 +        lastMonitorStubPtrAddr_ = icEntry_->addressOfFirstStub();
  1.1517 +    }
  1.1518 +
  1.1519 +    // Create a new monitor stub for the type of the given value, and
  1.1520 +    // add it to this chain.
  1.1521 +    bool addMonitorStubForValue(JSContext *cx, JSScript *script, HandleValue val);
  1.1522 +
  1.1523 +    void resetMonitorStubChain(Zone *zone);
  1.1524 +
  1.1525 +    // Compiler for this stub kind.
  1.1526 +    class Compiler : public ICStubCompiler {
  1.1527 +        ICMonitoredFallbackStub *mainFallbackStub_;
  1.1528 +        uint32_t argumentIndex_;
  1.1529 +
  1.1530 +      protected:
  1.1531 +        bool generateStubCode(MacroAssembler &masm);
  1.1532 +
  1.1533 +      public:
  1.1534 +        Compiler(JSContext *cx, ICMonitoredFallbackStub *mainFallbackStub)
  1.1535 +          : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
  1.1536 +            mainFallbackStub_(mainFallbackStub),
  1.1537 +            argumentIndex_(BYTECODE_INDEX)
  1.1538 +        { }
  1.1539 +
  1.1540 +        Compiler(JSContext *cx, uint32_t argumentIndex)
  1.1541 +          : ICStubCompiler(cx, ICStub::TypeMonitor_Fallback),
  1.1542 +            mainFallbackStub_(nullptr),
  1.1543 +            argumentIndex_(argumentIndex)
  1.1544 +        { }
  1.1545 +
  1.1546 +        ICTypeMonitor_Fallback *getStub(ICStubSpace *space) {
  1.1547 +            return ICTypeMonitor_Fallback::New(space, getStubCode(), mainFallbackStub_,
  1.1548 +                                               argumentIndex_);
  1.1549 +        }
  1.1550 +    };
  1.1551 +};
  1.1552 +
  1.1553 +class ICTypeMonitor_PrimitiveSet : public TypeCheckPrimitiveSetStub
  1.1554 +{
  1.1555 +    friend class ICStubSpace;
  1.1556 +
  1.1557 +    ICTypeMonitor_PrimitiveSet(JitCode *stubCode, uint16_t flags)
  1.1558 +        : TypeCheckPrimitiveSetStub(TypeMonitor_PrimitiveSet, stubCode, flags)
  1.1559 +    {}
  1.1560 +
  1.1561 +  public:
  1.1562 +    static inline ICTypeMonitor_PrimitiveSet *New(ICStubSpace *space, JitCode *code,
  1.1563 +                                                  uint16_t flags)
  1.1564 +    {
  1.1565 +        if (!code)
  1.1566 +            return nullptr;
  1.1567 +        return space->allocate<ICTypeMonitor_PrimitiveSet>(code, flags);
  1.1568 +    }
  1.1569 +
  1.1570 +    class Compiler : public TypeCheckPrimitiveSetStub::Compiler {
  1.1571 +      protected:
  1.1572 +        bool generateStubCode(MacroAssembler &masm);
  1.1573 +
  1.1574 +      public:
  1.1575 +        Compiler(JSContext *cx, ICTypeMonitor_PrimitiveSet *existingStub, JSValueType type)
  1.1576 +          : TypeCheckPrimitiveSetStub::Compiler(cx, TypeMonitor_PrimitiveSet, existingStub, type)
  1.1577 +        {}
  1.1578 +
  1.1579 +        ICTypeMonitor_PrimitiveSet *updateStub() {
  1.1580 +            TypeCheckPrimitiveSetStub *stub =
  1.1581 +                this->TypeCheckPrimitiveSetStub::Compiler::updateStub();
  1.1582 +            if (!stub)
  1.1583 +                return nullptr;
  1.1584 +            return stub->toMonitorStub();
  1.1585 +        }
  1.1586 +
  1.1587 +        ICTypeMonitor_PrimitiveSet *getStub(ICStubSpace *space) {
  1.1588 +            JS_ASSERT(!existingStub_);
  1.1589 +            return ICTypeMonitor_PrimitiveSet::New(space, getStubCode(), flags_);
  1.1590 +        }
  1.1591 +    };
  1.1592 +};
  1.1593 +
  1.1594 +class ICTypeMonitor_SingleObject : public ICStub
  1.1595 +{
  1.1596 +    friend class ICStubSpace;
  1.1597 +
  1.1598 +    HeapPtrObject obj_;
  1.1599 +
  1.1600 +    ICTypeMonitor_SingleObject(JitCode *stubCode, HandleObject obj);
  1.1601 +
  1.1602 +  public:
  1.1603 +    static inline ICTypeMonitor_SingleObject *New(
  1.1604 +            ICStubSpace *space, JitCode *code, HandleObject obj)
  1.1605 +    {
  1.1606 +        if (!code)
  1.1607 +            return nullptr;
  1.1608 +        return space->allocate<ICTypeMonitor_SingleObject>(code, obj);
  1.1609 +    }
  1.1610 +
  1.1611 +    HeapPtrObject &object() {
  1.1612 +        return obj_;
  1.1613 +    }
  1.1614 +
  1.1615 +    static size_t offsetOfObject() {
  1.1616 +        return offsetof(ICTypeMonitor_SingleObject, obj_);
  1.1617 +    }
  1.1618 +
  1.1619 +    class Compiler : public ICStubCompiler {
  1.1620 +      protected:
  1.1621 +        HandleObject obj_;
  1.1622 +        bool generateStubCode(MacroAssembler &masm);
  1.1623 +
  1.1624 +      public:
  1.1625 +        Compiler(JSContext *cx, HandleObject obj)
  1.1626 +          : ICStubCompiler(cx, TypeMonitor_SingleObject),
  1.1627 +            obj_(obj)
  1.1628 +        { }
  1.1629 +
  1.1630 +        ICTypeMonitor_SingleObject *getStub(ICStubSpace *space) {
  1.1631 +            return ICTypeMonitor_SingleObject::New(space, getStubCode(), obj_);
  1.1632 +        }
  1.1633 +    };
  1.1634 +};
  1.1635 +
  1.1636 +class ICTypeMonitor_TypeObject : public ICStub
  1.1637 +{
  1.1638 +    friend class ICStubSpace;
  1.1639 +
  1.1640 +    HeapPtrTypeObject type_;
  1.1641 +
  1.1642 +    ICTypeMonitor_TypeObject(JitCode *stubCode, HandleTypeObject type);
  1.1643 +
  1.1644 +  public:
  1.1645 +    static inline ICTypeMonitor_TypeObject *New(
  1.1646 +            ICStubSpace *space, JitCode *code, HandleTypeObject type)
  1.1647 +    {
  1.1648 +        if (!code)
  1.1649 +            return nullptr;
  1.1650 +        return space->allocate<ICTypeMonitor_TypeObject>(code, type);
  1.1651 +    }
  1.1652 +
  1.1653 +    HeapPtrTypeObject &type() {
  1.1654 +        return type_;
  1.1655 +    }
  1.1656 +
  1.1657 +    static size_t offsetOfType() {
  1.1658 +        return offsetof(ICTypeMonitor_TypeObject, type_);
  1.1659 +    }
  1.1660 +
  1.1661 +    class Compiler : public ICStubCompiler {
  1.1662 +      protected:
  1.1663 +        HandleTypeObject type_;
  1.1664 +        bool generateStubCode(MacroAssembler &masm);
  1.1665 +
  1.1666 +      public:
  1.1667 +        Compiler(JSContext *cx, HandleTypeObject type)
  1.1668 +          : ICStubCompiler(cx, TypeMonitor_TypeObject),
  1.1669 +            type_(type)
  1.1670 +        { }
  1.1671 +
  1.1672 +        ICTypeMonitor_TypeObject *getStub(ICStubSpace *space) {
  1.1673 +            return ICTypeMonitor_TypeObject::New(space, getStubCode(), type_);
  1.1674 +        }
  1.1675 +    };
  1.1676 +};
  1.1677 +
  1.1678 +// TypeUpdate
  1.1679 +
  1.1680 +extern const VMFunction DoTypeUpdateFallbackInfo;
  1.1681 +
  1.1682 +// The TypeUpdate fallback is not a regular fallback, since it just
  1.1683 +// forwards to a different entry point in the main fallback stub.
  1.1684 +class ICTypeUpdate_Fallback : public ICStub
  1.1685 +{
  1.1686 +    friend class ICStubSpace;
  1.1687 +
  1.1688 +    ICTypeUpdate_Fallback(JitCode *stubCode)
  1.1689 +      : ICStub(ICStub::TypeUpdate_Fallback, stubCode)
  1.1690 +    {}
  1.1691 +
  1.1692 +  public:
  1.1693 +    static inline ICTypeUpdate_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.1694 +        if (!code)
  1.1695 +            return nullptr;
  1.1696 +        return space->allocate<ICTypeUpdate_Fallback>(code);
  1.1697 +    }
  1.1698 +
  1.1699 +    // Compiler for this stub kind.
  1.1700 +    class Compiler : public ICStubCompiler {
  1.1701 +      protected:
  1.1702 +        bool generateStubCode(MacroAssembler &masm);
  1.1703 +
  1.1704 +      public:
  1.1705 +        Compiler(JSContext *cx)
  1.1706 +          : ICStubCompiler(cx, ICStub::TypeUpdate_Fallback)
  1.1707 +        { }
  1.1708 +
  1.1709 +        ICTypeUpdate_Fallback *getStub(ICStubSpace *space) {
  1.1710 +            return ICTypeUpdate_Fallback::New(space, getStubCode());
  1.1711 +        }
  1.1712 +    };
  1.1713 +};
  1.1714 +
  1.1715 +class ICTypeUpdate_PrimitiveSet : public TypeCheckPrimitiveSetStub
  1.1716 +{
  1.1717 +    friend class ICStubSpace;
  1.1718 +
  1.1719 +    ICTypeUpdate_PrimitiveSet(JitCode *stubCode, uint16_t flags)
  1.1720 +        : TypeCheckPrimitiveSetStub(TypeUpdate_PrimitiveSet, stubCode, flags)
  1.1721 +    {}
  1.1722 +
  1.1723 +  public:
  1.1724 +    static inline ICTypeUpdate_PrimitiveSet *New(ICStubSpace *space, JitCode *code,
  1.1725 +                                                 uint16_t flags)
  1.1726 +    {
  1.1727 +        if (!code)
  1.1728 +            return nullptr;
  1.1729 +        return space->allocate<ICTypeUpdate_PrimitiveSet>(code, flags);
  1.1730 +    }
  1.1731 +
  1.1732 +    class Compiler : public TypeCheckPrimitiveSetStub::Compiler {
  1.1733 +      protected:
  1.1734 +        bool generateStubCode(MacroAssembler &masm);
  1.1735 +
  1.1736 +      public:
  1.1737 +        Compiler(JSContext *cx, ICTypeUpdate_PrimitiveSet *existingStub, JSValueType type)
  1.1738 +          : TypeCheckPrimitiveSetStub::Compiler(cx, TypeUpdate_PrimitiveSet, existingStub, type)
  1.1739 +        {}
  1.1740 +
  1.1741 +        ICTypeUpdate_PrimitiveSet *updateStub() {
  1.1742 +            TypeCheckPrimitiveSetStub *stub =
  1.1743 +                this->TypeCheckPrimitiveSetStub::Compiler::updateStub();
  1.1744 +            if (!stub)
  1.1745 +                return nullptr;
  1.1746 +            return stub->toUpdateStub();
  1.1747 +        }
  1.1748 +
  1.1749 +        ICTypeUpdate_PrimitiveSet *getStub(ICStubSpace *space) {
  1.1750 +            JS_ASSERT(!existingStub_);
  1.1751 +            return ICTypeUpdate_PrimitiveSet::New(space, getStubCode(), flags_);
  1.1752 +        }
  1.1753 +    };
  1.1754 +};
  1.1755 +
  1.1756 +// Type update stub to handle a singleton object.
  1.1757 +class ICTypeUpdate_SingleObject : public ICStub
  1.1758 +{
  1.1759 +    friend class ICStubSpace;
  1.1760 +
  1.1761 +    HeapPtrObject obj_;
  1.1762 +
  1.1763 +    ICTypeUpdate_SingleObject(JitCode *stubCode, HandleObject obj);
  1.1764 +
  1.1765 +  public:
  1.1766 +    static inline ICTypeUpdate_SingleObject *New(ICStubSpace *space, JitCode *code,
  1.1767 +                                                 HandleObject obj)
  1.1768 +    {
  1.1769 +        if (!code)
  1.1770 +            return nullptr;
  1.1771 +        return space->allocate<ICTypeUpdate_SingleObject>(code, obj);
  1.1772 +    }
  1.1773 +
  1.1774 +    HeapPtrObject &object() {
  1.1775 +        return obj_;
  1.1776 +    }
  1.1777 +
  1.1778 +    static size_t offsetOfObject() {
  1.1779 +        return offsetof(ICTypeUpdate_SingleObject, obj_);
  1.1780 +    }
  1.1781 +
  1.1782 +    class Compiler : public ICStubCompiler {
  1.1783 +      protected:
  1.1784 +        HandleObject obj_;
  1.1785 +        bool generateStubCode(MacroAssembler &masm);
  1.1786 +
  1.1787 +      public:
  1.1788 +        Compiler(JSContext *cx, HandleObject obj)
  1.1789 +          : ICStubCompiler(cx, TypeUpdate_SingleObject),
  1.1790 +            obj_(obj)
  1.1791 +        { }
  1.1792 +
  1.1793 +        ICTypeUpdate_SingleObject *getStub(ICStubSpace *space) {
  1.1794 +            return ICTypeUpdate_SingleObject::New(space, getStubCode(), obj_);
  1.1795 +        }
  1.1796 +    };
  1.1797 +};
  1.1798 +
  1.1799 +// Type update stub to handle a single TypeObject.
  1.1800 +class ICTypeUpdate_TypeObject : public ICStub
  1.1801 +{
  1.1802 +    friend class ICStubSpace;
  1.1803 +
  1.1804 +    HeapPtrTypeObject type_;
  1.1805 +
  1.1806 +    ICTypeUpdate_TypeObject(JitCode *stubCode, HandleTypeObject type);
  1.1807 +
  1.1808 +  public:
  1.1809 +    static inline ICTypeUpdate_TypeObject *New(ICStubSpace *space, JitCode *code,
  1.1810 +                                               HandleTypeObject type)
  1.1811 +    {
  1.1812 +        if (!code)
  1.1813 +            return nullptr;
  1.1814 +        return space->allocate<ICTypeUpdate_TypeObject>(code, type);
  1.1815 +    }
  1.1816 +
  1.1817 +    HeapPtrTypeObject &type() {
  1.1818 +        return type_;
  1.1819 +    }
  1.1820 +
  1.1821 +    static size_t offsetOfType() {
  1.1822 +        return offsetof(ICTypeUpdate_TypeObject, type_);
  1.1823 +    }
  1.1824 +
  1.1825 +    class Compiler : public ICStubCompiler {
  1.1826 +      protected:
  1.1827 +        HandleTypeObject type_;
  1.1828 +        bool generateStubCode(MacroAssembler &masm);
  1.1829 +
  1.1830 +      public:
  1.1831 +        Compiler(JSContext *cx, HandleTypeObject type)
  1.1832 +          : ICStubCompiler(cx, TypeUpdate_TypeObject),
  1.1833 +            type_(type)
  1.1834 +        { }
  1.1835 +
  1.1836 +        ICTypeUpdate_TypeObject *getStub(ICStubSpace *space) {
  1.1837 +            return ICTypeUpdate_TypeObject::New(space, getStubCode(), type_);
  1.1838 +        }
  1.1839 +    };
  1.1840 +};
  1.1841 +
  1.1842 +// This
  1.1843 +//      JSOP_THIS
  1.1844 +
  1.1845 +class ICThis_Fallback : public ICFallbackStub
  1.1846 +{
  1.1847 +    friend class ICStubSpace;
  1.1848 +
  1.1849 +    ICThis_Fallback(JitCode *stubCode)
  1.1850 +      : ICFallbackStub(ICStub::This_Fallback, stubCode) {}
  1.1851 +
  1.1852 +  public:
  1.1853 +    static inline ICThis_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.1854 +        if (!code)
  1.1855 +            return nullptr;
  1.1856 +        return space->allocate<ICThis_Fallback>(code);
  1.1857 +    }
  1.1858 +
  1.1859 +    // Compiler for this stub kind.
  1.1860 +    class Compiler : public ICStubCompiler {
  1.1861 +      protected:
  1.1862 +        bool generateStubCode(MacroAssembler &masm);
  1.1863 +
  1.1864 +      public:
  1.1865 +        Compiler(JSContext *cx)
  1.1866 +          : ICStubCompiler(cx, ICStub::This_Fallback) {}
  1.1867 +
  1.1868 +        ICStub *getStub(ICStubSpace *space) {
  1.1869 +            return ICThis_Fallback::New(space, getStubCode());
  1.1870 +        }
  1.1871 +    };
  1.1872 +};
  1.1873 +
  1.1874 +class ICNewArray_Fallback : public ICFallbackStub
  1.1875 +{
  1.1876 +    friend class ICStubSpace;
  1.1877 +
  1.1878 +    HeapPtrObject templateObject_;
  1.1879 +
  1.1880 +    ICNewArray_Fallback(JitCode *stubCode, JSObject *templateObject)
  1.1881 +      : ICFallbackStub(ICStub::NewArray_Fallback, stubCode), templateObject_(templateObject)
  1.1882 +    {}
  1.1883 +
  1.1884 +  public:
  1.1885 +    static inline ICNewArray_Fallback *New(ICStubSpace *space, JitCode *code,
  1.1886 +                                           JSObject *templateObject) {
  1.1887 +        if (!code)
  1.1888 +            return nullptr;
  1.1889 +        return space->allocate<ICNewArray_Fallback>(code, templateObject);
  1.1890 +    }
  1.1891 +
  1.1892 +    class Compiler : public ICStubCompiler {
  1.1893 +        RootedObject templateObject;
  1.1894 +        bool generateStubCode(MacroAssembler &masm);
  1.1895 +
  1.1896 +      public:
  1.1897 +        Compiler(JSContext *cx, JSObject *templateObject)
  1.1898 +          : ICStubCompiler(cx, ICStub::NewArray_Fallback),
  1.1899 +            templateObject(cx, templateObject)
  1.1900 +        {}
  1.1901 +
  1.1902 +        ICStub *getStub(ICStubSpace *space) {
  1.1903 +            return ICNewArray_Fallback::New(space, getStubCode(), templateObject);
  1.1904 +        }
  1.1905 +    };
  1.1906 +
  1.1907 +    HeapPtrObject &templateObject() {
  1.1908 +        return templateObject_;
  1.1909 +    }
  1.1910 +};
  1.1911 +
  1.1912 +class ICNewObject_Fallback : public ICFallbackStub
  1.1913 +{
  1.1914 +    friend class ICStubSpace;
  1.1915 +
  1.1916 +    HeapPtrObject templateObject_;
  1.1917 +
  1.1918 +    ICNewObject_Fallback(JitCode *stubCode, JSObject *templateObject)
  1.1919 +      : ICFallbackStub(ICStub::NewObject_Fallback, stubCode), templateObject_(templateObject)
  1.1920 +    {}
  1.1921 +
  1.1922 +  public:
  1.1923 +    static inline ICNewObject_Fallback *New(ICStubSpace *space, JitCode *code,
  1.1924 +                                            JSObject *templateObject) {
  1.1925 +        if (!code)
  1.1926 +            return nullptr;
  1.1927 +        return space->allocate<ICNewObject_Fallback>(code, templateObject);
  1.1928 +    }
  1.1929 +
  1.1930 +    class Compiler : public ICStubCompiler {
  1.1931 +        RootedObject templateObject;
  1.1932 +        bool generateStubCode(MacroAssembler &masm);
  1.1933 +
  1.1934 +      public:
  1.1935 +        Compiler(JSContext *cx, JSObject *templateObject)
  1.1936 +          : ICStubCompiler(cx, ICStub::NewObject_Fallback),
  1.1937 +            templateObject(cx, templateObject)
  1.1938 +        {}
  1.1939 +
  1.1940 +        ICStub *getStub(ICStubSpace *space) {
  1.1941 +            return ICNewObject_Fallback::New(space, getStubCode(), templateObject);
  1.1942 +        }
  1.1943 +    };
  1.1944 +
  1.1945 +    HeapPtrObject &templateObject() {
  1.1946 +        return templateObject_;
  1.1947 +    }
  1.1948 +};
  1.1949 +
  1.1950 +// Compare
  1.1951 +//      JSOP_LT
  1.1952 +//      JSOP_GT
  1.1953 +
  1.1954 +class ICCompare_Fallback : public ICFallbackStub
  1.1955 +{
  1.1956 +    friend class ICStubSpace;
  1.1957 +
  1.1958 +    ICCompare_Fallback(JitCode *stubCode)
  1.1959 +      : ICFallbackStub(ICStub::Compare_Fallback, stubCode) {}
  1.1960 +
  1.1961 +  public:
  1.1962 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.1963 +
  1.1964 +    static inline ICCompare_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.1965 +        if (!code)
  1.1966 +            return nullptr;
  1.1967 +        return space->allocate<ICCompare_Fallback>(code);
  1.1968 +    }
  1.1969 +
  1.1970 +    // Compiler for this stub kind.
  1.1971 +    class Compiler : public ICStubCompiler {
  1.1972 +      protected:
  1.1973 +        bool generateStubCode(MacroAssembler &masm);
  1.1974 +
  1.1975 +      public:
  1.1976 +        Compiler(JSContext *cx)
  1.1977 +          : ICStubCompiler(cx, ICStub::Compare_Fallback) {}
  1.1978 +
  1.1979 +        ICStub *getStub(ICStubSpace *space) {
  1.1980 +            return ICCompare_Fallback::New(space, getStubCode());
  1.1981 +        }
  1.1982 +    };
  1.1983 +};
  1.1984 +
  1.1985 +class ICCompare_Int32 : public ICStub
  1.1986 +{
  1.1987 +    friend class ICStubSpace;
  1.1988 +
  1.1989 +    ICCompare_Int32(JitCode *stubCode)
  1.1990 +      : ICStub(ICStub::Compare_Int32, stubCode) {}
  1.1991 +
  1.1992 +  public:
  1.1993 +    static inline ICCompare_Int32 *New(ICStubSpace *space, JitCode *code) {
  1.1994 +        if (!code)
  1.1995 +            return nullptr;
  1.1996 +        return space->allocate<ICCompare_Int32>(code);
  1.1997 +    }
  1.1998 +
  1.1999 +    // Compiler for this stub kind.
  1.2000 +    class Compiler : public ICMultiStubCompiler {
  1.2001 +      protected:
  1.2002 +        bool generateStubCode(MacroAssembler &masm);
  1.2003 +
  1.2004 +      public:
  1.2005 +        Compiler(JSContext *cx, JSOp op)
  1.2006 +          : ICMultiStubCompiler(cx, ICStub::Compare_Int32, op) {}
  1.2007 +
  1.2008 +        ICStub *getStub(ICStubSpace *space) {
  1.2009 +            return ICCompare_Int32::New(space, getStubCode());
  1.2010 +        }
  1.2011 +    };
  1.2012 +};
  1.2013 +
  1.2014 +class ICCompare_Double : public ICStub
  1.2015 +{
  1.2016 +    friend class ICStubSpace;
  1.2017 +
  1.2018 +    ICCompare_Double(JitCode *stubCode)
  1.2019 +      : ICStub(ICStub::Compare_Double, stubCode)
  1.2020 +    {}
  1.2021 +
  1.2022 +  public:
  1.2023 +    static inline ICCompare_Double *New(ICStubSpace *space, JitCode *code) {
  1.2024 +        if (!code)
  1.2025 +            return nullptr;
  1.2026 +        return space->allocate<ICCompare_Double>(code);
  1.2027 +    }
  1.2028 +
  1.2029 +    class Compiler : public ICMultiStubCompiler {
  1.2030 +      protected:
  1.2031 +        bool generateStubCode(MacroAssembler &masm);
  1.2032 +
  1.2033 +      public:
  1.2034 +        Compiler(JSContext *cx, JSOp op)
  1.2035 +          : ICMultiStubCompiler(cx, ICStub::Compare_Double, op)
  1.2036 +        {}
  1.2037 +
  1.2038 +        ICStub *getStub(ICStubSpace *space) {
  1.2039 +            return ICCompare_Double::New(space, getStubCode());
  1.2040 +        }
  1.2041 +    };
  1.2042 +};
  1.2043 +
  1.2044 +class ICCompare_NumberWithUndefined : public ICStub
  1.2045 +{
  1.2046 +    friend class ICStubSpace;
  1.2047 +
  1.2048 +    ICCompare_NumberWithUndefined(JitCode *stubCode, bool lhsIsUndefined)
  1.2049 +      : ICStub(ICStub::Compare_NumberWithUndefined, stubCode)
  1.2050 +    {
  1.2051 +        extra_ = lhsIsUndefined;
  1.2052 +    }
  1.2053 +
  1.2054 +  public:
  1.2055 +    static inline ICCompare_NumberWithUndefined *New(ICStubSpace *space, JitCode *code, bool lhsIsUndefined) {
  1.2056 +        if (!code)
  1.2057 +            return nullptr;
  1.2058 +        return space->allocate<ICCompare_NumberWithUndefined>(code, lhsIsUndefined);
  1.2059 +    }
  1.2060 +
  1.2061 +    bool lhsIsUndefined() {
  1.2062 +        return extra_;
  1.2063 +    }
  1.2064 +
  1.2065 +    class Compiler : public ICMultiStubCompiler {
  1.2066 +      protected:
  1.2067 +        bool generateStubCode(MacroAssembler &masm);
  1.2068 +
  1.2069 +        bool lhsIsUndefined;
  1.2070 +
  1.2071 +      public:
  1.2072 +        Compiler(JSContext *cx, JSOp op, bool lhsIsUndefined)
  1.2073 +          : ICMultiStubCompiler(cx, ICStub::Compare_NumberWithUndefined, op),
  1.2074 +            lhsIsUndefined(lhsIsUndefined)
  1.2075 +        {}
  1.2076 +
  1.2077 +        virtual int32_t getKey() const {
  1.2078 +            return static_cast<int32_t>(kind)
  1.2079 +                 | (static_cast<int32_t>(op) << 16)
  1.2080 +                 | (static_cast<int32_t>(lhsIsUndefined) << 24);
  1.2081 +        }
  1.2082 +
  1.2083 +        ICStub *getStub(ICStubSpace *space) {
  1.2084 +            return ICCompare_NumberWithUndefined::New(space, getStubCode(), lhsIsUndefined);
  1.2085 +        }
  1.2086 +    };
  1.2087 +};
  1.2088 +
  1.2089 +class ICCompare_String : public ICStub
  1.2090 +{
  1.2091 +    friend class ICStubSpace;
  1.2092 +
  1.2093 +    ICCompare_String(JitCode *stubCode)
  1.2094 +      : ICStub(ICStub::Compare_String, stubCode)
  1.2095 +    {}
  1.2096 +
  1.2097 +  public:
  1.2098 +    static inline ICCompare_String *New(ICStubSpace *space, JitCode *code) {
  1.2099 +        if (!code)
  1.2100 +            return nullptr;
  1.2101 +        return space->allocate<ICCompare_String>(code);
  1.2102 +    }
  1.2103 +
  1.2104 +    class Compiler : public ICMultiStubCompiler {
  1.2105 +      protected:
  1.2106 +        bool generateStubCode(MacroAssembler &masm);
  1.2107 +
  1.2108 +      public:
  1.2109 +        Compiler(JSContext *cx, JSOp op)
  1.2110 +          : ICMultiStubCompiler(cx, ICStub::Compare_String, op)
  1.2111 +        {}
  1.2112 +
  1.2113 +        ICStub *getStub(ICStubSpace *space) {
  1.2114 +            return ICCompare_String::New(space, getStubCode());
  1.2115 +        }
  1.2116 +    };
  1.2117 +};
  1.2118 +
  1.2119 +class ICCompare_Boolean : public ICStub
  1.2120 +{
  1.2121 +    friend class ICStubSpace;
  1.2122 +
  1.2123 +    ICCompare_Boolean(JitCode *stubCode)
  1.2124 +      : ICStub(ICStub::Compare_Boolean, stubCode)
  1.2125 +    {}
  1.2126 +
  1.2127 +  public:
  1.2128 +    static inline ICCompare_Boolean *New(ICStubSpace *space, JitCode *code) {
  1.2129 +        if (!code)
  1.2130 +            return nullptr;
  1.2131 +        return space->allocate<ICCompare_Boolean>(code);
  1.2132 +    }
  1.2133 +
  1.2134 +    class Compiler : public ICMultiStubCompiler {
  1.2135 +      protected:
  1.2136 +        bool generateStubCode(MacroAssembler &masm);
  1.2137 +
  1.2138 +      public:
  1.2139 +        Compiler(JSContext *cx, JSOp op)
  1.2140 +          : ICMultiStubCompiler(cx, ICStub::Compare_Boolean, op)
  1.2141 +        {}
  1.2142 +
  1.2143 +        ICStub *getStub(ICStubSpace *space) {
  1.2144 +            return ICCompare_Boolean::New(space, getStubCode());
  1.2145 +        }
  1.2146 +    };
  1.2147 +};
  1.2148 +
  1.2149 +class ICCompare_Object : public ICStub
  1.2150 +{
  1.2151 +    friend class ICStubSpace;
  1.2152 +
  1.2153 +    ICCompare_Object(JitCode *stubCode)
  1.2154 +      : ICStub(ICStub::Compare_Object, stubCode)
  1.2155 +    {}
  1.2156 +
  1.2157 +  public:
  1.2158 +    static inline ICCompare_Object *New(ICStubSpace *space, JitCode *code) {
  1.2159 +        if (!code)
  1.2160 +            return nullptr;
  1.2161 +        return space->allocate<ICCompare_Object>(code);
  1.2162 +    }
  1.2163 +
  1.2164 +    class Compiler : public ICMultiStubCompiler {
  1.2165 +      protected:
  1.2166 +        bool generateStubCode(MacroAssembler &masm);
  1.2167 +
  1.2168 +      public:
  1.2169 +        Compiler(JSContext *cx, JSOp op)
  1.2170 +          : ICMultiStubCompiler(cx, ICStub::Compare_Object, op)
  1.2171 +        {}
  1.2172 +
  1.2173 +        ICStub *getStub(ICStubSpace *space) {
  1.2174 +            return ICCompare_Object::New(space, getStubCode());
  1.2175 +        }
  1.2176 +    };
  1.2177 +};
  1.2178 +
  1.2179 +class ICCompare_ObjectWithUndefined : public ICStub
  1.2180 +{
  1.2181 +    friend class ICStubSpace;
  1.2182 +
  1.2183 +    ICCompare_ObjectWithUndefined(JitCode *stubCode)
  1.2184 +      : ICStub(ICStub::Compare_ObjectWithUndefined, stubCode)
  1.2185 +    {}
  1.2186 +
  1.2187 +  public:
  1.2188 +    static inline ICCompare_ObjectWithUndefined *New(ICStubSpace *space, JitCode *code) {
  1.2189 +        if (!code)
  1.2190 +            return nullptr;
  1.2191 +        return space->allocate<ICCompare_ObjectWithUndefined>(code);
  1.2192 +    }
  1.2193 +
  1.2194 +    class Compiler : public ICMultiStubCompiler {
  1.2195 +      protected:
  1.2196 +        bool generateStubCode(MacroAssembler &masm);
  1.2197 +
  1.2198 +        bool lhsIsUndefined;
  1.2199 +        bool compareWithNull;
  1.2200 +
  1.2201 +      public:
  1.2202 +        Compiler(JSContext *cx, JSOp op, bool lhsIsUndefined, bool compareWithNull)
  1.2203 +          : ICMultiStubCompiler(cx, ICStub::Compare_ObjectWithUndefined, op),
  1.2204 +            lhsIsUndefined(lhsIsUndefined),
  1.2205 +            compareWithNull(compareWithNull)
  1.2206 +        {}
  1.2207 +
  1.2208 +        virtual int32_t getKey() const {
  1.2209 +            return static_cast<int32_t>(kind)
  1.2210 +                 | (static_cast<int32_t>(op) << 16)
  1.2211 +                 | (static_cast<int32_t>(lhsIsUndefined) << 24)
  1.2212 +                 | (static_cast<int32_t>(compareWithNull) << 25);
  1.2213 +        }
  1.2214 +
  1.2215 +        ICStub *getStub(ICStubSpace *space) {
  1.2216 +            return ICCompare_ObjectWithUndefined::New(space, getStubCode());
  1.2217 +        }
  1.2218 +    };
  1.2219 +};
  1.2220 +
  1.2221 +class ICCompare_Int32WithBoolean : public ICStub
  1.2222 +{
  1.2223 +    friend class ICStubSpace;
  1.2224 +
  1.2225 +    ICCompare_Int32WithBoolean(JitCode *stubCode, bool lhsIsInt32)
  1.2226 +      : ICStub(ICStub::Compare_Int32WithBoolean, stubCode)
  1.2227 +    {
  1.2228 +        extra_ = lhsIsInt32;
  1.2229 +    }
  1.2230 +
  1.2231 +  public:
  1.2232 +    static inline ICCompare_Int32WithBoolean *New(ICStubSpace *space, JitCode *code,
  1.2233 +                                                  bool lhsIsInt32)
  1.2234 +    {
  1.2235 +        if (!code)
  1.2236 +            return nullptr;
  1.2237 +        return space->allocate<ICCompare_Int32WithBoolean>(code, lhsIsInt32);
  1.2238 +    }
  1.2239 +
  1.2240 +    bool lhsIsInt32() const {
  1.2241 +        return extra_;
  1.2242 +    }
  1.2243 +
  1.2244 +    // Compiler for this stub kind.
  1.2245 +    class Compiler : public ICStubCompiler {
  1.2246 +      protected:
  1.2247 +        JSOp op_;
  1.2248 +        bool lhsIsInt32_;
  1.2249 +        bool generateStubCode(MacroAssembler &masm);
  1.2250 +
  1.2251 +        virtual int32_t getKey() const {
  1.2252 +            return (static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) |
  1.2253 +                    (static_cast<int32_t>(lhsIsInt32_) << 24));
  1.2254 +        }
  1.2255 +
  1.2256 +      public:
  1.2257 +        Compiler(JSContext *cx, JSOp op, bool lhsIsInt32)
  1.2258 +          : ICStubCompiler(cx, ICStub::Compare_Int32WithBoolean),
  1.2259 +            op_(op),
  1.2260 +            lhsIsInt32_(lhsIsInt32)
  1.2261 +        {}
  1.2262 +
  1.2263 +        ICStub *getStub(ICStubSpace *space) {
  1.2264 +            return ICCompare_Int32WithBoolean::New(space, getStubCode(), lhsIsInt32_);
  1.2265 +        }
  1.2266 +    };
  1.2267 +};
  1.2268 +
  1.2269 +// ToBool
  1.2270 +//      JSOP_IFNE
  1.2271 +
  1.2272 +class ICToBool_Fallback : public ICFallbackStub
  1.2273 +{
  1.2274 +    friend class ICStubSpace;
  1.2275 +
  1.2276 +    ICToBool_Fallback(JitCode *stubCode)
  1.2277 +      : ICFallbackStub(ICStub::ToBool_Fallback, stubCode) {}
  1.2278 +
  1.2279 +  public:
  1.2280 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.2281 +
  1.2282 +    static inline ICToBool_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.2283 +        if (!code)
  1.2284 +            return nullptr;
  1.2285 +        return space->allocate<ICToBool_Fallback>(code);
  1.2286 +    }
  1.2287 +
  1.2288 +    // Compiler for this stub kind.
  1.2289 +    class Compiler : public ICStubCompiler {
  1.2290 +      protected:
  1.2291 +        bool generateStubCode(MacroAssembler &masm);
  1.2292 +
  1.2293 +      public:
  1.2294 +        Compiler(JSContext *cx)
  1.2295 +          : ICStubCompiler(cx, ICStub::ToBool_Fallback) {}
  1.2296 +
  1.2297 +        ICStub *getStub(ICStubSpace *space) {
  1.2298 +            return ICToBool_Fallback::New(space, getStubCode());
  1.2299 +        }
  1.2300 +    };
  1.2301 +};
  1.2302 +
  1.2303 +class ICToBool_Int32 : public ICStub
  1.2304 +{
  1.2305 +    friend class ICStubSpace;
  1.2306 +
  1.2307 +    ICToBool_Int32(JitCode *stubCode)
  1.2308 +      : ICStub(ICStub::ToBool_Int32, stubCode) {}
  1.2309 +
  1.2310 +  public:
  1.2311 +    static inline ICToBool_Int32 *New(ICStubSpace *space, JitCode *code) {
  1.2312 +        if (!code)
  1.2313 +            return nullptr;
  1.2314 +        return space->allocate<ICToBool_Int32>(code);
  1.2315 +    }
  1.2316 +
  1.2317 +    // Compiler for this stub kind.
  1.2318 +    class Compiler : public ICStubCompiler {
  1.2319 +      protected:
  1.2320 +        bool generateStubCode(MacroAssembler &masm);
  1.2321 +
  1.2322 +      public:
  1.2323 +        Compiler(JSContext *cx)
  1.2324 +          : ICStubCompiler(cx, ICStub::ToBool_Int32) {}
  1.2325 +
  1.2326 +        ICStub *getStub(ICStubSpace *space) {
  1.2327 +            return ICToBool_Int32::New(space, getStubCode());
  1.2328 +        }
  1.2329 +    };
  1.2330 +};
  1.2331 +
  1.2332 +class ICToBool_String : public ICStub
  1.2333 +{
  1.2334 +    friend class ICStubSpace;
  1.2335 +
  1.2336 +    ICToBool_String(JitCode *stubCode)
  1.2337 +      : ICStub(ICStub::ToBool_String, stubCode) {}
  1.2338 +
  1.2339 +  public:
  1.2340 +    static inline ICToBool_String *New(ICStubSpace *space, JitCode *code) {
  1.2341 +        if (!code)
  1.2342 +            return nullptr;
  1.2343 +        return space->allocate<ICToBool_String>(code);
  1.2344 +    }
  1.2345 +
  1.2346 +    // Compiler for this stub kind.
  1.2347 +    class Compiler : public ICStubCompiler {
  1.2348 +      protected:
  1.2349 +        bool generateStubCode(MacroAssembler &masm);
  1.2350 +
  1.2351 +      public:
  1.2352 +        Compiler(JSContext *cx)
  1.2353 +          : ICStubCompiler(cx, ICStub::ToBool_String) {}
  1.2354 +
  1.2355 +        ICStub *getStub(ICStubSpace *space) {
  1.2356 +            return ICToBool_String::New(space, getStubCode());
  1.2357 +        }
  1.2358 +    };
  1.2359 +};
  1.2360 +
  1.2361 +class ICToBool_NullUndefined : public ICStub
  1.2362 +{
  1.2363 +    friend class ICStubSpace;
  1.2364 +
  1.2365 +    ICToBool_NullUndefined(JitCode *stubCode)
  1.2366 +      : ICStub(ICStub::ToBool_NullUndefined, stubCode) {}
  1.2367 +
  1.2368 +  public:
  1.2369 +    static inline ICToBool_NullUndefined *New(ICStubSpace *space, JitCode *code) {
  1.2370 +        if (!code)
  1.2371 +            return nullptr;
  1.2372 +        return space->allocate<ICToBool_NullUndefined>(code);
  1.2373 +    }
  1.2374 +
  1.2375 +    // Compiler for this stub kind.
  1.2376 +    class Compiler : public ICStubCompiler {
  1.2377 +      protected:
  1.2378 +        bool generateStubCode(MacroAssembler &masm);
  1.2379 +
  1.2380 +      public:
  1.2381 +        Compiler(JSContext *cx)
  1.2382 +          : ICStubCompiler(cx, ICStub::ToBool_NullUndefined) {}
  1.2383 +
  1.2384 +        ICStub *getStub(ICStubSpace *space) {
  1.2385 +            return ICToBool_NullUndefined::New(space, getStubCode());
  1.2386 +        }
  1.2387 +    };
  1.2388 +};
  1.2389 +
  1.2390 +class ICToBool_Double : public ICStub
  1.2391 +{
  1.2392 +    friend class ICStubSpace;
  1.2393 +
  1.2394 +    ICToBool_Double(JitCode *stubCode)
  1.2395 +      : ICStub(ICStub::ToBool_Double, stubCode) {}
  1.2396 +
  1.2397 +  public:
  1.2398 +    static inline ICToBool_Double *New(ICStubSpace *space, JitCode *code) {
  1.2399 +        if (!code)
  1.2400 +            return nullptr;
  1.2401 +        return space->allocate<ICToBool_Double>(code);
  1.2402 +    }
  1.2403 +
  1.2404 +    // Compiler for this stub kind.
  1.2405 +    class Compiler : public ICStubCompiler {
  1.2406 +      protected:
  1.2407 +        bool generateStubCode(MacroAssembler &masm);
  1.2408 +
  1.2409 +      public:
  1.2410 +        Compiler(JSContext *cx)
  1.2411 +          : ICStubCompiler(cx, ICStub::ToBool_Double) {}
  1.2412 +
  1.2413 +        ICStub *getStub(ICStubSpace *space) {
  1.2414 +            return ICToBool_Double::New(space, getStubCode());
  1.2415 +        }
  1.2416 +    };
  1.2417 +};
  1.2418 +
  1.2419 +class ICToBool_Object : public ICStub
  1.2420 +{
  1.2421 +    friend class ICStubSpace;
  1.2422 +
  1.2423 +    ICToBool_Object(JitCode *stubCode)
  1.2424 +      : ICStub(ICStub::ToBool_Object, stubCode) {}
  1.2425 +
  1.2426 +  public:
  1.2427 +    static inline ICToBool_Object *New(ICStubSpace *space, JitCode *code) {
  1.2428 +        if (!code)
  1.2429 +            return nullptr;
  1.2430 +        return space->allocate<ICToBool_Object>(code);
  1.2431 +    }
  1.2432 +
  1.2433 +    // Compiler for this stub kind.
  1.2434 +    class Compiler : public ICStubCompiler {
  1.2435 +      protected:
  1.2436 +        bool generateStubCode(MacroAssembler &masm);
  1.2437 +
  1.2438 +      public:
  1.2439 +        Compiler(JSContext *cx)
  1.2440 +          : ICStubCompiler(cx, ICStub::ToBool_Object) {}
  1.2441 +
  1.2442 +        ICStub *getStub(ICStubSpace *space) {
  1.2443 +            return ICToBool_Object::New(space, getStubCode());
  1.2444 +        }
  1.2445 +    };
  1.2446 +};
  1.2447 +
  1.2448 +// ToNumber
  1.2449 +//     JSOP_POS
  1.2450 +
  1.2451 +class ICToNumber_Fallback : public ICFallbackStub
  1.2452 +{
  1.2453 +    friend class ICStubSpace;
  1.2454 +
  1.2455 +    ICToNumber_Fallback(JitCode *stubCode)
  1.2456 +      : ICFallbackStub(ICStub::ToNumber_Fallback, stubCode) {}
  1.2457 +
  1.2458 +  public:
  1.2459 +    static inline ICToNumber_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.2460 +        if (!code)
  1.2461 +            return nullptr;
  1.2462 +        return space->allocate<ICToNumber_Fallback>(code);
  1.2463 +    }
  1.2464 +
  1.2465 +    // Compiler for this stub kind.
  1.2466 +    class Compiler : public ICStubCompiler {
  1.2467 +      protected:
  1.2468 +        bool generateStubCode(MacroAssembler &masm);
  1.2469 +
  1.2470 +      public:
  1.2471 +        Compiler(JSContext *cx)
  1.2472 +          : ICStubCompiler(cx, ICStub::ToNumber_Fallback) {}
  1.2473 +
  1.2474 +        ICStub *getStub(ICStubSpace *space) {
  1.2475 +            return ICToNumber_Fallback::New(space, getStubCode());
  1.2476 +        }
  1.2477 +    };
  1.2478 +};
  1.2479 +
  1.2480 +// BinaryArith
  1.2481 +//      JSOP_ADD
  1.2482 +//      JSOP_BITAND, JSOP_BITXOR, JSOP_BITOR
  1.2483 +//      JSOP_LSH, JSOP_RSH, JSOP_URSH
  1.2484 +
  1.2485 +class ICBinaryArith_Fallback : public ICFallbackStub
  1.2486 +{
  1.2487 +    friend class ICStubSpace;
  1.2488 +
  1.2489 +    ICBinaryArith_Fallback(JitCode *stubCode)
  1.2490 +      : ICFallbackStub(BinaryArith_Fallback, stubCode)
  1.2491 +    {
  1.2492 +        extra_ = 0;
  1.2493 +    }
  1.2494 +
  1.2495 +    static const uint16_t SAW_DOUBLE_RESULT_BIT = 0x1;
  1.2496 +    static const uint16_t UNOPTIMIZABLE_OPERANDS_BIT = 0x2;
  1.2497 +
  1.2498 +  public:
  1.2499 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.2500 +
  1.2501 +    static inline ICBinaryArith_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.2502 +        if (!code)
  1.2503 +            return nullptr;
  1.2504 +        return space->allocate<ICBinaryArith_Fallback>(code);
  1.2505 +    }
  1.2506 +
  1.2507 +    bool sawDoubleResult() const {
  1.2508 +        return extra_ & SAW_DOUBLE_RESULT_BIT;
  1.2509 +    }
  1.2510 +    void setSawDoubleResult() {
  1.2511 +        extra_ |= SAW_DOUBLE_RESULT_BIT;
  1.2512 +    }
  1.2513 +    bool hadUnoptimizableOperands() const {
  1.2514 +        return extra_ & UNOPTIMIZABLE_OPERANDS_BIT;
  1.2515 +    }
  1.2516 +    void noteUnoptimizableOperands() {
  1.2517 +        extra_ |= UNOPTIMIZABLE_OPERANDS_BIT;
  1.2518 +    }
  1.2519 +
  1.2520 +    // Compiler for this stub kind.
  1.2521 +    class Compiler : public ICStubCompiler {
  1.2522 +      protected:
  1.2523 +        bool generateStubCode(MacroAssembler &masm);
  1.2524 +
  1.2525 +      public:
  1.2526 +        Compiler(JSContext *cx)
  1.2527 +          : ICStubCompiler(cx, ICStub::BinaryArith_Fallback) {}
  1.2528 +
  1.2529 +        ICStub *getStub(ICStubSpace *space) {
  1.2530 +            return ICBinaryArith_Fallback::New(space, getStubCode());
  1.2531 +        }
  1.2532 +    };
  1.2533 +};
  1.2534 +
  1.2535 +class ICBinaryArith_Int32 : public ICStub
  1.2536 +{
  1.2537 +    friend class ICStubSpace;
  1.2538 +
  1.2539 +    ICBinaryArith_Int32(JitCode *stubCode, bool allowDouble)
  1.2540 +      : ICStub(BinaryArith_Int32, stubCode)
  1.2541 +    {
  1.2542 +        extra_ = allowDouble;
  1.2543 +    }
  1.2544 +
  1.2545 +  public:
  1.2546 +    static inline ICBinaryArith_Int32 *New(ICStubSpace *space, JitCode *code, bool allowDouble) {
  1.2547 +        if (!code)
  1.2548 +            return nullptr;
  1.2549 +        return space->allocate<ICBinaryArith_Int32>(code, allowDouble);
  1.2550 +    }
  1.2551 +    bool allowDouble() const {
  1.2552 +        return extra_;
  1.2553 +    }
  1.2554 +
  1.2555 +    // Compiler for this stub kind.
  1.2556 +    class Compiler : public ICStubCompiler {
  1.2557 +      protected:
  1.2558 +        JSOp op_;
  1.2559 +        bool allowDouble_;
  1.2560 +
  1.2561 +        bool generateStubCode(MacroAssembler &masm);
  1.2562 +
  1.2563 +        // Stub keys shift-stubs need to encode the kind, the JSOp and if we allow doubles.
  1.2564 +        virtual int32_t getKey() const {
  1.2565 +            return (static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) |
  1.2566 +                    (static_cast<int32_t>(allowDouble_) << 24));
  1.2567 +        }
  1.2568 +
  1.2569 +      public:
  1.2570 +        Compiler(JSContext *cx, JSOp op, bool allowDouble)
  1.2571 +          : ICStubCompiler(cx, ICStub::BinaryArith_Int32),
  1.2572 +            op_(op), allowDouble_(allowDouble) {}
  1.2573 +
  1.2574 +        ICStub *getStub(ICStubSpace *space) {
  1.2575 +            return ICBinaryArith_Int32::New(space, getStubCode(), allowDouble_);
  1.2576 +        }
  1.2577 +    };
  1.2578 +};
  1.2579 +
  1.2580 +class ICBinaryArith_StringConcat : public ICStub
  1.2581 +{
  1.2582 +    friend class ICStubSpace;
  1.2583 +
  1.2584 +    ICBinaryArith_StringConcat(JitCode *stubCode)
  1.2585 +      : ICStub(BinaryArith_StringConcat, stubCode)
  1.2586 +    {}
  1.2587 +
  1.2588 +  public:
  1.2589 +    static inline ICBinaryArith_StringConcat *New(ICStubSpace *space, JitCode *code) {
  1.2590 +        if (!code)
  1.2591 +            return nullptr;
  1.2592 +        return space->allocate<ICBinaryArith_StringConcat>(code);
  1.2593 +    }
  1.2594 +
  1.2595 +    class Compiler : public ICStubCompiler {
  1.2596 +      protected:
  1.2597 +        bool generateStubCode(MacroAssembler &masm);
  1.2598 +
  1.2599 +      public:
  1.2600 +        Compiler(JSContext *cx)
  1.2601 +          : ICStubCompiler(cx, ICStub::BinaryArith_StringConcat)
  1.2602 +        {}
  1.2603 +
  1.2604 +        ICStub *getStub(ICStubSpace *space) {
  1.2605 +            return ICBinaryArith_StringConcat::New(space, getStubCode());
  1.2606 +        }
  1.2607 +    };
  1.2608 +};
  1.2609 +
  1.2610 +class ICBinaryArith_StringObjectConcat : public ICStub
  1.2611 +{
  1.2612 +    friend class ICStubSpace;
  1.2613 +
  1.2614 +    ICBinaryArith_StringObjectConcat(JitCode *stubCode, bool lhsIsString)
  1.2615 +      : ICStub(BinaryArith_StringObjectConcat, stubCode)
  1.2616 +    {
  1.2617 +        extra_ = lhsIsString;
  1.2618 +    }
  1.2619 +
  1.2620 +  public:
  1.2621 +    static inline ICBinaryArith_StringObjectConcat *New(ICStubSpace *space, JitCode *code,
  1.2622 +                                                        bool lhsIsString) {
  1.2623 +        if (!code)
  1.2624 +            return nullptr;
  1.2625 +        return space->allocate<ICBinaryArith_StringObjectConcat>(code, lhsIsString);
  1.2626 +    }
  1.2627 +
  1.2628 +    bool lhsIsString() const {
  1.2629 +        return extra_;
  1.2630 +    }
  1.2631 +
  1.2632 +    class Compiler : public ICStubCompiler {
  1.2633 +      protected:
  1.2634 +        bool lhsIsString_;
  1.2635 +        bool generateStubCode(MacroAssembler &masm);
  1.2636 +
  1.2637 +        virtual int32_t getKey() const {
  1.2638 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(lhsIsString_) << 16);
  1.2639 +        }
  1.2640 +
  1.2641 +      public:
  1.2642 +        Compiler(JSContext *cx, bool lhsIsString)
  1.2643 +          : ICStubCompiler(cx, ICStub::BinaryArith_StringObjectConcat),
  1.2644 +            lhsIsString_(lhsIsString)
  1.2645 +        {}
  1.2646 +
  1.2647 +        ICStub *getStub(ICStubSpace *space) {
  1.2648 +            return ICBinaryArith_StringObjectConcat::New(space, getStubCode(), lhsIsString_);
  1.2649 +        }
  1.2650 +    };
  1.2651 +};
  1.2652 +
  1.2653 +class ICBinaryArith_Double : public ICStub
  1.2654 +{
  1.2655 +    friend class ICStubSpace;
  1.2656 +
  1.2657 +    ICBinaryArith_Double(JitCode *stubCode)
  1.2658 +      : ICStub(BinaryArith_Double, stubCode)
  1.2659 +    {}
  1.2660 +
  1.2661 +  public:
  1.2662 +    static inline ICBinaryArith_Double *New(ICStubSpace *space, JitCode *code) {
  1.2663 +        if (!code)
  1.2664 +            return nullptr;
  1.2665 +        return space->allocate<ICBinaryArith_Double>(code);
  1.2666 +    }
  1.2667 +
  1.2668 +    class Compiler : public ICMultiStubCompiler {
  1.2669 +      protected:
  1.2670 +        bool generateStubCode(MacroAssembler &masm);
  1.2671 +
  1.2672 +      public:
  1.2673 +        Compiler(JSContext *cx, JSOp op)
  1.2674 +          : ICMultiStubCompiler(cx, ICStub::BinaryArith_Double, op)
  1.2675 +        {}
  1.2676 +
  1.2677 +        ICStub *getStub(ICStubSpace *space) {
  1.2678 +            return ICBinaryArith_Double::New(space, getStubCode());
  1.2679 +        }
  1.2680 +    };
  1.2681 +};
  1.2682 +
  1.2683 +class ICBinaryArith_BooleanWithInt32 : public ICStub
  1.2684 +{
  1.2685 +    friend class ICStubSpace;
  1.2686 +
  1.2687 +    ICBinaryArith_BooleanWithInt32(JitCode *stubCode, bool lhsIsBool, bool rhsIsBool)
  1.2688 +      : ICStub(BinaryArith_BooleanWithInt32, stubCode)
  1.2689 +    {
  1.2690 +        JS_ASSERT(lhsIsBool || rhsIsBool);
  1.2691 +        extra_ = 0;
  1.2692 +        if (lhsIsBool)
  1.2693 +            extra_ |= 1;
  1.2694 +        if (rhsIsBool)
  1.2695 +            extra_ |= 2;
  1.2696 +    }
  1.2697 +
  1.2698 +  public:
  1.2699 +    static inline ICBinaryArith_BooleanWithInt32 *New(ICStubSpace *space, JitCode *code,
  1.2700 +                                                      bool lhsIsBool, bool rhsIsBool) {
  1.2701 +        if (!code)
  1.2702 +            return nullptr;
  1.2703 +        return space->allocate<ICBinaryArith_BooleanWithInt32>(code, lhsIsBool, rhsIsBool);
  1.2704 +    }
  1.2705 +
  1.2706 +    bool lhsIsBoolean() const {
  1.2707 +        return extra_ & 1;
  1.2708 +    }
  1.2709 +
  1.2710 +    bool rhsIsBoolean() const {
  1.2711 +        return extra_ & 2;
  1.2712 +    }
  1.2713 +
  1.2714 +    class Compiler : public ICStubCompiler {
  1.2715 +      protected:
  1.2716 +        JSOp op_;
  1.2717 +        bool lhsIsBool_;
  1.2718 +        bool rhsIsBool_;
  1.2719 +        bool generateStubCode(MacroAssembler &masm);
  1.2720 +
  1.2721 +        virtual int32_t getKey() const {
  1.2722 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(op_) << 16) |
  1.2723 +                   (static_cast<int32_t>(lhsIsBool_) << 24) |
  1.2724 +                   (static_cast<int32_t>(rhsIsBool_) << 25);
  1.2725 +        }
  1.2726 +
  1.2727 +      public:
  1.2728 +        Compiler(JSContext *cx, JSOp op, bool lhsIsBool, bool rhsIsBool)
  1.2729 +          : ICStubCompiler(cx, ICStub::BinaryArith_BooleanWithInt32),
  1.2730 +            op_(op), lhsIsBool_(lhsIsBool), rhsIsBool_(rhsIsBool)
  1.2731 +        {
  1.2732 +            JS_ASSERT(op_ == JSOP_ADD || op_ == JSOP_SUB || op_ == JSOP_BITOR ||
  1.2733 +                      op_ == JSOP_BITAND || op_ == JSOP_BITXOR);
  1.2734 +            JS_ASSERT(lhsIsBool_ || rhsIsBool_);
  1.2735 +        }
  1.2736 +
  1.2737 +        ICStub *getStub(ICStubSpace *space) {
  1.2738 +            return ICBinaryArith_BooleanWithInt32::New(space, getStubCode(),
  1.2739 +                                                       lhsIsBool_, rhsIsBool_);
  1.2740 +        }
  1.2741 +    };
  1.2742 +};
  1.2743 +
  1.2744 +class ICBinaryArith_DoubleWithInt32 : public ICStub
  1.2745 +{
  1.2746 +    friend class ICStubSpace;
  1.2747 +
  1.2748 +    ICBinaryArith_DoubleWithInt32(JitCode *stubCode, bool lhsIsDouble)
  1.2749 +      : ICStub(BinaryArith_DoubleWithInt32, stubCode)
  1.2750 +    {
  1.2751 +        extra_ = lhsIsDouble;
  1.2752 +    }
  1.2753 +
  1.2754 +  public:
  1.2755 +    static inline ICBinaryArith_DoubleWithInt32 *New(ICStubSpace *space, JitCode *code,
  1.2756 +                                                     bool lhsIsDouble) {
  1.2757 +        if (!code)
  1.2758 +            return nullptr;
  1.2759 +        return space->allocate<ICBinaryArith_DoubleWithInt32>(code, lhsIsDouble);
  1.2760 +    }
  1.2761 +
  1.2762 +    bool lhsIsDouble() const {
  1.2763 +        return extra_;
  1.2764 +    }
  1.2765 +
  1.2766 +    class Compiler : public ICMultiStubCompiler {
  1.2767 +      protected:
  1.2768 +        bool lhsIsDouble_;
  1.2769 +        bool generateStubCode(MacroAssembler &masm);
  1.2770 +
  1.2771 +        virtual int32_t getKey() const {
  1.2772 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(op) << 16) |
  1.2773 +                   (static_cast<int32_t>(lhsIsDouble_) << 24);
  1.2774 +        }
  1.2775 +
  1.2776 +      public:
  1.2777 +        Compiler(JSContext *cx, JSOp op, bool lhsIsDouble)
  1.2778 +          : ICMultiStubCompiler(cx, ICStub::BinaryArith_DoubleWithInt32, op),
  1.2779 +            lhsIsDouble_(lhsIsDouble)
  1.2780 +        {}
  1.2781 +
  1.2782 +        ICStub *getStub(ICStubSpace *space) {
  1.2783 +            return ICBinaryArith_DoubleWithInt32::New(space, getStubCode(), lhsIsDouble_);
  1.2784 +        }
  1.2785 +    };
  1.2786 +};
  1.2787 +
  1.2788 +// UnaryArith
  1.2789 +//     JSOP_BITNOT
  1.2790 +//     JSOP_NEG
  1.2791 +
  1.2792 +class ICUnaryArith_Fallback : public ICFallbackStub
  1.2793 +{
  1.2794 +    friend class ICStubSpace;
  1.2795 +
  1.2796 +    ICUnaryArith_Fallback(JitCode *stubCode)
  1.2797 +      : ICFallbackStub(UnaryArith_Fallback, stubCode)
  1.2798 +    {
  1.2799 +        extra_ = 0;
  1.2800 +    }
  1.2801 +
  1.2802 +  public:
  1.2803 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.2804 +
  1.2805 +    static inline ICUnaryArith_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.2806 +        if (!code)
  1.2807 +            return nullptr;
  1.2808 +        return space->allocate<ICUnaryArith_Fallback>(code);
  1.2809 +    }
  1.2810 +
  1.2811 +    bool sawDoubleResult() {
  1.2812 +        return extra_;
  1.2813 +    }
  1.2814 +    void setSawDoubleResult() {
  1.2815 +        extra_ = 1;
  1.2816 +    }
  1.2817 +
  1.2818 +    // Compiler for this stub kind.
  1.2819 +    class Compiler : public ICStubCompiler {
  1.2820 +      protected:
  1.2821 +        bool generateStubCode(MacroAssembler &masm);
  1.2822 +
  1.2823 +      public:
  1.2824 +        Compiler(JSContext *cx)
  1.2825 +          : ICStubCompiler(cx, ICStub::UnaryArith_Fallback)
  1.2826 +        {}
  1.2827 +
  1.2828 +        ICStub *getStub(ICStubSpace *space) {
  1.2829 +            return ICUnaryArith_Fallback::New(space, getStubCode());
  1.2830 +        }
  1.2831 +    };
  1.2832 +};
  1.2833 +
  1.2834 +class ICUnaryArith_Int32 : public ICStub
  1.2835 +{
  1.2836 +    friend class ICStubSpace;
  1.2837 +
  1.2838 +    ICUnaryArith_Int32(JitCode *stubCode)
  1.2839 +      : ICStub(UnaryArith_Int32, stubCode)
  1.2840 +    {}
  1.2841 +
  1.2842 +  public:
  1.2843 +    static inline ICUnaryArith_Int32 *New(ICStubSpace *space, JitCode *code) {
  1.2844 +        if (!code)
  1.2845 +            return nullptr;
  1.2846 +        return space->allocate<ICUnaryArith_Int32>(code);
  1.2847 +    }
  1.2848 +
  1.2849 +    class Compiler : public ICMultiStubCompiler {
  1.2850 +      protected:
  1.2851 +        bool generateStubCode(MacroAssembler &masm);
  1.2852 +
  1.2853 +      public:
  1.2854 +        Compiler(JSContext *cx, JSOp op)
  1.2855 +          : ICMultiStubCompiler(cx, ICStub::UnaryArith_Int32, op)
  1.2856 +        {}
  1.2857 +
  1.2858 +        ICStub *getStub(ICStubSpace *space) {
  1.2859 +            return ICUnaryArith_Int32::New(space, getStubCode());
  1.2860 +        }
  1.2861 +    };
  1.2862 +};
  1.2863 +
  1.2864 +class ICUnaryArith_Double : public ICStub
  1.2865 +{
  1.2866 +    friend class ICStubSpace;
  1.2867 +
  1.2868 +    ICUnaryArith_Double(JitCode *stubCode)
  1.2869 +      : ICStub(UnaryArith_Double, stubCode)
  1.2870 +    {}
  1.2871 +
  1.2872 +  public:
  1.2873 +    static inline ICUnaryArith_Double *New(ICStubSpace *space, JitCode *code) {
  1.2874 +        if (!code)
  1.2875 +            return nullptr;
  1.2876 +        return space->allocate<ICUnaryArith_Double>(code);
  1.2877 +    }
  1.2878 +
  1.2879 +    class Compiler : public ICMultiStubCompiler {
  1.2880 +      protected:
  1.2881 +        bool generateStubCode(MacroAssembler &masm);
  1.2882 +
  1.2883 +      public:
  1.2884 +        Compiler(JSContext *cx, JSOp op)
  1.2885 +          : ICMultiStubCompiler(cx, ICStub::UnaryArith_Double, op)
  1.2886 +        {}
  1.2887 +
  1.2888 +        ICStub *getStub(ICStubSpace *space) {
  1.2889 +            return ICUnaryArith_Double::New(space, getStubCode());
  1.2890 +        }
  1.2891 +    };
  1.2892 +};
  1.2893 +
  1.2894 +// GetElem
  1.2895 +//      JSOP_GETELEM
  1.2896 +
  1.2897 +class ICGetElem_Fallback : public ICMonitoredFallbackStub
  1.2898 +{
  1.2899 +    friend class ICStubSpace;
  1.2900 +
  1.2901 +    ICGetElem_Fallback(JitCode *stubCode)
  1.2902 +      : ICMonitoredFallbackStub(ICStub::GetElem_Fallback, stubCode)
  1.2903 +    { }
  1.2904 +
  1.2905 +    static const uint16_t EXTRA_NON_NATIVE = 0x1;
  1.2906 +    static const uint16_t EXTRA_NEGATIVE_INDEX = 0x2;
  1.2907 +
  1.2908 +  public:
  1.2909 +    static const uint32_t MAX_OPTIMIZED_STUBS = 16;
  1.2910 +
  1.2911 +    static inline ICGetElem_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.2912 +        if (!code)
  1.2913 +            return nullptr;
  1.2914 +        return space->allocate<ICGetElem_Fallback>(code);
  1.2915 +    }
  1.2916 +
  1.2917 +    void noteNonNativeAccess() {
  1.2918 +        extra_ |= EXTRA_NON_NATIVE;
  1.2919 +    }
  1.2920 +    bool hasNonNativeAccess() const {
  1.2921 +        return extra_ & EXTRA_NON_NATIVE;
  1.2922 +    }
  1.2923 +
  1.2924 +    void noteNegativeIndex() {
  1.2925 +        extra_ |= EXTRA_NEGATIVE_INDEX;
  1.2926 +    }
  1.2927 +    bool hasNegativeIndex() const {
  1.2928 +        return extra_ & EXTRA_NEGATIVE_INDEX;
  1.2929 +    }
  1.2930 +
  1.2931 +    // Compiler for this stub kind.
  1.2932 +    class Compiler : public ICStubCompiler {
  1.2933 +      protected:
  1.2934 +        bool generateStubCode(MacroAssembler &masm);
  1.2935 +
  1.2936 +      public:
  1.2937 +        Compiler(JSContext *cx)
  1.2938 +          : ICStubCompiler(cx, ICStub::GetElem_Fallback)
  1.2939 +        { }
  1.2940 +
  1.2941 +        ICStub *getStub(ICStubSpace *space) {
  1.2942 +            ICGetElem_Fallback *stub = ICGetElem_Fallback::New(space, getStubCode());
  1.2943 +            if (!stub)
  1.2944 +                return nullptr;
  1.2945 +            if (!stub->initMonitoringChain(cx, space))
  1.2946 +                return nullptr;
  1.2947 +            return stub;
  1.2948 +        }
  1.2949 +    };
  1.2950 +};
  1.2951 +
  1.2952 +class ICGetElemNativeStub : public ICMonitoredStub
  1.2953 +{
  1.2954 +  public:
  1.2955 +    enum AccessType { FixedSlot = 0, DynamicSlot, NativeGetter, ScriptedGetter };
  1.2956 +
  1.2957 +  protected:
  1.2958 +    HeapPtrShape shape_;
  1.2959 +    HeapPtrPropertyName name_;
  1.2960 +
  1.2961 +    static const unsigned NEEDS_ATOMIZE_SHIFT = 0;
  1.2962 +    static const uint16_t NEEDS_ATOMIZE_MASK = 0x1;
  1.2963 +
  1.2964 +    static const unsigned ACCESSTYPE_SHIFT = 1;
  1.2965 +    static const uint16_t ACCESSTYPE_MASK = 0x3;
  1.2966 +
  1.2967 +    ICGetElemNativeStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  1.2968 +                        HandleShape shape, HandlePropertyName name, AccessType acctype,
  1.2969 +                        bool needsAtomize);
  1.2970 +
  1.2971 +    ~ICGetElemNativeStub();
  1.2972 +
  1.2973 +  public:
  1.2974 +    HeapPtrShape &shape() {
  1.2975 +        return shape_;
  1.2976 +    }
  1.2977 +    static size_t offsetOfShape() {
  1.2978 +        return offsetof(ICGetElemNativeStub, shape_);
  1.2979 +    }
  1.2980 +
  1.2981 +    HeapPtrPropertyName &name() {
  1.2982 +        return name_;
  1.2983 +    }
  1.2984 +    static size_t offsetOfName() {
  1.2985 +        return offsetof(ICGetElemNativeStub, name_);
  1.2986 +    }
  1.2987 +
  1.2988 +    AccessType accessType() const {
  1.2989 +        return static_cast<AccessType>((extra_ >> ACCESSTYPE_SHIFT) & ACCESSTYPE_MASK);
  1.2990 +    }
  1.2991 +
  1.2992 +    bool needsAtomize() const {
  1.2993 +        return (extra_ >> NEEDS_ATOMIZE_SHIFT) & NEEDS_ATOMIZE_MASK;
  1.2994 +    }
  1.2995 +};
  1.2996 +
  1.2997 +class ICGetElemNativeSlotStub : public ICGetElemNativeStub
  1.2998 +{
  1.2999 +  protected:
  1.3000 +    uint32_t offset_;
  1.3001 +
  1.3002 +    ICGetElemNativeSlotStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  1.3003 +                            HandleShape shape, HandlePropertyName name,
  1.3004 +                            AccessType acctype, bool needsAtomize, uint32_t offset)
  1.3005 +      : ICGetElemNativeStub(kind, stubCode, firstMonitorStub, shape, name, acctype, needsAtomize),
  1.3006 +        offset_(offset)
  1.3007 +    {
  1.3008 +        JS_ASSERT(kind == GetElem_NativeSlot || kind == GetElem_NativePrototypeSlot);
  1.3009 +        JS_ASSERT(acctype == FixedSlot || acctype == DynamicSlot);
  1.3010 +    }
  1.3011 +
  1.3012 +  public:
  1.3013 +    uint32_t offset() const {
  1.3014 +        return offset_;
  1.3015 +    }
  1.3016 +
  1.3017 +    static size_t offsetOfOffset() {
  1.3018 +        return offsetof(ICGetElemNativeSlotStub, offset_);
  1.3019 +    }
  1.3020 +};
  1.3021 +
  1.3022 +class ICGetElemNativeGetterStub : public ICGetElemNativeStub
  1.3023 +{
  1.3024 +  protected:
  1.3025 +    HeapPtrFunction getter_;
  1.3026 +    uint32_t pcOffset_;
  1.3027 +
  1.3028 +    ICGetElemNativeGetterStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  1.3029 +                            HandleShape shape, HandlePropertyName name, AccessType acctype,
  1.3030 +                            bool needsAtomize, HandleFunction getter, uint32_t pcOffset);
  1.3031 +
  1.3032 +  public:
  1.3033 +    HeapPtrFunction &getter() {
  1.3034 +        return getter_;
  1.3035 +    }
  1.3036 +    static size_t offsetOfGetter() {
  1.3037 +        return offsetof(ICGetElemNativeGetterStub, getter_);
  1.3038 +    }
  1.3039 +
  1.3040 +    static size_t offsetOfPCOffset() {
  1.3041 +        return offsetof(ICGetElemNativeGetterStub, pcOffset_);
  1.3042 +    }
  1.3043 +};
  1.3044 +
  1.3045 +class ICGetElem_NativeSlot : public ICGetElemNativeSlotStub
  1.3046 +{
  1.3047 +    friend class ICStubSpace;
  1.3048 +    ICGetElem_NativeSlot(JitCode *stubCode, ICStub *firstMonitorStub,
  1.3049 +                         HandleShape shape, HandlePropertyName name,
  1.3050 +                         AccessType acctype, bool needsAtomize, uint32_t offset)
  1.3051 +      : ICGetElemNativeSlotStub(ICStub::GetElem_NativeSlot, stubCode, firstMonitorStub, shape,
  1.3052 +                                name, acctype, needsAtomize, offset)
  1.3053 +    {}
  1.3054 +
  1.3055 +  public:
  1.3056 +    static inline ICGetElem_NativeSlot *New(ICStubSpace *space, JitCode *code,
  1.3057 +                                            ICStub *firstMonitorStub,
  1.3058 +                                            HandleShape shape, HandlePropertyName name,
  1.3059 +                                            AccessType acctype, bool needsAtomize, uint32_t offset)
  1.3060 +    {
  1.3061 +        if (!code)
  1.3062 +            return nullptr;
  1.3063 +        return space->allocate<ICGetElem_NativeSlot>(code, firstMonitorStub, shape, name,
  1.3064 +                                                     acctype, needsAtomize, offset);
  1.3065 +    }
  1.3066 +};
  1.3067 +
  1.3068 +class ICGetElem_NativePrototypeSlot : public ICGetElemNativeSlotStub
  1.3069 +{
  1.3070 +    friend class ICStubSpace;
  1.3071 +    HeapPtrObject holder_;
  1.3072 +    HeapPtrShape holderShape_;
  1.3073 +
  1.3074 +    ICGetElem_NativePrototypeSlot(JitCode *stubCode, ICStub *firstMonitorStub,
  1.3075 +                                  HandleShape shape, HandlePropertyName name,
  1.3076 +                                  AccessType acctype, bool needsAtomize, uint32_t offset,
  1.3077 +                                  HandleObject holder, HandleShape holderShape);
  1.3078 +
  1.3079 +  public:
  1.3080 +    static inline ICGetElem_NativePrototypeSlot *New(ICStubSpace *space, JitCode *code,
  1.3081 +                                                     ICStub *firstMonitorStub,
  1.3082 +                                                     HandleShape shape, HandlePropertyName name,
  1.3083 +                                                     AccessType acctype, bool needsAtomize,
  1.3084 +                                                     uint32_t offset, HandleObject holder,
  1.3085 +                                                     HandleShape holderShape)
  1.3086 +    {
  1.3087 +        if (!code)
  1.3088 +            return nullptr;
  1.3089 +        return space->allocate<ICGetElem_NativePrototypeSlot>(
  1.3090 +                    code, firstMonitorStub, shape, name, acctype, needsAtomize, offset, holder,
  1.3091 +                    holderShape);
  1.3092 +    }
  1.3093 +
  1.3094 +    HeapPtrObject &holder() {
  1.3095 +        return holder_;
  1.3096 +    }
  1.3097 +    static size_t offsetOfHolder() {
  1.3098 +        return offsetof(ICGetElem_NativePrototypeSlot, holder_);
  1.3099 +    }
  1.3100 +
  1.3101 +    HeapPtrShape &holderShape() {
  1.3102 +        return holderShape_;
  1.3103 +    }
  1.3104 +    static size_t offsetOfHolderShape() {
  1.3105 +        return offsetof(ICGetElem_NativePrototypeSlot, holderShape_);
  1.3106 +    }
  1.3107 +};
  1.3108 +
  1.3109 +class ICGetElemNativePrototypeCallStub : public ICGetElemNativeGetterStub
  1.3110 +{
  1.3111 +    friend class ICStubSpace;
  1.3112 +    HeapPtrObject holder_;
  1.3113 +    HeapPtrShape holderShape_;
  1.3114 +
  1.3115 +  protected:
  1.3116 +    ICGetElemNativePrototypeCallStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  1.3117 +                                     HandleShape shape, HandlePropertyName name,
  1.3118 +                                     AccessType acctype, bool needsAtomize, HandleFunction getter,
  1.3119 +                                     uint32_t pcOffset, HandleObject holder,
  1.3120 +                                     HandleShape holderShape);
  1.3121 +
  1.3122 +  public:
  1.3123 +    HeapPtrObject &holder() {
  1.3124 +        return holder_;
  1.3125 +    }
  1.3126 +    static size_t offsetOfHolder() {
  1.3127 +        return offsetof(ICGetElemNativePrototypeCallStub, holder_);
  1.3128 +    }
  1.3129 +
  1.3130 +    HeapPtrShape &holderShape() {
  1.3131 +        return holderShape_;
  1.3132 +    }
  1.3133 +    static size_t offsetOfHolderShape() {
  1.3134 +        return offsetof(ICGetElemNativePrototypeCallStub, holderShape_);
  1.3135 +    }
  1.3136 +};
  1.3137 +
  1.3138 +class ICGetElem_NativePrototypeCallNative : public ICGetElemNativePrototypeCallStub
  1.3139 +{
  1.3140 +    friend class ICStubSpace;
  1.3141 +
  1.3142 +    ICGetElem_NativePrototypeCallNative(JitCode *stubCode, ICStub *firstMonitorStub,
  1.3143 +                                        HandleShape shape, HandlePropertyName name,
  1.3144 +                                        AccessType acctype, bool needsAtomize,
  1.3145 +                                        HandleFunction getter, uint32_t pcOffset,
  1.3146 +                                        HandleObject holder, HandleShape holderShape)
  1.3147 +      : ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallNative,
  1.3148 +                                         stubCode, firstMonitorStub, shape, name,
  1.3149 +                                         acctype, needsAtomize, getter, pcOffset, holder,
  1.3150 +                                         holderShape)
  1.3151 +    {}
  1.3152 +
  1.3153 +  public:
  1.3154 +    static inline ICGetElem_NativePrototypeCallNative *New(
  1.3155 +                    ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.3156 +                    HandleShape shape, HandlePropertyName name, AccessType acctype,
  1.3157 +                    bool needsAtomize, HandleFunction getter, uint32_t pcOffset,
  1.3158 +                    HandleObject holder, HandleShape holderShape)
  1.3159 +    {
  1.3160 +        if (!code)
  1.3161 +            return nullptr;
  1.3162 +        return space->allocate<ICGetElem_NativePrototypeCallNative>(
  1.3163 +                        code, firstMonitorStub, shape, name, acctype, needsAtomize, getter,
  1.3164 +                        pcOffset, holder, holderShape);
  1.3165 +    }
  1.3166 +};
  1.3167 +
  1.3168 +class ICGetElem_NativePrototypeCallScripted : public ICGetElemNativePrototypeCallStub
  1.3169 +{
  1.3170 +    friend class ICStubSpace;
  1.3171 +
  1.3172 +    ICGetElem_NativePrototypeCallScripted(JitCode *stubCode, ICStub *firstMonitorStub,
  1.3173 +                                        HandleShape shape, HandlePropertyName name,
  1.3174 +                                        AccessType acctype, bool needsAtomize,
  1.3175 +                                        HandleFunction getter, uint32_t pcOffset,
  1.3176 +                                        HandleObject holder, HandleShape holderShape)
  1.3177 +      : ICGetElemNativePrototypeCallStub(GetElem_NativePrototypeCallScripted,
  1.3178 +                                         stubCode, firstMonitorStub, shape, name,
  1.3179 +                                         acctype, needsAtomize, getter, pcOffset, holder,
  1.3180 +                                         holderShape)
  1.3181 +    {}
  1.3182 +
  1.3183 +  public:
  1.3184 +    static inline ICGetElem_NativePrototypeCallScripted *New(
  1.3185 +                    ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.3186 +                    HandleShape shape, HandlePropertyName name, AccessType acctype,
  1.3187 +                    bool needsAtomize, HandleFunction getter, uint32_t pcOffset,
  1.3188 +                    HandleObject holder, HandleShape holderShape)
  1.3189 +    {
  1.3190 +        if (!code)
  1.3191 +            return nullptr;
  1.3192 +        return space->allocate<ICGetElem_NativePrototypeCallScripted>(
  1.3193 +                        code, firstMonitorStub, shape, name, acctype, needsAtomize, getter,
  1.3194 +                        pcOffset, holder, holderShape);
  1.3195 +    }
  1.3196 +};
  1.3197 +
  1.3198 +// Compiler for GetElem_NativeSlot and GetElem_NativePrototypeSlot stubs.
  1.3199 +class ICGetElemNativeCompiler : public ICStubCompiler
  1.3200 +{
  1.3201 +    bool isCallElem_;
  1.3202 +    ICStub *firstMonitorStub_;
  1.3203 +    HandleObject obj_;
  1.3204 +    HandleObject holder_;
  1.3205 +    HandlePropertyName name_;
  1.3206 +    ICGetElemNativeStub::AccessType acctype_;
  1.3207 +    bool needsAtomize_;
  1.3208 +    uint32_t offset_;
  1.3209 +    HandleFunction getter_;
  1.3210 +    uint32_t pcOffset_;
  1.3211 +
  1.3212 +    bool emitCallNative(MacroAssembler &masm, Register objReg);
  1.3213 +    bool emitCallScripted(MacroAssembler &masm, Register objReg);
  1.3214 +    bool generateStubCode(MacroAssembler &masm);
  1.3215 +
  1.3216 +  protected:
  1.3217 +    virtual int32_t getKey() const {
  1.3218 +#if JS_HAS_NO_SUCH_METHOD
  1.3219 +        return static_cast<int32_t>(kind) |
  1.3220 +               (static_cast<int32_t>(isCallElem_) << 16) |
  1.3221 +               (static_cast<int32_t>(needsAtomize_) << 17) |
  1.3222 +               (static_cast<int32_t>(acctype_) << 18);
  1.3223 +#else
  1.3224 +        return static_cast<int32_t>(kind) | (static_cast<int32_t>(needsAtomize_) << 16) |
  1.3225 +               (static_cast<int32_t>(acctype_) << 17);
  1.3226 +#endif
  1.3227 +    }
  1.3228 +
  1.3229 +  public:
  1.3230 +    ICGetElemNativeCompiler(JSContext *cx, ICStub::Kind kind, bool isCallElem,
  1.3231 +                            ICStub *firstMonitorStub, HandleObject obj, HandleObject holder,
  1.3232 +                            HandlePropertyName name, ICGetElemNativeStub::AccessType acctype,
  1.3233 +                            bool needsAtomize, uint32_t offset)
  1.3234 +      : ICStubCompiler(cx, kind),
  1.3235 +        isCallElem_(isCallElem),
  1.3236 +        firstMonitorStub_(firstMonitorStub),
  1.3237 +        obj_(obj),
  1.3238 +        holder_(holder),
  1.3239 +        name_(name),
  1.3240 +        acctype_(acctype),
  1.3241 +        needsAtomize_(needsAtomize),
  1.3242 +        offset_(offset),
  1.3243 +        getter_(js::NullPtr()),
  1.3244 +        pcOffset_(0)
  1.3245 +    {}
  1.3246 +
  1.3247 +    ICGetElemNativeCompiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
  1.3248 +                            HandleObject obj, HandleObject holder, HandlePropertyName name,
  1.3249 +                            ICGetElemNativeStub::AccessType acctype, bool needsAtomize,
  1.3250 +                            HandleFunction getter, uint32_t pcOffset, bool isCallElem)
  1.3251 +      : ICStubCompiler(cx, kind),
  1.3252 +        isCallElem_(false),
  1.3253 +        firstMonitorStub_(firstMonitorStub),
  1.3254 +        obj_(obj),
  1.3255 +        holder_(holder),
  1.3256 +        name_(name),
  1.3257 +        acctype_(acctype),
  1.3258 +        needsAtomize_(needsAtomize),
  1.3259 +        offset_(0),
  1.3260 +        getter_(getter),
  1.3261 +        pcOffset_(pcOffset)
  1.3262 +    {}
  1.3263 +
  1.3264 +    ICStub *getStub(ICStubSpace *space) {
  1.3265 +        RootedShape shape(cx, obj_->lastProperty());
  1.3266 +        if (kind == ICStub::GetElem_NativeSlot) {
  1.3267 +            JS_ASSERT(obj_ == holder_);
  1.3268 +            return ICGetElem_NativeSlot::New(
  1.3269 +                    space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
  1.3270 +                    offset_);
  1.3271 +        }
  1.3272 +
  1.3273 +        JS_ASSERT(obj_ != holder_);
  1.3274 +        RootedShape holderShape(cx, holder_->lastProperty());
  1.3275 +        if (kind == ICStub::GetElem_NativePrototypeSlot) {
  1.3276 +            return ICGetElem_NativePrototypeSlot::New(
  1.3277 +                    space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
  1.3278 +                    offset_, holder_, holderShape);
  1.3279 +        }
  1.3280 +
  1.3281 +        if (kind == ICStub::GetElem_NativePrototypeCallNative) {
  1.3282 +            return ICGetElem_NativePrototypeCallNative::New(
  1.3283 +                    space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
  1.3284 +                    getter_, pcOffset_, holder_, holderShape);
  1.3285 +        }
  1.3286 +
  1.3287 +        JS_ASSERT(kind == ICStub::GetElem_NativePrototypeCallScripted);
  1.3288 +        if (kind == ICStub::GetElem_NativePrototypeCallScripted) {
  1.3289 +            return ICGetElem_NativePrototypeCallScripted::New(
  1.3290 +                    space, getStubCode(), firstMonitorStub_, shape, name_, acctype_, needsAtomize_,
  1.3291 +                    getter_, pcOffset_, holder_, holderShape);
  1.3292 +        }
  1.3293 +
  1.3294 +        MOZ_ASSUME_UNREACHABLE("Invalid kind.");
  1.3295 +        return nullptr;
  1.3296 +    }
  1.3297 +};
  1.3298 +
  1.3299 +class ICGetElem_String : public ICStub
  1.3300 +{
  1.3301 +    friend class ICStubSpace;
  1.3302 +
  1.3303 +    ICGetElem_String(JitCode *stubCode)
  1.3304 +      : ICStub(ICStub::GetElem_String, stubCode) {}
  1.3305 +
  1.3306 +  public:
  1.3307 +    static inline ICGetElem_String *New(ICStubSpace *space, JitCode *code) {
  1.3308 +        if (!code)
  1.3309 +            return nullptr;
  1.3310 +        return space->allocate<ICGetElem_String>(code);
  1.3311 +    }
  1.3312 +
  1.3313 +    // Compiler for this stub kind.
  1.3314 +    class Compiler : public ICStubCompiler {
  1.3315 +      protected:
  1.3316 +        bool generateStubCode(MacroAssembler &masm);
  1.3317 +
  1.3318 +      public:
  1.3319 +        Compiler(JSContext *cx)
  1.3320 +          : ICStubCompiler(cx, ICStub::GetElem_String) {}
  1.3321 +
  1.3322 +        ICStub *getStub(ICStubSpace *space) {
  1.3323 +            return ICGetElem_String::New(space, getStubCode());
  1.3324 +        }
  1.3325 +    };
  1.3326 +};
  1.3327 +
  1.3328 +class ICGetElem_Dense : public ICMonitoredStub
  1.3329 +{
  1.3330 +    friend class ICStubSpace;
  1.3331 +
  1.3332 +    HeapPtrShape shape_;
  1.3333 +
  1.3334 +    ICGetElem_Dense(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape);
  1.3335 +
  1.3336 +  public:
  1.3337 +    static inline ICGetElem_Dense *New(ICStubSpace *space, JitCode *code,
  1.3338 +                                       ICStub *firstMonitorStub, HandleShape shape)
  1.3339 +    {
  1.3340 +        if (!code)
  1.3341 +            return nullptr;
  1.3342 +        return space->allocate<ICGetElem_Dense>(code, firstMonitorStub, shape);
  1.3343 +    }
  1.3344 +
  1.3345 +    static size_t offsetOfShape() {
  1.3346 +        return offsetof(ICGetElem_Dense, shape_);
  1.3347 +    }
  1.3348 +
  1.3349 +    HeapPtrShape &shape() {
  1.3350 +        return shape_;
  1.3351 +    }
  1.3352 +
  1.3353 +    class Compiler : public ICStubCompiler {
  1.3354 +      ICStub *firstMonitorStub_;
  1.3355 +      RootedShape shape_;
  1.3356 +      bool isCallElem_;
  1.3357 +
  1.3358 +      protected:
  1.3359 +        bool generateStubCode(MacroAssembler &masm);
  1.3360 +
  1.3361 +        virtual int32_t getKey() const {
  1.3362 +#if JS_HAS_NO_SUCH_METHOD
  1.3363 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(isCallElem_) << 16);
  1.3364 +#else
  1.3365 +            return static_cast<int32_t>(kind);
  1.3366 +#endif
  1.3367 +        }
  1.3368 +
  1.3369 +      public:
  1.3370 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, Shape *shape, bool isCallElem)
  1.3371 +          : ICStubCompiler(cx, ICStub::GetElem_Dense),
  1.3372 +            firstMonitorStub_(firstMonitorStub),
  1.3373 +            shape_(cx, shape),
  1.3374 +            isCallElem_(isCallElem)
  1.3375 +        {}
  1.3376 +
  1.3377 +        ICStub *getStub(ICStubSpace *space) {
  1.3378 +            return ICGetElem_Dense::New(space, getStubCode(), firstMonitorStub_, shape_);
  1.3379 +        }
  1.3380 +    };
  1.3381 +};
  1.3382 +
  1.3383 +class ICGetElem_TypedArray : public ICStub
  1.3384 +{
  1.3385 +    friend class ICStubSpace;
  1.3386 +
  1.3387 +  protected: // Protected to silence Clang warning.
  1.3388 +    HeapPtrShape shape_;
  1.3389 +
  1.3390 +    ICGetElem_TypedArray(JitCode *stubCode, HandleShape shape, uint32_t type);
  1.3391 +
  1.3392 +  public:
  1.3393 +    static inline ICGetElem_TypedArray *New(ICStubSpace *space, JitCode *code,
  1.3394 +                                            HandleShape shape, uint32_t type)
  1.3395 +    {
  1.3396 +        if (!code)
  1.3397 +            return nullptr;
  1.3398 +        return space->allocate<ICGetElem_TypedArray>(code, shape, type);
  1.3399 +    }
  1.3400 +
  1.3401 +    static size_t offsetOfShape() {
  1.3402 +        return offsetof(ICGetElem_TypedArray, shape_);
  1.3403 +    }
  1.3404 +
  1.3405 +    HeapPtrShape &shape() {
  1.3406 +        return shape_;
  1.3407 +    }
  1.3408 +
  1.3409 +    class Compiler : public ICStubCompiler {
  1.3410 +      RootedShape shape_;
  1.3411 +      uint32_t type_;
  1.3412 +
  1.3413 +      protected:
  1.3414 +        bool generateStubCode(MacroAssembler &masm);
  1.3415 +
  1.3416 +        virtual int32_t getKey() const {
  1.3417 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16);
  1.3418 +        }
  1.3419 +
  1.3420 +      public:
  1.3421 +        Compiler(JSContext *cx, Shape *shape, uint32_t type)
  1.3422 +          : ICStubCompiler(cx, ICStub::GetElem_TypedArray),
  1.3423 +            shape_(cx, shape),
  1.3424 +            type_(type)
  1.3425 +        {}
  1.3426 +
  1.3427 +        ICStub *getStub(ICStubSpace *space) {
  1.3428 +            return ICGetElem_TypedArray::New(space, getStubCode(), shape_, type_);
  1.3429 +        }
  1.3430 +    };
  1.3431 +};
  1.3432 +
  1.3433 +class ICGetElem_Arguments : public ICMonitoredStub
  1.3434 +{
  1.3435 +    friend class ICStubSpace;
  1.3436 +  public:
  1.3437 +    enum Which { Normal, Strict, Magic };
  1.3438 +
  1.3439 +  private:
  1.3440 +    ICGetElem_Arguments(JitCode *stubCode, ICStub *firstMonitorStub, Which which)
  1.3441 +      : ICMonitoredStub(ICStub::GetElem_Arguments, stubCode, firstMonitorStub)
  1.3442 +    {
  1.3443 +        extra_ = static_cast<uint16_t>(which);
  1.3444 +    }
  1.3445 +
  1.3446 +  public:
  1.3447 +    static inline ICGetElem_Arguments *New(ICStubSpace *space, JitCode *code,
  1.3448 +                                           ICStub *firstMonitorStub, Which which)
  1.3449 +    {
  1.3450 +        if (!code)
  1.3451 +            return nullptr;
  1.3452 +        return space->allocate<ICGetElem_Arguments>(code, firstMonitorStub, which);
  1.3453 +    }
  1.3454 +
  1.3455 +    Which which() const {
  1.3456 +        return static_cast<Which>(extra_);
  1.3457 +    }
  1.3458 +
  1.3459 +    class Compiler : public ICStubCompiler {
  1.3460 +      ICStub *firstMonitorStub_;
  1.3461 +      Which which_;
  1.3462 +      bool isCallElem_;
  1.3463 +
  1.3464 +      protected:
  1.3465 +        bool generateStubCode(MacroAssembler &masm);
  1.3466 +
  1.3467 +        virtual int32_t getKey() const {
  1.3468 +#if JS_HAS_NO_SUCH_METHOD
  1.3469 +            return static_cast<int32_t>(kind) |
  1.3470 +                   static_cast<int32_t>(isCallElem_ << 16) |
  1.3471 +                   (static_cast<int32_t>(which_) << 17);
  1.3472 +#else
  1.3473 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(which_) << 16);
  1.3474 +#endif
  1.3475 +        }
  1.3476 +
  1.3477 +      public:
  1.3478 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, Which which, bool isCallElem)
  1.3479 +          : ICStubCompiler(cx, ICStub::GetElem_Arguments),
  1.3480 +            firstMonitorStub_(firstMonitorStub),
  1.3481 +            which_(which),
  1.3482 +            isCallElem_(isCallElem)
  1.3483 +        {}
  1.3484 +
  1.3485 +        ICStub *getStub(ICStubSpace *space) {
  1.3486 +            return ICGetElem_Arguments::New(space, getStubCode(), firstMonitorStub_, which_);
  1.3487 +        }
  1.3488 +    };
  1.3489 +};
  1.3490 +
  1.3491 +// SetElem
  1.3492 +//      JSOP_SETELEM
  1.3493 +//      JSOP_INITELEM
  1.3494 +
  1.3495 +class ICSetElem_Fallback : public ICFallbackStub
  1.3496 +{
  1.3497 +    friend class ICStubSpace;
  1.3498 +
  1.3499 +    ICSetElem_Fallback(JitCode *stubCode)
  1.3500 +      : ICFallbackStub(ICStub::SetElem_Fallback, stubCode)
  1.3501 +    { }
  1.3502 +
  1.3503 +  public:
  1.3504 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.3505 +
  1.3506 +    static inline ICSetElem_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.3507 +        if (!code)
  1.3508 +            return nullptr;
  1.3509 +        return space->allocate<ICSetElem_Fallback>(code);
  1.3510 +    }
  1.3511 +
  1.3512 +    void noteArrayWriteHole() {
  1.3513 +        extra_ = 1;
  1.3514 +    }
  1.3515 +    bool hasArrayWriteHole() const {
  1.3516 +        return extra_;
  1.3517 +    }
  1.3518 +
  1.3519 +    // Compiler for this stub kind.
  1.3520 +    class Compiler : public ICStubCompiler {
  1.3521 +      protected:
  1.3522 +        bool generateStubCode(MacroAssembler &masm);
  1.3523 +
  1.3524 +      public:
  1.3525 +        Compiler(JSContext *cx)
  1.3526 +          : ICStubCompiler(cx, ICStub::SetElem_Fallback)
  1.3527 +        { }
  1.3528 +
  1.3529 +        ICStub *getStub(ICStubSpace *space) {
  1.3530 +            return ICSetElem_Fallback::New(space, getStubCode());
  1.3531 +        }
  1.3532 +    };
  1.3533 +};
  1.3534 +
  1.3535 +class ICSetElem_Dense : public ICUpdatedStub
  1.3536 +{
  1.3537 +    friend class ICStubSpace;
  1.3538 +
  1.3539 +    HeapPtrShape shape_;
  1.3540 +    HeapPtrTypeObject type_;
  1.3541 +
  1.3542 +    ICSetElem_Dense(JitCode *stubCode, HandleShape shape, HandleTypeObject type);
  1.3543 +
  1.3544 +  public:
  1.3545 +    static inline ICSetElem_Dense *New(ICStubSpace *space, JitCode *code, HandleShape shape,
  1.3546 +                                       HandleTypeObject type) {
  1.3547 +        if (!code)
  1.3548 +            return nullptr;
  1.3549 +        return space->allocate<ICSetElem_Dense>(code, shape, type);
  1.3550 +    }
  1.3551 +
  1.3552 +    static size_t offsetOfShape() {
  1.3553 +        return offsetof(ICSetElem_Dense, shape_);
  1.3554 +    }
  1.3555 +    static size_t offsetOfType() {
  1.3556 +        return offsetof(ICSetElem_Dense, type_);
  1.3557 +    }
  1.3558 +
  1.3559 +    HeapPtrShape &shape() {
  1.3560 +        return shape_;
  1.3561 +    }
  1.3562 +    HeapPtrTypeObject &type() {
  1.3563 +        return type_;
  1.3564 +    }
  1.3565 +
  1.3566 +    class Compiler : public ICStubCompiler {
  1.3567 +        RootedShape shape_;
  1.3568 +
  1.3569 +        // Compiler is only live on stack during compilation, it should
  1.3570 +        // outlive any RootedTypeObject it's passed.  So it can just
  1.3571 +        // use the handle.
  1.3572 +        HandleTypeObject type_;
  1.3573 +
  1.3574 +        bool generateStubCode(MacroAssembler &masm);
  1.3575 +
  1.3576 +      public:
  1.3577 +        Compiler(JSContext *cx, Shape *shape, HandleTypeObject type)
  1.3578 +          : ICStubCompiler(cx, ICStub::SetElem_Dense),
  1.3579 +            shape_(cx, shape),
  1.3580 +            type_(type)
  1.3581 +        {}
  1.3582 +
  1.3583 +        ICUpdatedStub *getStub(ICStubSpace *space) {
  1.3584 +            ICSetElem_Dense *stub = ICSetElem_Dense::New(space, getStubCode(), shape_, type_);
  1.3585 +            if (!stub || !stub->initUpdatingChain(cx, space))
  1.3586 +                return nullptr;
  1.3587 +            return stub;
  1.3588 +        }
  1.3589 +    };
  1.3590 +};
  1.3591 +
  1.3592 +template <size_t ProtoChainDepth> class ICSetElem_DenseAddImpl;
  1.3593 +
  1.3594 +class ICSetElem_DenseAdd : public ICUpdatedStub
  1.3595 +{
  1.3596 +    friend class ICStubSpace;
  1.3597 +
  1.3598 +  public:
  1.3599 +    static const size_t MAX_PROTO_CHAIN_DEPTH = 4;
  1.3600 +
  1.3601 +  protected:
  1.3602 +    HeapPtrTypeObject type_;
  1.3603 +
  1.3604 +    ICSetElem_DenseAdd(JitCode *stubCode, types::TypeObject *type, size_t protoChainDepth);
  1.3605 +
  1.3606 +  public:
  1.3607 +    static size_t offsetOfType() {
  1.3608 +        return offsetof(ICSetElem_DenseAdd, type_);
  1.3609 +    }
  1.3610 +
  1.3611 +    HeapPtrTypeObject &type() {
  1.3612 +        return type_;
  1.3613 +    }
  1.3614 +    size_t protoChainDepth() const {
  1.3615 +        MOZ_ASSERT(extra_ <= MAX_PROTO_CHAIN_DEPTH);
  1.3616 +        return extra_;
  1.3617 +    }
  1.3618 +
  1.3619 +    template <size_t ProtoChainDepth>
  1.3620 +    ICSetElem_DenseAddImpl<ProtoChainDepth> *toImplUnchecked() {
  1.3621 +        return static_cast<ICSetElem_DenseAddImpl<ProtoChainDepth> *>(this);
  1.3622 +    }
  1.3623 +
  1.3624 +    template <size_t ProtoChainDepth>
  1.3625 +    ICSetElem_DenseAddImpl<ProtoChainDepth> *toImpl() {
  1.3626 +        JS_ASSERT(ProtoChainDepth == protoChainDepth());
  1.3627 +        return toImplUnchecked<ProtoChainDepth>();
  1.3628 +    }
  1.3629 +};
  1.3630 +
  1.3631 +template <size_t ProtoChainDepth>
  1.3632 +class ICSetElem_DenseAddImpl : public ICSetElem_DenseAdd
  1.3633 +{
  1.3634 +    friend class ICStubSpace;
  1.3635 +
  1.3636 +    static const size_t NumShapes = ProtoChainDepth + 1;
  1.3637 +    mozilla::Array<HeapPtrShape, NumShapes> shapes_;
  1.3638 +
  1.3639 +    ICSetElem_DenseAddImpl(JitCode *stubCode, types::TypeObject *type,
  1.3640 +                           const AutoShapeVector *shapes)
  1.3641 +      : ICSetElem_DenseAdd(stubCode, type, ProtoChainDepth)
  1.3642 +    {
  1.3643 +        JS_ASSERT(shapes->length() == NumShapes);
  1.3644 +        for (size_t i = 0; i < NumShapes; i++)
  1.3645 +            shapes_[i].init((*shapes)[i]);
  1.3646 +    }
  1.3647 +
  1.3648 +  public:
  1.3649 +    static inline ICSetElem_DenseAddImpl *New(ICStubSpace *space, JitCode *code,
  1.3650 +                                              types::TypeObject *type,
  1.3651 +                                              const AutoShapeVector *shapes)
  1.3652 +    {
  1.3653 +        if (!code)
  1.3654 +            return nullptr;
  1.3655 +        return space->allocate<ICSetElem_DenseAddImpl<ProtoChainDepth> >(code, type, shapes);
  1.3656 +    }
  1.3657 +
  1.3658 +    void traceShapes(JSTracer *trc) {
  1.3659 +        for (size_t i = 0; i < NumShapes; i++)
  1.3660 +            MarkShape(trc, &shapes_[i], "baseline-setelem-denseadd-stub-shape");
  1.3661 +    }
  1.3662 +    Shape *shape(size_t i) const {
  1.3663 +        JS_ASSERT(i < NumShapes);
  1.3664 +        return shapes_[i];
  1.3665 +    }
  1.3666 +    static size_t offsetOfShape(size_t idx) {
  1.3667 +        return offsetof(ICSetElem_DenseAddImpl, shapes_) + idx * sizeof(HeapPtrShape);
  1.3668 +    }
  1.3669 +};
  1.3670 +
  1.3671 +class ICSetElemDenseAddCompiler : public ICStubCompiler {
  1.3672 +    RootedObject obj_;
  1.3673 +    size_t protoChainDepth_;
  1.3674 +
  1.3675 +    bool generateStubCode(MacroAssembler &masm);
  1.3676 +
  1.3677 +  protected:
  1.3678 +    virtual int32_t getKey() const {
  1.3679 +        return static_cast<int32_t>(kind) | (static_cast<int32_t>(protoChainDepth_) << 16);
  1.3680 +    }
  1.3681 +
  1.3682 +  public:
  1.3683 +    ICSetElemDenseAddCompiler(JSContext *cx, HandleObject obj, size_t protoChainDepth)
  1.3684 +        : ICStubCompiler(cx, ICStub::SetElem_DenseAdd),
  1.3685 +          obj_(cx, obj),
  1.3686 +          protoChainDepth_(protoChainDepth)
  1.3687 +    {}
  1.3688 +
  1.3689 +    template <size_t ProtoChainDepth>
  1.3690 +    ICUpdatedStub *getStubSpecific(ICStubSpace *space, const AutoShapeVector *shapes);
  1.3691 +
  1.3692 +    ICUpdatedStub *getStub(ICStubSpace *space);
  1.3693 +};
  1.3694 +
  1.3695 +class ICSetElem_TypedArray : public ICStub
  1.3696 +{
  1.3697 +    friend class ICStubSpace;
  1.3698 +
  1.3699 +  protected: // Protected to silence Clang warning.
  1.3700 +    HeapPtrShape shape_;
  1.3701 +
  1.3702 +    ICSetElem_TypedArray(JitCode *stubCode, HandleShape shape, uint32_t type,
  1.3703 +                         bool expectOutOfBounds);
  1.3704 +
  1.3705 +  public:
  1.3706 +    static inline ICSetElem_TypedArray *New(ICStubSpace *space, JitCode *code,
  1.3707 +                                            HandleShape shape, uint32_t type,
  1.3708 +                                            bool expectOutOfBounds)
  1.3709 +    {
  1.3710 +        if (!code)
  1.3711 +            return nullptr;
  1.3712 +        return space->allocate<ICSetElem_TypedArray>(code, shape, type, expectOutOfBounds);
  1.3713 +    }
  1.3714 +
  1.3715 +    uint32_t type() const {
  1.3716 +        return extra_ & 0xff;
  1.3717 +    }
  1.3718 +
  1.3719 +    bool expectOutOfBounds() const {
  1.3720 +        return (extra_ >> 8) & 1;
  1.3721 +    }
  1.3722 +
  1.3723 +    static size_t offsetOfShape() {
  1.3724 +        return offsetof(ICSetElem_TypedArray, shape_);
  1.3725 +    }
  1.3726 +
  1.3727 +    HeapPtrShape &shape() {
  1.3728 +        return shape_;
  1.3729 +    }
  1.3730 +
  1.3731 +    class Compiler : public ICStubCompiler {
  1.3732 +        RootedShape shape_;
  1.3733 +        uint32_t type_;
  1.3734 +        bool expectOutOfBounds_;
  1.3735 +
  1.3736 +      protected:
  1.3737 +        bool generateStubCode(MacroAssembler &masm);
  1.3738 +
  1.3739 +        virtual int32_t getKey() const {
  1.3740 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16) |
  1.3741 +                   (static_cast<int32_t>(expectOutOfBounds_) << 24);
  1.3742 +        }
  1.3743 +
  1.3744 +      public:
  1.3745 +        Compiler(JSContext *cx, Shape *shape, uint32_t type, bool expectOutOfBounds)
  1.3746 +          : ICStubCompiler(cx, ICStub::SetElem_TypedArray),
  1.3747 +            shape_(cx, shape),
  1.3748 +            type_(type),
  1.3749 +            expectOutOfBounds_(expectOutOfBounds)
  1.3750 +        {}
  1.3751 +
  1.3752 +        ICStub *getStub(ICStubSpace *space) {
  1.3753 +            return ICSetElem_TypedArray::New(space, getStubCode(), shape_, type_,
  1.3754 +                                             expectOutOfBounds_);
  1.3755 +        }
  1.3756 +    };
  1.3757 +};
  1.3758 +
  1.3759 +// In
  1.3760 +//      JSOP_IN
  1.3761 +class ICIn_Fallback : public ICFallbackStub
  1.3762 +{
  1.3763 +    friend class ICStubSpace;
  1.3764 +
  1.3765 +    ICIn_Fallback(JitCode *stubCode)
  1.3766 +      : ICFallbackStub(ICStub::In_Fallback, stubCode)
  1.3767 +    { }
  1.3768 +
  1.3769 +  public:
  1.3770 +    static inline ICIn_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.3771 +        if (!code)
  1.3772 +            return nullptr;
  1.3773 +        return space->allocate<ICIn_Fallback>(code);
  1.3774 +    }
  1.3775 +
  1.3776 +    class Compiler : public ICStubCompiler {
  1.3777 +      protected:
  1.3778 +        bool generateStubCode(MacroAssembler &masm);
  1.3779 +
  1.3780 +      public:
  1.3781 +        Compiler(JSContext *cx)
  1.3782 +          : ICStubCompiler(cx, ICStub::In_Fallback)
  1.3783 +        { }
  1.3784 +
  1.3785 +        ICStub *getStub(ICStubSpace *space) {
  1.3786 +            return ICIn_Fallback::New(space, getStubCode());
  1.3787 +        }
  1.3788 +    };
  1.3789 +};
  1.3790 +
  1.3791 +// GetName
  1.3792 +//      JSOP_NAME
  1.3793 +//      JSOP_GETGNAME
  1.3794 +class ICGetName_Fallback : public ICMonitoredFallbackStub
  1.3795 +{
  1.3796 +    friend class ICStubSpace;
  1.3797 +
  1.3798 +    ICGetName_Fallback(JitCode *stubCode)
  1.3799 +      : ICMonitoredFallbackStub(ICStub::GetName_Fallback, stubCode)
  1.3800 +    { }
  1.3801 +
  1.3802 +  public:
  1.3803 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.3804 +
  1.3805 +    static inline ICGetName_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.3806 +        if (!code)
  1.3807 +            return nullptr;
  1.3808 +        return space->allocate<ICGetName_Fallback>(code);
  1.3809 +    }
  1.3810 +
  1.3811 +    class Compiler : public ICStubCompiler {
  1.3812 +      protected:
  1.3813 +        bool generateStubCode(MacroAssembler &masm);
  1.3814 +
  1.3815 +      public:
  1.3816 +        Compiler(JSContext *cx)
  1.3817 +          : ICStubCompiler(cx, ICStub::GetName_Fallback)
  1.3818 +        { }
  1.3819 +
  1.3820 +        ICStub *getStub(ICStubSpace *space) {
  1.3821 +            ICGetName_Fallback *stub = ICGetName_Fallback::New(space, getStubCode());
  1.3822 +            if (!stub || !stub->initMonitoringChain(cx, space))
  1.3823 +                return nullptr;
  1.3824 +            return stub;
  1.3825 +        }
  1.3826 +    };
  1.3827 +};
  1.3828 +
  1.3829 +// Optimized GETGNAME/CALLGNAME stub.
  1.3830 +class ICGetName_Global : public ICMonitoredStub
  1.3831 +{
  1.3832 +    friend class ICStubSpace;
  1.3833 +
  1.3834 +  protected: // Protected to silence Clang warning.
  1.3835 +    HeapPtrShape shape_;
  1.3836 +    uint32_t slot_;
  1.3837 +
  1.3838 +    ICGetName_Global(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape, uint32_t slot);
  1.3839 +
  1.3840 +  public:
  1.3841 +    static inline ICGetName_Global *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.3842 +                                        HandleShape shape, uint32_t slot)
  1.3843 +    {
  1.3844 +        if (!code)
  1.3845 +            return nullptr;
  1.3846 +        return space->allocate<ICGetName_Global>(code, firstMonitorStub, shape, slot);
  1.3847 +    }
  1.3848 +
  1.3849 +    HeapPtrShape &shape() {
  1.3850 +        return shape_;
  1.3851 +    }
  1.3852 +    static size_t offsetOfShape() {
  1.3853 +        return offsetof(ICGetName_Global, shape_);
  1.3854 +    }
  1.3855 +    static size_t offsetOfSlot() {
  1.3856 +        return offsetof(ICGetName_Global, slot_);
  1.3857 +    }
  1.3858 +
  1.3859 +    class Compiler : public ICStubCompiler {
  1.3860 +        ICStub *firstMonitorStub_;
  1.3861 +        RootedShape shape_;
  1.3862 +        uint32_t slot_;
  1.3863 +
  1.3864 +      protected:
  1.3865 +        bool generateStubCode(MacroAssembler &masm);
  1.3866 +
  1.3867 +      public:
  1.3868 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, Shape *shape, uint32_t slot)
  1.3869 +          : ICStubCompiler(cx, ICStub::GetName_Global),
  1.3870 +            firstMonitorStub_(firstMonitorStub),
  1.3871 +            shape_(cx, shape),
  1.3872 +            slot_(slot)
  1.3873 +        {}
  1.3874 +
  1.3875 +        ICStub *getStub(ICStubSpace *space) {
  1.3876 +            return ICGetName_Global::New(space, getStubCode(), firstMonitorStub_, shape_, slot_);
  1.3877 +        }
  1.3878 +    };
  1.3879 +};
  1.3880 +
  1.3881 +// Optimized GETNAME/CALLNAME stub, making a variable number of hops to get an
  1.3882 +// 'own' property off some scope object. Unlike GETPROP on an object's
  1.3883 +// prototype, there is no teleporting optimization to take advantage of and
  1.3884 +// shape checks are required all along the scope chain.
  1.3885 +template <size_t NumHops>
  1.3886 +class ICGetName_Scope : public ICMonitoredStub
  1.3887 +{
  1.3888 +    friend class ICStubSpace;
  1.3889 +
  1.3890 +    static const size_t MAX_HOPS = 6;
  1.3891 +
  1.3892 +    mozilla::Array<HeapPtrShape, NumHops + 1> shapes_;
  1.3893 +    uint32_t offset_;
  1.3894 +
  1.3895 +    ICGetName_Scope(JitCode *stubCode, ICStub *firstMonitorStub,
  1.3896 +                    AutoShapeVector *shapes, uint32_t offset);
  1.3897 +
  1.3898 +    static Kind GetStubKind() {
  1.3899 +        return (Kind) (GetName_Scope0 + NumHops);
  1.3900 +    }
  1.3901 +
  1.3902 +  public:
  1.3903 +    static inline ICGetName_Scope *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.3904 +                                       AutoShapeVector *shapes, uint32_t offset)
  1.3905 +    {
  1.3906 +        if (!code)
  1.3907 +            return nullptr;
  1.3908 +        return space->allocate<ICGetName_Scope<NumHops> >(code, firstMonitorStub, shapes, offset);
  1.3909 +    }
  1.3910 +
  1.3911 +    void traceScopes(JSTracer *trc) {
  1.3912 +        for (size_t i = 0; i < NumHops + 1; i++)
  1.3913 +            MarkShape(trc, &shapes_[i], "baseline-scope-stub-shape");
  1.3914 +    }
  1.3915 +
  1.3916 +    static size_t offsetOfShape(size_t index) {
  1.3917 +        JS_ASSERT(index <= NumHops);
  1.3918 +        return offsetof(ICGetName_Scope, shapes_) + (index * sizeof(HeapPtrShape));
  1.3919 +    }
  1.3920 +    static size_t offsetOfOffset() {
  1.3921 +        return offsetof(ICGetName_Scope, offset_);
  1.3922 +    }
  1.3923 +
  1.3924 +    class Compiler : public ICStubCompiler {
  1.3925 +        ICStub *firstMonitorStub_;
  1.3926 +        AutoShapeVector *shapes_;
  1.3927 +        bool isFixedSlot_;
  1.3928 +        uint32_t offset_;
  1.3929 +
  1.3930 +      protected:
  1.3931 +        bool generateStubCode(MacroAssembler &masm);
  1.3932 +
  1.3933 +      protected:
  1.3934 +        virtual int32_t getKey() const {
  1.3935 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16);
  1.3936 +        }
  1.3937 +
  1.3938 +      public:
  1.3939 +        Compiler(JSContext *cx, ICStub *firstMonitorStub,
  1.3940 +                 AutoShapeVector *shapes, bool isFixedSlot, uint32_t offset)
  1.3941 +          : ICStubCompiler(cx, GetStubKind()),
  1.3942 +            firstMonitorStub_(firstMonitorStub),
  1.3943 +            shapes_(shapes),
  1.3944 +            isFixedSlot_(isFixedSlot),
  1.3945 +            offset_(offset)
  1.3946 +        {
  1.3947 +        }
  1.3948 +
  1.3949 +        ICStub *getStub(ICStubSpace *space) {
  1.3950 +            return ICGetName_Scope::New(space, getStubCode(), firstMonitorStub_, shapes_, offset_);
  1.3951 +        }
  1.3952 +    };
  1.3953 +};
  1.3954 +
  1.3955 +// BindName
  1.3956 +//      JSOP_BINDNAME
  1.3957 +class ICBindName_Fallback : public ICFallbackStub
  1.3958 +{
  1.3959 +    friend class ICStubSpace;
  1.3960 +
  1.3961 +    ICBindName_Fallback(JitCode *stubCode)
  1.3962 +      : ICFallbackStub(ICStub::BindName_Fallback, stubCode)
  1.3963 +    { }
  1.3964 +
  1.3965 +  public:
  1.3966 +    static inline ICBindName_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.3967 +        if (!code)
  1.3968 +            return nullptr;
  1.3969 +        return space->allocate<ICBindName_Fallback>(code);
  1.3970 +    }
  1.3971 +
  1.3972 +    class Compiler : public ICStubCompiler {
  1.3973 +      protected:
  1.3974 +        bool generateStubCode(MacroAssembler &masm);
  1.3975 +
  1.3976 +      public:
  1.3977 +        Compiler(JSContext *cx)
  1.3978 +          : ICStubCompiler(cx, ICStub::BindName_Fallback)
  1.3979 +        { }
  1.3980 +
  1.3981 +        ICStub *getStub(ICStubSpace *space) {
  1.3982 +            return ICBindName_Fallback::New(space, getStubCode());
  1.3983 +        }
  1.3984 +    };
  1.3985 +};
  1.3986 +
  1.3987 +// GetIntrinsic
  1.3988 +//      JSOP_GETINTRINSIC
  1.3989 +class ICGetIntrinsic_Fallback : public ICMonitoredFallbackStub
  1.3990 +{
  1.3991 +    friend class ICStubSpace;
  1.3992 +
  1.3993 +    ICGetIntrinsic_Fallback(JitCode *stubCode)
  1.3994 +      : ICMonitoredFallbackStub(ICStub::GetIntrinsic_Fallback, stubCode)
  1.3995 +    { }
  1.3996 +
  1.3997 +  public:
  1.3998 +    static inline ICGetIntrinsic_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.3999 +        if (!code)
  1.4000 +            return nullptr;
  1.4001 +        return space->allocate<ICGetIntrinsic_Fallback>(code);
  1.4002 +    }
  1.4003 +
  1.4004 +    class Compiler : public ICStubCompiler {
  1.4005 +      protected:
  1.4006 +        bool generateStubCode(MacroAssembler &masm);
  1.4007 +
  1.4008 +      public:
  1.4009 +        Compiler(JSContext *cx)
  1.4010 +          : ICStubCompiler(cx, ICStub::GetIntrinsic_Fallback)
  1.4011 +        { }
  1.4012 +
  1.4013 +        ICStub *getStub(ICStubSpace *space) {
  1.4014 +            ICGetIntrinsic_Fallback *stub = ICGetIntrinsic_Fallback::New(space, getStubCode());
  1.4015 +            if (!stub || !stub->initMonitoringChain(cx, space))
  1.4016 +                return nullptr;
  1.4017 +            return stub;
  1.4018 +        }
  1.4019 +    };
  1.4020 +};
  1.4021 +
  1.4022 +// Stub that loads the constant result of a GETINTRINSIC operation.
  1.4023 +class ICGetIntrinsic_Constant : public ICStub
  1.4024 +{
  1.4025 +    friend class ICStubSpace;
  1.4026 +
  1.4027 +    HeapValue value_;
  1.4028 +
  1.4029 +    ICGetIntrinsic_Constant(JitCode *stubCode, HandleValue value);
  1.4030 +    ~ICGetIntrinsic_Constant();
  1.4031 +
  1.4032 +  public:
  1.4033 +    static inline ICGetIntrinsic_Constant *New(ICStubSpace *space, JitCode *code,
  1.4034 +                                               HandleValue value)
  1.4035 +    {
  1.4036 +        if (!code)
  1.4037 +            return nullptr;
  1.4038 +        return space->allocate<ICGetIntrinsic_Constant>(code, value);
  1.4039 +    }
  1.4040 +
  1.4041 +    HeapValue &value() {
  1.4042 +        return value_;
  1.4043 +    }
  1.4044 +    static size_t offsetOfValue() {
  1.4045 +        return offsetof(ICGetIntrinsic_Constant, value_);
  1.4046 +    }
  1.4047 +
  1.4048 +    class Compiler : public ICStubCompiler {
  1.4049 +        bool generateStubCode(MacroAssembler &masm);
  1.4050 +
  1.4051 +        HandleValue value_;
  1.4052 +
  1.4053 +      public:
  1.4054 +        Compiler(JSContext *cx, HandleValue value)
  1.4055 +          : ICStubCompiler(cx, ICStub::GetIntrinsic_Constant),
  1.4056 +            value_(value)
  1.4057 +        {}
  1.4058 +
  1.4059 +        ICStub *getStub(ICStubSpace *space) {
  1.4060 +            return ICGetIntrinsic_Constant::New(space, getStubCode(), value_);
  1.4061 +        }
  1.4062 +    };
  1.4063 +};
  1.4064 +
  1.4065 +class ICGetProp_Fallback : public ICMonitoredFallbackStub
  1.4066 +{
  1.4067 +    friend class ICStubSpace;
  1.4068 +
  1.4069 +    ICGetProp_Fallback(JitCode *stubCode)
  1.4070 +      : ICMonitoredFallbackStub(ICStub::GetProp_Fallback, stubCode)
  1.4071 +    { }
  1.4072 +
  1.4073 +  public:
  1.4074 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.4075 +
  1.4076 +    static inline ICGetProp_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.4077 +        if (!code)
  1.4078 +            return nullptr;
  1.4079 +        return space->allocate<ICGetProp_Fallback>(code);
  1.4080 +    }
  1.4081 +
  1.4082 +    static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
  1.4083 +    static const size_t ACCESSED_GETTER_BIT = 1;
  1.4084 +
  1.4085 +    void noteUnoptimizableAccess() {
  1.4086 +        extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
  1.4087 +    }
  1.4088 +    bool hadUnoptimizableAccess() const {
  1.4089 +        return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
  1.4090 +    }
  1.4091 +
  1.4092 +    void noteAccessedGetter() {
  1.4093 +        extra_ |= (1u << ACCESSED_GETTER_BIT);
  1.4094 +    }
  1.4095 +    bool hasAccessedGetter() const {
  1.4096 +        return extra_ & (1u << ACCESSED_GETTER_BIT);
  1.4097 +    }
  1.4098 +
  1.4099 +    class Compiler : public ICStubCompiler {
  1.4100 +      protected:
  1.4101 +        uint32_t returnFromIonOffset_;
  1.4102 +        uint32_t returnFromStubOffset_;
  1.4103 +        bool generateStubCode(MacroAssembler &masm);
  1.4104 +        bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> code);
  1.4105 +
  1.4106 +      public:
  1.4107 +        Compiler(JSContext *cx)
  1.4108 +          : ICStubCompiler(cx, ICStub::GetProp_Fallback)
  1.4109 +        { }
  1.4110 +
  1.4111 +        ICStub *getStub(ICStubSpace *space) {
  1.4112 +            ICGetProp_Fallback *stub = ICGetProp_Fallback::New(space, getStubCode());
  1.4113 +            if (!stub || !stub->initMonitoringChain(cx, space))
  1.4114 +                return nullptr;
  1.4115 +            return stub;
  1.4116 +        }
  1.4117 +    };
  1.4118 +};
  1.4119 +
  1.4120 +// Stub for accessing a dense array's length.
  1.4121 +class ICGetProp_ArrayLength : public ICStub
  1.4122 +{
  1.4123 +    friend class ICStubSpace;
  1.4124 +
  1.4125 +    ICGetProp_ArrayLength(JitCode *stubCode)
  1.4126 +      : ICStub(GetProp_ArrayLength, stubCode)
  1.4127 +    {}
  1.4128 +
  1.4129 +  public:
  1.4130 +    static inline ICGetProp_ArrayLength *New(ICStubSpace *space, JitCode *code) {
  1.4131 +        if (!code)
  1.4132 +            return nullptr;
  1.4133 +        return space->allocate<ICGetProp_ArrayLength>(code);
  1.4134 +    }
  1.4135 +
  1.4136 +    class Compiler : public ICStubCompiler {
  1.4137 +        bool generateStubCode(MacroAssembler &masm);
  1.4138 +
  1.4139 +      public:
  1.4140 +        Compiler(JSContext *cx)
  1.4141 +          : ICStubCompiler(cx, ICStub::GetProp_ArrayLength)
  1.4142 +        {}
  1.4143 +
  1.4144 +        ICStub *getStub(ICStubSpace *space) {
  1.4145 +            return ICGetProp_ArrayLength::New(space, getStubCode());
  1.4146 +        }
  1.4147 +    };
  1.4148 +};
  1.4149 +
  1.4150 +// Stub for accessing a typed array's length.
  1.4151 +class ICGetProp_TypedArrayLength : public ICStub
  1.4152 +{
  1.4153 +    friend class ICStubSpace;
  1.4154 +
  1.4155 +    ICGetProp_TypedArrayLength(JitCode *stubCode)
  1.4156 +      : ICStub(GetProp_TypedArrayLength, stubCode)
  1.4157 +    {}
  1.4158 +
  1.4159 +  public:
  1.4160 +    static inline ICGetProp_TypedArrayLength *New(ICStubSpace *space, JitCode *code) {
  1.4161 +        if (!code)
  1.4162 +            return nullptr;
  1.4163 +        return space->allocate<ICGetProp_TypedArrayLength>(code);
  1.4164 +    }
  1.4165 +
  1.4166 +    class Compiler : public ICStubCompiler {
  1.4167 +        bool generateStubCode(MacroAssembler &masm);
  1.4168 +
  1.4169 +      public:
  1.4170 +        Compiler(JSContext *cx)
  1.4171 +          : ICStubCompiler(cx, ICStub::GetProp_TypedArrayLength)
  1.4172 +        {}
  1.4173 +
  1.4174 +        ICStub *getStub(ICStubSpace *space) {
  1.4175 +            return ICGetProp_TypedArrayLength::New(space, getStubCode());
  1.4176 +        }
  1.4177 +    };
  1.4178 +};
  1.4179 +
  1.4180 +// Stub for accessing a property on a primitive's prototype.
  1.4181 +class ICGetProp_Primitive : public ICMonitoredStub
  1.4182 +{
  1.4183 +    friend class ICStubSpace;
  1.4184 +
  1.4185 +  protected: // Protected to silence Clang warning.
  1.4186 +    // Shape of String.prototype/Number.prototype to check for.
  1.4187 +    HeapPtrShape protoShape_;
  1.4188 +
  1.4189 +    // Fixed or dynamic slot offset.
  1.4190 +    uint32_t offset_;
  1.4191 +
  1.4192 +    ICGetProp_Primitive(JitCode *stubCode, ICStub *firstMonitorStub,
  1.4193 +                        HandleShape protoShape, uint32_t offset);
  1.4194 +
  1.4195 +  public:
  1.4196 +    static inline ICGetProp_Primitive *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.4197 +                                           HandleShape protoShape, uint32_t offset)
  1.4198 +    {
  1.4199 +        if (!code)
  1.4200 +            return nullptr;
  1.4201 +        return space->allocate<ICGetProp_Primitive>(code, firstMonitorStub, protoShape, offset);
  1.4202 +    }
  1.4203 +
  1.4204 +    HeapPtrShape &protoShape() {
  1.4205 +        return protoShape_;
  1.4206 +    }
  1.4207 +    static size_t offsetOfProtoShape() {
  1.4208 +        return offsetof(ICGetProp_Primitive, protoShape_);
  1.4209 +    }
  1.4210 +
  1.4211 +    static size_t offsetOfOffset() {
  1.4212 +        return offsetof(ICGetProp_Primitive, offset_);
  1.4213 +    }
  1.4214 +
  1.4215 +    class Compiler : public ICStubCompiler {
  1.4216 +        ICStub *firstMonitorStub_;
  1.4217 +        JSValueType primitiveType_;
  1.4218 +        RootedObject prototype_;
  1.4219 +        bool isFixedSlot_;
  1.4220 +        uint32_t offset_;
  1.4221 +
  1.4222 +        bool generateStubCode(MacroAssembler &masm);
  1.4223 +
  1.4224 +      protected:
  1.4225 +        virtual int32_t getKey() const {
  1.4226 +            static_assert(sizeof(JSValueType) == 1, "JSValueType should fit in one byte");
  1.4227 +            return static_cast<int32_t>(kind)
  1.4228 +                | (static_cast<int32_t>(isFixedSlot_) << 16)
  1.4229 +                | (static_cast<int32_t>(primitiveType_) << 24);
  1.4230 +        }
  1.4231 +
  1.4232 +      public:
  1.4233 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, JSValueType primitiveType,
  1.4234 +                 HandleObject prototype, bool isFixedSlot, uint32_t offset)
  1.4235 +          : ICStubCompiler(cx, ICStub::GetProp_Primitive),
  1.4236 +            firstMonitorStub_(firstMonitorStub),
  1.4237 +            primitiveType_(primitiveType),
  1.4238 +            prototype_(cx, prototype),
  1.4239 +            isFixedSlot_(isFixedSlot),
  1.4240 +            offset_(offset)
  1.4241 +        {}
  1.4242 +
  1.4243 +        ICStub *getStub(ICStubSpace *space) {
  1.4244 +            RootedShape protoShape(cx, prototype_->lastProperty());
  1.4245 +            return ICGetProp_Primitive::New(space, getStubCode(), firstMonitorStub_,
  1.4246 +                                            protoShape, offset_);
  1.4247 +        }
  1.4248 +    };
  1.4249 +};
  1.4250 +
  1.4251 +// Stub for accessing a string's length.
  1.4252 +class ICGetProp_StringLength : public ICStub
  1.4253 +{
  1.4254 +    friend class ICStubSpace;
  1.4255 +
  1.4256 +    ICGetProp_StringLength(JitCode *stubCode)
  1.4257 +      : ICStub(GetProp_StringLength, stubCode)
  1.4258 +    {}
  1.4259 +
  1.4260 +  public:
  1.4261 +    static inline ICGetProp_StringLength *New(ICStubSpace *space, JitCode *code) {
  1.4262 +        if (!code)
  1.4263 +            return nullptr;
  1.4264 +        return space->allocate<ICGetProp_StringLength>(code);
  1.4265 +    }
  1.4266 +
  1.4267 +    class Compiler : public ICStubCompiler {
  1.4268 +        bool generateStubCode(MacroAssembler &masm);
  1.4269 +
  1.4270 +      public:
  1.4271 +        Compiler(JSContext *cx)
  1.4272 +          : ICStubCompiler(cx, ICStub::GetProp_StringLength)
  1.4273 +        {}
  1.4274 +
  1.4275 +        ICStub *getStub(ICStubSpace *space) {
  1.4276 +            return ICGetProp_StringLength::New(space, getStubCode());
  1.4277 +        }
  1.4278 +    };
  1.4279 +};
  1.4280 +
  1.4281 +// Base class for GetProp_Native and GetProp_NativePrototype stubs.
  1.4282 +class ICGetPropNativeStub : public ICMonitoredStub
  1.4283 +{
  1.4284 +    // Object shape (lastProperty).
  1.4285 +    HeapPtrShape shape_;
  1.4286 +
  1.4287 +    // Fixed or dynamic slot offset.
  1.4288 +    uint32_t offset_;
  1.4289 +
  1.4290 +  protected:
  1.4291 +    ICGetPropNativeStub(ICStub::Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  1.4292 +                        HandleShape shape, uint32_t offset);
  1.4293 +
  1.4294 +  public:
  1.4295 +    HeapPtrShape &shape() {
  1.4296 +        return shape_;
  1.4297 +    }
  1.4298 +    uint32_t offset() const {
  1.4299 +        return offset_;
  1.4300 +    }
  1.4301 +    static size_t offsetOfShape() {
  1.4302 +        return offsetof(ICGetPropNativeStub, shape_);
  1.4303 +    }
  1.4304 +    static size_t offsetOfOffset() {
  1.4305 +        return offsetof(ICGetPropNativeStub, offset_);
  1.4306 +    }
  1.4307 +};
  1.4308 +
  1.4309 +// Stub for accessing an own property on a native object.
  1.4310 +class ICGetProp_Native : public ICGetPropNativeStub
  1.4311 +{
  1.4312 +    friend class ICStubSpace;
  1.4313 +
  1.4314 +    ICGetProp_Native(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape,
  1.4315 +                     uint32_t offset)
  1.4316 +      : ICGetPropNativeStub(GetProp_Native, stubCode, firstMonitorStub, shape, offset)
  1.4317 +    {}
  1.4318 +
  1.4319 +  public:
  1.4320 +    static inline ICGetProp_Native *New(ICStubSpace *space, JitCode *code,
  1.4321 +                                        ICStub *firstMonitorStub, HandleShape shape,
  1.4322 +                                        uint32_t offset)
  1.4323 +    {
  1.4324 +        if (!code)
  1.4325 +            return nullptr;
  1.4326 +        return space->allocate<ICGetProp_Native>(code, firstMonitorStub, shape, offset);
  1.4327 +    }
  1.4328 +};
  1.4329 +
  1.4330 +// Stub for accessing a property on a native object's prototype. Note that due to
  1.4331 +// the shape teleporting optimization, we only have to guard on the object's shape
  1.4332 +// and the holder's shape.
  1.4333 +class ICGetProp_NativePrototype : public ICGetPropNativeStub
  1.4334 +{
  1.4335 +    friend class ICStubSpace;
  1.4336 +
  1.4337 +  protected:
  1.4338 +    // Holder and its shape.
  1.4339 +    HeapPtrObject holder_;
  1.4340 +    HeapPtrShape holderShape_;
  1.4341 +
  1.4342 +    ICGetProp_NativePrototype(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape,
  1.4343 +                              uint32_t offset, HandleObject holder, HandleShape holderShape);
  1.4344 +
  1.4345 +  public:
  1.4346 +    static inline ICGetProp_NativePrototype *New(ICStubSpace *space, JitCode *code,
  1.4347 +                                                 ICStub *firstMonitorStub, HandleShape shape,
  1.4348 +                                                 uint32_t offset, HandleObject holder,
  1.4349 +                                                 HandleShape holderShape)
  1.4350 +    {
  1.4351 +        if (!code)
  1.4352 +            return nullptr;
  1.4353 +        return space->allocate<ICGetProp_NativePrototype>(code, firstMonitorStub, shape, offset,
  1.4354 +                                                          holder, holderShape);
  1.4355 +    }
  1.4356 +
  1.4357 +  public:
  1.4358 +    HeapPtrObject &holder() {
  1.4359 +        return holder_;
  1.4360 +    }
  1.4361 +    HeapPtrShape &holderShape() {
  1.4362 +        return holderShape_;
  1.4363 +    }
  1.4364 +    static size_t offsetOfHolder() {
  1.4365 +        return offsetof(ICGetProp_NativePrototype, holder_);
  1.4366 +    }
  1.4367 +    static size_t offsetOfHolderShape() {
  1.4368 +        return offsetof(ICGetProp_NativePrototype, holderShape_);
  1.4369 +    }
  1.4370 +};
  1.4371 +
  1.4372 +
  1.4373 +// Compiler for GetProp_Native and GetProp_NativePrototype stubs.
  1.4374 +class ICGetPropNativeCompiler : public ICStubCompiler
  1.4375 +{
  1.4376 +    bool isCallProp_;
  1.4377 +    ICStub *firstMonitorStub_;
  1.4378 +    HandleObject obj_;
  1.4379 +    HandleObject holder_;
  1.4380 +    HandlePropertyName propName_;
  1.4381 +    bool isFixedSlot_;
  1.4382 +    uint32_t offset_;
  1.4383 +
  1.4384 +    bool generateStubCode(MacroAssembler &masm);
  1.4385 +
  1.4386 +  protected:
  1.4387 +    virtual int32_t getKey() const {
  1.4388 +#if JS_HAS_NO_SUCH_METHOD
  1.4389 +        return static_cast<int32_t>(kind) |
  1.4390 +               (static_cast<int32_t>(isCallProp_) << 16) |
  1.4391 +               (static_cast<int32_t>(isFixedSlot_) << 17);
  1.4392 +#else
  1.4393 +        return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16);
  1.4394 +#endif
  1.4395 +    }
  1.4396 +
  1.4397 +  public:
  1.4398 +    ICGetPropNativeCompiler(JSContext *cx, ICStub::Kind kind, bool isCallProp,
  1.4399 +                            ICStub *firstMonitorStub, HandleObject obj, HandleObject holder,
  1.4400 +                            HandlePropertyName propName, bool isFixedSlot, uint32_t offset)
  1.4401 +      : ICStubCompiler(cx, kind),
  1.4402 +        isCallProp_(isCallProp),
  1.4403 +        firstMonitorStub_(firstMonitorStub),
  1.4404 +        obj_(obj),
  1.4405 +        holder_(holder),
  1.4406 +        propName_(propName),
  1.4407 +        isFixedSlot_(isFixedSlot),
  1.4408 +        offset_(offset)
  1.4409 +    {}
  1.4410 +
  1.4411 +    ICStub *getStub(ICStubSpace *space) {
  1.4412 +        RootedShape shape(cx, obj_->lastProperty());
  1.4413 +        if (kind == ICStub::GetProp_Native) {
  1.4414 +            JS_ASSERT(obj_ == holder_);
  1.4415 +            return ICGetProp_Native::New(space, getStubCode(), firstMonitorStub_, shape, offset_);
  1.4416 +        }
  1.4417 +
  1.4418 +        JS_ASSERT(obj_ != holder_);
  1.4419 +        JS_ASSERT(kind == ICStub::GetProp_NativePrototype);
  1.4420 +        RootedShape holderShape(cx, holder_->lastProperty());
  1.4421 +        return ICGetProp_NativePrototype::New(space, getStubCode(), firstMonitorStub_, shape,
  1.4422 +                                              offset_, holder_, holderShape);
  1.4423 +    }
  1.4424 +};
  1.4425 +
  1.4426 +class ICGetPropCallGetter : public ICMonitoredStub
  1.4427 +{
  1.4428 +    friend class ICStubSpace;
  1.4429 +
  1.4430 +  protected:
  1.4431 +    // We don't strictly need this for own property getters, but we need it to do
  1.4432 +    // Ion optimizations, so we should keep it around.
  1.4433 +    HeapPtrObject holder_;
  1.4434 +
  1.4435 +    HeapPtrShape holderShape_;
  1.4436 +
  1.4437 +    // Function to call.
  1.4438 +    HeapPtrFunction getter_;
  1.4439 +
  1.4440 +    // PC offset of call
  1.4441 +    uint32_t pcOffset_;
  1.4442 +
  1.4443 +    ICGetPropCallGetter(Kind kind, JitCode *stubCode, ICStub *firstMonitorStub, HandleObject holder,
  1.4444 +                        HandleShape holderShape, HandleFunction getter, uint32_t pcOffset);
  1.4445 +
  1.4446 +  public:
  1.4447 +    HeapPtrObject &holder() {
  1.4448 +        return holder_;
  1.4449 +    }
  1.4450 +    HeapPtrShape &holderShape() {
  1.4451 +        return holderShape_;
  1.4452 +    }
  1.4453 +    HeapPtrFunction &getter() {
  1.4454 +        return getter_;
  1.4455 +    }
  1.4456 +
  1.4457 +    static size_t offsetOfHolder() {
  1.4458 +        return offsetof(ICGetPropCallGetter, holder_);
  1.4459 +    }
  1.4460 +    static size_t offsetOfHolderShape() {
  1.4461 +        return offsetof(ICGetPropCallGetter, holderShape_);
  1.4462 +    }
  1.4463 +    static size_t offsetOfGetter() {
  1.4464 +        return offsetof(ICGetPropCallGetter, getter_);
  1.4465 +    }
  1.4466 +    static size_t offsetOfPCOffset() {
  1.4467 +        return offsetof(ICGetPropCallGetter, pcOffset_);
  1.4468 +    }
  1.4469 +
  1.4470 +    class Compiler : public ICStubCompiler {
  1.4471 +      protected:
  1.4472 +        ICStub *firstMonitorStub_;
  1.4473 +        RootedObject holder_;
  1.4474 +        RootedFunction getter_;
  1.4475 +        uint32_t pcOffset_;
  1.4476 +
  1.4477 +      public:
  1.4478 +        Compiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
  1.4479 +                 HandleObject holder, HandleFunction getter, uint32_t pcOffset)
  1.4480 +          : ICStubCompiler(cx, kind),
  1.4481 +            firstMonitorStub_(firstMonitorStub),
  1.4482 +            holder_(cx, holder),
  1.4483 +            getter_(cx, getter),
  1.4484 +            pcOffset_(pcOffset)
  1.4485 +        {
  1.4486 +            JS_ASSERT(kind == ICStub::GetProp_CallScripted ||
  1.4487 +                      kind == ICStub::GetProp_CallNative ||
  1.4488 +                      kind == ICStub::GetProp_CallNativePrototype);
  1.4489 +        }
  1.4490 +    };
  1.4491 +};
  1.4492 +
  1.4493 +// Stub for calling a getter (native or scripted) on a native object when the getter is kept on
  1.4494 +// the proto-chain.
  1.4495 +class ICGetPropCallPrototypeGetter : public ICGetPropCallGetter
  1.4496 +{
  1.4497 +    friend class ICStubSpace;
  1.4498 +
  1.4499 +  protected:
  1.4500 +    // shape of receiver object.
  1.4501 +    HeapPtrShape receiverShape_;
  1.4502 +
  1.4503 +    ICGetPropCallPrototypeGetter(Kind kind, JitCode *stubCode, ICStub *firstMonitorStub,
  1.4504 +                                 HandleShape receiverShape,
  1.4505 +                                 HandleObject holder, HandleShape holderShape,
  1.4506 +                                 HandleFunction getter, uint32_t pcOffset);
  1.4507 +
  1.4508 +  public:
  1.4509 +    HeapPtrShape &receiverShape() {
  1.4510 +        return receiverShape_;
  1.4511 +    }
  1.4512 +
  1.4513 +    static size_t offsetOfReceiverShape() {
  1.4514 +        return offsetof(ICGetPropCallPrototypeGetter, receiverShape_);
  1.4515 +    }
  1.4516 +
  1.4517 +    class Compiler : public ICGetPropCallGetter::Compiler {
  1.4518 +      protected:
  1.4519 +        RootedObject receiver_;
  1.4520 +
  1.4521 +      public:
  1.4522 +        Compiler(JSContext *cx, ICStub::Kind kind, ICStub *firstMonitorStub,
  1.4523 +                 HandleObject obj, HandleObject holder, HandleFunction getter, uint32_t pcOffset)
  1.4524 +          : ICGetPropCallGetter::Compiler(cx, kind, firstMonitorStub, holder, getter, pcOffset),
  1.4525 +            receiver_(cx, obj)
  1.4526 +        {
  1.4527 +            JS_ASSERT(kind == ICStub::GetProp_CallScripted ||
  1.4528 +                      kind == ICStub::GetProp_CallNativePrototype);
  1.4529 +        }
  1.4530 +    };
  1.4531 +};
  1.4532 +
  1.4533 +// Stub for calling a scripted getter on a native object when the getter is kept on the
  1.4534 +// proto-chain.
  1.4535 +class ICGetProp_CallScripted : public ICGetPropCallPrototypeGetter
  1.4536 +{
  1.4537 +    friend class ICStubSpace;
  1.4538 +
  1.4539 +  protected:
  1.4540 +    ICGetProp_CallScripted(JitCode *stubCode, ICStub *firstMonitorStub,
  1.4541 +                           HandleShape receiverShape, HandleObject holder, HandleShape holderShape,
  1.4542 +                           HandleFunction getter, uint32_t pcOffset)
  1.4543 +      : ICGetPropCallPrototypeGetter(GetProp_CallScripted, stubCode, firstMonitorStub,
  1.4544 +                                     receiverShape, holder, holderShape, getter, pcOffset)
  1.4545 +    {}
  1.4546 +
  1.4547 +  public:
  1.4548 +    static inline ICGetProp_CallScripted *New(
  1.4549 +                ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.4550 +                HandleShape receiverShape, HandleObject holder, HandleShape holderShape,
  1.4551 +                HandleFunction getter, uint32_t pcOffset)
  1.4552 +    {
  1.4553 +        if (!code)
  1.4554 +            return nullptr;
  1.4555 +        return space->allocate<ICGetProp_CallScripted>(code, firstMonitorStub,
  1.4556 +                                                       receiverShape, holder, holderShape, getter,
  1.4557 +                                                       pcOffset);
  1.4558 +    }
  1.4559 +
  1.4560 +    class Compiler : public ICGetPropCallPrototypeGetter::Compiler {
  1.4561 +      protected:
  1.4562 +        bool generateStubCode(MacroAssembler &masm);
  1.4563 +
  1.4564 +      public:
  1.4565 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
  1.4566 +                 HandleObject holder, HandleFunction getter, uint32_t pcOffset)
  1.4567 +          : ICGetPropCallPrototypeGetter::Compiler(cx, ICStub::GetProp_CallScripted,
  1.4568 +                                                   firstMonitorStub, obj, holder,
  1.4569 +                                                   getter, pcOffset)
  1.4570 +        {}
  1.4571 +
  1.4572 +        ICStub *getStub(ICStubSpace *space) {
  1.4573 +            RootedShape receiverShape(cx, receiver_->lastProperty());
  1.4574 +            RootedShape holderShape(cx, holder_->lastProperty());
  1.4575 +            return ICGetProp_CallScripted::New(space, getStubCode(), firstMonitorStub_, receiverShape,
  1.4576 +                                               holder_, holderShape, getter_, pcOffset_);
  1.4577 +        }
  1.4578 +    };
  1.4579 +};
  1.4580 +
  1.4581 +// Stub for calling an own native getter on a native object.
  1.4582 +class ICGetProp_CallNative : public ICGetPropCallGetter
  1.4583 +{
  1.4584 +    friend class ICStubSpace;
  1.4585 +
  1.4586 +  protected:
  1.4587 +
  1.4588 +    ICGetProp_CallNative(JitCode *stubCode, ICStub *firstMonitorStub, HandleObject obj,
  1.4589 +                            HandleShape shape, HandleFunction getter, uint32_t pcOffset)
  1.4590 +      : ICGetPropCallGetter(GetProp_CallNative, stubCode, firstMonitorStub, obj, shape,
  1.4591 +                            getter, pcOffset)
  1.4592 +    { }
  1.4593 +
  1.4594 +  public:
  1.4595 +    static inline ICGetProp_CallNative *New(ICStubSpace *space, JitCode *code,
  1.4596 +                                            ICStub *firstMonitorStub, HandleObject obj,
  1.4597 +                                            HandleShape shape, HandleFunction getter,
  1.4598 +                                            uint32_t pcOffset)
  1.4599 +    {
  1.4600 +        if (!code)
  1.4601 +            return nullptr;
  1.4602 +        return space->allocate<ICGetProp_CallNative>(code, firstMonitorStub, obj, shape,
  1.4603 +                                                     getter, pcOffset);
  1.4604 +    }
  1.4605 +
  1.4606 +    class Compiler : public ICGetPropCallGetter::Compiler
  1.4607 +    {
  1.4608 +        bool inputDefinitelyObject_;
  1.4609 +      protected:
  1.4610 +        bool generateStubCode(MacroAssembler &masm);
  1.4611 +
  1.4612 +        virtual int32_t getKey() const {
  1.4613 +            return static_cast<int32_t>(kind) |
  1.4614 +                   (static_cast<int32_t>(inputDefinitelyObject_) << 16);
  1.4615 +        }
  1.4616 +
  1.4617 +      public:
  1.4618 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
  1.4619 +                 HandleFunction getter, uint32_t pcOffset, bool inputDefinitelyObject = false)
  1.4620 +          : ICGetPropCallGetter::Compiler(cx, ICStub::GetProp_CallNative, firstMonitorStub,
  1.4621 +                                          obj, getter, pcOffset),
  1.4622 +            inputDefinitelyObject_(inputDefinitelyObject)
  1.4623 +        {}
  1.4624 +
  1.4625 +        ICStub *getStub(ICStubSpace *space) {
  1.4626 +            RootedShape shape(cx, holder_->lastProperty());
  1.4627 +            return ICGetProp_CallNative::New(space, getStubCode(), firstMonitorStub_, holder_,
  1.4628 +                                             shape, getter_, pcOffset_);
  1.4629 +        }
  1.4630 +    };
  1.4631 +};
  1.4632 +
  1.4633 +// Stub for calling an native getter on a native object when the getter is kept on the proto-chain.
  1.4634 +class ICGetProp_CallNativePrototype : public ICGetPropCallPrototypeGetter
  1.4635 +{
  1.4636 +    friend class ICStubSpace;
  1.4637 +
  1.4638 +  protected:
  1.4639 +    ICGetProp_CallNativePrototype(JitCode *stubCode, ICStub *firstMonitorStub,
  1.4640 +                         HandleShape receiverShape, HandleObject holder, HandleShape holderShape,
  1.4641 +                         HandleFunction getter, uint32_t pcOffset)
  1.4642 +      : ICGetPropCallPrototypeGetter(GetProp_CallNativePrototype, stubCode, firstMonitorStub,
  1.4643 +                                     receiverShape, holder, holderShape, getter, pcOffset)
  1.4644 +    {}
  1.4645 +
  1.4646 +  public:
  1.4647 +    static inline ICGetProp_CallNativePrototype *New(
  1.4648 +                ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.4649 +                HandleShape receiverShape, HandleObject holder, HandleShape holderShape,
  1.4650 +                HandleFunction getter, uint32_t pcOffset)
  1.4651 +    {
  1.4652 +        if (!code)
  1.4653 +            return nullptr;
  1.4654 +        return space->allocate<ICGetProp_CallNativePrototype>(code, firstMonitorStub,
  1.4655 +                                                              receiverShape, holder, holderShape,
  1.4656 +                                                              getter, pcOffset);
  1.4657 +    }
  1.4658 +
  1.4659 +    class Compiler : public ICGetPropCallPrototypeGetter::Compiler {
  1.4660 +      protected:
  1.4661 +        bool generateStubCode(MacroAssembler &masm);
  1.4662 +
  1.4663 +      public:
  1.4664 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, HandleObject obj,
  1.4665 +                 HandleObject holder, HandleFunction getter, uint32_t pcOffset)
  1.4666 +          : ICGetPropCallPrototypeGetter::Compiler(cx, ICStub::GetProp_CallNativePrototype,
  1.4667 +                                                   firstMonitorStub, obj, holder,
  1.4668 +                                                   getter, pcOffset)
  1.4669 +        {}
  1.4670 +
  1.4671 +        ICStub *getStub(ICStubSpace *space) {
  1.4672 +            RootedShape receiverShape(cx, receiver_->lastProperty());
  1.4673 +            RootedShape holderShape(cx, holder_->lastProperty());
  1.4674 +            return ICGetProp_CallNativePrototype::New(space, getStubCode(), firstMonitorStub_, receiverShape,
  1.4675 +                                                      holder_, holderShape, getter_, pcOffset_);
  1.4676 +        }
  1.4677 +    };
  1.4678 +};
  1.4679 +
  1.4680 +class ICGetPropCallDOMProxyNativeStub : public ICMonitoredStub
  1.4681 +{
  1.4682 +  friend class ICStubSpace;
  1.4683 +  protected:
  1.4684 +    // Shape of the DOMProxy
  1.4685 +    HeapPtrShape shape_;
  1.4686 +
  1.4687 +    // Proxy handler to check against.
  1.4688 +    BaseProxyHandler *proxyHandler_;
  1.4689 +
  1.4690 +    // Object shape of expected expando object. (nullptr if no expando object should be there)
  1.4691 +    HeapPtrShape expandoShape_;
  1.4692 +
  1.4693 +    // Holder and its shape.
  1.4694 +    HeapPtrObject holder_;
  1.4695 +    HeapPtrShape holderShape_;
  1.4696 +
  1.4697 +    // Function to call.
  1.4698 +    HeapPtrFunction getter_;
  1.4699 +
  1.4700 +    // PC offset of call
  1.4701 +    uint32_t pcOffset_;
  1.4702 +
  1.4703 +    ICGetPropCallDOMProxyNativeStub(ICStub::Kind kind, JitCode *stubCode,
  1.4704 +                                    ICStub *firstMonitorStub, HandleShape shape,
  1.4705 +                                    BaseProxyHandler *proxyHandler, HandleShape expandoShape,
  1.4706 +                                    HandleObject holder, HandleShape holderShape,
  1.4707 +                                    HandleFunction getter, uint32_t pcOffset);
  1.4708 +
  1.4709 +  public:
  1.4710 +    HeapPtrShape &shape() {
  1.4711 +        return shape_;
  1.4712 +    }
  1.4713 +    HeapPtrShape &expandoShape() {
  1.4714 +        return expandoShape_;
  1.4715 +    }
  1.4716 +    HeapPtrObject &holder() {
  1.4717 +        return holder_;
  1.4718 +    }
  1.4719 +    HeapPtrShape &holderShape() {
  1.4720 +        return holderShape_;
  1.4721 +    }
  1.4722 +    HeapPtrFunction &getter() {
  1.4723 +        return getter_;
  1.4724 +    }
  1.4725 +    uint32_t pcOffset() const {
  1.4726 +        return pcOffset_;
  1.4727 +    }
  1.4728 +
  1.4729 +    static size_t offsetOfShape() {
  1.4730 +        return offsetof(ICGetPropCallDOMProxyNativeStub, shape_);
  1.4731 +    }
  1.4732 +    static size_t offsetOfProxyHandler() {
  1.4733 +        return offsetof(ICGetPropCallDOMProxyNativeStub, proxyHandler_);
  1.4734 +    }
  1.4735 +    static size_t offsetOfExpandoShape() {
  1.4736 +        return offsetof(ICGetPropCallDOMProxyNativeStub, expandoShape_);
  1.4737 +    }
  1.4738 +    static size_t offsetOfHolder() {
  1.4739 +        return offsetof(ICGetPropCallDOMProxyNativeStub, holder_);
  1.4740 +    }
  1.4741 +    static size_t offsetOfHolderShape() {
  1.4742 +        return offsetof(ICGetPropCallDOMProxyNativeStub, holderShape_);
  1.4743 +    }
  1.4744 +    static size_t offsetOfGetter() {
  1.4745 +        return offsetof(ICGetPropCallDOMProxyNativeStub, getter_);
  1.4746 +    }
  1.4747 +    static size_t offsetOfPCOffset() {
  1.4748 +        return offsetof(ICGetPropCallDOMProxyNativeStub, pcOffset_);
  1.4749 +    }
  1.4750 +};
  1.4751 +
  1.4752 +class ICGetProp_CallDOMProxyNative : public ICGetPropCallDOMProxyNativeStub
  1.4753 +{
  1.4754 +    friend class ICStubSpace;
  1.4755 +    ICGetProp_CallDOMProxyNative(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape,
  1.4756 +                                 BaseProxyHandler *proxyHandler, HandleShape expandoShape,
  1.4757 +                                 HandleObject holder, HandleShape holderShape,
  1.4758 +                                 HandleFunction getter, uint32_t pcOffset)
  1.4759 +      : ICGetPropCallDOMProxyNativeStub(ICStub::GetProp_CallDOMProxyNative, stubCode,
  1.4760 +                                        firstMonitorStub, shape, proxyHandler, expandoShape,
  1.4761 +                                        holder, holderShape, getter, pcOffset)
  1.4762 +    {}
  1.4763 +
  1.4764 +  public:
  1.4765 +    static inline ICGetProp_CallDOMProxyNative *New(
  1.4766 +            ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.4767 +            HandleShape shape, BaseProxyHandler *proxyHandler,
  1.4768 +            HandleShape expandoShape, HandleObject holder, HandleShape holderShape,
  1.4769 +            HandleFunction getter, uint32_t pcOffset)
  1.4770 +    {
  1.4771 +        if (!code)
  1.4772 +            return nullptr;
  1.4773 +        return space->allocate<ICGetProp_CallDOMProxyNative>(code, firstMonitorStub, shape,
  1.4774 +                                                   proxyHandler, expandoShape, holder,
  1.4775 +                                                   holderShape, getter, pcOffset);
  1.4776 +    }
  1.4777 +};
  1.4778 +
  1.4779 +class ICGetProp_CallDOMProxyWithGenerationNative : public ICGetPropCallDOMProxyNativeStub
  1.4780 +{
  1.4781 +  protected:
  1.4782 +    ExpandoAndGeneration *expandoAndGeneration_;
  1.4783 +    uint32_t generation_;
  1.4784 +
  1.4785 +  public:
  1.4786 +    ICGetProp_CallDOMProxyWithGenerationNative(JitCode *stubCode, ICStub *firstMonitorStub,
  1.4787 +                                               HandleShape shape, BaseProxyHandler *proxyHandler,
  1.4788 +                                               ExpandoAndGeneration *expandoAndGeneration,
  1.4789 +                                               uint32_t generation, HandleShape expandoShape,
  1.4790 +                                               HandleObject holder, HandleShape holderShape,
  1.4791 +                                               HandleFunction getter, uint32_t pcOffset)
  1.4792 +      : ICGetPropCallDOMProxyNativeStub(ICStub::GetProp_CallDOMProxyWithGenerationNative,
  1.4793 +                                        stubCode, firstMonitorStub, shape, proxyHandler,
  1.4794 +                                        expandoShape, holder, holderShape, getter, pcOffset),
  1.4795 +        expandoAndGeneration_(expandoAndGeneration),
  1.4796 +        generation_(generation)
  1.4797 +    {
  1.4798 +    }
  1.4799 +
  1.4800 +    static inline ICGetProp_CallDOMProxyWithGenerationNative *New(
  1.4801 +            ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.4802 +            HandleShape shape, BaseProxyHandler *proxyHandler,
  1.4803 +            ExpandoAndGeneration *expandoAndGeneration, uint32_t generation,
  1.4804 +            HandleShape expandoShape, HandleObject holder, HandleShape holderShape,
  1.4805 +            HandleFunction getter, uint32_t pcOffset)
  1.4806 +    {
  1.4807 +        if (!code)
  1.4808 +            return nullptr;
  1.4809 +        return space->allocate<ICGetProp_CallDOMProxyWithGenerationNative>(code, firstMonitorStub,
  1.4810 +                                                   shape, proxyHandler, expandoAndGeneration,
  1.4811 +                                                   generation, expandoShape, holder, holderShape,
  1.4812 +                                                   getter, pcOffset);
  1.4813 +    }
  1.4814 +
  1.4815 +    void *expandoAndGeneration() const {
  1.4816 +        return expandoAndGeneration_;
  1.4817 +    }
  1.4818 +    uint32_t generation() const {
  1.4819 +        return generation_;
  1.4820 +    }
  1.4821 +
  1.4822 +    void setGeneration(uint32_t value) {
  1.4823 +        generation_ = value;
  1.4824 +    }
  1.4825 +
  1.4826 +    static size_t offsetOfInternalStruct() {
  1.4827 +        return offsetof(ICGetProp_CallDOMProxyWithGenerationNative, expandoAndGeneration_);
  1.4828 +    }
  1.4829 +    static size_t offsetOfGeneration() {
  1.4830 +        return offsetof(ICGetProp_CallDOMProxyWithGenerationNative, generation_);
  1.4831 +    }
  1.4832 +};
  1.4833 +
  1.4834 +class ICGetPropCallDOMProxyNativeCompiler : public ICStubCompiler {
  1.4835 +    ICStub *firstMonitorStub_;
  1.4836 +    Rooted<ProxyObject*> proxy_;
  1.4837 +    RootedObject holder_;
  1.4838 +    RootedFunction getter_;
  1.4839 +    uint32_t pcOffset_;
  1.4840 +
  1.4841 +    bool generateStubCode(MacroAssembler &masm, Address* internalStructAddr,
  1.4842 +                          Address* generationAddr);
  1.4843 +    bool generateStubCode(MacroAssembler &masm);
  1.4844 +
  1.4845 +  public:
  1.4846 +    ICGetPropCallDOMProxyNativeCompiler(JSContext *cx, ICStub::Kind kind,
  1.4847 +                                        ICStub *firstMonitorStub, Handle<ProxyObject*> proxy,
  1.4848 +                                        HandleObject holder, HandleFunction getter,
  1.4849 +                                        uint32_t pcOffset);
  1.4850 +
  1.4851 +    ICStub *getStub(ICStubSpace *space);
  1.4852 +};
  1.4853 +
  1.4854 +class ICGetProp_DOMProxyShadowed : public ICMonitoredStub
  1.4855 +{
  1.4856 +  friend class ICStubSpace;
  1.4857 +  protected:
  1.4858 +    HeapPtrShape shape_;
  1.4859 +    BaseProxyHandler *proxyHandler_;
  1.4860 +    HeapPtrPropertyName name_;
  1.4861 +    uint32_t pcOffset_;
  1.4862 +
  1.4863 +    ICGetProp_DOMProxyShadowed(JitCode *stubCode, ICStub *firstMonitorStub, HandleShape shape,
  1.4864 +                               BaseProxyHandler *proxyHandler, HandlePropertyName name,
  1.4865 +                               uint32_t pcOffset);
  1.4866 +
  1.4867 +  public:
  1.4868 +    static inline ICGetProp_DOMProxyShadowed *New(ICStubSpace *space, JitCode *code,
  1.4869 +                                                  ICStub *firstMonitorStub, HandleShape shape,
  1.4870 +                                                  BaseProxyHandler *proxyHandler,
  1.4871 +                                                  HandlePropertyName name, uint32_t pcOffset)
  1.4872 +    {
  1.4873 +        if (!code)
  1.4874 +            return nullptr;
  1.4875 +        return space->allocate<ICGetProp_DOMProxyShadowed>(code, firstMonitorStub, shape,
  1.4876 +                                                           proxyHandler, name, pcOffset);
  1.4877 +    }
  1.4878 +
  1.4879 +    HeapPtrShape &shape() {
  1.4880 +        return shape_;
  1.4881 +    }
  1.4882 +    HeapPtrPropertyName &name() {
  1.4883 +        return name_;
  1.4884 +    }
  1.4885 +
  1.4886 +    static size_t offsetOfShape() {
  1.4887 +        return offsetof(ICGetProp_DOMProxyShadowed, shape_);
  1.4888 +    }
  1.4889 +    static size_t offsetOfProxyHandler() {
  1.4890 +        return offsetof(ICGetProp_DOMProxyShadowed, proxyHandler_);
  1.4891 +    }
  1.4892 +    static size_t offsetOfName() {
  1.4893 +        return offsetof(ICGetProp_DOMProxyShadowed, name_);
  1.4894 +    }
  1.4895 +    static size_t offsetOfPCOffset() {
  1.4896 +        return offsetof(ICGetProp_DOMProxyShadowed, pcOffset_);
  1.4897 +    }
  1.4898 +
  1.4899 +    class Compiler : public ICStubCompiler {
  1.4900 +        ICStub *firstMonitorStub_;
  1.4901 +        Rooted<ProxyObject*> proxy_;
  1.4902 +        RootedPropertyName name_;
  1.4903 +        uint32_t pcOffset_;
  1.4904 +
  1.4905 +        bool generateStubCode(MacroAssembler &masm);
  1.4906 +
  1.4907 +      public:
  1.4908 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, Handle<ProxyObject*> proxy,
  1.4909 +                 HandlePropertyName name, uint32_t pcOffset)
  1.4910 +          : ICStubCompiler(cx, ICStub::GetProp_CallNative),
  1.4911 +            firstMonitorStub_(firstMonitorStub),
  1.4912 +            proxy_(cx, proxy),
  1.4913 +            name_(cx, name),
  1.4914 +            pcOffset_(pcOffset)
  1.4915 +        {}
  1.4916 +
  1.4917 +        ICStub *getStub(ICStubSpace *space);
  1.4918 +    };
  1.4919 +};
  1.4920 +
  1.4921 +class ICGetProp_ArgumentsLength : public ICStub
  1.4922 +{
  1.4923 +  friend class ICStubSpace;
  1.4924 +  public:
  1.4925 +    enum Which { Normal, Strict, Magic };
  1.4926 +
  1.4927 +  protected:
  1.4928 +    ICGetProp_ArgumentsLength(JitCode *stubCode)
  1.4929 +      : ICStub(ICStub::GetProp_ArgumentsLength, stubCode)
  1.4930 +    { }
  1.4931 +
  1.4932 +  public:
  1.4933 +    static inline ICGetProp_ArgumentsLength *New(ICStubSpace *space, JitCode *code)
  1.4934 +    {
  1.4935 +        if (!code)
  1.4936 +            return nullptr;
  1.4937 +        return space->allocate<ICGetProp_ArgumentsLength>(code);
  1.4938 +    }
  1.4939 +
  1.4940 +    class Compiler : public ICStubCompiler {
  1.4941 +      protected:
  1.4942 +        Which which_;
  1.4943 +
  1.4944 +        bool generateStubCode(MacroAssembler &masm);
  1.4945 +
  1.4946 +        virtual int32_t getKey() const {
  1.4947 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(which_) << 16);
  1.4948 +        }
  1.4949 +
  1.4950 +      public:
  1.4951 +        Compiler(JSContext *cx, Which which)
  1.4952 +          : ICStubCompiler(cx, ICStub::GetProp_ArgumentsLength),
  1.4953 +            which_(which)
  1.4954 +        {}
  1.4955 +
  1.4956 +        ICStub *getStub(ICStubSpace *space) {
  1.4957 +            return ICGetProp_ArgumentsLength::New(space, getStubCode());
  1.4958 +        }
  1.4959 +    };
  1.4960 +};
  1.4961 +
  1.4962 +// SetProp
  1.4963 +//     JSOP_SETPROP
  1.4964 +//     JSOP_SETNAME
  1.4965 +//     JSOP_SETGNAME
  1.4966 +//     JSOP_INITPROP
  1.4967 +
  1.4968 +class ICSetProp_Fallback : public ICFallbackStub
  1.4969 +{
  1.4970 +    friend class ICStubSpace;
  1.4971 +
  1.4972 +    ICSetProp_Fallback(JitCode *stubCode)
  1.4973 +      : ICFallbackStub(ICStub::SetProp_Fallback, stubCode)
  1.4974 +    { }
  1.4975 +
  1.4976 +  public:
  1.4977 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.4978 +
  1.4979 +    static inline ICSetProp_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.4980 +        if (!code)
  1.4981 +            return nullptr;
  1.4982 +        return space->allocate<ICSetProp_Fallback>(code);
  1.4983 +    }
  1.4984 +
  1.4985 +    static const size_t UNOPTIMIZABLE_ACCESS_BIT = 0;
  1.4986 +    void noteUnoptimizableAccess() {
  1.4987 +        extra_ |= (1u << UNOPTIMIZABLE_ACCESS_BIT);
  1.4988 +    }
  1.4989 +    bool hadUnoptimizableAccess() const {
  1.4990 +        return extra_ & (1u << UNOPTIMIZABLE_ACCESS_BIT);
  1.4991 +    }
  1.4992 +
  1.4993 +    class Compiler : public ICStubCompiler {
  1.4994 +      protected:
  1.4995 +        uint32_t returnFromIonOffset_;
  1.4996 +        uint32_t returnFromStubOffset_;
  1.4997 +        bool generateStubCode(MacroAssembler &masm);
  1.4998 +        bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> code);
  1.4999 +
  1.5000 +      public:
  1.5001 +        Compiler(JSContext *cx)
  1.5002 +          : ICStubCompiler(cx, ICStub::SetProp_Fallback)
  1.5003 +        { }
  1.5004 +
  1.5005 +        ICStub *getStub(ICStubSpace *space) {
  1.5006 +            return ICSetProp_Fallback::New(space, getStubCode());
  1.5007 +        }
  1.5008 +    };
  1.5009 +};
  1.5010 +
  1.5011 +// Optimized SETPROP/SETGNAME/SETNAME stub.
  1.5012 +class ICSetProp_Native : public ICUpdatedStub
  1.5013 +{
  1.5014 +    friend class ICStubSpace;
  1.5015 +
  1.5016 +  protected: // Protected to silence Clang warning.
  1.5017 +    HeapPtrTypeObject type_;
  1.5018 +    HeapPtrShape shape_;
  1.5019 +    uint32_t offset_;
  1.5020 +
  1.5021 +    ICSetProp_Native(JitCode *stubCode, HandleTypeObject type, HandleShape shape, uint32_t offset);
  1.5022 +
  1.5023 +  public:
  1.5024 +    static inline ICSetProp_Native *New(ICStubSpace *space, JitCode *code, HandleTypeObject type,
  1.5025 +                                        HandleShape shape, uint32_t offset)
  1.5026 +    {
  1.5027 +        if (!code)
  1.5028 +            return nullptr;
  1.5029 +        return space->allocate<ICSetProp_Native>(code, type, shape, offset);
  1.5030 +    }
  1.5031 +    HeapPtrTypeObject &type() {
  1.5032 +        return type_;
  1.5033 +    }
  1.5034 +    HeapPtrShape &shape() {
  1.5035 +        return shape_;
  1.5036 +    }
  1.5037 +    static size_t offsetOfType() {
  1.5038 +        return offsetof(ICSetProp_Native, type_);
  1.5039 +    }
  1.5040 +    static size_t offsetOfShape() {
  1.5041 +        return offsetof(ICSetProp_Native, shape_);
  1.5042 +    }
  1.5043 +    static size_t offsetOfOffset() {
  1.5044 +        return offsetof(ICSetProp_Native, offset_);
  1.5045 +    }
  1.5046 +
  1.5047 +    class Compiler : public ICStubCompiler {
  1.5048 +        RootedObject obj_;
  1.5049 +        bool isFixedSlot_;
  1.5050 +        uint32_t offset_;
  1.5051 +
  1.5052 +      protected:
  1.5053 +        virtual int32_t getKey() const {
  1.5054 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16);
  1.5055 +        }
  1.5056 +
  1.5057 +        bool generateStubCode(MacroAssembler &masm);
  1.5058 +
  1.5059 +      public:
  1.5060 +        Compiler(JSContext *cx, HandleObject obj, bool isFixedSlot, uint32_t offset)
  1.5061 +          : ICStubCompiler(cx, ICStub::SetProp_Native),
  1.5062 +            obj_(cx, obj),
  1.5063 +            isFixedSlot_(isFixedSlot),
  1.5064 +            offset_(offset)
  1.5065 +        {}
  1.5066 +
  1.5067 +        ICUpdatedStub *getStub(ICStubSpace *space);
  1.5068 +    };
  1.5069 +};
  1.5070 +
  1.5071 +
  1.5072 +template <size_t ProtoChainDepth> class ICSetProp_NativeAddImpl;
  1.5073 +
  1.5074 +class ICSetProp_NativeAdd : public ICUpdatedStub
  1.5075 +{
  1.5076 +  public:
  1.5077 +    static const size_t MAX_PROTO_CHAIN_DEPTH = 4;
  1.5078 +
  1.5079 +  protected: // Protected to silence Clang warning.
  1.5080 +    HeapPtrTypeObject type_;
  1.5081 +    HeapPtrShape newShape_;
  1.5082 +    uint32_t offset_;
  1.5083 +
  1.5084 +    ICSetProp_NativeAdd(JitCode *stubCode, HandleTypeObject type, size_t protoChainDepth,
  1.5085 +                        HandleShape newShape, uint32_t offset);
  1.5086 +
  1.5087 +  public:
  1.5088 +    size_t protoChainDepth() const {
  1.5089 +        return extra_;
  1.5090 +    }
  1.5091 +    HeapPtrTypeObject &type() {
  1.5092 +        return type_;
  1.5093 +    }
  1.5094 +    HeapPtrShape &newShape() {
  1.5095 +        return newShape_;
  1.5096 +    }
  1.5097 +
  1.5098 +    template <size_t ProtoChainDepth>
  1.5099 +    ICSetProp_NativeAddImpl<ProtoChainDepth> *toImpl() {
  1.5100 +        JS_ASSERT(ProtoChainDepth == protoChainDepth());
  1.5101 +        return static_cast<ICSetProp_NativeAddImpl<ProtoChainDepth> *>(this);
  1.5102 +    }
  1.5103 +
  1.5104 +    static size_t offsetOfType() {
  1.5105 +        return offsetof(ICSetProp_NativeAdd, type_);
  1.5106 +    }
  1.5107 +    static size_t offsetOfNewShape() {
  1.5108 +        return offsetof(ICSetProp_NativeAdd, newShape_);
  1.5109 +    }
  1.5110 +    static size_t offsetOfOffset() {
  1.5111 +        return offsetof(ICSetProp_NativeAdd, offset_);
  1.5112 +    }
  1.5113 +};
  1.5114 +
  1.5115 +template <size_t ProtoChainDepth>
  1.5116 +class ICSetProp_NativeAddImpl : public ICSetProp_NativeAdd
  1.5117 +{
  1.5118 +    friend class ICStubSpace;
  1.5119 +
  1.5120 +    static const size_t NumShapes = ProtoChainDepth + 1;
  1.5121 +    mozilla::Array<HeapPtrShape, NumShapes> shapes_;
  1.5122 +
  1.5123 +    ICSetProp_NativeAddImpl(JitCode *stubCode, HandleTypeObject type,
  1.5124 +                            const AutoShapeVector *shapes,
  1.5125 +                            HandleShape newShape, uint32_t offset);
  1.5126 +
  1.5127 +  public:
  1.5128 +    static inline ICSetProp_NativeAddImpl *New(
  1.5129 +            ICStubSpace *space, JitCode *code, HandleTypeObject type,
  1.5130 +            const AutoShapeVector *shapes, HandleShape newShape, uint32_t offset)
  1.5131 +    {
  1.5132 +        if (!code)
  1.5133 +            return nullptr;
  1.5134 +        return space->allocate<ICSetProp_NativeAddImpl<ProtoChainDepth> >(
  1.5135 +                            code, type, shapes, newShape, offset);
  1.5136 +    }
  1.5137 +
  1.5138 +    void traceShapes(JSTracer *trc) {
  1.5139 +        for (size_t i = 0; i < NumShapes; i++)
  1.5140 +            MarkShape(trc, &shapes_[i], "baseline-setpropnativeadd-stub-shape");
  1.5141 +    }
  1.5142 +
  1.5143 +    static size_t offsetOfShape(size_t idx) {
  1.5144 +        return offsetof(ICSetProp_NativeAddImpl, shapes_) + (idx * sizeof(HeapPtrShape));
  1.5145 +    }
  1.5146 +};
  1.5147 +
  1.5148 +class ICSetPropNativeAddCompiler : public ICStubCompiler {
  1.5149 +    RootedObject obj_;
  1.5150 +    RootedShape oldShape_;
  1.5151 +    size_t protoChainDepth_;
  1.5152 +    bool isFixedSlot_;
  1.5153 +    uint32_t offset_;
  1.5154 +
  1.5155 +  protected:
  1.5156 +    virtual int32_t getKey() const {
  1.5157 +        return static_cast<int32_t>(kind) | (static_cast<int32_t>(isFixedSlot_) << 16) |
  1.5158 +               (static_cast<int32_t>(protoChainDepth_) << 20);
  1.5159 +    }
  1.5160 +
  1.5161 +    bool generateStubCode(MacroAssembler &masm);
  1.5162 +
  1.5163 +  public:
  1.5164 +    ICSetPropNativeAddCompiler(JSContext *cx, HandleObject obj, HandleShape oldShape,
  1.5165 +                               size_t protoChainDepth, bool isFixedSlot, uint32_t offset);
  1.5166 +
  1.5167 +    template <size_t ProtoChainDepth>
  1.5168 +    ICUpdatedStub *getStubSpecific(ICStubSpace *space, const AutoShapeVector *shapes)
  1.5169 +    {
  1.5170 +        RootedTypeObject type(cx, obj_->getType(cx));
  1.5171 +        if (!type)
  1.5172 +            return nullptr;
  1.5173 +
  1.5174 +        RootedShape newShape(cx, obj_->lastProperty());
  1.5175 +
  1.5176 +        return ICSetProp_NativeAddImpl<ProtoChainDepth>::New(
  1.5177 +                    space, getStubCode(), type, shapes, newShape, offset_);
  1.5178 +    }
  1.5179 +
  1.5180 +    ICUpdatedStub *getStub(ICStubSpace *space);
  1.5181 +};
  1.5182 +
  1.5183 +// Base stub for calling a setters on a native object.
  1.5184 +class ICSetPropCallSetter : public ICStub
  1.5185 +{
  1.5186 +    friend class ICStubSpace;
  1.5187 +
  1.5188 +  protected:
  1.5189 +    // Object shape (lastProperty).
  1.5190 +    HeapPtrShape shape_;
  1.5191 +
  1.5192 +    // Holder and shape.
  1.5193 +    HeapPtrObject holder_;
  1.5194 +    HeapPtrShape holderShape_;
  1.5195 +
  1.5196 +    // Function to call.
  1.5197 +    HeapPtrFunction setter_;
  1.5198 +
  1.5199 +    // PC of call, for profiler
  1.5200 +    uint32_t pcOffset_;
  1.5201 +
  1.5202 +    ICSetPropCallSetter(Kind kind, JitCode *stubCode, HandleShape shape, HandleObject holder,
  1.5203 +                        HandleShape holderShape, HandleFunction setter, uint32_t pcOffset);
  1.5204 +
  1.5205 +  public:
  1.5206 +    HeapPtrShape &shape() {
  1.5207 +        return shape_;
  1.5208 +    }
  1.5209 +    HeapPtrObject &holder() {
  1.5210 +        return holder_;
  1.5211 +    }
  1.5212 +    HeapPtrShape &holderShape() {
  1.5213 +        return holderShape_;
  1.5214 +    }
  1.5215 +    HeapPtrFunction &setter() {
  1.5216 +        return setter_;
  1.5217 +    }
  1.5218 +
  1.5219 +    static size_t offsetOfShape() {
  1.5220 +        return offsetof(ICSetPropCallSetter, shape_);
  1.5221 +    }
  1.5222 +    static size_t offsetOfHolder() {
  1.5223 +        return offsetof(ICSetPropCallSetter, holder_);
  1.5224 +    }
  1.5225 +    static size_t offsetOfHolderShape() {
  1.5226 +        return offsetof(ICSetPropCallSetter, holderShape_);
  1.5227 +    }
  1.5228 +    static size_t offsetOfSetter() {
  1.5229 +        return offsetof(ICSetPropCallSetter, setter_);
  1.5230 +    }
  1.5231 +    static size_t offsetOfPCOffset() {
  1.5232 +        return offsetof(ICSetPropCallSetter, pcOffset_);
  1.5233 +    }
  1.5234 +
  1.5235 +    class Compiler : public ICStubCompiler {
  1.5236 +      protected:
  1.5237 +        RootedObject obj_;
  1.5238 +        RootedObject holder_;
  1.5239 +        RootedFunction setter_;
  1.5240 +        uint32_t pcOffset_;
  1.5241 +
  1.5242 +      public:
  1.5243 +        Compiler(JSContext *cx, ICStub::Kind kind, HandleObject obj, HandleObject holder,
  1.5244 +                 HandleFunction setter, uint32_t pcOffset)
  1.5245 +          : ICStubCompiler(cx, kind),
  1.5246 +            obj_(cx, obj),
  1.5247 +            holder_(cx, holder),
  1.5248 +            setter_(cx, setter),
  1.5249 +            pcOffset_(pcOffset)
  1.5250 +        {
  1.5251 +            JS_ASSERT(kind == ICStub::SetProp_CallScripted || kind == ICStub::SetProp_CallNative);
  1.5252 +        }
  1.5253 +    };
  1.5254 +};
  1.5255 +
  1.5256 +// Stub for calling a scripted setter on a native object.
  1.5257 +class ICSetProp_CallScripted : public ICSetPropCallSetter
  1.5258 +{
  1.5259 +    friend class ICStubSpace;
  1.5260 +
  1.5261 +  protected:
  1.5262 +    ICSetProp_CallScripted(JitCode *stubCode, HandleShape shape, HandleObject holder,
  1.5263 +                           HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
  1.5264 +      : ICSetPropCallSetter(SetProp_CallScripted, stubCode, shape, holder, holderShape,
  1.5265 +                            setter, pcOffset)
  1.5266 +    {}
  1.5267 +
  1.5268 +  public:
  1.5269 +    static inline ICSetProp_CallScripted *New(ICStubSpace *space, JitCode *code,
  1.5270 +                                              HandleShape shape, HandleObject holder,
  1.5271 +                                              HandleShape holderShape, HandleFunction setter,
  1.5272 +                                              uint32_t pcOffset)
  1.5273 +    {
  1.5274 +        if (!code)
  1.5275 +            return nullptr;
  1.5276 +        return space->allocate<ICSetProp_CallScripted>(code, shape, holder, holderShape, setter,
  1.5277 +                                                       pcOffset);
  1.5278 +    }
  1.5279 +
  1.5280 +    class Compiler : public ICSetPropCallSetter::Compiler {
  1.5281 +      protected:
  1.5282 +        bool generateStubCode(MacroAssembler &masm);
  1.5283 +
  1.5284 +      public:
  1.5285 +        Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter,
  1.5286 +                 uint32_t pcOffset)
  1.5287 +          : ICSetPropCallSetter::Compiler(cx, ICStub::SetProp_CallScripted,
  1.5288 +                                          obj, holder, setter, pcOffset)
  1.5289 +        {}
  1.5290 +
  1.5291 +        ICStub *getStub(ICStubSpace *space) {
  1.5292 +            RootedShape shape(cx, obj_->lastProperty());
  1.5293 +            RootedShape holderShape(cx, holder_->lastProperty());
  1.5294 +            return ICSetProp_CallScripted::New(space, getStubCode(), shape, holder_, holderShape,
  1.5295 +                                               setter_, pcOffset_);
  1.5296 +        }
  1.5297 +    };
  1.5298 +};
  1.5299 +
  1.5300 +// Stub for calling a native setter on a native object.
  1.5301 +class ICSetProp_CallNative : public ICSetPropCallSetter
  1.5302 +{
  1.5303 +    friend class ICStubSpace;
  1.5304 +
  1.5305 +  protected:
  1.5306 +    ICSetProp_CallNative(JitCode *stubCode, HandleShape shape, HandleObject holder,
  1.5307 +                           HandleShape holderShape, HandleFunction setter, uint32_t pcOffset)
  1.5308 +      : ICSetPropCallSetter(SetProp_CallNative, stubCode, shape, holder, holderShape,
  1.5309 +                            setter, pcOffset)
  1.5310 +    {}
  1.5311 +
  1.5312 +  public:
  1.5313 +    static inline ICSetProp_CallNative *New(ICStubSpace *space, JitCode *code,
  1.5314 +                                            HandleShape shape, HandleObject holder,
  1.5315 +                                            HandleShape holderShape, HandleFunction setter,
  1.5316 +                                            uint32_t pcOffset)
  1.5317 +    {
  1.5318 +        if (!code)
  1.5319 +            return nullptr;
  1.5320 +        return space->allocate<ICSetProp_CallNative>(code, shape, holder, holderShape, setter,
  1.5321 +                                                     pcOffset);
  1.5322 +    }
  1.5323 +
  1.5324 +    class Compiler : public ICSetPropCallSetter::Compiler {
  1.5325 +      protected:
  1.5326 +        bool generateStubCode(MacroAssembler &masm);
  1.5327 +
  1.5328 +      public:
  1.5329 +        Compiler(JSContext *cx, HandleObject obj, HandleObject holder, HandleFunction setter,
  1.5330 +                 uint32_t pcOffset)
  1.5331 +          : ICSetPropCallSetter::Compiler(cx, ICStub::SetProp_CallNative,
  1.5332 +                                          obj, holder, setter, pcOffset)
  1.5333 +        {}
  1.5334 +
  1.5335 +        ICStub *getStub(ICStubSpace *space) {
  1.5336 +            RootedShape shape(cx, obj_->lastProperty());
  1.5337 +            RootedShape holderShape(cx, holder_->lastProperty());
  1.5338 +            return ICSetProp_CallNative::New(space, getStubCode(), shape, holder_, holderShape,
  1.5339 +                                               setter_, pcOffset_);
  1.5340 +        }
  1.5341 +    };
  1.5342 +};
  1.5343 +
  1.5344 +// Call
  1.5345 +//      JSOP_CALL
  1.5346 +//      JSOP_FUNAPPLY
  1.5347 +//      JSOP_FUNCALL
  1.5348 +//      JSOP_NEW
  1.5349 +
  1.5350 +class ICCallStubCompiler : public ICStubCompiler
  1.5351 +{
  1.5352 +  protected:
  1.5353 +    ICCallStubCompiler(JSContext *cx, ICStub::Kind kind)
  1.5354 +      : ICStubCompiler(cx, kind)
  1.5355 +    { }
  1.5356 +
  1.5357 +    enum FunApplyThing {
  1.5358 +        FunApply_MagicArgs,
  1.5359 +        FunApply_Array
  1.5360 +    };
  1.5361 +
  1.5362 +    void pushCallArguments(MacroAssembler &masm, GeneralRegisterSet regs, Register argcReg);
  1.5363 +    Register guardFunApply(MacroAssembler &masm, GeneralRegisterSet regs, Register argcReg,
  1.5364 +                           bool checkNative, FunApplyThing applyThing, Label *failure);
  1.5365 +    void pushCallerArguments(MacroAssembler &masm, GeneralRegisterSet regs);
  1.5366 +    void pushArrayArguments(MacroAssembler &masm, Address arrayVal, GeneralRegisterSet regs);
  1.5367 +};
  1.5368 +
  1.5369 +class ICCall_Fallback : public ICMonitoredFallbackStub
  1.5370 +{
  1.5371 +    friend class ICStubSpace;
  1.5372 +  public:
  1.5373 +    static const unsigned CONSTRUCTING_FLAG = 0x0001;
  1.5374 +
  1.5375 +    static const uint32_t MAX_OPTIMIZED_STUBS = 16;
  1.5376 +    static const uint32_t MAX_SCRIPTED_STUBS = 7;
  1.5377 +    static const uint32_t MAX_NATIVE_STUBS = 7;
  1.5378 +  private:
  1.5379 +
  1.5380 +    ICCall_Fallback(JitCode *stubCode, bool isConstructing)
  1.5381 +      : ICMonitoredFallbackStub(ICStub::Call_Fallback, stubCode)
  1.5382 +    {
  1.5383 +        extra_ = 0;
  1.5384 +        if (isConstructing)
  1.5385 +            extra_ |= CONSTRUCTING_FLAG;
  1.5386 +    }
  1.5387 +
  1.5388 +  public:
  1.5389 +
  1.5390 +    static inline ICCall_Fallback *New(ICStubSpace *space, JitCode *code, bool isConstructing)
  1.5391 +    {
  1.5392 +        if (!code)
  1.5393 +            return nullptr;
  1.5394 +        return space->allocate<ICCall_Fallback>(code, isConstructing);
  1.5395 +    }
  1.5396 +
  1.5397 +    bool isConstructing() const {
  1.5398 +        return extra_ & CONSTRUCTING_FLAG;
  1.5399 +    }
  1.5400 +
  1.5401 +    unsigned scriptedStubCount() const {
  1.5402 +        return numStubsWithKind(Call_Scripted);
  1.5403 +    }
  1.5404 +    bool scriptedStubsAreGeneralized() const {
  1.5405 +        return hasStub(Call_AnyScripted);
  1.5406 +    }
  1.5407 +
  1.5408 +    unsigned nativeStubCount() const {
  1.5409 +        return numStubsWithKind(Call_Native);
  1.5410 +    }
  1.5411 +    bool nativeStubsAreGeneralized() const {
  1.5412 +        // Return hasStub(Call_AnyNative) after Call_AnyNative stub is added.
  1.5413 +        return false;
  1.5414 +    }
  1.5415 +
  1.5416 +    // Compiler for this stub kind.
  1.5417 +    class Compiler : public ICCallStubCompiler {
  1.5418 +      protected:
  1.5419 +        bool isConstructing_;
  1.5420 +        uint32_t returnFromIonOffset_;
  1.5421 +        uint32_t returnFromStubOffset_;
  1.5422 +        bool generateStubCode(MacroAssembler &masm);
  1.5423 +        bool postGenerateStubCode(MacroAssembler &masm, Handle<JitCode *> code);
  1.5424 +
  1.5425 +      public:
  1.5426 +        Compiler(JSContext *cx, bool isConstructing)
  1.5427 +          : ICCallStubCompiler(cx, ICStub::Call_Fallback),
  1.5428 +            isConstructing_(isConstructing)
  1.5429 +        { }
  1.5430 +
  1.5431 +        ICStub *getStub(ICStubSpace *space) {
  1.5432 +            ICCall_Fallback *stub = ICCall_Fallback::New(space, getStubCode(), isConstructing_);
  1.5433 +            if (!stub || !stub->initMonitoringChain(cx, space))
  1.5434 +                return nullptr;
  1.5435 +            return stub;
  1.5436 +        }
  1.5437 +    };
  1.5438 +};
  1.5439 +
  1.5440 +class ICCall_Scripted : public ICMonitoredStub
  1.5441 +{
  1.5442 +    friend class ICStubSpace;
  1.5443 +
  1.5444 +  protected:
  1.5445 +    HeapPtrScript calleeScript_;
  1.5446 +    HeapPtrObject templateObject_;
  1.5447 +    uint32_t pcOffset_;
  1.5448 +
  1.5449 +    ICCall_Scripted(JitCode *stubCode, ICStub *firstMonitorStub,
  1.5450 +                    HandleScript calleeScript, HandleObject templateObject,
  1.5451 +                    uint32_t pcOffset);
  1.5452 +
  1.5453 +  public:
  1.5454 +    static inline ICCall_Scripted *New(
  1.5455 +            ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.5456 +            HandleScript calleeScript, HandleObject templateObject,
  1.5457 +            uint32_t pcOffset)
  1.5458 +    {
  1.5459 +        if (!code)
  1.5460 +            return nullptr;
  1.5461 +        return space->allocate<ICCall_Scripted>(code, firstMonitorStub,
  1.5462 +                                                calleeScript, templateObject, pcOffset);
  1.5463 +    }
  1.5464 +
  1.5465 +    HeapPtrScript &calleeScript() {
  1.5466 +        return calleeScript_;
  1.5467 +    }
  1.5468 +    HeapPtrObject &templateObject() {
  1.5469 +        return templateObject_;
  1.5470 +    }
  1.5471 +
  1.5472 +    static size_t offsetOfCalleeScript() {
  1.5473 +        return offsetof(ICCall_Scripted, calleeScript_);
  1.5474 +    }
  1.5475 +    static size_t offsetOfPCOffset() {
  1.5476 +        return offsetof(ICCall_Scripted, pcOffset_);
  1.5477 +    }
  1.5478 +};
  1.5479 +
  1.5480 +class ICCall_AnyScripted : public ICMonitoredStub
  1.5481 +{
  1.5482 +    friend class ICStubSpace;
  1.5483 +
  1.5484 +  protected:
  1.5485 +    uint32_t pcOffset_;
  1.5486 +
  1.5487 +    ICCall_AnyScripted(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5488 +      : ICMonitoredStub(ICStub::Call_AnyScripted, stubCode, firstMonitorStub),
  1.5489 +        pcOffset_(pcOffset)
  1.5490 +    { }
  1.5491 +
  1.5492 +  public:
  1.5493 +    static inline ICCall_AnyScripted *New(ICStubSpace *space, JitCode *code,
  1.5494 +                                          ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5495 +    {
  1.5496 +        if (!code)
  1.5497 +            return nullptr;
  1.5498 +        return space->allocate<ICCall_AnyScripted>(code, firstMonitorStub, pcOffset);
  1.5499 +    }
  1.5500 +
  1.5501 +    static size_t offsetOfPCOffset() {
  1.5502 +        return offsetof(ICCall_AnyScripted, pcOffset_);
  1.5503 +    }
  1.5504 +};
  1.5505 +
  1.5506 +// Compiler for Call_Scripted and Call_AnyScripted stubs.
  1.5507 +class ICCallScriptedCompiler : public ICCallStubCompiler {
  1.5508 +  protected:
  1.5509 +    ICStub *firstMonitorStub_;
  1.5510 +    bool isConstructing_;
  1.5511 +    RootedScript calleeScript_;
  1.5512 +    RootedObject templateObject_;
  1.5513 +    uint32_t pcOffset_;
  1.5514 +    bool generateStubCode(MacroAssembler &masm);
  1.5515 +
  1.5516 +    virtual int32_t getKey() const {
  1.5517 +        return static_cast<int32_t>(kind) | (static_cast<int32_t>(isConstructing_) << 16);
  1.5518 +    }
  1.5519 +
  1.5520 +  public:
  1.5521 +    ICCallScriptedCompiler(JSContext *cx, ICStub *firstMonitorStub,
  1.5522 +                           HandleScript calleeScript, HandleObject templateObject,
  1.5523 +                           bool isConstructing, uint32_t pcOffset)
  1.5524 +      : ICCallStubCompiler(cx, ICStub::Call_Scripted),
  1.5525 +        firstMonitorStub_(firstMonitorStub),
  1.5526 +        isConstructing_(isConstructing),
  1.5527 +        calleeScript_(cx, calleeScript),
  1.5528 +        templateObject_(cx, templateObject),
  1.5529 +        pcOffset_(pcOffset)
  1.5530 +    { }
  1.5531 +
  1.5532 +    ICCallScriptedCompiler(JSContext *cx, ICStub *firstMonitorStub, bool isConstructing,
  1.5533 +                           uint32_t pcOffset)
  1.5534 +      : ICCallStubCompiler(cx, ICStub::Call_AnyScripted),
  1.5535 +        firstMonitorStub_(firstMonitorStub),
  1.5536 +        isConstructing_(isConstructing),
  1.5537 +        calleeScript_(cx, nullptr),
  1.5538 +        templateObject_(cx, nullptr),
  1.5539 +        pcOffset_(pcOffset)
  1.5540 +    { }
  1.5541 +
  1.5542 +    ICStub *getStub(ICStubSpace *space) {
  1.5543 +        if (calleeScript_) {
  1.5544 +            return ICCall_Scripted::New(space, getStubCode(), firstMonitorStub_,
  1.5545 +                                        calleeScript_, templateObject_,
  1.5546 +                                        pcOffset_);
  1.5547 +        }
  1.5548 +        return ICCall_AnyScripted::New(space, getStubCode(), firstMonitorStub_, pcOffset_);
  1.5549 +    }
  1.5550 +};
  1.5551 +
  1.5552 +class ICCall_Native : public ICMonitoredStub
  1.5553 +{
  1.5554 +    friend class ICStubSpace;
  1.5555 +
  1.5556 +  protected:
  1.5557 +    HeapPtrFunction callee_;
  1.5558 +    HeapPtrObject templateObject_;
  1.5559 +    uint32_t pcOffset_;
  1.5560 +
  1.5561 +#ifdef JS_ARM_SIMULATOR
  1.5562 +    void *native_;
  1.5563 +#endif
  1.5564 +
  1.5565 +    ICCall_Native(JitCode *stubCode, ICStub *firstMonitorStub,
  1.5566 +                  HandleFunction callee, HandleObject templateObject,
  1.5567 +                  uint32_t pcOffset);
  1.5568 +
  1.5569 +  public:
  1.5570 +    static inline ICCall_Native *New(ICStubSpace *space, JitCode *code, ICStub *firstMonitorStub,
  1.5571 +                                     HandleFunction callee, HandleObject templateObject,
  1.5572 +                                     uint32_t pcOffset)
  1.5573 +    {
  1.5574 +        if (!code)
  1.5575 +            return nullptr;
  1.5576 +        return space->allocate<ICCall_Native>(code, firstMonitorStub,
  1.5577 +                                              callee, templateObject, pcOffset);
  1.5578 +    }
  1.5579 +
  1.5580 +    HeapPtrFunction &callee() {
  1.5581 +        return callee_;
  1.5582 +    }
  1.5583 +    HeapPtrObject &templateObject() {
  1.5584 +        return templateObject_;
  1.5585 +    }
  1.5586 +
  1.5587 +    static size_t offsetOfCallee() {
  1.5588 +        return offsetof(ICCall_Native, callee_);
  1.5589 +    }
  1.5590 +    static size_t offsetOfPCOffset() {
  1.5591 +        return offsetof(ICCall_Native, pcOffset_);
  1.5592 +    }
  1.5593 +
  1.5594 +#ifdef JS_ARM_SIMULATOR
  1.5595 +    static size_t offsetOfNative() {
  1.5596 +        return offsetof(ICCall_Native, native_);
  1.5597 +    }
  1.5598 +#endif
  1.5599 +
  1.5600 +    // Compiler for this stub kind.
  1.5601 +    class Compiler : public ICCallStubCompiler {
  1.5602 +      protected:
  1.5603 +        ICStub *firstMonitorStub_;
  1.5604 +        bool isConstructing_;
  1.5605 +        RootedFunction callee_;
  1.5606 +        RootedObject templateObject_;
  1.5607 +        uint32_t pcOffset_;
  1.5608 +        bool generateStubCode(MacroAssembler &masm);
  1.5609 +
  1.5610 +        virtual int32_t getKey() const {
  1.5611 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(isConstructing_) << 16);
  1.5612 +        }
  1.5613 +
  1.5614 +      public:
  1.5615 +        Compiler(JSContext *cx, ICStub *firstMonitorStub,
  1.5616 +                 HandleFunction callee, HandleObject templateObject,
  1.5617 +                 bool isConstructing, uint32_t pcOffset)
  1.5618 +          : ICCallStubCompiler(cx, ICStub::Call_Native),
  1.5619 +            firstMonitorStub_(firstMonitorStub),
  1.5620 +            isConstructing_(isConstructing),
  1.5621 +            callee_(cx, callee),
  1.5622 +            templateObject_(cx, templateObject),
  1.5623 +            pcOffset_(pcOffset)
  1.5624 +        { }
  1.5625 +
  1.5626 +        ICStub *getStub(ICStubSpace *space) {
  1.5627 +            return ICCall_Native::New(space, getStubCode(), firstMonitorStub_,
  1.5628 +                                      callee_, templateObject_, pcOffset_);
  1.5629 +        }
  1.5630 +    };
  1.5631 +};
  1.5632 +
  1.5633 +class ICCall_ScriptedApplyArray : public ICMonitoredStub
  1.5634 +{
  1.5635 +    friend class ICStubSpace;
  1.5636 +  public:
  1.5637 +    // The maximum length of an inlineable funcall array.
  1.5638 +    // Keep this small to avoid controllable stack overflows by attackers passing large
  1.5639 +    // arrays to fun.apply.
  1.5640 +    static const uint32_t MAX_ARGS_ARRAY_LENGTH = 16;
  1.5641 +
  1.5642 +  protected:
  1.5643 +    uint32_t pcOffset_;
  1.5644 +
  1.5645 +    ICCall_ScriptedApplyArray(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5646 +      : ICMonitoredStub(ICStub::Call_ScriptedApplyArray, stubCode, firstMonitorStub),
  1.5647 +        pcOffset_(pcOffset)
  1.5648 +    {}
  1.5649 +
  1.5650 +  public:
  1.5651 +    static inline ICCall_ScriptedApplyArray *New(ICStubSpace *space, JitCode *code,
  1.5652 +                                                 ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5653 +    {
  1.5654 +        if (!code)
  1.5655 +            return nullptr;
  1.5656 +        return space->allocate<ICCall_ScriptedApplyArray>(code, firstMonitorStub, pcOffset);
  1.5657 +    }
  1.5658 +
  1.5659 +    static size_t offsetOfPCOffset() {
  1.5660 +        return offsetof(ICCall_ScriptedApplyArray, pcOffset_);
  1.5661 +    }
  1.5662 +
  1.5663 +    // Compiler for this stub kind.
  1.5664 +    class Compiler : public ICCallStubCompiler {
  1.5665 +      protected:
  1.5666 +        ICStub *firstMonitorStub_;
  1.5667 +        uint32_t pcOffset_;
  1.5668 +        bool generateStubCode(MacroAssembler &masm);
  1.5669 +
  1.5670 +        virtual int32_t getKey() const {
  1.5671 +            return static_cast<int32_t>(kind);
  1.5672 +        }
  1.5673 +
  1.5674 +      public:
  1.5675 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5676 +          : ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArray),
  1.5677 +            firstMonitorStub_(firstMonitorStub),
  1.5678 +            pcOffset_(pcOffset)
  1.5679 +        { }
  1.5680 +
  1.5681 +        ICStub *getStub(ICStubSpace *space) {
  1.5682 +            return ICCall_ScriptedApplyArray::New(space, getStubCode(), firstMonitorStub_,
  1.5683 +                                                      pcOffset_);
  1.5684 +        }
  1.5685 +    };
  1.5686 +};
  1.5687 +
  1.5688 +class ICCall_ScriptedApplyArguments : public ICMonitoredStub
  1.5689 +{
  1.5690 +    friend class ICStubSpace;
  1.5691 +
  1.5692 +  protected:
  1.5693 +    uint32_t pcOffset_;
  1.5694 +
  1.5695 +    ICCall_ScriptedApplyArguments(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5696 +      : ICMonitoredStub(ICStub::Call_ScriptedApplyArguments, stubCode, firstMonitorStub),
  1.5697 +        pcOffset_(pcOffset)
  1.5698 +    {}
  1.5699 +
  1.5700 +  public:
  1.5701 +    static inline ICCall_ScriptedApplyArguments *New(ICStubSpace *space, JitCode *code,
  1.5702 +                                                     ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5703 +    {
  1.5704 +        if (!code)
  1.5705 +            return nullptr;
  1.5706 +        return space->allocate<ICCall_ScriptedApplyArguments>(code, firstMonitorStub, pcOffset);
  1.5707 +    }
  1.5708 +
  1.5709 +    static size_t offsetOfPCOffset() {
  1.5710 +        return offsetof(ICCall_ScriptedApplyArguments, pcOffset_);
  1.5711 +    }
  1.5712 +
  1.5713 +    // Compiler for this stub kind.
  1.5714 +    class Compiler : public ICCallStubCompiler {
  1.5715 +      protected:
  1.5716 +        ICStub *firstMonitorStub_;
  1.5717 +        uint32_t pcOffset_;
  1.5718 +        bool generateStubCode(MacroAssembler &masm);
  1.5719 +
  1.5720 +        virtual int32_t getKey() const {
  1.5721 +            return static_cast<int32_t>(kind);
  1.5722 +        }
  1.5723 +
  1.5724 +      public:
  1.5725 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5726 +          : ICCallStubCompiler(cx, ICStub::Call_ScriptedApplyArguments),
  1.5727 +            firstMonitorStub_(firstMonitorStub),
  1.5728 +            pcOffset_(pcOffset)
  1.5729 +        { }
  1.5730 +
  1.5731 +        ICStub *getStub(ICStubSpace *space) {
  1.5732 +            return ICCall_ScriptedApplyArguments::New(space, getStubCode(), firstMonitorStub_,
  1.5733 +                                                      pcOffset_);
  1.5734 +        }
  1.5735 +    };
  1.5736 +};
  1.5737 +
  1.5738 +// Handles calls of the form |fun.call(...)| where fun is a scripted function.
  1.5739 +class ICCall_ScriptedFunCall : public ICMonitoredStub
  1.5740 +{
  1.5741 +    friend class ICStubSpace;
  1.5742 +
  1.5743 +  protected:
  1.5744 +    uint32_t pcOffset_;
  1.5745 +
  1.5746 +    ICCall_ScriptedFunCall(JitCode *stubCode, ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5747 +      : ICMonitoredStub(ICStub::Call_ScriptedFunCall, stubCode, firstMonitorStub),
  1.5748 +        pcOffset_(pcOffset)
  1.5749 +    {}
  1.5750 +
  1.5751 +  public:
  1.5752 +    static inline ICCall_ScriptedFunCall *New(ICStubSpace *space, JitCode *code,
  1.5753 +                                              ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5754 +    {
  1.5755 +        if (!code)
  1.5756 +            return nullptr;
  1.5757 +        return space->allocate<ICCall_ScriptedFunCall>(code, firstMonitorStub, pcOffset);
  1.5758 +    }
  1.5759 +
  1.5760 +    static size_t offsetOfPCOffset() {
  1.5761 +        return offsetof(ICCall_ScriptedFunCall, pcOffset_);
  1.5762 +    }
  1.5763 +
  1.5764 +    // Compiler for this stub kind.
  1.5765 +    class Compiler : public ICCallStubCompiler {
  1.5766 +      protected:
  1.5767 +        ICStub *firstMonitorStub_;
  1.5768 +        uint32_t pcOffset_;
  1.5769 +        bool generateStubCode(MacroAssembler &masm);
  1.5770 +
  1.5771 +        virtual int32_t getKey() const {
  1.5772 +            return static_cast<int32_t>(kind);
  1.5773 +        }
  1.5774 +
  1.5775 +      public:
  1.5776 +        Compiler(JSContext *cx, ICStub *firstMonitorStub, uint32_t pcOffset)
  1.5777 +          : ICCallStubCompiler(cx, ICStub::Call_ScriptedFunCall),
  1.5778 +            firstMonitorStub_(firstMonitorStub),
  1.5779 +            pcOffset_(pcOffset)
  1.5780 +        { }
  1.5781 +
  1.5782 +        ICStub *getStub(ICStubSpace *space) {
  1.5783 +            return ICCall_ScriptedFunCall::New(space, getStubCode(), firstMonitorStub_,
  1.5784 +                                               pcOffset_);
  1.5785 +        }
  1.5786 +    };
  1.5787 +};
  1.5788 +
  1.5789 +// Stub for performing a TableSwitch, updating the IC's return address to jump
  1.5790 +// to whatever point the switch is branching to.
  1.5791 +class ICTableSwitch : public ICStub
  1.5792 +{
  1.5793 +    friend class ICStubSpace;
  1.5794 +
  1.5795 +  protected: // Protected to silence Clang warning.
  1.5796 +    void **table_;
  1.5797 +    int32_t min_;
  1.5798 +    int32_t length_;
  1.5799 +    void *defaultTarget_;
  1.5800 +
  1.5801 +    ICTableSwitch(JitCode *stubCode, void **table,
  1.5802 +                  int32_t min, int32_t length, void *defaultTarget)
  1.5803 +      : ICStub(TableSwitch, stubCode), table_(table),
  1.5804 +        min_(min), length_(length), defaultTarget_(defaultTarget)
  1.5805 +    {}
  1.5806 +
  1.5807 +  public:
  1.5808 +    static inline ICTableSwitch *New(ICStubSpace *space, JitCode *code, void **table,
  1.5809 +                                     int32_t min, int32_t length, void *defaultTarget) {
  1.5810 +        if (!code)
  1.5811 +            return nullptr;
  1.5812 +        return space->allocate<ICTableSwitch>(code, table, min, length, defaultTarget);
  1.5813 +    }
  1.5814 +
  1.5815 +    void fixupJumpTable(JSScript *script, BaselineScript *baseline);
  1.5816 +
  1.5817 +    class Compiler : public ICStubCompiler {
  1.5818 +        bool generateStubCode(MacroAssembler &masm);
  1.5819 +
  1.5820 +        jsbytecode *pc_;
  1.5821 +
  1.5822 +      public:
  1.5823 +        Compiler(JSContext *cx, jsbytecode *pc)
  1.5824 +          : ICStubCompiler(cx, ICStub::TableSwitch), pc_(pc)
  1.5825 +        {}
  1.5826 +
  1.5827 +        ICStub *getStub(ICStubSpace *space);
  1.5828 +    };
  1.5829 +};
  1.5830 +
  1.5831 +// IC for constructing an iterator from an input value.
  1.5832 +class ICIteratorNew_Fallback : public ICFallbackStub
  1.5833 +{
  1.5834 +    friend class ICStubSpace;
  1.5835 +
  1.5836 +    ICIteratorNew_Fallback(JitCode *stubCode)
  1.5837 +      : ICFallbackStub(ICStub::IteratorNew_Fallback, stubCode)
  1.5838 +    { }
  1.5839 +
  1.5840 +  public:
  1.5841 +    static inline ICIteratorNew_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.5842 +        if (!code)
  1.5843 +            return nullptr;
  1.5844 +        return space->allocate<ICIteratorNew_Fallback>(code);
  1.5845 +    }
  1.5846 +
  1.5847 +    class Compiler : public ICStubCompiler {
  1.5848 +      protected:
  1.5849 +        bool generateStubCode(MacroAssembler &masm);
  1.5850 +
  1.5851 +      public:
  1.5852 +        Compiler(JSContext *cx)
  1.5853 +          : ICStubCompiler(cx, ICStub::IteratorNew_Fallback)
  1.5854 +        { }
  1.5855 +
  1.5856 +        ICStub *getStub(ICStubSpace *space) {
  1.5857 +            return ICIteratorNew_Fallback::New(space, getStubCode());
  1.5858 +        }
  1.5859 +    };
  1.5860 +};
  1.5861 +
  1.5862 +// IC for testing if there are more values in an iterator.
  1.5863 +class ICIteratorMore_Fallback : public ICFallbackStub
  1.5864 +{
  1.5865 +    friend class ICStubSpace;
  1.5866 +
  1.5867 +    ICIteratorMore_Fallback(JitCode *stubCode)
  1.5868 +      : ICFallbackStub(ICStub::IteratorMore_Fallback, stubCode)
  1.5869 +    { }
  1.5870 +
  1.5871 +  public:
  1.5872 +    static inline ICIteratorMore_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.5873 +        if (!code)
  1.5874 +            return nullptr;
  1.5875 +        return space->allocate<ICIteratorMore_Fallback>(code);
  1.5876 +    }
  1.5877 +
  1.5878 +    class Compiler : public ICStubCompiler {
  1.5879 +      protected:
  1.5880 +        bool generateStubCode(MacroAssembler &masm);
  1.5881 +
  1.5882 +      public:
  1.5883 +        Compiler(JSContext *cx)
  1.5884 +          : ICStubCompiler(cx, ICStub::IteratorMore_Fallback)
  1.5885 +        { }
  1.5886 +
  1.5887 +        ICStub *getStub(ICStubSpace *space) {
  1.5888 +            return ICIteratorMore_Fallback::New(space, getStubCode());
  1.5889 +        }
  1.5890 +    };
  1.5891 +};
  1.5892 +
  1.5893 +// IC for testing if there are more values in a native iterator.
  1.5894 +class ICIteratorMore_Native : public ICStub
  1.5895 +{
  1.5896 +    friend class ICStubSpace;
  1.5897 +
  1.5898 +    ICIteratorMore_Native(JitCode *stubCode)
  1.5899 +      : ICStub(ICStub::IteratorMore_Native, stubCode)
  1.5900 +    { }
  1.5901 +
  1.5902 +  public:
  1.5903 +    static inline ICIteratorMore_Native *New(ICStubSpace *space, JitCode *code) {
  1.5904 +        if (!code)
  1.5905 +            return nullptr;
  1.5906 +        return space->allocate<ICIteratorMore_Native>(code);
  1.5907 +    }
  1.5908 +
  1.5909 +    class Compiler : public ICStubCompiler {
  1.5910 +      protected:
  1.5911 +        bool generateStubCode(MacroAssembler &masm);
  1.5912 +
  1.5913 +      public:
  1.5914 +        Compiler(JSContext *cx)
  1.5915 +          : ICStubCompiler(cx, ICStub::IteratorMore_Native)
  1.5916 +        { }
  1.5917 +
  1.5918 +        ICStub *getStub(ICStubSpace *space) {
  1.5919 +            return ICIteratorMore_Native::New(space, getStubCode());
  1.5920 +        }
  1.5921 +    };
  1.5922 +};
  1.5923 +
  1.5924 +// IC for getting the next value in an iterator.
  1.5925 +class ICIteratorNext_Fallback : public ICFallbackStub
  1.5926 +{
  1.5927 +    friend class ICStubSpace;
  1.5928 +
  1.5929 +    ICIteratorNext_Fallback(JitCode *stubCode)
  1.5930 +      : ICFallbackStub(ICStub::IteratorNext_Fallback, stubCode)
  1.5931 +    { }
  1.5932 +
  1.5933 +  public:
  1.5934 +    static inline ICIteratorNext_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.5935 +        if (!code)
  1.5936 +            return nullptr;
  1.5937 +        return space->allocate<ICIteratorNext_Fallback>(code);
  1.5938 +    }
  1.5939 +
  1.5940 +    void setHasNonStringResult() {
  1.5941 +        JS_ASSERT(extra_ == 0);
  1.5942 +        extra_ = 1;
  1.5943 +    }
  1.5944 +    bool hasNonStringResult() const {
  1.5945 +        return extra_;
  1.5946 +    }
  1.5947 +
  1.5948 +    class Compiler : public ICStubCompiler {
  1.5949 +      protected:
  1.5950 +        bool generateStubCode(MacroAssembler &masm);
  1.5951 +
  1.5952 +      public:
  1.5953 +        Compiler(JSContext *cx)
  1.5954 +          : ICStubCompiler(cx, ICStub::IteratorNext_Fallback)
  1.5955 +        { }
  1.5956 +
  1.5957 +        ICStub *getStub(ICStubSpace *space) {
  1.5958 +            return ICIteratorNext_Fallback::New(space, getStubCode());
  1.5959 +        }
  1.5960 +    };
  1.5961 +};
  1.5962 +
  1.5963 +// IC for getting the next value in a native iterator.
  1.5964 +class ICIteratorNext_Native : public ICStub
  1.5965 +{
  1.5966 +    friend class ICStubSpace;
  1.5967 +
  1.5968 +    ICIteratorNext_Native(JitCode *stubCode)
  1.5969 +      : ICStub(ICStub::IteratorNext_Native, stubCode)
  1.5970 +    { }
  1.5971 +
  1.5972 +  public:
  1.5973 +    static inline ICIteratorNext_Native *New(ICStubSpace *space, JitCode *code) {
  1.5974 +        if (!code)
  1.5975 +            return nullptr;
  1.5976 +        return space->allocate<ICIteratorNext_Native>(code);
  1.5977 +    }
  1.5978 +
  1.5979 +    class Compiler : public ICStubCompiler {
  1.5980 +      protected:
  1.5981 +        bool generateStubCode(MacroAssembler &masm);
  1.5982 +
  1.5983 +      public:
  1.5984 +        Compiler(JSContext *cx)
  1.5985 +          : ICStubCompiler(cx, ICStub::IteratorNext_Native)
  1.5986 +        { }
  1.5987 +
  1.5988 +        ICStub *getStub(ICStubSpace *space) {
  1.5989 +            return ICIteratorNext_Native::New(space, getStubCode());
  1.5990 +        }
  1.5991 +    };
  1.5992 +};
  1.5993 +
  1.5994 +// IC for closing an iterator.
  1.5995 +class ICIteratorClose_Fallback : public ICFallbackStub
  1.5996 +{
  1.5997 +    friend class ICStubSpace;
  1.5998 +
  1.5999 +    ICIteratorClose_Fallback(JitCode *stubCode)
  1.6000 +      : ICFallbackStub(ICStub::IteratorClose_Fallback, stubCode)
  1.6001 +    { }
  1.6002 +
  1.6003 +  public:
  1.6004 +    static inline ICIteratorClose_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.6005 +        if (!code)
  1.6006 +            return nullptr;
  1.6007 +        return space->allocate<ICIteratorClose_Fallback>(code);
  1.6008 +    }
  1.6009 +
  1.6010 +    class Compiler : public ICStubCompiler {
  1.6011 +      protected:
  1.6012 +        bool generateStubCode(MacroAssembler &masm);
  1.6013 +
  1.6014 +      public:
  1.6015 +        Compiler(JSContext *cx)
  1.6016 +          : ICStubCompiler(cx, ICStub::IteratorClose_Fallback)
  1.6017 +        { }
  1.6018 +
  1.6019 +        ICStub *getStub(ICStubSpace *space) {
  1.6020 +            return ICIteratorClose_Fallback::New(space, getStubCode());
  1.6021 +        }
  1.6022 +    };
  1.6023 +};
  1.6024 +
  1.6025 +// InstanceOf
  1.6026 +//      JSOP_INSTANCEOF
  1.6027 +class ICInstanceOf_Fallback : public ICFallbackStub
  1.6028 +{
  1.6029 +    friend class ICStubSpace;
  1.6030 +
  1.6031 +    ICInstanceOf_Fallback(JitCode *stubCode)
  1.6032 +      : ICFallbackStub(ICStub::InstanceOf_Fallback, stubCode)
  1.6033 +    { }
  1.6034 +
  1.6035 +  public:
  1.6036 +    static inline ICInstanceOf_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.6037 +        if (!code)
  1.6038 +            return nullptr;
  1.6039 +        return space->allocate<ICInstanceOf_Fallback>(code);
  1.6040 +    }
  1.6041 +
  1.6042 +    class Compiler : public ICStubCompiler {
  1.6043 +      protected:
  1.6044 +        bool generateStubCode(MacroAssembler &masm);
  1.6045 +
  1.6046 +      public:
  1.6047 +        Compiler(JSContext *cx)
  1.6048 +          : ICStubCompiler(cx, ICStub::InstanceOf_Fallback)
  1.6049 +        { }
  1.6050 +
  1.6051 +        ICStub *getStub(ICStubSpace *space) {
  1.6052 +            return ICInstanceOf_Fallback::New(space, getStubCode());
  1.6053 +        }
  1.6054 +    };
  1.6055 +};
  1.6056 +
  1.6057 +// TypeOf
  1.6058 +//      JSOP_TYPEOF
  1.6059 +//      JSOP_TYPEOFEXPR
  1.6060 +class ICTypeOf_Fallback : public ICFallbackStub
  1.6061 +{
  1.6062 +    friend class ICStubSpace;
  1.6063 +
  1.6064 +    ICTypeOf_Fallback(JitCode *stubCode)
  1.6065 +      : ICFallbackStub(ICStub::TypeOf_Fallback, stubCode)
  1.6066 +    { }
  1.6067 +
  1.6068 +  public:
  1.6069 +    static inline ICTypeOf_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.6070 +        if (!code)
  1.6071 +            return nullptr;
  1.6072 +        return space->allocate<ICTypeOf_Fallback>(code);
  1.6073 +    }
  1.6074 +
  1.6075 +    class Compiler : public ICStubCompiler {
  1.6076 +      protected:
  1.6077 +        bool generateStubCode(MacroAssembler &masm);
  1.6078 +
  1.6079 +      public:
  1.6080 +        Compiler(JSContext *cx)
  1.6081 +          : ICStubCompiler(cx, ICStub::TypeOf_Fallback)
  1.6082 +        { }
  1.6083 +
  1.6084 +        ICStub *getStub(ICStubSpace *space) {
  1.6085 +            return ICTypeOf_Fallback::New(space, getStubCode());
  1.6086 +        }
  1.6087 +    };
  1.6088 +};
  1.6089 +
  1.6090 +class ICTypeOf_Typed : public ICFallbackStub
  1.6091 +{
  1.6092 +    friend class ICStubSpace;
  1.6093 +
  1.6094 +    ICTypeOf_Typed(JitCode *stubCode, JSType type)
  1.6095 +      : ICFallbackStub(ICStub::TypeOf_Typed, stubCode)
  1.6096 +    {
  1.6097 +        extra_ = uint16_t(type);
  1.6098 +        JS_ASSERT(JSType(extra_) == type);
  1.6099 +    }
  1.6100 +
  1.6101 +  public:
  1.6102 +    static inline ICTypeOf_Typed *New(ICStubSpace *space, JitCode *code, JSType type) {
  1.6103 +        if (!code)
  1.6104 +            return nullptr;
  1.6105 +        return space->allocate<ICTypeOf_Typed>(code, type);
  1.6106 +    }
  1.6107 +
  1.6108 +    JSType type() const {
  1.6109 +        return JSType(extra_);
  1.6110 +    }
  1.6111 +
  1.6112 +    class Compiler : public ICStubCompiler {
  1.6113 +      protected:
  1.6114 +        JSType type_;
  1.6115 +        RootedString typeString_;
  1.6116 +        bool generateStubCode(MacroAssembler &masm);
  1.6117 +
  1.6118 +        virtual int32_t getKey() const {
  1.6119 +            return static_cast<int32_t>(kind) | (static_cast<int32_t>(type_) << 16);
  1.6120 +        }
  1.6121 +
  1.6122 +      public:
  1.6123 +        Compiler(JSContext *cx, JSType type, HandleString string)
  1.6124 +          : ICStubCompiler(cx, ICStub::TypeOf_Typed),
  1.6125 +            type_(type),
  1.6126 +            typeString_(cx, string)
  1.6127 +        { }
  1.6128 +
  1.6129 +        ICStub *getStub(ICStubSpace *space) {
  1.6130 +            return ICTypeOf_Typed::New(space, getStubCode(), type_);
  1.6131 +        }
  1.6132 +    };
  1.6133 +};
  1.6134 +
  1.6135 +class ICRest_Fallback : public ICFallbackStub
  1.6136 +{
  1.6137 +    friend class ICStubSpace;
  1.6138 +
  1.6139 +    HeapPtrObject templateObject_;
  1.6140 +
  1.6141 +    ICRest_Fallback(JitCode *stubCode, JSObject *templateObject)
  1.6142 +      : ICFallbackStub(ICStub::Rest_Fallback, stubCode), templateObject_(templateObject)
  1.6143 +    { }
  1.6144 +
  1.6145 +  public:
  1.6146 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.6147 +
  1.6148 +    static inline ICRest_Fallback *New(ICStubSpace *space, JitCode *code,
  1.6149 +                                       JSObject *templateObject) {
  1.6150 +        if (!code)
  1.6151 +            return nullptr;
  1.6152 +        return space->allocate<ICRest_Fallback>(code, templateObject);
  1.6153 +    }
  1.6154 +
  1.6155 +    HeapPtrObject &templateObject() {
  1.6156 +        return templateObject_;
  1.6157 +    }
  1.6158 +
  1.6159 +    class Compiler : public ICStubCompiler {
  1.6160 +      protected:
  1.6161 +        RootedObject templateObject;
  1.6162 +        bool generateStubCode(MacroAssembler &masm);
  1.6163 +
  1.6164 +      public:
  1.6165 +        Compiler(JSContext *cx, JSObject *templateObject)
  1.6166 +          : ICStubCompiler(cx, ICStub::Rest_Fallback),
  1.6167 +            templateObject(cx, templateObject)
  1.6168 +        { }
  1.6169 +
  1.6170 +        ICStub *getStub(ICStubSpace *space) {
  1.6171 +            return ICRest_Fallback::New(space, getStubCode(), templateObject);
  1.6172 +        }
  1.6173 +    };
  1.6174 +};
  1.6175 +
  1.6176 +// Stub for JSOP_RETSUB ("returning" from a |finally| block).
  1.6177 +class ICRetSub_Fallback : public ICFallbackStub
  1.6178 +{
  1.6179 +    friend class ICStubSpace;
  1.6180 +
  1.6181 +    ICRetSub_Fallback(JitCode *stubCode)
  1.6182 +      : ICFallbackStub(ICStub::RetSub_Fallback, stubCode)
  1.6183 +    { }
  1.6184 +
  1.6185 +  public:
  1.6186 +    static const uint32_t MAX_OPTIMIZED_STUBS = 8;
  1.6187 +
  1.6188 +    static inline ICRetSub_Fallback *New(ICStubSpace *space, JitCode *code) {
  1.6189 +        if (!code)
  1.6190 +            return nullptr;
  1.6191 +        return space->allocate<ICRetSub_Fallback>(code);
  1.6192 +    }
  1.6193 +
  1.6194 +    class Compiler : public ICStubCompiler {
  1.6195 +      protected:
  1.6196 +        bool generateStubCode(MacroAssembler &masm);
  1.6197 +
  1.6198 +      public:
  1.6199 +        Compiler(JSContext *cx)
  1.6200 +          : ICStubCompiler(cx, ICStub::RetSub_Fallback)
  1.6201 +        { }
  1.6202 +
  1.6203 +        ICStub *getStub(ICStubSpace *space) {
  1.6204 +            return ICRetSub_Fallback::New(space, getStubCode());
  1.6205 +        }
  1.6206 +    };
  1.6207 +};
  1.6208 +
  1.6209 +// Optimized JSOP_RETSUB stub. Every stub maps a single pc offset to its
  1.6210 +// native code address.
  1.6211 +class ICRetSub_Resume : public ICStub
  1.6212 +{
  1.6213 +    friend class ICStubSpace;
  1.6214 +
  1.6215 +  protected:
  1.6216 +    uint32_t pcOffset_;
  1.6217 +    uint8_t *addr_;
  1.6218 +
  1.6219 +    ICRetSub_Resume(JitCode *stubCode, uint32_t pcOffset, uint8_t *addr)
  1.6220 +      : ICStub(ICStub::RetSub_Resume, stubCode),
  1.6221 +        pcOffset_(pcOffset),
  1.6222 +        addr_(addr)
  1.6223 +    { }
  1.6224 +
  1.6225 +  public:
  1.6226 +    static ICRetSub_Resume *New(ICStubSpace *space, JitCode *code, uint32_t pcOffset,
  1.6227 +                                uint8_t *addr) {
  1.6228 +        if (!code)
  1.6229 +            return nullptr;
  1.6230 +        return space->allocate<ICRetSub_Resume>(code, pcOffset, addr);
  1.6231 +    }
  1.6232 +
  1.6233 +    static size_t offsetOfPCOffset() {
  1.6234 +        return offsetof(ICRetSub_Resume, pcOffset_);
  1.6235 +    }
  1.6236 +    static size_t offsetOfAddr() {
  1.6237 +        return offsetof(ICRetSub_Resume, addr_);
  1.6238 +    }
  1.6239 +
  1.6240 +    class Compiler : public ICStubCompiler {
  1.6241 +        uint32_t pcOffset_;
  1.6242 +        uint8_t *addr_;
  1.6243 +
  1.6244 +        bool generateStubCode(MacroAssembler &masm);
  1.6245 +
  1.6246 +      public:
  1.6247 +        Compiler(JSContext *cx, uint32_t pcOffset, uint8_t *addr)
  1.6248 +          : ICStubCompiler(cx, ICStub::RetSub_Resume),
  1.6249 +            pcOffset_(pcOffset),
  1.6250 +            addr_(addr)
  1.6251 +        { }
  1.6252 +
  1.6253 +        ICStub *getStub(ICStubSpace *space) {
  1.6254 +            return ICRetSub_Resume::New(space, getStubCode(), pcOffset_, addr_);
  1.6255 +        }
  1.6256 +    };
  1.6257 +};
  1.6258 +
  1.6259 +} // namespace jit
  1.6260 +} // namespace js
  1.6261 +
  1.6262 +#endif // JS_ION
  1.6263 +
  1.6264 +#endif /* jit_BaselineIC_h */

mercurial