LCOV - code coverage report
Current view: top level - js/src/jit - CacheIR.h (source / functions) Hit Total Coverage
Test: output.info Lines: 514 664 77.4 %
Date: 2017-07-14 16:53:18 Functions: 165 201 82.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef jit_CacheIR_h
       8             : #define jit_CacheIR_h
       9             : 
      10             : #include "mozilla/Maybe.h"
      11             : 
      12             : #include "NamespaceImports.h"
      13             : 
      14             : #include "gc/Rooting.h"
      15             : #include "jit/CompactBuffer.h"
      16             : #include "jit/ICState.h"
      17             : #include "jit/SharedIC.h"
      18             : 
      19             : namespace js {
      20             : namespace jit {
      21             : 
      22             : // CacheIR is an (extremely simple) linear IR language for inline caches.
      23             : // From this IR, we can generate machine code for Baseline or Ion IC stubs.
      24             : //
      25             : // IRWriter
      26             : // --------
      27             : // CacheIR bytecode is written using IRWriter. This class also records some
      28             : // metadata that's used by the Baseline and Ion code generators to generate
      29             : // (efficient) machine code.
      30             : //
      31             : // Sharing Baseline stub code
      32             : // --------------------------
      33             : // Baseline stores data (like Shape* and fixed slot offsets) inside the ICStub
      34             : // structure, instead of embedding them directly in the JitCode. This makes
      35             : // Baseline IC code slightly slower, but allows us to share IC code between
      36             : // caches. CacheIR makes it easy to share code between stubs: stubs that have
      37             : // the same CacheIR (and CacheKind), will have the same Baseline stub code.
      38             : //
      39             : // Baseline stubs that share JitCode also share a CacheIRStubInfo structure.
      40             : // This class stores the CacheIR and the location of GC things stored in the
      41             : // stub, for the GC.
      42             : //
      43             : // JitCompartment has a CacheIRStubInfo* -> JitCode* weak map that's used to
      44             : // share both the IR and JitCode between CacheIR stubs. This HashMap owns the
      45             : // stubInfo (it uses UniquePtr), so once there are no references left to the
      46             : // shared stub code, we can also free the CacheIRStubInfo.
      47             : //
      48             : // Ion stubs
      49             : // ---------
      50             : // Unlike Baseline stubs, Ion stubs do not share stub code, and data stored in
      51             : // the IonICStub is baked into JIT code. This is one of the reasons Ion stubs
      52             : // are faster than Baseline stubs. Also note that Ion ICs contain more state
      53             : // (see IonGetPropertyIC for example) and use dynamic input/output registers,
      54             : // so sharing stub code for Ion would be much more difficult.
      55             : 
      56             : // An OperandId represents either a cache input or a value returned by a
      57             : // CacheIR instruction. Most code should use the ValOperandId and ObjOperandId
      58             : // classes below. The ObjOperandId class represents an operand that's known to
      59             : // be an object.
      60             : class OperandId
      61             : {
      62             :   protected:
      63             :     static const uint16_t InvalidId = UINT16_MAX;
      64             :     uint16_t id_;
      65             : 
      66        2064 :     OperandId() : id_(InvalidId) {}
      67       27532 :     explicit OperandId(uint16_t id) : id_(id) {}
      68             : 
      69             :   public:
      70      158377 :     uint16_t id() const { return id_; }
      71        2957 :     bool valid() const { return id_ != InvalidId; }
      72             : };
      73             : 
      74             : class ValOperandId : public OperandId
      75             : {
      76             :   public:
      77        1711 :     ValOperandId() = default;
      78       13289 :     explicit ValOperandId(uint16_t id) : OperandId(id) {}
      79             : };
      80             : 
      81             : class ObjOperandId : public OperandId
      82             : {
      83             :   public:
      84             :     ObjOperandId() = default;
      85       10999 :     explicit ObjOperandId(uint16_t id) : OperandId(id) {}
      86             : 
      87             :     bool operator==(const ObjOperandId& other) const { return id_ == other.id_; }
      88             :     bool operator!=(const ObjOperandId& other) const { return id_ != other.id_; }
      89             : };
      90             : 
      91             : class StringOperandId : public OperandId
      92             : {
      93             :   public:
      94             :     StringOperandId() = default;
      95        1614 :     explicit StringOperandId(uint16_t id) : OperandId(id) {}
      96             : };
      97             : 
      98             : class SymbolOperandId : public OperandId
      99             : {
     100             :   public:
     101             :     SymbolOperandId() = default;
     102         133 :     explicit SymbolOperandId(uint16_t id) : OperandId(id) {}
     103             : };
     104             : 
     105             : class Int32OperandId : public OperandId
     106             : {
     107             :   public:
     108         353 :     Int32OperandId() = default;
     109         410 :     explicit Int32OperandId(uint16_t id) : OperandId(id) {}
     110             : };
     111             : 
     112             : class TypedOperandId : public OperandId
     113             : {
     114             :     JSValueType type_;
     115             : 
     116             :   public:
     117         937 :     MOZ_IMPLICIT TypedOperandId(ObjOperandId id)
     118         937 :       : OperandId(id.id()), type_(JSVAL_TYPE_OBJECT)
     119         937 :     {}
     120          70 :     MOZ_IMPLICIT TypedOperandId(StringOperandId id)
     121          70 :       : OperandId(id.id()), type_(JSVAL_TYPE_STRING)
     122          70 :     {}
     123          14 :     MOZ_IMPLICIT TypedOperandId(SymbolOperandId id)
     124          14 :       : OperandId(id.id()), type_(JSVAL_TYPE_SYMBOL)
     125          14 :     {}
     126          66 :     MOZ_IMPLICIT TypedOperandId(Int32OperandId id)
     127          66 :       : OperandId(id.id()), type_(JSVAL_TYPE_INT32)
     128          66 :     {}
     129           0 :     TypedOperandId(ValOperandId val, JSValueType type)
     130           0 :       : OperandId(val.id()), type_(type)
     131           0 :     {}
     132             : 
     133         461 :     JSValueType type() const { return type_; }
     134             : };
     135             : 
     136             : #define CACHE_IR_KINDS(_)   \
     137             :     _(GetProp)              \
     138             :     _(GetElem)              \
     139             :     _(GetName)              \
     140             :     _(GetPropSuper)         \
     141             :     _(GetElemSuper)         \
     142             :     _(SetProp)              \
     143             :     _(SetElem)              \
     144             :     _(BindName)             \
     145             :     _(In)                   \
     146             :     _(HasOwn)               \
     147             :     _(TypeOf)               \
     148             :     _(Compare)              \
     149             :     _(Call)
     150             : 
     151             : enum class CacheKind : uint8_t
     152             : {
     153             : #define DEFINE_KIND(kind) kind,
     154             :     CACHE_IR_KINDS(DEFINE_KIND)
     155             : #undef DEFINE_KIND
     156             : };
     157             : 
     158             : extern const char* CacheKindNames[];
     159             : 
     160             : #define CACHE_IR_OPS(_)                   \
     161             :     _(GuardIsObject)                      \
     162             :     _(GuardIsObjectOrNull)                \
     163             :     _(GuardIsString)                      \
     164             :     _(GuardIsSymbol)                      \
     165             :     _(GuardIsInt32Index)                  \
     166             :     _(GuardType)                          \
     167             :     _(GuardShape)                         \
     168             :     _(GuardGroup)                         \
     169             :     _(GuardProto)                         \
     170             :     _(GuardClass)                         \
     171             :     _(GuardCompartment)                   \
     172             :     _(GuardIsNativeFunction)              \
     173             :     _(GuardIsProxy)                       \
     174             :     _(GuardIsCrossCompartmentWrapper)     \
     175             :     _(GuardNotDOMProxy)                   \
     176             :     _(GuardSpecificObject)                \
     177             :     _(GuardSpecificAtom)                  \
     178             :     _(GuardSpecificSymbol)                \
     179             :     _(GuardSpecificInt32Immediate)        \
     180             :     _(GuardNoDetachedTypedObjects)        \
     181             :     _(GuardMagicValue)                    \
     182             :     _(GuardFrameHasNoArgumentsObject)     \
     183             :     _(GuardNoDenseElements)               \
     184             :     _(GuardNoUnboxedExpando)              \
     185             :     _(GuardAndLoadUnboxedExpando)         \
     186             :     _(GuardAndGetIndexFromString)         \
     187             :     _(GuardHasGetterSetter)               \
     188             :     _(GuardGroupHasUnanalyzedNewScript)   \
     189             :     _(LoadStackValue)                     \
     190             :     _(LoadObject)                         \
     191             :     _(LoadProto)                          \
     192             :     _(LoadEnclosingEnvironment)           \
     193             :     _(LoadWrapperTarget)                  \
     194             :                                           \
     195             :     _(MegamorphicLoadSlotResult)          \
     196             :     _(MegamorphicLoadSlotByValueResult)   \
     197             :     _(MegamorphicStoreSlot)               \
     198             :     _(MegamorphicHasOwnResult)            \
     199             :                                           \
     200             :     /* See CacheIR.cpp 'DOM proxies' comment. */ \
     201             :     _(LoadDOMExpandoValue)                \
     202             :     _(LoadDOMExpandoValueGuardGeneration) \
     203             :     _(LoadDOMExpandoValueIgnoreGeneration)\
     204             :     _(GuardDOMExpandoMissingOrGuardShape) \
     205             :                                           \
     206             :     _(StoreFixedSlot)                     \
     207             :     _(StoreDynamicSlot)                   \
     208             :     _(AddAndStoreFixedSlot)               \
     209             :     _(AddAndStoreDynamicSlot)             \
     210             :     _(AllocateAndStoreDynamicSlot)        \
     211             :     _(StoreTypedObjectReferenceProperty)  \
     212             :     _(StoreTypedObjectScalarProperty)     \
     213             :     _(StoreUnboxedProperty)               \
     214             :     _(StoreDenseElement)                  \
     215             :     _(StoreDenseElementHole)              \
     216             :     _(StoreTypedElement)                  \
     217             :     _(StoreUnboxedArrayElement)           \
     218             :     _(StoreUnboxedArrayElementHole)       \
     219             :     _(CallNativeSetter)                   \
     220             :     _(CallScriptedSetter)                 \
     221             :     _(CallSetArrayLength)                 \
     222             :     _(CallProxySet)                       \
     223             :     _(CallProxySetByValue)                \
     224             :                                           \
     225             :     /* The *Result ops load a value into the cache's result register. */ \
     226             :     _(LoadFixedSlotResult)                \
     227             :     _(LoadDynamicSlotResult)              \
     228             :     _(LoadUnboxedPropertyResult)          \
     229             :     _(LoadTypedObjectResult)              \
     230             :     _(LoadDenseElementResult)             \
     231             :     _(LoadDenseElementHoleResult)         \
     232             :     _(LoadDenseElementExistsResult)       \
     233             :     _(LoadDenseElementHoleExistsResult)   \
     234             :     _(LoadUnboxedArrayElementResult)      \
     235             :     _(LoadTypedElementResult)             \
     236             :     _(LoadInt32ArrayLengthResult)         \
     237             :     _(LoadUnboxedArrayLengthResult)       \
     238             :     _(LoadArgumentsObjectArgResult)       \
     239             :     _(LoadArgumentsObjectLengthResult)    \
     240             :     _(LoadFunctionLengthResult)           \
     241             :     _(LoadStringCharResult)               \
     242             :     _(LoadStringLengthResult)             \
     243             :     _(LoadFrameCalleeResult)              \
     244             :     _(LoadFrameNumActualArgsResult)       \
     245             :     _(LoadFrameArgumentResult)            \
     246             :     _(LoadEnvironmentFixedSlotResult)     \
     247             :     _(LoadEnvironmentDynamicSlotResult)   \
     248             :     _(LoadObjectResult)                   \
     249             :     _(CallScriptedGetterResult)           \
     250             :     _(CallNativeGetterResult)             \
     251             :     _(CallProxyGetResult)                 \
     252             :     _(CallProxyGetByValueResult)          \
     253             :     _(CallProxyHasOwnResult)              \
     254             :     _(LoadUndefinedResult)                \
     255             :     _(LoadBooleanResult)                  \
     256             :     _(LoadStringResult)                   \
     257             :     _(LoadTypeOfObjectResult)             \
     258             :                                           \
     259             :     _(CallStringSplitResult)              \
     260             :                                           \
     261             :     _(CompareStringResult)                \
     262             :     _(CompareObjectResult)                \
     263             :     _(CompareSymbolResult)                \
     264             :                                           \
     265             :     _(CallPrintString)                    \
     266             :     _(Breakpoint)                         \
     267             :                                           \
     268             :     _(TypeMonitorResult)                  \
     269             :     _(ReturnFromIC)                       \
     270             :     _(WrapResult)
     271             : 
     272             : enum class CacheOp {
     273             : #define DEFINE_OP(op) op,
     274             :     CACHE_IR_OPS(DEFINE_OP)
     275             : #undef DEFINE_OP
     276             : };
     277             : 
     278             : class StubField
     279             : {
     280             :   public:
     281             :     enum class Type : uint8_t {
     282             :         // These fields take up a single word.
     283             :         RawWord,
     284             :         Shape,
     285             :         ObjectGroup,
     286             :         JSObject,
     287             :         Symbol,
     288             :         String,
     289             :         Id,
     290             : 
     291             :         // These fields take up 64 bits on all platforms.
     292             :         RawInt64,
     293             :         First64BitType = RawInt64,
     294             :         DOMExpandoGeneration,
     295             :         Value,
     296             : 
     297             :         Limit
     298             :     };
     299             : 
     300      115489 :     static bool sizeIsWord(Type type) {
     301      115489 :         MOZ_ASSERT(type != Type::Limit);
     302      115489 :         return type < Type::First64BitType;
     303             :     }
     304           0 :     static bool sizeIsInt64(Type type) {
     305           0 :         MOZ_ASSERT(type != Type::Limit);
     306           0 :         return type >= Type::First64BitType;
     307             :     }
     308       70530 :     static size_t sizeInBytes(Type type) {
     309       70530 :         if (sizeIsWord(type))
     310       70530 :             return sizeof(uintptr_t);
     311           0 :         MOZ_ASSERT(sizeIsInt64(type));
     312           0 :         return sizeof(int64_t);
     313             :     }
     314             : 
     315             :   private:
     316             :     union {
     317             :         uintptr_t dataWord_;
     318             :         uint64_t dataInt64_;
     319             :     };
     320             :     Type type_;
     321             : 
     322             :   public:
     323       17887 :     StubField(uint64_t data, Type type)
     324       17887 :       : dataInt64_(data), type_(type)
     325             :     {
     326       17887 :         MOZ_ASSERT_IF(sizeIsWord(), data <= UINTPTR_MAX);
     327       17887 :     }
     328             : 
     329       35372 :     Type type() const { return type_; }
     330             : 
     331       44959 :     bool sizeIsWord() const { return sizeIsWord(type_); }
     332           0 :     bool sizeIsInt64() const { return sizeIsInt64(type_); }
     333             : 
     334       22205 :     uintptr_t asWord() const { MOZ_ASSERT(sizeIsWord()); return dataWord_; }
     335           0 :     uint64_t asInt64() const { MOZ_ASSERT(sizeIsInt64()); return dataInt64_; }
     336             : } JS_HAZ_GC_POINTER;
     337             : 
     338             : // We use this enum as GuardClass operand, instead of storing Class* pointers
     339             : // in the IR, to keep the IR compact and the same size on all platforms.
     340             : enum class GuardClassKind : uint8_t
     341             : {
     342             :     Array,
     343             :     UnboxedArray,
     344             :     MappedArguments,
     345             :     UnmappedArguments,
     346             :     WindowProxy,
     347             :     JSFunction,
     348             : };
     349             : 
     350             : // Class to record CacheIR + some additional metadata for code generation.
     351       12114 : class MOZ_RAII CacheIRWriter : public JS::CustomAutoRooter
     352             : {
     353             :     CompactBufferWriter buffer_;
     354             : 
     355             :     uint32_t nextOperandId_;
     356             :     uint32_t nextInstructionId_;
     357             :     uint32_t numInputOperands_;
     358             : 
     359             :     // The data (shapes, slot offsets, etc.) that will be stored in the ICStub.
     360             :     Vector<StubField, 8, SystemAllocPolicy> stubFields_;
     361             :     size_t stubDataSize_;
     362             : 
     363             :     // For each operand id, record which instruction accessed it last. This
     364             :     // information greatly improves register allocation.
     365             :     Vector<uint32_t, 8, SystemAllocPolicy> operandLastUsed_;
     366             : 
     367             :     // OperandId and stub offsets are stored in a single byte, so make sure
     368             :     // this doesn't overflow. We use a very conservative limit for now.
     369             :     static const size_t MaxOperandIds = 20;
     370             :     static const size_t MaxStubDataSizeInBytes = 20 * sizeof(uintptr_t);
     371             :     bool tooLarge_;
     372             : 
     373       36377 :     void writeOp(CacheOp op) {
     374       36377 :         MOZ_ASSERT(uint32_t(op) <= UINT8_MAX);
     375       36377 :         buffer_.writeByte(uint32_t(op));
     376       36377 :         nextInstructionId_++;
     377       36377 :     }
     378             : 
     379       33329 :     void writeOperandId(OperandId opId) {
     380       33329 :         if (opId.id() < MaxOperandIds) {
     381             :             static_assert(MaxOperandIds <= UINT8_MAX, "operand id must fit in a single byte");
     382       33329 :             buffer_.writeByte(opId.id());
     383             :         } else {
     384           0 :             tooLarge_ = true;
     385           0 :             return;
     386             :         }
     387       33329 :         if (opId.id() >= operandLastUsed_.length()) {
     388       12696 :             buffer_.propagateOOM(operandLastUsed_.resize(opId.id() + 1));
     389       12696 :             if (buffer_.oom())
     390           0 :                 return;
     391             :         }
     392       33329 :         MOZ_ASSERT(nextInstructionId_ > 0);
     393       33329 :         operandLastUsed_[opId.id()] = nextInstructionId_ - 1;
     394             :     }
     395             : 
     396           1 :     void writeInt32Immediate(int32_t i32) {
     397           1 :         buffer_.writeSigned(i32);
     398           1 :     }
     399           3 :     void writeUint32Immediate(uint32_t u32) {
     400           3 :         buffer_.writeUnsigned(u32);
     401           3 :     }
     402           1 :     void writePointer(void* ptr) {
     403           1 :         buffer_.writeRawPointer(ptr);
     404           1 :     }
     405             : 
     406       28936 :     void writeOpWithOperandId(CacheOp op, OperandId opId) {
     407       28936 :         writeOp(op);
     408       28936 :         writeOperandId(opId);
     409       28936 :     }
     410             : 
     411       17887 :     void addStubField(uint64_t value, StubField::Type fieldType) {
     412       17887 :         size_t newStubDataSize = stubDataSize_ + StubField::sizeInBytes(fieldType);
     413       17887 :         if (newStubDataSize < MaxStubDataSizeInBytes) {
     414       17887 :             buffer_.propagateOOM(stubFields_.append(StubField(value, fieldType)));
     415       17887 :             MOZ_ASSERT((stubDataSize_ % sizeof(uintptr_t)) == 0);
     416       17887 :             buffer_.writeByte(stubDataSize_ / sizeof(uintptr_t));
     417       17887 :             stubDataSize_ = newStubDataSize;
     418             :         } else {
     419           0 :             tooLarge_ = true;
     420             :         }
     421       17887 :     }
     422             : 
     423             :     CacheIRWriter(const CacheIRWriter&) = delete;
     424             :     CacheIRWriter& operator=(const CacheIRWriter&) = delete;
     425             : 
     426             :   public:
     427       12114 :     explicit CacheIRWriter(JSContext* cx)
     428       12114 :       : CustomAutoRooter(cx),
     429             :         nextOperandId_(0),
     430             :         nextInstructionId_(0),
     431             :         numInputOperands_(0),
     432             :         stubDataSize_(0),
     433       12114 :         tooLarge_(false)
     434       12114 :     {}
     435             : 
     436       30564 :     bool failed() const { return buffer_.oom() || tooLarge_; }
     437             : 
     438        5892 :     uint32_t numInputOperands() const { return numInputOperands_; }
     439         266 :     uint32_t numOperandIds() const { return nextOperandId_; }
     440             :     uint32_t numInstructions() const { return nextInstructionId_; }
     441             : 
     442         272 :     size_t numStubFields() const { return stubFields_.length(); }
     443         725 :     StubField::Type stubFieldType(uint32_t i) const { return stubFields_[i].type(); }
     444             : 
     445       12626 :     uint32_t setInputOperandId(uint32_t op) {
     446       12626 :         MOZ_ASSERT(op == nextOperandId_);
     447       12626 :         nextOperandId_++;
     448       12626 :         numInputOperands_++;
     449       12626 :         return op;
     450             :     }
     451             : 
     452          14 :     void trace(JSTracer* trc) override {
     453             :         // For now, assert we only GC before we append stub fields.
     454          14 :         MOZ_RELEASE_ASSERT(stubFields_.empty());
     455          14 :     }
     456             : 
     457        6361 :     size_t stubDataSize() const {
     458        6361 :         return stubDataSize_;
     459             :     }
     460             :     void copyStubData(uint8_t* dest) const;
     461             :     bool stubDataEqualsMaybeUpdate(uint8_t* stubData, bool* updated) const;
     462             : 
     463         259 :     bool operandIsDead(uint32_t operandId, uint32_t currentInstruction) const {
     464         259 :         if (operandId >= operandLastUsed_.length())
     465           0 :             return false;
     466         259 :         return currentInstruction > operandLastUsed_[operandId];
     467             :     }
     468        6899 :     const uint8_t* codeStart() const {
     469        6899 :         MOZ_ASSERT(!failed());
     470        6899 :         return buffer_.buffer();
     471             :     }
     472         266 :     const uint8_t* codeEnd() const {
     473         266 :         MOZ_ASSERT(!failed());
     474         266 :         return buffer_.buffer() + buffer_.length();
     475             :     }
     476        7386 :     uint32_t codeLength() const {
     477        7386 :         MOZ_ASSERT(!failed());
     478        7386 :         return buffer_.length();
     479             :     }
     480             : 
     481             :     // This should not be used when compiling Baseline code, as Baseline code
     482             :     // shouldn't bake in stub values.
     483          29 :     StubField readStubFieldForIon(size_t i, StubField::Type type) const {
     484          29 :         MOZ_ASSERT(stubFields_[i].type() == type);
     485          29 :         return stubFields_[i];
     486             :     }
     487             : 
     488        5930 :     ObjOperandId guardIsObject(ValOperandId val) {
     489        5930 :         writeOpWithOperandId(CacheOp::GuardIsObject, val);
     490        5930 :         return ObjOperandId(val.id());
     491             :     }
     492        1544 :     StringOperandId guardIsString(ValOperandId val) {
     493        1544 :         writeOpWithOperandId(CacheOp::GuardIsString, val);
     494        1544 :         return StringOperandId(val.id());
     495             :     }
     496         119 :     SymbolOperandId guardIsSymbol(ValOperandId val) {
     497         119 :         writeOpWithOperandId(CacheOp::GuardIsSymbol, val);
     498         119 :         return SymbolOperandId(val.id());
     499             :     }
     500         341 :     Int32OperandId guardIsInt32Index(ValOperandId val) {
     501         341 :         Int32OperandId res(nextOperandId_++);
     502         341 :         writeOpWithOperandId(CacheOp::GuardIsInt32Index, val);
     503         341 :         writeOperandId(res);
     504         341 :         return res;
     505             :     }
     506         130 :     void guardType(ValOperandId val, JSValueType type) {
     507         130 :         writeOpWithOperandId(CacheOp::GuardType, val);
     508             :         static_assert(sizeof(type) == sizeof(uint8_t), "JSValueType should fit in a byte");
     509         130 :         buffer_.writeByte(uint32_t(type));
     510         130 :     }
     511          21 :     void guardIsObjectOrNull(ValOperandId val) {
     512          21 :         writeOpWithOperandId(CacheOp::GuardIsObjectOrNull, val);
     513          21 :     }
     514        7772 :     void guardShape(ObjOperandId obj, Shape* shape) {
     515        7772 :         writeOpWithOperandId(CacheOp::GuardShape, obj);
     516        7772 :         addStubField(uintptr_t(shape), StubField::Type::Shape);
     517        7772 :     }
     518        1043 :     void guardGroup(ObjOperandId obj, ObjectGroup* group) {
     519        1043 :         writeOpWithOperandId(CacheOp::GuardGroup, obj);
     520        1043 :         addStubField(uintptr_t(group), StubField::Type::ObjectGroup);
     521        1043 :     }
     522          88 :     void guardProto(ObjOperandId obj, JSObject* proto) {
     523          88 :         writeOpWithOperandId(CacheOp::GuardProto, obj);
     524          88 :         addStubField(uintptr_t(proto), StubField::Type::JSObject);
     525          88 :     }
     526         110 :     void guardClass(ObjOperandId obj, GuardClassKind kind) {
     527             :         static_assert(sizeof(GuardClassKind) == sizeof(uint8_t),
     528             :                       "GuardClassKind must fit in a byte");
     529         110 :         writeOpWithOperandId(CacheOp::GuardClass, obj);
     530         110 :         buffer_.writeByte(uint32_t(kind));
     531         110 :     }
     532           1 :     void guardIsNativeFunction(ObjOperandId obj, JSNative nativeFunc) {
     533           1 :         writeOpWithOperandId(CacheOp::GuardIsNativeFunction, obj);
     534           1 :         writePointer(JS_FUNC_TO_DATA_PTR(void*, nativeFunc));
     535           1 :     }
     536         683 :     void guardIsProxy(ObjOperandId obj) {
     537         683 :         writeOpWithOperandId(CacheOp::GuardIsProxy, obj);
     538         683 :     }
     539         544 :     void guardIsCrossCompartmentWrapper(ObjOperandId obj) {
     540         544 :         writeOpWithOperandId(CacheOp::GuardIsCrossCompartmentWrapper, obj);
     541         544 :     }
     542          95 :     void guardNotDOMProxy(ObjOperandId obj) {
     543          95 :         writeOpWithOperandId(CacheOp::GuardNotDOMProxy, obj);
     544          95 :     }
     545           0 :     void guardSpecificObject(ObjOperandId obj, JSObject* expected) {
     546           0 :         writeOpWithOperandId(CacheOp::GuardSpecificObject, obj);
     547           0 :         addStubField(uintptr_t(expected), StubField::Type::JSObject);
     548           0 :     }
     549         792 :     void guardSpecificAtom(StringOperandId str, JSAtom* expected) {
     550         792 :         writeOpWithOperandId(CacheOp::GuardSpecificAtom, str);
     551         792 :         addStubField(uintptr_t(expected), StubField::Type::String);
     552         792 :     }
     553         119 :     void guardSpecificSymbol(SymbolOperandId sym, JS::Symbol* expected) {
     554         119 :         writeOpWithOperandId(CacheOp::GuardSpecificSymbol, sym);
     555         119 :         addStubField(uintptr_t(expected), StubField::Type::Symbol);
     556         119 :     }
     557           1 :     void guardSpecificInt32Immediate(Int32OperandId operand, int32_t expected) {
     558           1 :         writeOp(CacheOp::GuardSpecificInt32Immediate);
     559           1 :         writeOperandId(operand);
     560           1 :         writeInt32Immediate(expected);
     561           1 :     }
     562          54 :     void guardMagicValue(ValOperandId val, JSWhyMagic magic) {
     563          54 :         writeOpWithOperandId(CacheOp::GuardMagicValue, val);
     564          54 :         buffer_.writeByte(uint32_t(magic));
     565          54 :     }
     566         544 :     void guardCompartment(ObjOperandId obj, JSObject* global, JSCompartment* compartment) {
     567         544 :         writeOpWithOperandId(CacheOp::GuardCompartment, obj);
     568             :         // Add a reference to the compartment's global to keep it alive.
     569         544 :         addStubField(uintptr_t(global), StubField::Type::JSObject);
     570             :         // Use RawWord, because compartments never move and it can't be GCed.
     571         544 :         addStubField(uintptr_t(compartment), StubField::Type::RawWord);
     572         544 :     }
     573           0 :     void guardNoDetachedTypedObjects() {
     574           0 :         writeOp(CacheOp::GuardNoDetachedTypedObjects);
     575           0 :     }
     576          54 :     void guardFrameHasNoArgumentsObject() {
     577          54 :         writeOp(CacheOp::GuardFrameHasNoArgumentsObject);
     578          54 :     }
     579             : 
     580           2 :     Int32OperandId guardAndGetIndexFromString(StringOperandId str) {
     581           2 :         Int32OperandId res(nextOperandId_++);
     582           2 :         writeOpWithOperandId(CacheOp::GuardAndGetIndexFromString, str);
     583           2 :         writeOperandId(res);
     584           2 :         return res;
     585             :     }
     586             : 
     587          16 :     void guardHasGetterSetter(ObjOperandId obj, Shape* shape) {
     588          16 :         writeOpWithOperandId(CacheOp::GuardHasGetterSetter, obj);
     589          16 :         addStubField(uintptr_t(shape), StubField::Type::Shape);
     590          16 :     }
     591         111 :     void guardGroupHasUnanalyzedNewScript(ObjectGroup* group) {
     592         111 :         writeOp(CacheOp::GuardGroupHasUnanalyzedNewScript);
     593         111 :         addStubField(uintptr_t(group), StubField::Type::ObjectGroup);
     594         111 :     }
     595             : 
     596           0 :     void loadFrameCalleeResult() {
     597           0 :         writeOp(CacheOp::LoadFrameCalleeResult);
     598           0 :     }
     599          38 :     void loadFrameNumActualArgsResult() {
     600          38 :         writeOp(CacheOp::LoadFrameNumActualArgsResult);
     601          38 :     }
     602          16 :     void loadFrameArgumentResult(Int32OperandId index) {
     603          16 :         writeOpWithOperandId(CacheOp::LoadFrameArgumentResult, index);
     604          16 :     }
     605           2 :     void guardNoDenseElements(ObjOperandId obj) {
     606           2 :         writeOpWithOperandId(CacheOp::GuardNoDenseElements, obj);
     607           2 :     }
     608           0 :     void guardNoUnboxedExpando(ObjOperandId obj) {
     609           0 :         writeOpWithOperandId(CacheOp::GuardNoUnboxedExpando, obj);
     610           0 :     }
     611           0 :     ObjOperandId guardAndLoadUnboxedExpando(ObjOperandId obj) {
     612           0 :         ObjOperandId res(nextOperandId_++);
     613           0 :         writeOpWithOperandId(CacheOp::GuardAndLoadUnboxedExpando, obj);
     614           0 :         writeOperandId(res);
     615           0 :         return res;
     616             :     }
     617             : 
     618           3 :     ValOperandId loadStackValue(uint32_t idx) {
     619           3 :         ValOperandId res(nextOperandId_++);
     620           3 :         writeOpWithOperandId(CacheOp::LoadStackValue, res);
     621           3 :         writeUint32Immediate(idx);
     622           3 :         return res;
     623             :     }
     624         788 :     ObjOperandId loadObject(JSObject* obj) {
     625         788 :         ObjOperandId res(nextOperandId_++);
     626         788 :         writeOpWithOperandId(CacheOp::LoadObject, res);
     627         788 :         addStubField(uintptr_t(obj), StubField::Type::JSObject);
     628         788 :         return res;
     629             :     }
     630         948 :     ObjOperandId loadProto(ObjOperandId obj) {
     631         948 :         ObjOperandId res(nextOperandId_++);
     632         948 :         writeOpWithOperandId(CacheOp::LoadProto, obj);
     633         948 :         writeOperandId(res);
     634         948 :         return res;
     635             :     }
     636             : 
     637         731 :     ObjOperandId loadEnclosingEnvironment(ObjOperandId obj) {
     638         731 :         ObjOperandId res(nextOperandId_++);
     639         731 :         writeOpWithOperandId(CacheOp::LoadEnclosingEnvironment, obj);
     640         731 :         writeOperandId(res);
     641         731 :         return res;
     642             :     }
     643             : 
     644         544 :     ObjOperandId loadWrapperTarget(ObjOperandId obj) {
     645         544 :         ObjOperandId res(nextOperandId_++);
     646         544 :         writeOpWithOperandId(CacheOp::LoadWrapperTarget, obj);
     647         544 :         writeOperandId(res);
     648         544 :         return res;
     649             :     }
     650             : 
     651           6 :     ValOperandId loadDOMExpandoValue(ObjOperandId obj) {
     652           6 :         ValOperandId res(nextOperandId_++);
     653           6 :         writeOpWithOperandId(CacheOp::LoadDOMExpandoValue, obj);
     654           6 :         writeOperandId(res);
     655           6 :         return res;
     656             :     }
     657           0 :     void guardDOMExpandoMissingOrGuardShape(ValOperandId expando, Shape* shape) {
     658           0 :         writeOpWithOperandId(CacheOp::GuardDOMExpandoMissingOrGuardShape, expando);
     659           0 :         addStubField(uintptr_t(shape), StubField::Type::Shape);
     660           0 :     }
     661           0 :     ValOperandId loadDOMExpandoValueGuardGeneration(ObjOperandId obj,
     662             :                                                     ExpandoAndGeneration* expandoAndGeneration)
     663             :     {
     664           0 :         ValOperandId res(nextOperandId_++);
     665           0 :         writeOpWithOperandId(CacheOp::LoadDOMExpandoValueGuardGeneration, obj);
     666           0 :         addStubField(uintptr_t(expandoAndGeneration), StubField::Type::RawWord);
     667           0 :         addStubField(expandoAndGeneration->generation, StubField::Type::DOMExpandoGeneration);
     668           0 :         writeOperandId(res);
     669           0 :         return res;
     670             :     }
     671           0 :     ValOperandId loadDOMExpandoValueIgnoreGeneration(ObjOperandId obj) {
     672           0 :         ValOperandId res(nextOperandId_++);
     673           0 :         writeOpWithOperandId(CacheOp::LoadDOMExpandoValueIgnoreGeneration, obj);
     674           0 :         writeOperandId(res);
     675           0 :         return res;
     676             :     }
     677             : 
     678         381 :     void storeFixedSlot(ObjOperandId obj, size_t offset, ValOperandId rhs) {
     679         381 :         writeOpWithOperandId(CacheOp::StoreFixedSlot, obj);
     680         381 :         addStubField(offset, StubField::Type::RawWord);
     681         381 :         writeOperandId(rhs);
     682         381 :     }
     683          41 :     void storeDynamicSlot(ObjOperandId obj, size_t offset, ValOperandId rhs) {
     684          41 :         writeOpWithOperandId(CacheOp::StoreDynamicSlot, obj);
     685          41 :         addStubField(offset, StubField::Type::RawWord);
     686          41 :         writeOperandId(rhs);
     687          41 :     }
     688         110 :     void addAndStoreFixedSlot(ObjOperandId obj, size_t offset, ValOperandId rhs,
     689             :                               Shape* newShape, bool changeGroup, ObjectGroup* newGroup)
     690             :     {
     691         110 :         writeOpWithOperandId(CacheOp::AddAndStoreFixedSlot, obj);
     692         110 :         addStubField(offset, StubField::Type::RawWord);
     693         110 :         writeOperandId(rhs);
     694         110 :         buffer_.writeByte(changeGroup);
     695         110 :         addStubField(uintptr_t(newGroup), StubField::Type::ObjectGroup);
     696         110 :         addStubField(uintptr_t(newShape), StubField::Type::Shape);
     697         110 :     }
     698         274 :     void addAndStoreDynamicSlot(ObjOperandId obj, size_t offset, ValOperandId rhs,
     699             :                                 Shape* newShape, bool changeGroup, ObjectGroup* newGroup)
     700             :     {
     701         274 :         writeOpWithOperandId(CacheOp::AddAndStoreDynamicSlot, obj);
     702         274 :         addStubField(offset, StubField::Type::RawWord);
     703         274 :         writeOperandId(rhs);
     704         274 :         buffer_.writeByte(changeGroup);
     705         274 :         addStubField(uintptr_t(newGroup), StubField::Type::ObjectGroup);
     706         274 :         addStubField(uintptr_t(newShape), StubField::Type::Shape);
     707         274 :     }
     708          60 :     void allocateAndStoreDynamicSlot(ObjOperandId obj, size_t offset, ValOperandId rhs,
     709             :                                      Shape* newShape, bool changeGroup, ObjectGroup* newGroup,
     710             :                                      uint32_t numNewSlots)
     711             :     {
     712          60 :         writeOpWithOperandId(CacheOp::AllocateAndStoreDynamicSlot, obj);
     713          60 :         addStubField(offset, StubField::Type::RawWord);
     714          60 :         writeOperandId(rhs);
     715          60 :         buffer_.writeByte(changeGroup);
     716          60 :         addStubField(uintptr_t(newGroup), StubField::Type::ObjectGroup);
     717          60 :         addStubField(uintptr_t(newShape), StubField::Type::Shape);
     718          60 :         addStubField(numNewSlots, StubField::Type::RawWord);
     719          60 :     }
     720             : 
     721           0 :     void storeTypedObjectReferenceProperty(ObjOperandId obj, uint32_t offset,
     722             :                                            TypedThingLayout layout, ReferenceTypeDescr::Type type,
     723             :                                            ValOperandId rhs)
     724             :     {
     725           0 :         writeOpWithOperandId(CacheOp::StoreTypedObjectReferenceProperty, obj);
     726           0 :         addStubField(offset, StubField::Type::RawWord);
     727           0 :         buffer_.writeByte(uint32_t(layout));
     728           0 :         buffer_.writeByte(uint32_t(type));
     729           0 :         writeOperandId(rhs);
     730           0 :     }
     731           0 :     void storeTypedObjectScalarProperty(ObjOperandId obj, uint32_t offset, TypedThingLayout layout,
     732             :                                         Scalar::Type type, ValOperandId rhs)
     733             :     {
     734           0 :         writeOpWithOperandId(CacheOp::StoreTypedObjectScalarProperty, obj);
     735           0 :         addStubField(offset, StubField::Type::RawWord);
     736           0 :         buffer_.writeByte(uint32_t(layout));
     737           0 :         buffer_.writeByte(uint32_t(type));
     738           0 :         writeOperandId(rhs);
     739           0 :     }
     740          47 :     void storeUnboxedProperty(ObjOperandId obj, JSValueType type, size_t offset,
     741             :                               ValOperandId rhs)
     742             :     {
     743          47 :         writeOpWithOperandId(CacheOp::StoreUnboxedProperty, obj);
     744          47 :         buffer_.writeByte(uint32_t(type));
     745          47 :         addStubField(offset, StubField::Type::RawWord);
     746          47 :         writeOperandId(rhs);
     747          47 :     }
     748          26 :     void storeDenseElement(ObjOperandId obj, Int32OperandId index, ValOperandId rhs) {
     749          26 :         writeOpWithOperandId(CacheOp::StoreDenseElement, obj);
     750          26 :         writeOperandId(index);
     751          26 :         writeOperandId(rhs);
     752          26 :     }
     753           0 :     void storeTypedElement(ObjOperandId obj, Int32OperandId index, ValOperandId rhs,
     754             :                            TypedThingLayout layout, Scalar::Type elementType, bool handleOOB)
     755             :     {
     756           0 :         writeOpWithOperandId(CacheOp::StoreTypedElement, obj);
     757           0 :         writeOperandId(index);
     758           0 :         writeOperandId(rhs);
     759           0 :         buffer_.writeByte(uint32_t(layout));
     760           0 :         buffer_.writeByte(uint32_t(elementType));
     761           0 :         buffer_.writeByte(uint32_t(handleOOB));
     762           0 :     }
     763           0 :     void storeUnboxedArrayElement(ObjOperandId obj, Int32OperandId index, ValOperandId rhs,
     764             :                                   JSValueType elementType)
     765             :     {
     766           0 :         writeOpWithOperandId(CacheOp::StoreUnboxedArrayElement, obj);
     767           0 :         writeOperandId(index);
     768           0 :         writeOperandId(rhs);
     769           0 :         buffer_.writeByte(uint32_t(elementType));
     770           0 :     }
     771           0 :     void storeUnboxedArrayElementHole(ObjOperandId obj, Int32OperandId index, ValOperandId rhs,
     772             :                                       JSValueType elementType)
     773             :     {
     774           0 :         writeOpWithOperandId(CacheOp::StoreUnboxedArrayElementHole, obj);
     775           0 :         writeOperandId(index);
     776           0 :         writeOperandId(rhs);
     777           0 :         buffer_.writeByte(uint32_t(elementType));
     778           0 :     }
     779          96 :     void storeDenseElementHole(ObjOperandId obj, Int32OperandId index, ValOperandId rhs,
     780             :                                bool handleAdd)
     781             :     {
     782          96 :         writeOpWithOperandId(CacheOp::StoreDenseElementHole, obj);
     783          96 :         writeOperandId(index);
     784          96 :         writeOperandId(rhs);
     785          96 :         buffer_.writeByte(handleAdd);
     786          96 :     }
     787           4 :     void callScriptedSetter(ObjOperandId obj, JSFunction* setter, ValOperandId rhs) {
     788           4 :         writeOpWithOperandId(CacheOp::CallScriptedSetter, obj);
     789           4 :         addStubField(uintptr_t(setter), StubField::Type::JSObject);
     790           4 :         writeOperandId(rhs);
     791           4 :     }
     792           6 :     void callNativeSetter(ObjOperandId obj, JSFunction* setter, ValOperandId rhs) {
     793           6 :         writeOpWithOperandId(CacheOp::CallNativeSetter, obj);
     794           6 :         addStubField(uintptr_t(setter), StubField::Type::JSObject);
     795           6 :         writeOperandId(rhs);
     796           6 :     }
     797          10 :     void callSetArrayLength(ObjOperandId obj, bool strict, ValOperandId rhs) {
     798          10 :         writeOpWithOperandId(CacheOp::CallSetArrayLength, obj);
     799          10 :         buffer_.writeByte(uint32_t(strict));
     800          10 :         writeOperandId(rhs);
     801          10 :     }
     802          14 :     void callProxySet(ObjOperandId obj, jsid id, ValOperandId rhs, bool strict) {
     803          14 :         writeOpWithOperandId(CacheOp::CallProxySet, obj);
     804          14 :         writeOperandId(rhs);
     805          14 :         addStubField(uintptr_t(JSID_BITS(id)), StubField::Type::Id);
     806          14 :         buffer_.writeByte(uint32_t(strict));
     807          14 :     }
     808           1 :     void callProxySetByValue(ObjOperandId obj, ValOperandId id, ValOperandId rhs, bool strict) {
     809           1 :         writeOpWithOperandId(CacheOp::CallProxySetByValue, obj);
     810           1 :         writeOperandId(id);
     811           1 :         writeOperandId(rhs);
     812           1 :         buffer_.writeByte(uint32_t(strict));
     813           1 :     }
     814             : 
     815          28 :     void megamorphicLoadSlotResult(ObjOperandId obj, PropertyName* name, bool handleMissing) {
     816          28 :         writeOpWithOperandId(CacheOp::MegamorphicLoadSlotResult, obj);
     817          28 :         addStubField(uintptr_t(name), StubField::Type::String);
     818          28 :         buffer_.writeByte(uint32_t(handleMissing));
     819          28 :     }
     820          33 :     void megamorphicLoadSlotByValueResult(ObjOperandId obj, ValOperandId id, bool handleMissing) {
     821          33 :         writeOpWithOperandId(CacheOp::MegamorphicLoadSlotByValueResult, obj);
     822          33 :         writeOperandId(id);
     823          33 :         buffer_.writeByte(uint32_t(handleMissing));
     824          33 :     }
     825           0 :     void megamorphicStoreSlot(ObjOperandId obj, PropertyName* name, ValOperandId rhs,
     826             :                               bool needsTypeBarrier) {
     827           0 :         writeOpWithOperandId(CacheOp::MegamorphicStoreSlot, obj);
     828           0 :         addStubField(uintptr_t(name), StubField::Type::String);
     829           0 :         writeOperandId(rhs);
     830           0 :         buffer_.writeByte(needsTypeBarrier);
     831           0 :     }
     832           0 :     void megamorphicHasOwnResult(ObjOperandId obj, ValOperandId id) {
     833           0 :         writeOpWithOperandId(CacheOp::MegamorphicHasOwnResult, obj);
     834           0 :         writeOperandId(id);
     835           0 :     }
     836             : 
     837         123 :     void loadBooleanResult(bool val) {
     838         123 :         writeOp(CacheOp::LoadBooleanResult);
     839         123 :         buffer_.writeByte(uint32_t(val));
     840         123 :     }
     841         193 :     void loadUndefinedResult() {
     842         193 :         writeOp(CacheOp::LoadUndefinedResult);
     843         193 :     }
     844          61 :     void loadStringResult(JSString* str) {
     845          61 :         writeOp(CacheOp::LoadStringResult);
     846          61 :         addStubField(uintptr_t(str), StubField::Type::String);
     847          61 :     }
     848        1034 :     void loadFixedSlotResult(ObjOperandId obj, size_t offset) {
     849        1034 :         writeOpWithOperandId(CacheOp::LoadFixedSlotResult, obj);
     850        1034 :         addStubField(offset, StubField::Type::RawWord);
     851        1034 :     }
     852        2760 :     void loadDynamicSlotResult(ObjOperandId obj, size_t offset) {
     853        2760 :         writeOpWithOperandId(CacheOp::LoadDynamicSlotResult, obj);
     854        2760 :         addStubField(offset, StubField::Type::RawWord);
     855        2760 :     }
     856           8 :     void loadUnboxedPropertyResult(ObjOperandId obj, JSValueType type, size_t offset) {
     857           8 :         writeOpWithOperandId(CacheOp::LoadUnboxedPropertyResult, obj);
     858           8 :         buffer_.writeByte(uint32_t(type));
     859           8 :         addStubField(offset, StubField::Type::RawWord);
     860           8 :     }
     861           0 :     void loadTypedObjectResult(ObjOperandId obj, uint32_t offset, TypedThingLayout layout,
     862             :                                uint32_t typeDescr) {
     863           0 :         MOZ_ASSERT(uint32_t(layout) <= UINT8_MAX);
     864           0 :         MOZ_ASSERT(typeDescr <= UINT8_MAX);
     865           0 :         writeOpWithOperandId(CacheOp::LoadTypedObjectResult, obj);
     866           0 :         buffer_.writeByte(uint32_t(layout));
     867           0 :         buffer_.writeByte(typeDescr);
     868           0 :         addStubField(offset, StubField::Type::RawWord);
     869           0 :     }
     870          99 :     void loadInt32ArrayLengthResult(ObjOperandId obj) {
     871          99 :         writeOpWithOperandId(CacheOp::LoadInt32ArrayLengthResult, obj);
     872          99 :     }
     873           0 :     void loadUnboxedArrayLengthResult(ObjOperandId obj) {
     874           0 :         writeOpWithOperandId(CacheOp::LoadUnboxedArrayLengthResult, obj);
     875           0 :     }
     876           1 :     void loadArgumentsObjectLengthResult(ObjOperandId obj) {
     877           1 :         writeOpWithOperandId(CacheOp::LoadArgumentsObjectLengthResult, obj);
     878           1 :     }
     879           0 :     void loadFunctionLengthResult(ObjOperandId obj) {
     880           0 :         writeOpWithOperandId(CacheOp::LoadFunctionLengthResult, obj);
     881           0 :     }
     882           0 :     void loadArgumentsObjectArgResult(ObjOperandId obj, Int32OperandId index) {
     883           0 :         writeOpWithOperandId(CacheOp::LoadArgumentsObjectArgResult, obj);
     884           0 :         writeOperandId(index);
     885           0 :     }
     886         145 :     void loadDenseElementResult(ObjOperandId obj, Int32OperandId index) {
     887         145 :         writeOpWithOperandId(CacheOp::LoadDenseElementResult, obj);
     888         145 :         writeOperandId(index);
     889         145 :     }
     890           2 :     void loadDenseElementHoleResult(ObjOperandId obj, Int32OperandId index) {
     891           2 :         writeOpWithOperandId(CacheOp::LoadDenseElementHoleResult, obj);
     892           2 :         writeOperandId(index);
     893           2 :     }
     894          37 :     void loadDenseElementExistsResult(ObjOperandId obj, Int32OperandId index) {
     895          37 :         writeOpWithOperandId(CacheOp::LoadDenseElementExistsResult, obj);
     896          37 :         writeOperandId(index);
     897          37 :     }
     898           0 :     void loadDenseElementHoleExistsResult(ObjOperandId obj, Int32OperandId index) {
     899           0 :         writeOpWithOperandId(CacheOp::LoadDenseElementHoleExistsResult, obj);
     900           0 :         writeOperandId(index);
     901           0 :     }
     902           0 :     void loadUnboxedArrayElementResult(ObjOperandId obj, Int32OperandId index, JSValueType elementType) {
     903           0 :         writeOpWithOperandId(CacheOp::LoadUnboxedArrayElementResult, obj);
     904           0 :         writeOperandId(index);
     905           0 :         buffer_.writeByte(uint32_t(elementType));
     906           0 :     }
     907           0 :     void loadTypedElementResult(ObjOperandId obj, Int32OperandId index, TypedThingLayout layout,
     908             :                                 Scalar::Type elementType) {
     909           0 :         writeOpWithOperandId(CacheOp::LoadTypedElementResult, obj);
     910           0 :         writeOperandId(index);
     911           0 :         buffer_.writeByte(uint32_t(layout));
     912           0 :         buffer_.writeByte(uint32_t(elementType));
     913           0 :     }
     914          13 :     void loadStringLengthResult(StringOperandId str) {
     915          13 :         writeOpWithOperandId(CacheOp::LoadStringLengthResult, str);
     916          13 :     }
     917           3 :     void loadStringCharResult(StringOperandId str, Int32OperandId index) {
     918           3 :         writeOpWithOperandId(CacheOp::LoadStringCharResult, str);
     919           3 :         writeOperandId(index);
     920           3 :     }
     921          66 :     void callScriptedGetterResult(ObjOperandId obj, JSFunction* getter) {
     922          66 :         writeOpWithOperandId(CacheOp::CallScriptedGetterResult, obj);
     923          66 :         addStubField(uintptr_t(getter), StubField::Type::JSObject);
     924          66 :     }
     925         112 :     void callNativeGetterResult(ObjOperandId obj, JSFunction* getter) {
     926         112 :         writeOpWithOperandId(CacheOp::CallNativeGetterResult, obj);
     927         112 :         addStubField(uintptr_t(getter), StubField::Type::JSObject);
     928         112 :     }
     929         104 :     void callProxyGetResult(ObjOperandId obj, jsid id) {
     930         104 :         writeOpWithOperandId(CacheOp::CallProxyGetResult, obj);
     931         104 :         addStubField(uintptr_t(JSID_BITS(id)), StubField::Type::Id);
     932         104 :     }
     933          20 :     void callProxyGetByValueResult(ObjOperandId obj, ValOperandId idVal) {
     934          20 :         writeOpWithOperandId(CacheOp::CallProxyGetByValueResult, obj);
     935          20 :         writeOperandId(idVal);
     936          20 :     }
     937           0 :     void callProxyHasOwnResult(ObjOperandId obj, ValOperandId idVal) {
     938           0 :         writeOpWithOperandId(CacheOp::CallProxyHasOwnResult, obj);
     939           0 :         writeOperandId(idVal);
     940           0 :     }
     941           4 :     void loadEnvironmentFixedSlotResult(ObjOperandId obj, size_t offset) {
     942           4 :         writeOpWithOperandId(CacheOp::LoadEnvironmentFixedSlotResult, obj);
     943           4 :         addStubField(offset, StubField::Type::RawWord);
     944           4 :     }
     945           7 :     void loadEnvironmentDynamicSlotResult(ObjOperandId obj, size_t offset) {
     946           7 :         writeOpWithOperandId(CacheOp::LoadEnvironmentDynamicSlotResult, obj);
     947           7 :         addStubField(offset, StubField::Type::RawWord);
     948           7 :     }
     949           0 :     void loadObjectResult(ObjOperandId obj) {
     950           0 :         writeOpWithOperandId(CacheOp::LoadObjectResult, obj);
     951           0 :     }
     952          19 :     void loadTypeOfObjectResult(ObjOperandId obj) {
     953          19 :         writeOpWithOperandId(CacheOp::LoadTypeOfObjectResult, obj);
     954          19 :     }
     955             : 
     956           1 :     void callStringSplitResult(StringOperandId str, StringOperandId sep, ObjectGroup* group) {
     957           1 :         writeOp(CacheOp::CallStringSplitResult);
     958           1 :         writeOperandId(str);
     959           1 :         writeOperandId(sep);
     960           1 :         addStubField(uintptr_t(group), StubField::Type::ObjectGroup);
     961           1 :     }
     962             : 
     963         366 :     void compareStringResult(uint32_t op, StringOperandId lhs, StringOperandId rhs) {
     964         366 :         writeOpWithOperandId(CacheOp::CompareStringResult, lhs);
     965         366 :         writeOperandId(rhs);
     966         366 :         buffer_.writeByte(uint32_t(op));
     967         366 :     }
     968          19 :     void compareObjectResult(uint32_t op, ObjOperandId lhs, ObjOperandId rhs) {
     969          19 :         writeOpWithOperandId(CacheOp::CompareObjectResult, lhs);
     970          19 :         writeOperandId(rhs);
     971          19 :         buffer_.writeByte(uint32_t(op));
     972          19 :     }
     973           0 :     void compareSymbolResult(uint32_t op, SymbolOperandId lhs, SymbolOperandId rhs) {
     974           0 :         writeOpWithOperandId(CacheOp::CompareSymbolResult, lhs);
     975           0 :         writeOperandId(rhs);
     976           0 :         buffer_.writeByte(uint32_t(op));
     977           0 :     }
     978             : 
     979             :     void callPrintString(const char* str) {
     980             :         writeOp(CacheOp::CallPrintString);
     981             :         writePointer(const_cast<char*>(str));
     982             :     }
     983             :     void breakpoint() {
     984             :         writeOp(CacheOp::Breakpoint);
     985             :     }
     986             : 
     987        4335 :     void typeMonitorResult() {
     988        4335 :         writeOp(CacheOp::TypeMonitorResult);
     989        4335 :     }
     990        2047 :     void returnFromIC() {
     991        2047 :         writeOp(CacheOp::ReturnFromIC);
     992        2047 :     }
     993         477 :     void wrapResult() {
     994         477 :         writeOp(CacheOp::WrapResult);
     995         477 :     }
     996             : };
     997             : 
     998             : class CacheIRStubInfo;
     999             : 
    1000             : // Helper class for reading CacheIR bytecode.
    1001             : class MOZ_RAII CacheIRReader
    1002             : {
    1003             :     CompactBufferReader buffer_;
    1004             : 
    1005             :     CacheIRReader(const CacheIRReader&) = delete;
    1006             :     CacheIRReader& operator=(const CacheIRReader&) = delete;
    1007             : 
    1008             :   public:
    1009         410 :     CacheIRReader(const uint8_t* start, const uint8_t* end)
    1010         410 :       : buffer_(start, end)
    1011         410 :     {}
    1012         266 :     explicit CacheIRReader(const CacheIRWriter& writer)
    1013         266 :       : CacheIRReader(writer.codeStart(), writer.codeEnd())
    1014         266 :     {}
    1015             :     explicit CacheIRReader(const CacheIRStubInfo* stubInfo);
    1016             : 
    1017        1609 :     bool more() const { return buffer_.more(); }
    1018             : 
    1019        2188 :     CacheOp readOp() {
    1020        2188 :         return CacheOp(buffer_.readByte());
    1021             :     }
    1022             : 
    1023         454 :     ValOperandId valOperandId() { return ValOperandId(buffer_.readByte()); }
    1024         937 :     ObjOperandId objOperandId() { return ObjOperandId(buffer_.readByte()); }
    1025          70 :     StringOperandId stringOperandId() { return StringOperandId(buffer_.readByte()); }
    1026          14 :     SymbolOperandId symbolOperandId() { return SymbolOperandId(buffer_.readByte()); }
    1027          59 :     Int32OperandId int32OperandId() { return Int32OperandId(buffer_.readByte()); }
    1028             : 
    1029         805 :     uint32_t stubOffset() { return buffer_.readByte() * sizeof(uintptr_t); }
    1030          14 :     GuardClassKind guardClassKind() { return GuardClassKind(buffer_.readByte()); }
    1031          38 :     JSValueType valueType() { return JSValueType(buffer_.readByte()); }
    1032           0 :     TypedThingLayout typedThingLayout() { return TypedThingLayout(buffer_.readByte()); }
    1033           0 :     Scalar::Type scalarType() { return Scalar::Type(buffer_.readByte()); }
    1034           0 :     uint32_t typeDescrKey() { return buffer_.readByte(); }
    1035           6 :     JSWhyMagic whyMagic() { return JSWhyMagic(buffer_.readByte()); }
    1036          15 :     JSOp jsop() { return JSOp(buffer_.readByte()); }
    1037           1 :     int32_t int32Immediate() { return buffer_.readSigned(); }
    1038           3 :     uint32_t uint32Immediate() { return buffer_.readUnsigned(); }
    1039           1 :     void* pointer() { return buffer_.readRawPointer(); }
    1040             : 
    1041           0 :     ReferenceTypeDescr::Type referenceTypeDescrType() {
    1042           0 :         return ReferenceTypeDescr::Type(buffer_.readByte());
    1043             :     }
    1044             : 
    1045          60 :     bool readBool() {
    1046          60 :         uint8_t b = buffer_.readByte();
    1047          60 :         MOZ_ASSERT(b <= 1);
    1048          60 :         return bool(b);
    1049             :     }
    1050             : 
    1051          46 :     bool matchOp(CacheOp op) {
    1052          46 :         const uint8_t* pos = buffer_.currentPosition();
    1053          46 :         if (readOp() == op)
    1054           0 :             return true;
    1055          46 :         buffer_.seek(pos, 0);
    1056          46 :         return false;
    1057             :     }
    1058         522 :     bool matchOp(CacheOp op, OperandId id) {
    1059         522 :         const uint8_t* pos = buffer_.currentPosition();
    1060         522 :         if (readOp() == op && buffer_.readByte() == id.id())
    1061         203 :             return true;
    1062         319 :         buffer_.seek(pos, 0);
    1063         319 :         return false;
    1064             :     }
    1065          11 :     bool matchOpEither(CacheOp op1, CacheOp op2) {
    1066          11 :         const uint8_t* pos = buffer_.currentPosition();
    1067          11 :         CacheOp op = readOp();
    1068          11 :         if (op == op1 || op == op2)
    1069          10 :             return true;
    1070           1 :         buffer_.seek(pos, 0);
    1071           1 :         return false;
    1072             :     }
    1073             : };
    1074             : 
    1075       12114 : class MOZ_RAII IRGenerator
    1076             : {
    1077             :   protected:
    1078             :     CacheIRWriter writer;
    1079             :     JSContext* cx_;
    1080             :     HandleScript script_;
    1081             :     jsbytecode* pc_;
    1082             :     CacheKind cacheKind_;
    1083             :     ICState::Mode mode_;
    1084             : 
    1085             :     IRGenerator(const IRGenerator&) = delete;
    1086             :     IRGenerator& operator=(const IRGenerator&) = delete;
    1087             : 
    1088             :     bool maybeGuardInt32Index(const Value& index, ValOperandId indexId,
    1089             :                               uint32_t* int32Index, Int32OperandId* int32IndexId);
    1090             : 
    1091             :     ObjOperandId guardDOMProxyExpandoObjectAndShape(JSObject* obj, ObjOperandId objId,
    1092             :                                                     const Value& expandoVal, JSObject* expandoObj);
    1093             : 
    1094             :     void emitIdGuard(ValOperandId valId, jsid id);
    1095             : 
    1096             :     friend class CacheIRSpewer;
    1097             : 
    1098             :   public:
    1099             :     explicit IRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, CacheKind cacheKind,
    1100             :                          ICState::Mode mode);
    1101             : 
    1102        6382 :     const CacheIRWriter& writerRef() const { return writer; }
    1103        6382 :     CacheKind cacheKind() const { return cacheKind_; }
    1104             : };
    1105             : 
    1106             : enum class CanAttachGetter { Yes, No };
    1107             : 
    1108             : // GetPropIRGenerator generates CacheIR for a GetProp IC.
    1109        4189 : class MOZ_RAII GetPropIRGenerator : public IRGenerator
    1110             : {
    1111             :     HandleValue val_;
    1112             :     HandleValue idVal_;
    1113             :     HandleValue receiver_;
    1114             :     bool* isTemporarilyUnoptimizable_;
    1115             :     CanAttachGetter canAttachGetter_;
    1116             : 
    1117             :     enum class PreliminaryObjectAction { None, Unlink, NotePreliminary };
    1118             :     PreliminaryObjectAction preliminaryObjectAction_;
    1119             : 
    1120             :     bool tryAttachNative(HandleObject obj, ObjOperandId objId, HandleId id);
    1121             :     bool tryAttachUnboxed(HandleObject obj, ObjOperandId objId, HandleId id);
    1122             :     bool tryAttachUnboxedExpando(HandleObject obj, ObjOperandId objId, HandleId id);
    1123             :     bool tryAttachTypedObject(HandleObject obj, ObjOperandId objId, HandleId id);
    1124             :     bool tryAttachObjectLength(HandleObject obj, ObjOperandId objId, HandleId id);
    1125             :     bool tryAttachModuleNamespace(HandleObject obj, ObjOperandId objId, HandleId id);
    1126             :     bool tryAttachWindowProxy(HandleObject obj, ObjOperandId objId, HandleId id);
    1127             :     bool tryAttachCrossCompartmentWrapper(HandleObject obj, ObjOperandId objId, HandleId id);
    1128             :     bool tryAttachFunction(HandleObject obj, ObjOperandId objId, HandleId id);
    1129             : 
    1130             :     bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id,
    1131             :                                bool handleDOMProxies);
    1132             :     bool tryAttachDOMProxyExpando(HandleObject obj, ObjOperandId objId, HandleId id);
    1133             :     bool tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId, HandleId id);
    1134             :     bool tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId, HandleId id);
    1135             :     bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id);
    1136             : 
    1137             :     bool tryAttachPrimitive(ValOperandId valId, HandleId id);
    1138             :     bool tryAttachStringChar(ValOperandId valId, ValOperandId indexId);
    1139             :     bool tryAttachStringLength(ValOperandId valId, HandleId id);
    1140             :     bool tryAttachMagicArgumentsName(ValOperandId valId, HandleId id);
    1141             : 
    1142             :     bool tryAttachMagicArgument(ValOperandId valId, ValOperandId indexId);
    1143             :     bool tryAttachArgumentsObjectArg(HandleObject obj, ObjOperandId objId,
    1144             :                                      uint32_t index, Int32OperandId indexId);
    1145             : 
    1146             :     bool tryAttachDenseElement(HandleObject obj, ObjOperandId objId,
    1147             :                                uint32_t index, Int32OperandId indexId);
    1148             :     bool tryAttachDenseElementHole(HandleObject obj, ObjOperandId objId,
    1149             :                                    uint32_t index, Int32OperandId indexId);
    1150             :     bool tryAttachUnboxedArrayElement(HandleObject obj, ObjOperandId objId,
    1151             :                                       uint32_t index, Int32OperandId indexId);
    1152             :     bool tryAttachTypedElement(HandleObject obj, ObjOperandId objId,
    1153             :                                uint32_t index, Int32OperandId indexId);
    1154             : 
    1155             :     bool tryAttachProxyElement(HandleObject obj, ObjOperandId objId);
    1156             : 
    1157             :     void attachMegamorphicNativeSlot(ObjOperandId objId, jsid id, bool handleMissing);
    1158             : 
    1159        1524 :     ValOperandId getElemKeyValueId() const {
    1160        1524 :         MOZ_ASSERT(cacheKind_ == CacheKind::GetElem || cacheKind_ == CacheKind::GetElemSuper);
    1161        1524 :         return ValOperandId(1);
    1162             :     }
    1163             : 
    1164           0 :     ValOperandId getSuperReceiverValueId() const {
    1165           0 :         if (cacheKind_ == CacheKind::GetPropSuper)
    1166           0 :             return ValOperandId(1);
    1167             : 
    1168           0 :         MOZ_ASSERT(cacheKind_ == CacheKind::GetElemSuper);
    1169           0 :         return ValOperandId(2);
    1170             :     }
    1171             : 
    1172        4615 :     bool isSuper() const {
    1173        9230 :         return (cacheKind_ == CacheKind::GetPropSuper ||
    1174        9230 :                 cacheKind_ == CacheKind::GetElemSuper);
    1175             :     }
    1176             : 
    1177             :     // No pc if idempotent, as there can be multiple bytecode locations
    1178             :     // due to GVN.
    1179        7992 :     bool idempotent() const { return pc_ == nullptr; }
    1180             : 
    1181             :     // If this is a GetElem cache, emit instructions to guard the incoming Value
    1182             :     // matches |id|.
    1183             :     void maybeEmitIdGuard(jsid id);
    1184             : 
    1185             :     void trackAttached(const char* name);
    1186             :     void trackNotAttached();
    1187             : 
    1188             :   public:
    1189             :     GetPropIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, CacheKind cacheKind,
    1190             :                        ICState::Mode mode, bool* isTemporarilyUnoptimizable, HandleValue val,
    1191             :                        HandleValue idVal, HandleValue receiver, CanAttachGetter canAttachGetter);
    1192             : 
    1193             :     bool tryAttachStub();
    1194             :     bool tryAttachIdempotentStub();
    1195             : 
    1196        3242 :     bool shouldUnlinkPreliminaryObjectStubs() const {
    1197        3242 :         return preliminaryObjectAction_ == PreliminaryObjectAction::Unlink;
    1198             :     }
    1199        3669 :     bool shouldNotePreliminaryObjectStub() const {
    1200        3669 :         return preliminaryObjectAction_ == PreliminaryObjectAction::NotePreliminary;
    1201             :     }
    1202             : };
    1203             : 
    1204             : // GetNameIRGenerator generates CacheIR for a GetName IC.
    1205         977 : class MOZ_RAII GetNameIRGenerator : public IRGenerator
    1206             : {
    1207             :     HandleObject env_;
    1208             :     HandlePropertyName name_;
    1209             : 
    1210             :     bool tryAttachGlobalNameValue(ObjOperandId objId, HandleId id);
    1211             :     bool tryAttachGlobalNameGetter(ObjOperandId objId, HandleId id);
    1212             :     bool tryAttachEnvironmentName(ObjOperandId objId, HandleId id);
    1213             : 
    1214             :     void trackAttached(const char* name);
    1215             :     void trackNotAttached();
    1216             : 
    1217             :   public:
    1218             :     GetNameIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, ICState::Mode mode,
    1219             :                        HandleObject env, HandlePropertyName name);
    1220             : 
    1221             :     bool tryAttachStub();
    1222             : };
    1223             : 
    1224             : // BindNameIRGenerator generates CacheIR for a BindName IC.
    1225           0 : class MOZ_RAII BindNameIRGenerator : public IRGenerator
    1226             : {
    1227             :     HandleObject env_;
    1228             :     HandlePropertyName name_;
    1229             : 
    1230             :     bool tryAttachGlobalName(ObjOperandId objId, HandleId id);
    1231             :     bool tryAttachEnvironmentName(ObjOperandId objId, HandleId id);
    1232             : 
    1233             :     void trackAttached(const char* name);
    1234             :     void trackNotAttached();
    1235             : 
    1236             :   public:
    1237             :     BindNameIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, ICState::Mode mode,
    1238             :                         HandleObject env, HandlePropertyName name);
    1239             : 
    1240             :     bool tryAttachStub();
    1241             : };
    1242             : 
    1243             : // Information used by SetProp/SetElem stubs to check/update property types.
    1244        1705 : class MOZ_RAII PropertyTypeCheckInfo
    1245             : {
    1246             :     RootedObjectGroup group_;
    1247             :     RootedId id_;
    1248             :     bool needsTypeBarrier_;
    1249             : 
    1250             :     PropertyTypeCheckInfo(const PropertyTypeCheckInfo&) = delete;
    1251             :     void operator=(const PropertyTypeCheckInfo&) = delete;
    1252             : 
    1253             :   public:
    1254        1705 :     PropertyTypeCheckInfo(JSContext* cx, bool needsTypeBarrier)
    1255        1705 :       : group_(cx), id_(cx), needsTypeBarrier_(needsTypeBarrier)
    1256        1705 :     {}
    1257             : 
    1258         544 :     bool needsTypeBarrier() const { return needsTypeBarrier_; }
    1259        3137 :     bool isSet() const { return group_ != nullptr; }
    1260        1034 :     ObjectGroup* group() const { MOZ_ASSERT(isSet()); return group_; }
    1261        1034 :     jsid id() const { MOZ_ASSERT(isSet()); return id_; }
    1262             : 
    1263        1035 :     void set(ObjectGroup* group, jsid id) {
    1264        1035 :         MOZ_ASSERT(!group_);
    1265        1035 :         MOZ_ASSERT(group);
    1266        1035 :         if (needsTypeBarrier_) {
    1267        1035 :             group_ = group;
    1268        1035 :             id_ = id;
    1269             :         }
    1270        1035 :     }
    1271             : };
    1272             : 
    1273             : // SetPropIRGenerator generates CacheIR for a SetProp IC.
    1274        1705 : class MOZ_RAII SetPropIRGenerator : public IRGenerator
    1275             : {
    1276             :     HandleValue lhsVal_;
    1277             :     HandleValue idVal_;
    1278             :     HandleValue rhsVal_;
    1279             :     bool* isTemporarilyUnoptimizable_;
    1280             :     PropertyTypeCheckInfo typeCheckInfo_;
    1281             : 
    1282             :     enum class PreliminaryObjectAction { None, Unlink, NotePreliminary };
    1283             :     PreliminaryObjectAction preliminaryObjectAction_;
    1284             :     bool attachedTypedArrayOOBStub_;
    1285             : 
    1286             :     bool maybeHasExtraIndexedProps_;
    1287             : 
    1288        1258 :     ValOperandId setElemKeyValueId() const {
    1289        1258 :         MOZ_ASSERT(cacheKind_ == CacheKind::SetElem);
    1290        1258 :         return ValOperandId(1);
    1291             :     }
    1292             :     ValOperandId rhsValueId() const {
    1293             :         if (cacheKind_ == CacheKind::SetProp)
    1294             :             return ValOperandId(1);
    1295             :         MOZ_ASSERT(cacheKind_ == CacheKind::SetElem);
    1296             :         return ValOperandId(2);
    1297             :     }
    1298             : 
    1299             :     // If this is a SetElem cache, emit instructions to guard the incoming Value
    1300             :     // matches |id|.
    1301             :     void maybeEmitIdGuard(jsid id);
    1302             : 
    1303             :     bool tryAttachNativeSetSlot(HandleObject obj, ObjOperandId objId, HandleId id,
    1304             :                                  ValOperandId rhsId);
    1305             :     bool tryAttachUnboxedExpandoSetSlot(HandleObject obj, ObjOperandId objId, HandleId id,
    1306             :                                         ValOperandId rhsId);
    1307             :     bool tryAttachUnboxedProperty(HandleObject obj, ObjOperandId objId, HandleId id,
    1308             :                                   ValOperandId rhsId);
    1309             :     bool tryAttachTypedObjectProperty(HandleObject obj, ObjOperandId objId, HandleId id,
    1310             :                                       ValOperandId rhsId);
    1311             :     bool tryAttachSetter(HandleObject obj, ObjOperandId objId, HandleId id,
    1312             :                          ValOperandId rhsId);
    1313             :     bool tryAttachSetArrayLength(HandleObject obj, ObjOperandId objId, HandleId id,
    1314             :                                  ValOperandId rhsId);
    1315             :     bool tryAttachWindowProxy(HandleObject obj, ObjOperandId objId, HandleId id,
    1316             :                               ValOperandId rhsId);
    1317             : 
    1318             :     bool tryAttachSetDenseElement(HandleObject obj, ObjOperandId objId, uint32_t index,
    1319             :                                   Int32OperandId indexId, ValOperandId rhsId);
    1320             :     bool tryAttachSetUnboxedArrayElement(HandleObject obj, ObjOperandId objId, uint32_t index,
    1321             :                                          Int32OperandId indexId, ValOperandId rhsId);    
    1322             :     bool tryAttachSetTypedElement(HandleObject obj, ObjOperandId objId, uint32_t index,
    1323             :                                   Int32OperandId indexId, ValOperandId rhsId);
    1324             : 
    1325             :     bool tryAttachSetDenseElementHole(HandleObject obj, ObjOperandId objId, uint32_t index,
    1326             :                                       Int32OperandId indexId, ValOperandId rhsId);
    1327             :     bool tryAttachSetUnboxedArrayElementHole(HandleObject obj, ObjOperandId objId, uint32_t index,
    1328             :                                              Int32OperandId indexId, ValOperandId rhsId);
    1329             : 
    1330             :     bool tryAttachGenericProxy(HandleObject obj, ObjOperandId objId, HandleId id,
    1331             :                                ValOperandId rhsId, bool handleDOMProxies);
    1332             :     bool tryAttachDOMProxyShadowed(HandleObject obj, ObjOperandId objId, HandleId id,
    1333             :                                    ValOperandId rhsId);
    1334             :     bool tryAttachDOMProxyUnshadowed(HandleObject obj, ObjOperandId objId, HandleId id,
    1335             :                                      ValOperandId rhsId);
    1336             :     bool tryAttachDOMProxyExpando(HandleObject obj, ObjOperandId objId, HandleId id,
    1337             :                                   ValOperandId rhsId);
    1338             :     bool tryAttachProxy(HandleObject obj, ObjOperandId objId, HandleId id, ValOperandId rhsId);
    1339             :     bool tryAttachProxyElement(HandleObject obj, ObjOperandId objId, ValOperandId rhsId);
    1340             : 
    1341             :     void trackAttached(const char* name);
    1342             : 
    1343             :   public:
    1344             :     SetPropIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, CacheKind cacheKind,
    1345             :                        ICState::Mode mode, bool* isTemporarilyUnoptimizable, HandleValue lhsVal,
    1346             :                        HandleValue idVal, HandleValue rhsVal, bool needsTypeBarrier = true,
    1347             :                        bool maybeHasExtraIndexedProps = true);
    1348             : 
    1349             :     bool tryAttachStub();
    1350             :     bool tryAttachAddSlotStub(HandleObjectGroup oldGroup, HandleShape oldShape);
    1351             :     void trackNotAttached();
    1352             : 
    1353         605 :     bool shouldUnlinkPreliminaryObjectStubs() const {
    1354         605 :         return preliminaryObjectAction_ == PreliminaryObjectAction::Unlink;
    1355             :     }
    1356        1069 :     bool shouldNotePreliminaryObjectStub() const {
    1357        1069 :         return preliminaryObjectAction_ == PreliminaryObjectAction::NotePreliminary;
    1358             :     }
    1359             : 
    1360        1069 :     const PropertyTypeCheckInfo* typeCheckInfo() const {
    1361        1069 :         return &typeCheckInfo_;
    1362             :     }
    1363             : 
    1364         146 :     bool attachedTypedArrayOOBStub() const {
    1365         146 :         return attachedTypedArrayOOBStub_;
    1366             :     }
    1367             : };
    1368             : 
    1369             : // HasPropIRGenerator generates CacheIR for a HasProp IC. Used for
    1370             : // CacheKind::In / CacheKind::HasOwn.
    1371         184 : class MOZ_RAII HasPropIRGenerator : public IRGenerator
    1372             : {
    1373             :     HandleValue val_;
    1374             :     HandleValue idVal_;
    1375             : 
    1376             :     bool tryAttachDense(HandleObject obj, ObjOperandId objId,
    1377             :                         uint32_t index, Int32OperandId indexId);
    1378             :     bool tryAttachDenseHole(HandleObject obj, ObjOperandId objId,
    1379             :                             uint32_t index, Int32OperandId indexId);
    1380             :     bool tryAttachNative(HandleObject obj, ObjOperandId objId,
    1381             :                          HandleId key, ValOperandId keyId);
    1382             :     bool tryAttachNativeDoesNotExist(HandleObject obj, ObjOperandId objId,
    1383             :                                      HandleId key, ValOperandId keyId);
    1384             :     bool tryAttachProxyElement(HandleObject obj, ObjOperandId objId,
    1385             :                                ValOperandId keyId);
    1386             : 
    1387             :     void trackAttached(const char* name);
    1388             :     void trackNotAttached();
    1389             : 
    1390             :   public:
    1391             :     // NOTE: Argument order is PROPERTY, OBJECT
    1392             :     HasPropIRGenerator(JSContext* cx, HandleScript script, jsbytecode* pc, CacheKind cacheKind,
    1393             :                        ICState::Mode mode, HandleValue idVal, HandleValue val);
    1394             : 
    1395             :     bool tryAttachStub();
    1396             : };
    1397             : 
    1398          80 : class MOZ_RAII TypeOfIRGenerator : public IRGenerator
    1399             : {
    1400             :     HandleValue val_;
    1401             : 
    1402             :     bool tryAttachPrimitive(ValOperandId valId);
    1403             :     bool tryAttachObject(ValOperandId valId);
    1404             : 
    1405             :   public:
    1406             :     TypeOfIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode, HandleValue value);
    1407             : 
    1408             :     bool tryAttachStub();
    1409             : };
    1410             : 
    1411        3981 : class MOZ_RAII CallIRGenerator : public IRGenerator
    1412             : {
    1413             :   public:
    1414             :     enum class OptStrategy {
    1415             :         None = 0,
    1416             :         StringSplit
    1417             :     };
    1418             : 
    1419             :   private:
    1420             :     uint32_t argc_;
    1421             :     HandleValue callee_;
    1422             :     HandleValue thisval_;
    1423             :     HandleValueArray args_;
    1424             : 
    1425             :     mozilla::Maybe<OptStrategy> cachedStrategy_;
    1426             : 
    1427             :     OptStrategy canOptimize();
    1428             :     OptStrategy canOptimizeStringSplit(HandleFunction calleeFunc);
    1429             :     bool tryAttachStringSplit();
    1430             : 
    1431             :   public:
    1432             :     CallIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode,
    1433             :                     uint32_t argc, HandleValue callee, HandleValue thisval,
    1434             :                     HandleValueArray args);
    1435             : 
    1436             :     OptStrategy getOptStrategy(bool* optimizeAfterCall = nullptr);
    1437             :     bool tryAttachStub();
    1438             : };
    1439             : 
    1440         998 : class MOZ_RAII CompareIRGenerator : public IRGenerator
    1441             : {
    1442             :     JSOp op_;
    1443             :     HandleValue lhsVal_;
    1444             :     HandleValue rhsVal_;
    1445             : 
    1446             :     bool tryAttachString(ValOperandId lhsId, ValOperandId rhsId);
    1447             :     bool tryAttachObject(ValOperandId lhsId, ValOperandId rhsId);
    1448             :     bool tryAttachSymbol(ValOperandId lhsId, ValOperandId rhsId);
    1449             : 
    1450             :     void trackAttached(const char* name);
    1451             :     void trackNotAttached();
    1452             : 
    1453             :   public:
    1454             :     CompareIRGenerator(JSContext* cx, HandleScript, jsbytecode* pc, ICState::Mode mode,
    1455             :                        JSOp op, HandleValue lhsVal, HandleValue rhsVal);
    1456             : 
    1457             :     bool tryAttachStub();
    1458             : };
    1459             : 
    1460             : } // namespace jit
    1461             : } // namespace js
    1462             : 
    1463             : #endif /* jit_CacheIR_h */

Generated by: LCOV version 1.13