LCOV - code coverage report
Current view: top level - js/src/builtin - TypedObject.h (source / functions) Hit Total Coverage
Test: output.info Lines: 41 128 32.0 %
Date: 2017-07-14 16:53:18 Functions: 14 57 24.6 %
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 builtin_TypedObject_h
       8             : #define builtin_TypedObject_h
       9             : 
      10             : #include "jsobj.h"
      11             : #include "jsweakmap.h"
      12             : 
      13             : #include "builtin/TypedObjectConstants.h"
      14             : #include "js/Conversions.h"
      15             : #include "vm/ArrayBufferObject.h"
      16             : #include "vm/ShapedObject.h"
      17             : 
      18             : /*
      19             :  * -------------
      20             :  * Typed Objects
      21             :  * -------------
      22             :  *
      23             :  * Typed objects are a special kind of JS object where the data is
      24             :  * given well-structured form. To use a typed object, users first
      25             :  * create *type objects* (no relation to the type objects used in TI)
      26             :  * that define the type layout. For example, a statement like:
      27             :  *
      28             :  *    var PointType = new StructType({x: uint8, y: uint8});
      29             :  *
      30             :  * would create a type object PointType that is a struct with
      31             :  * two fields, each of uint8 type.
      32             :  *
      33             :  * This comment typically assumes familiary with the API.  For more
      34             :  * info on the API itself, see the Harmony wiki page at
      35             :  * http://wiki.ecmascript.org/doku.php?id=harmony:typed_objects or the
      36             :  * ES6 spec (not finalized at the time of this writing).
      37             :  *
      38             :  * - Initialization:
      39             :  *
      40             :  * Currently, all "globals" related to typed objects are packaged
      41             :  * within a single "module" object `TypedObject`. This module has its
      42             :  * own js::Class and when that class is initialized, we also create
      43             :  * and define all other values (in `js::InitTypedObjectModuleClass()`).
      44             :  *
      45             :  * - Type objects, meta type objects, and type representations:
      46             :  *
      47             :  * There are a number of pre-defined type objects, one for each
      48             :  * scalar type (`uint8` etc). Each of these has its own class_,
      49             :  * defined in `DefineNumericClass()`.
      50             :  *
      51             :  * There are also meta type objects (`ArrayType`, `StructType`).
      52             :  * These constructors are not themselves type objects but rather the
      53             :  * means for the *user* to construct new typed objects.
      54             :  *
      55             :  * Each type object is associated with a *type representation* (see
      56             :  * TypeRepresentation.h). Type representations are canonical versions
      57             :  * of type objects. We attach them to TI type objects and (eventually)
      58             :  * use them for shape guards etc. They are purely internal to the
      59             :  * engine and are not exposed to end users (though self-hosted code
      60             :  * sometimes accesses them).
      61             :  *
      62             :  * - Typed objects:
      63             :  *
      64             :  * A typed object is an instance of a *type object* (note the past participle).
      65             :  * Typed objects can be either transparent or opaque, depending on whether
      66             :  * their underlying buffer can be accessed. Transparent and opaque typed
      67             :  * objects have different classes, and can have different physical layouts.
      68             :  * The following layouts are possible:
      69             :  *
      70             :  * InlineTypedObject: Typed objects whose data immediately follows the object's
      71             :  *   header are inline typed objects. The buffer for these objects is created
      72             :  *   lazily and stored via the compartment's LazyArrayBufferTable, and points
      73             :  *   back into the object's internal data.
      74             :  *
      75             :  * OutlineTypedObject: Typed objects whose data is owned by another object,
      76             :  *   which can be either an array buffer or an inline typed object. Outline
      77             :  *   typed objects may be attached or unattached. An unattached typed object
      78             :  *   has no data associated with it. When first created, objects are always
      79             :  *   attached, but they can become unattached if their buffer becomes detached.
      80             :  *
      81             :  * Note that whether a typed object is opaque is not directly
      82             :  * connected to its type. That is, opaque types are *always*
      83             :  * represented by opaque typed objects, but you may have opaque typed
      84             :  * objects for transparent types too. This can occur for two reasons:
      85             :  * (1) a transparent type may be embedded within an opaque type or (2)
      86             :  * users can choose to convert transparent typed objects into opaque
      87             :  * ones to avoid giving access to the buffer itself.
      88             :  *
      89             :  * Typed objects (no matter their class) are non-native objects that
      90             :  * fully override the property accessors etc. The overridden accessor
      91             :  * methods are the same in each and are defined in methods of
      92             :  * TypedObject.
      93             :  */
      94             : 
      95             : namespace js {
      96             : 
      97             : /*
      98             :  * Helper method for converting a double into other scalar
      99             :  * types in the same way that JavaScript would. In particular,
     100             :  * simple C casting from double to int32_t gets things wrong
     101             :  * for values like 0xF0000000.
     102             :  */
     103             : template <typename T>
     104           0 : static T ConvertScalar(double d)
     105             : {
     106           0 :     if (TypeIsFloatingPoint<T>())
     107           0 :         return T(d);
     108           0 :     if (TypeIsUnsigned<T>()) {
     109           0 :         uint32_t n = JS::ToUint32(d);
     110           0 :         return T(n);
     111             :     }
     112           0 :     int32_t n = JS::ToInt32(d);
     113           0 :     return T(n);
     114             : }
     115             : 
     116             : namespace type {
     117             : 
     118             : enum Kind {
     119             :     Scalar = JS_TYPEREPR_SCALAR_KIND,
     120             :     Reference = JS_TYPEREPR_REFERENCE_KIND,
     121             :     Simd = JS_TYPEREPR_SIMD_KIND,
     122             :     Struct = JS_TYPEREPR_STRUCT_KIND,
     123             :     Array = JS_TYPEREPR_ARRAY_KIND
     124             : };
     125             : 
     126             : } // namespace type
     127             : 
     128             : ///////////////////////////////////////////////////////////////////////////
     129             : // Typed Prototypes
     130             : 
     131             : class SimpleTypeDescr;
     132             : class ComplexTypeDescr;
     133             : class SimdTypeDescr;
     134             : class StructTypeDescr;
     135             : class TypedProto;
     136             : 
     137             : /*
     138             :  * The prototype for a typed object.
     139             :  */
     140             : class TypedProto : public NativeObject
     141             : {
     142             :   public:
     143             :     static const Class class_;
     144             : };
     145             : 
     146             : class TypeDescr : public NativeObject
     147             : {
     148             :   public:
     149           0 :     TypedProto& typedProto() const {
     150           0 :         return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>();
     151             :     }
     152             : 
     153           0 :     JSAtom& stringRepr() const {
     154           0 :         return getReservedSlot(JS_DESCR_SLOT_STRING_REPR).toString()->asAtom();
     155             :     }
     156             : 
     157          18 :     type::Kind kind() const {
     158          18 :         return (type::Kind) getReservedSlot(JS_DESCR_SLOT_KIND).toInt32();
     159             :     }
     160             : 
     161         162 :     bool opaque() const {
     162         162 :         return getReservedSlot(JS_DESCR_SLOT_OPAQUE).toBoolean();
     163             :     }
     164             : 
     165         162 :     bool transparent() const {
     166         162 :         return !opaque();
     167             :     }
     168             : 
     169          54 :     uint32_t alignment() const {
     170          54 :         int32_t i = getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
     171          54 :         MOZ_ASSERT(i >= 0);
     172          54 :         return uint32_t(i);
     173             :     }
     174             : 
     175         126 :     uint32_t size() const {
     176         126 :         int32_t i = getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
     177         126 :         MOZ_ASSERT(i >= 0);
     178         126 :         return uint32_t(i);
     179             :     }
     180             : 
     181             :     // Whether id is an 'own' property of objects with this descriptor.
     182             :     MOZ_MUST_USE bool hasProperty(const JSAtomState& names, jsid id);
     183             : 
     184             :     // Type descriptors may contain a list of their references for use during
     185             :     // scanning. Marking code is optimized to use this list to mark inline
     186             :     // typed objects, rather than the slower trace hook. This list is only
     187             :     // specified when (a) the descriptor is short enough that it can fit in an
     188             :     // InlineTypedObject, and (b) the descriptor contains at least one
     189             :     // reference. Otherwise its value is undefined.
     190             :     //
     191             :     // The list is three consecutive arrays of int32_t offsets, with each array
     192             :     // terminated by -1. The arrays store offsets of string, object, and value
     193             :     // references in the descriptor, in that order.
     194           0 :     MOZ_MUST_USE bool hasTraceList() const {
     195           0 :         return !getFixedSlot(JS_DESCR_SLOT_TRACE_LIST).isUndefined();
     196             :     }
     197           0 :     const int32_t* traceList() const {
     198           0 :         MOZ_ASSERT(hasTraceList());
     199           0 :         return reinterpret_cast<int32_t*>(getFixedSlot(JS_DESCR_SLOT_TRACE_LIST).toPrivate());
     200             :     }
     201             : 
     202             :     void initInstances(const JSRuntime* rt, uint8_t* mem, size_t length);
     203             :     void traceInstances(JSTracer* trace, uint8_t* mem, size_t length);
     204             : 
     205             :     static void finalize(FreeOp* fop, JSObject* obj);
     206             : };
     207             : 
     208             : typedef Handle<TypeDescr*> HandleTypeDescr;
     209             : 
     210             : class SimpleTypeDescr : public TypeDescr
     211             : {
     212             : };
     213             : 
     214             : // Type for scalar type constructors like `uint8`. All such type
     215             : // constructors share a common js::Class and JSFunctionSpec. Scalar
     216             : // types are non-opaque (their storage is visible unless combined with
     217             : // an opaque reference type.)
     218             : class ScalarTypeDescr : public SimpleTypeDescr
     219             : {
     220             :   public:
     221             :     typedef Scalar::Type Type;
     222             : 
     223             :     static const type::Kind Kind = type::Scalar;
     224             :     static const bool Opaque = false;
     225             :     static uint32_t size(Type t);
     226             :     static uint32_t alignment(Type t);
     227             :     static const char* typeName(Type type);
     228             : 
     229             :     static const Class class_;
     230             :     static const JSFunctionSpec typeObjectMethods[];
     231             : 
     232           0 :     Type type() const {
     233             :         // Make sure the values baked into TypedObjectConstants.h line up with
     234             :         // the Scalar::Type enum. We don't define Scalar::Type directly in
     235             :         // terms of these constants to avoid making TypedObjectConstants.h a
     236             :         // public header file.
     237             :         static_assert(Scalar::Int8 == JS_SCALARTYPEREPR_INT8,
     238             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     239             :         static_assert(Scalar::Uint8 == JS_SCALARTYPEREPR_UINT8,
     240             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     241             :         static_assert(Scalar::Int16 == JS_SCALARTYPEREPR_INT16,
     242             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     243             :         static_assert(Scalar::Uint16 == JS_SCALARTYPEREPR_UINT16,
     244             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     245             :         static_assert(Scalar::Int32 == JS_SCALARTYPEREPR_INT32,
     246             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     247             :         static_assert(Scalar::Uint32 == JS_SCALARTYPEREPR_UINT32,
     248             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     249             :         static_assert(Scalar::Float32 == JS_SCALARTYPEREPR_FLOAT32,
     250             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     251             :         static_assert(Scalar::Float64 == JS_SCALARTYPEREPR_FLOAT64,
     252             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     253             :         static_assert(Scalar::Uint8Clamped == JS_SCALARTYPEREPR_UINT8_CLAMPED,
     254             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     255             :         static_assert(Scalar::Float32x4 == JS_SCALARTYPEREPR_FLOAT32X4,
     256             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     257             :         static_assert(Scalar::Int8x16 == JS_SCALARTYPEREPR_INT8X16,
     258             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     259             :         static_assert(Scalar::Int16x8 == JS_SCALARTYPEREPR_INT16X8,
     260             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     261             :         static_assert(Scalar::Int32x4 == JS_SCALARTYPEREPR_INT32X4,
     262             :                       "TypedObjectConstants.h must be consistent with Scalar::Type");
     263             : 
     264           0 :         return Type(getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32());
     265             :     }
     266             : 
     267             :     static MOZ_MUST_USE bool call(JSContext* cx, unsigned argc, Value* vp);
     268             : };
     269             : 
     270             : // Enumerates the cases of ScalarTypeDescr::Type which have
     271             : // unique C representation. In particular, omits Uint8Clamped since it
     272             : // is just a Uint8.
     273             : #define JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_)       \
     274             :     macro_(Scalar::Int8,    int8_t,   int8)                     \
     275             :     macro_(Scalar::Uint8,   uint8_t,  uint8)                    \
     276             :     macro_(Scalar::Int16,   int16_t,  int16)                    \
     277             :     macro_(Scalar::Uint16,  uint16_t, uint16)                   \
     278             :     macro_(Scalar::Int32,   int32_t,  int32)                    \
     279             :     macro_(Scalar::Uint32,  uint32_t, uint32)                   \
     280             :     macro_(Scalar::Float32, float,    float32)                  \
     281             :     macro_(Scalar::Float64, double,   float64)
     282             : 
     283             : // Must be in same order as the enum ScalarTypeDescr::Type:
     284             : #define JS_FOR_EACH_SCALAR_TYPE_REPR(macro_)                    \
     285             :     JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_)           \
     286             :     macro_(Scalar::Uint8Clamped, uint8_t, uint8Clamped)
     287             : 
     288             : // Type for reference type constructors like `Any`, `String`, and
     289             : // `Object`. All such type constructors share a common js::Class and
     290             : // JSFunctionSpec. All these types are opaque.
     291             : class ReferenceTypeDescr : public SimpleTypeDescr
     292             : {
     293             :   public:
     294             :     // Must match order of JS_FOR_EACH_REFERENCE_TYPE_REPR below
     295             :     enum Type {
     296             :         TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
     297             :         TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
     298             :         TYPE_STRING = JS_REFERENCETYPEREPR_STRING,
     299             :     };
     300             :     static const int32_t TYPE_MAX = TYPE_STRING + 1;
     301             :     static const char* typeName(Type type);
     302             : 
     303             :     static const type::Kind Kind = type::Reference;
     304             :     static const bool Opaque = true;
     305             :     static const Class class_;
     306             :     static uint32_t size(Type t);
     307             :     static uint32_t alignment(Type t);
     308             :     static const JSFunctionSpec typeObjectMethods[];
     309             : 
     310          18 :     ReferenceTypeDescr::Type type() const {
     311          18 :         return (ReferenceTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
     312             :     }
     313             : 
     314           0 :     const char* typeName() const {
     315           0 :         return typeName(type());
     316             :     }
     317             : 
     318             :     static MOZ_MUST_USE bool call(JSContext* cx, unsigned argc, Value* vp);
     319             : };
     320             : 
     321             : #define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_) \
     322             :     macro_(ReferenceTypeDescr::TYPE_ANY, GCPtrValue, Any) \
     323             :     macro_(ReferenceTypeDescr::TYPE_OBJECT, GCPtrObject, Object) \
     324             :     macro_(ReferenceTypeDescr::TYPE_STRING, GCPtrString, string)
     325             : 
     326             : // Type descriptors whose instances are objects and hence which have
     327             : // an associated `prototype` property.
     328             : class ComplexTypeDescr : public TypeDescr
     329             : {
     330             :   public:
     331             :     // Returns the prototype that instances of this type descriptor
     332             :     // will have.
     333           0 :     TypedProto& instancePrototype() const {
     334           0 :         return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>();
     335             :     }
     336             : };
     337             : 
     338             : enum class SimdType;
     339             : 
     340             : /*
     341             :  * SIMD Type descriptors.
     342             :  */
     343             : class SimdTypeDescr : public ComplexTypeDescr
     344             : {
     345             :   public:
     346             :     static const type::Kind Kind = type::Simd;
     347             :     static const bool Opaque = false;
     348             :     static const Class class_;
     349             :     static uint32_t size(SimdType t);
     350             :     static uint32_t alignment(SimdType t);
     351             :     static MOZ_MUST_USE bool call(JSContext* cx, unsigned argc, Value* vp);
     352             :     static bool is(const Value& v);
     353             : 
     354             :     SimdType type() const;
     355             : };
     356             : 
     357             : bool IsTypedObjectClass(const Class* clasp); // Defined below
     358             : bool IsTypedObjectArray(JSObject& obj);
     359             : 
     360             : MOZ_MUST_USE bool CreateUserSizeAndAlignmentProperties(JSContext* cx, HandleTypeDescr obj);
     361             : 
     362             : class ArrayTypeDescr;
     363             : 
     364             : /*
     365             :  * Properties and methods of the `ArrayType` meta type object. There
     366             :  * is no `class_` field because `ArrayType` is just a native
     367             :  * constructor function.
     368             :  */
     369             : class ArrayMetaTypeDescr : public NativeObject
     370             : {
     371             :   private:
     372             :     // Helper for creating a new ArrayType object.
     373             :     //
     374             :     // - `arrayTypePrototype` - prototype for the new object to be created
     375             :     // - `elementType` - type object for the elements in the array
     376             :     // - `stringRepr` - canonical string representation for the array
     377             :     // - `size` - length of the array
     378             :     static ArrayTypeDescr* create(JSContext* cx,
     379             :                                   HandleObject arrayTypePrototype,
     380             :                                   HandleTypeDescr elementType,
     381             :                                   HandleAtom stringRepr,
     382             :                                   int32_t size,
     383             :                                   int32_t length);
     384             : 
     385             :   public:
     386             :     // Properties and methods to be installed on ArrayType.prototype,
     387             :     // and hence inherited by all array type objects:
     388             :     static const JSPropertySpec typeObjectProperties[];
     389             :     static const JSFunctionSpec typeObjectMethods[];
     390             : 
     391             :     // Properties and methods to be installed on ArrayType.prototype.prototype,
     392             :     // and hence inherited by all array *typed* objects:
     393             :     static const JSPropertySpec typedObjectProperties[];
     394             :     static const JSFunctionSpec typedObjectMethods[];
     395             : 
     396             :     // This is the function that gets called when the user
     397             :     // does `new ArrayType(elem)`. It produces an array type object.
     398             :     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
     399             : };
     400             : 
     401             : /*
     402             :  * Type descriptor created by `new ArrayType(type, n)`
     403             :  */
     404             : class ArrayTypeDescr : public ComplexTypeDescr
     405             : {
     406             :   public:
     407             :     static const Class class_;
     408             :     static const type::Kind Kind = type::Array;
     409             : 
     410           0 :     TypeDescr& elementType() const {
     411           0 :         return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<TypeDescr>();
     412             :     }
     413             : 
     414           0 :     uint32_t length() const {
     415           0 :         int32_t i = getReservedSlot(JS_DESCR_SLOT_ARRAY_LENGTH).toInt32();
     416           0 :         MOZ_ASSERT(i >= 0);
     417           0 :         return uint32_t(i);
     418             :     }
     419             : 
     420           0 :     static int32_t offsetOfLength() {
     421           0 :         return getFixedSlotOffset(JS_DESCR_SLOT_ARRAY_LENGTH);
     422             :     }
     423             : };
     424             : 
     425             : /*
     426             :  * Properties and methods of the `StructType` meta type object. There
     427             :  * is no `class_` field because `StructType` is just a native
     428             :  * constructor function.
     429             :  */
     430             : class StructMetaTypeDescr : public NativeObject
     431             : {
     432             :   private:
     433             :     static JSObject* create(JSContext* cx, HandleObject structTypeGlobal,
     434             :                             HandleObject fields);
     435             : 
     436             :   public:
     437             :     // Properties and methods to be installed on StructType.prototype,
     438             :     // and hence inherited by all struct type objects:
     439             :     static const JSPropertySpec typeObjectProperties[];
     440             :     static const JSFunctionSpec typeObjectMethods[];
     441             : 
     442             :     // Properties and methods to be installed on StructType.prototype.prototype,
     443             :     // and hence inherited by all struct *typed* objects:
     444             :     static const JSPropertySpec typedObjectProperties[];
     445             :     static const JSFunctionSpec typedObjectMethods[];
     446             : 
     447             :     // This is the function that gets called when the user
     448             :     // does `new StructType(...)`. It produces a struct type object.
     449             :     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
     450             : };
     451             : 
     452             : class StructTypeDescr : public ComplexTypeDescr
     453             : {
     454             :   public:
     455             :     static const Class class_;
     456             : 
     457             :     // Returns the number of fields defined in this struct.
     458             :     size_t fieldCount() const;
     459             : 
     460             :     // Set `*out` to the index of the field named `id` and returns true,
     461             :     // or return false if no such field exists.
     462             :     MOZ_MUST_USE bool fieldIndex(jsid id, size_t* out) const;
     463             : 
     464             :     // Return the name of the field at index `index`.
     465             :     JSAtom& fieldName(size_t index) const;
     466             : 
     467             :     // Return the type descr of the field at index `index`.
     468             :     TypeDescr& fieldDescr(size_t index) const;
     469             : 
     470             :     // Return the offset of the field at index `index`.
     471             :     size_t fieldOffset(size_t index) const;
     472             : 
     473             :   private:
     474           0 :     ArrayObject& fieldInfoObject(size_t slot) const {
     475           0 :         return getReservedSlot(slot).toObject().as<ArrayObject>();
     476             :     }
     477             : };
     478             : 
     479             : typedef Handle<StructTypeDescr*> HandleStructTypeDescr;
     480             : 
     481             : /*
     482             :  * This object exists in order to encapsulate the typed object types
     483             :  * somewhat, rather than sticking them all into the global object.
     484             :  * Eventually it will go away and become a module.
     485             :  */
     486             : class TypedObjectModuleObject : public NativeObject {
     487             :   public:
     488             :     enum Slot {
     489             :         ArrayTypePrototype,
     490             :         StructTypePrototype,
     491             :         SlotCount
     492             :     };
     493             : 
     494             :     static const Class class_;
     495             : };
     496             : 
     497             : /* Base type for transparent and opaque typed objects. */
     498             : class TypedObject : public ShapedObject
     499             : {
     500             :     static const bool IsTypedObjectClass = true;
     501             : 
     502             :     static MOZ_MUST_USE bool obj_getArrayElement(JSContext* cx,
     503             :                                                  Handle<TypedObject*> typedObj,
     504             :                                                  Handle<TypeDescr*> typeDescr,
     505             :                                                  uint32_t index,
     506             :                                                  MutableHandleValue vp);
     507             : 
     508             :   protected:
     509             :     static const ObjectOps objectOps_;
     510             : 
     511             :     static MOZ_MUST_USE bool obj_lookupProperty(JSContext* cx, HandleObject obj,
     512             :                                                 HandleId id, MutableHandleObject objp,
     513             :                                                 MutableHandle<PropertyResult> propp);
     514             : 
     515             :     static MOZ_MUST_USE bool obj_defineProperty(JSContext* cx, HandleObject obj, HandleId id,
     516             :                                                 Handle<PropertyDescriptor> desc,
     517             :                                                 ObjectOpResult& result);
     518             : 
     519             :     static MOZ_MUST_USE bool obj_hasProperty(JSContext* cx, HandleObject obj, HandleId id,
     520             :                                              bool* foundp);
     521             : 
     522             :     static MOZ_MUST_USE bool obj_getProperty(JSContext* cx, HandleObject obj, HandleValue receiver,
     523             :                                              HandleId id, MutableHandleValue vp);
     524             : 
     525             :     static MOZ_MUST_USE bool obj_getElement(JSContext* cx, HandleObject obj, HandleValue receiver,
     526             :                                             uint32_t index, MutableHandleValue vp);
     527             : 
     528             :     static MOZ_MUST_USE bool obj_setProperty(JSContext* cx, HandleObject obj, HandleId id,
     529             :                                              HandleValue v, HandleValue receiver,
     530             :                                              ObjectOpResult& result);
     531             : 
     532             :     static MOZ_MUST_USE bool obj_getOwnPropertyDescriptor(JSContext* cx, HandleObject obj,
     533             :                                                           HandleId id,
     534             :                                                           MutableHandle<PropertyDescriptor> desc);
     535             : 
     536             :     static MOZ_MUST_USE bool obj_deleteProperty(JSContext* cx, HandleObject obj, HandleId id,
     537             :                                                 ObjectOpResult& result);
     538             : 
     539             : 
     540             :     uint8_t* typedMem() const;
     541             :     uint8_t* typedMemBase() const;
     542             : 
     543             :   public:
     544             :     static MOZ_MUST_USE bool obj_newEnumerate(JSContext* cx, HandleObject obj,
     545             :                                               AutoIdVector& properties, bool enumerableOnly);
     546             : 
     547             :     TypedProto& typedProto() const {
     548             :         // Typed objects' prototypes can't be modified.
     549             :         return staticPrototype()->as<TypedProto>();
     550             :     }
     551             : 
     552           0 :     TypeDescr& typeDescr() const {
     553           0 :         return group()->typeDescr();
     554             :     }
     555             : 
     556             :     static JS::Result<TypedObject*, JS::OOM&>
     557             :     create(JSContext* cx, js::gc::AllocKind kind, js::gc::InitialHeap heap,
     558             :            js::HandleShape shape, js::HandleObjectGroup group);
     559             : 
     560             :     uint32_t offset() const;
     561             :     uint32_t length() const;
     562           0 :     uint8_t* typedMem(const JS::AutoRequireNoGC&) const { return typedMem(); }
     563             :     bool isAttached() const;
     564             : 
     565           0 :     uint32_t size() const {
     566           0 :         return typeDescr().size();
     567             :     }
     568             : 
     569           0 :     uint8_t* typedMem(size_t offset, const JS::AutoRequireNoGC& nogc) const {
     570             :         // It seems a bit surprising that one might request an offset
     571             :         // == size(), but it can happen when taking the "address of" a
     572             :         // 0-sized value. (In other words, we maintain the invariant
     573             :         // that `offset + size <= size()` -- this is always checked in
     574             :         // the caller's side.)
     575           0 :         MOZ_ASSERT(offset <= (size_t) size());
     576           0 :         return typedMem(nogc) + offset;
     577             :     }
     578             : 
     579             :     inline MOZ_MUST_USE bool opaque() const;
     580             : 
     581             :     // Creates a new typed object whose memory is freshly allocated and
     582             :     // initialized with zeroes (or, in the case of references, an appropriate
     583             :     // default value).
     584             :     static TypedObject* createZeroed(JSContext* cx, HandleTypeDescr typeObj, int32_t length,
     585             :                                      gc::InitialHeap heap = gc::DefaultHeap);
     586             : 
     587             :     // User-accessible constructor (`new TypeDescriptor(...)`). Note that the
     588             :     // callee here is the type descriptor.
     589             :     static MOZ_MUST_USE bool construct(JSContext* cx, unsigned argc, Value* vp);
     590             : 
     591             :     /* Accessors for self hosted code. */
     592             :     static MOZ_MUST_USE bool GetBuffer(JSContext* cx, unsigned argc, Value* vp);
     593             :     static MOZ_MUST_USE bool GetByteOffset(JSContext* cx, unsigned argc, Value* vp);
     594             : 
     595           0 :     Shape** addressOfShapeFromGC() { return shape_.unsafeUnbarrieredForTracing(); }
     596             : };
     597             : 
     598             : typedef Handle<TypedObject*> HandleTypedObject;
     599             : 
     600             : class OutlineTypedObject : public TypedObject
     601             : {
     602             :     // The object which owns the data this object points to. Because this
     603             :     // pointer is managed in tandem with |data|, this is not a GCPtr and
     604             :     // barriers are managed directly.
     605             :     JSObject* owner_;
     606             : 
     607             :     // Data pointer to some offset in the owner's contents.
     608             :     uint8_t* data_;
     609             : 
     610             :     void setOwnerAndData(JSObject* owner, uint8_t* data);
     611             : 
     612             :   public:
     613             :     // JIT accessors.
     614           0 :     static size_t offsetOfData() { return offsetof(OutlineTypedObject, data_); }
     615           0 :     static size_t offsetOfOwner() { return offsetof(OutlineTypedObject, owner_); }
     616             : 
     617           0 :     JSObject& owner() const {
     618           0 :         MOZ_ASSERT(owner_);
     619           0 :         return *owner_;
     620             :     }
     621             : 
     622             :     JSObject* maybeOwner() const {
     623             :         return owner_;
     624             :     }
     625             : 
     626           0 :     uint8_t* outOfLineTypedMem() const {
     627           0 :         return data_;
     628             :     }
     629             : 
     630           0 :     void setData(uint8_t* data) {
     631           0 :         data_ = data;
     632           0 :     }
     633             : 
     634           0 :     void resetOffset(size_t offset) {
     635           0 :         MOZ_ASSERT(offset <= (size_t) size());
     636           0 :         setData(typedMemBase() + offset);
     637           0 :     }
     638             : 
     639             :     // Helper for createUnattached()
     640             :     static OutlineTypedObject* createUnattachedWithClass(JSContext* cx,
     641             :                                                          const Class* clasp,
     642             :                                                          HandleTypeDescr type,
     643             :                                                          int32_t length,
     644             :                                                          gc::InitialHeap heap = gc::DefaultHeap);
     645             : 
     646             :     // Creates an unattached typed object or handle (depending on the
     647             :     // type parameter T). Note that it is only legal for unattached
     648             :     // handles to escape to the end user; for non-handles, the caller
     649             :     // should always invoke one of the `attach()` methods below.
     650             :     //
     651             :     // Arguments:
     652             :     // - type: type object for resulting object
     653             :     // - length: 0 unless this is an array, otherwise the length
     654             :     static OutlineTypedObject* createUnattached(JSContext* cx, HandleTypeDescr type,
     655             :                                                 int32_t length, gc::InitialHeap heap = gc::DefaultHeap);
     656             : 
     657             :     // Creates a typedObj that aliases the memory pointed at by `owner`
     658             :     // at the given offset. The typedObj will be a handle iff type is a
     659             :     // handle and a typed object otherwise.
     660             :     static OutlineTypedObject* createDerived(JSContext* cx,
     661             :                                              HandleTypeDescr type,
     662             :                                              Handle<TypedObject*> typedContents,
     663             :                                              uint32_t offset);
     664             : 
     665             :     // Use this method when `buffer` is the owner of the memory.
     666             :     void attach(JSContext* cx, ArrayBufferObject& buffer, uint32_t offset);
     667             : 
     668             :     // Otherwise, use this to attach to memory referenced by another typedObj.
     669             :     void attach(JSContext* cx, TypedObject& typedObj, uint32_t offset);
     670             : 
     671             :     // Invoked when array buffer is transferred elsewhere
     672             :     void notifyBufferDetached(void* newData);
     673             : 
     674             :     static void obj_trace(JSTracer* trace, JSObject* object);
     675             : };
     676             : 
     677             : // Class for a transparent typed object whose owner is an array buffer.
     678             : class OutlineTransparentTypedObject : public OutlineTypedObject
     679             : {
     680             :   public:
     681             :     static const Class class_;
     682             : 
     683             :     ArrayBufferObject* getOrCreateBuffer(JSContext* cx);
     684             : };
     685             : 
     686             : // Class for an opaque typed object whose owner may be either an array buffer
     687             : // or an opaque inlined typed object.
     688             : class OutlineOpaqueTypedObject : public OutlineTypedObject
     689             : {
     690             :   public:
     691             :     static const Class class_;
     692             : };
     693             : 
     694             : // Class for a typed object whose data is allocated inline.
     695             : class InlineTypedObject : public TypedObject
     696             : {
     697             :     friend class TypedObject;
     698             : 
     699             :     // Start of the inline data, which immediately follows the shape and type.
     700             :     uint8_t data_[1];
     701             : 
     702             :   protected:
     703           0 :     uint8_t* inlineTypedMem() const {
     704           0 :         return (uint8_t*) &data_;
     705             :     }
     706             : 
     707             :   public:
     708             :     static const size_t MaximumSize = JSObject::MAX_BYTE_SIZE - sizeof(TypedObject);
     709             : 
     710           0 :     static gc::AllocKind allocKindForTypeDescriptor(TypeDescr* descr) {
     711           0 :         size_t nbytes = descr->size();
     712           0 :         MOZ_ASSERT(nbytes <= MaximumSize);
     713             : 
     714           0 :         return gc::GetGCObjectKindForBytes(nbytes + sizeof(TypedObject));
     715             :     }
     716             : 
     717           0 :     uint8_t* inlineTypedMem(const JS::AutoRequireNoGC&) const {
     718           0 :         return inlineTypedMem();
     719             :     }
     720             : 
     721           0 :     uint8_t* inlineTypedMemForGC() const {
     722           0 :         return inlineTypedMem();
     723             :     }
     724             : 
     725             :     static void obj_trace(JSTracer* trace, JSObject* object);
     726             :     static void objectMovedDuringMinorGC(JSTracer* trc, JSObject* dst, JSObject* src);
     727             : 
     728           0 :     static size_t offsetOfDataStart() {
     729           0 :         return offsetof(InlineTypedObject, data_);
     730             :     }
     731             : 
     732             :     static InlineTypedObject* create(JSContext* cx, HandleTypeDescr descr,
     733             :                                      gc::InitialHeap heap = gc::DefaultHeap);
     734             :     static InlineTypedObject* createCopy(JSContext* cx, Handle<InlineTypedObject*> templateObject,
     735             :                                          gc::InitialHeap heap);
     736             : };
     737             : 
     738             : // Class for a transparent typed object with inline data, which may have a
     739             : // lazily allocated array buffer.
     740             : class InlineTransparentTypedObject : public InlineTypedObject
     741             : {
     742             :   public:
     743             :     static const Class class_;
     744             : 
     745             :     ArrayBufferObject* getOrCreateBuffer(JSContext* cx);
     746             : 
     747           0 :     uint8_t* inlineTypedMem() const {
     748           0 :         return InlineTypedObject::inlineTypedMem();
     749             :     }
     750             : };
     751             : 
     752             : // Class for an opaque typed object with inline data and no array buffer.
     753             : class InlineOpaqueTypedObject : public InlineTypedObject
     754             : {
     755             :   public:
     756             :     static const Class class_;
     757             : };
     758             : 
     759             : // Class for the global SIMD object.
     760             : class SimdObject : public JSObject
     761             : {
     762             :   public:
     763             :     static const Class class_;
     764             :     static MOZ_MUST_USE bool toString(JSContext* cx, unsigned int argc, Value* vp);
     765             :     static MOZ_MUST_USE bool resolve(JSContext* cx, JS::HandleObject obj, JS::HandleId,
     766             :                                      bool* resolved);
     767             : };
     768             : 
     769             : /*
     770             :  * Usage: NewOpaqueTypedObject(typeObj)
     771             :  *
     772             :  * Constructs a new, unattached instance of `Handle`.
     773             :  */
     774             : MOZ_MUST_USE bool NewOpaqueTypedObject(JSContext* cx, unsigned argc, Value* vp);
     775             : 
     776             : /*
     777             :  * Usage: NewDerivedTypedObject(typeObj, owner, offset)
     778             :  *
     779             :  * Constructs a new, unattached instance of `Handle`.
     780             :  */
     781             : MOZ_MUST_USE bool NewDerivedTypedObject(JSContext* cx, unsigned argc, Value* vp);
     782             : 
     783             : /*
     784             :  * Usage: AttachTypedObject(typedObj, newDatum, newOffset)
     785             :  *
     786             :  * Moves `typedObj` to point at the memory referenced by `newDatum` with
     787             :  * the offset `newOffset`.
     788             :  */
     789             : MOZ_MUST_USE bool AttachTypedObject(JSContext* cx, unsigned argc, Value* vp);
     790             : 
     791             : /*
     792             :  * Usage: SetTypedObjectOffset(typedObj, offset)
     793             :  *
     794             :  * Changes the offset for `typedObj` within its buffer to `offset`.
     795             :  * `typedObj` must already be attached.
     796             :  */
     797             : MOZ_MUST_USE bool SetTypedObjectOffset(JSContext*, unsigned argc, Value* vp);
     798             : 
     799             : /*
     800             :  * Usage: ObjectIsTypeDescr(obj)
     801             :  *
     802             :  * True if `obj` is a type object.
     803             :  */
     804             : MOZ_MUST_USE bool ObjectIsTypeDescr(JSContext* cx, unsigned argc, Value* vp);
     805             : 
     806             : /*
     807             :  * Usage: ObjectIsTypedObject(obj)
     808             :  *
     809             :  * True if `obj` is a transparent or opaque typed object.
     810             :  */
     811             : MOZ_MUST_USE bool ObjectIsTypedObject(JSContext* cx, unsigned argc, Value* vp);
     812             : 
     813             : /*
     814             :  * Usage: ObjectIsOpaqueTypedObject(obj)
     815             :  *
     816             :  * True if `obj` is an opaque typed object.
     817             :  */
     818             : MOZ_MUST_USE bool ObjectIsOpaqueTypedObject(JSContext* cx, unsigned argc, Value* vp);
     819             : 
     820             : /*
     821             :  * Usage: ObjectIsTransparentTypedObject(obj)
     822             :  *
     823             :  * True if `obj` is a transparent typed object.
     824             :  */
     825             : MOZ_MUST_USE bool ObjectIsTransparentTypedObject(JSContext* cx, unsigned argc, Value* vp);
     826             : 
     827             : /* Predicates on type descriptor objects.  In all cases, 'obj' must be a type descriptor. */
     828             : 
     829             : MOZ_MUST_USE bool TypeDescrIsSimpleType(JSContext*, unsigned argc, Value* vp);
     830             : 
     831             : MOZ_MUST_USE bool TypeDescrIsArrayType(JSContext*, unsigned argc, Value* vp);
     832             : 
     833             : /*
     834             :  * Usage: TypedObjectIsAttached(obj)
     835             :  *
     836             :  * Given a TypedObject `obj`, returns true if `obj` is
     837             :  * "attached" (i.e., its data pointer is nullptr).
     838             :  */
     839             : MOZ_MUST_USE bool TypedObjectIsAttached(JSContext* cx, unsigned argc, Value* vp);
     840             : 
     841             : /*
     842             :  * Usage: TypedObjectTypeDescr(obj)
     843             :  *
     844             :  * Given a TypedObject `obj`, returns the object's type descriptor.
     845             :  */
     846             : MOZ_MUST_USE bool TypedObjectTypeDescr(JSContext* cx, unsigned argc, Value* vp);
     847             : 
     848             : /*
     849             :  * Usage: ClampToUint8(v)
     850             :  *
     851             :  * Same as the C function ClampDoubleToUint8. `v` must be a number.
     852             :  */
     853             : MOZ_MUST_USE bool ClampToUint8(JSContext* cx, unsigned argc, Value* vp);
     854             : 
     855             : /*
     856             :  * Usage: GetTypedObjectModule()
     857             :  *
     858             :  * Returns the global "typed object" module, which provides access
     859             :  * to the various builtin type descriptors. These are currently
     860             :  * exported as immutable properties so it is safe for self-hosted code
     861             :  * to access them; eventually this should be linked into the module
     862             :  * system.
     863             :  */
     864             : MOZ_MUST_USE bool GetTypedObjectModule(JSContext* cx, unsigned argc, Value* vp);
     865             : 
     866             : /*
     867             :  * Usage: GetSimdTypeDescr(simdTypeRepr)
     868             :  *
     869             :  * Returns one of the SIMD type objects, identified by `simdTypeRepr` which must
     870             :  * be one of the JS_SIMDTYPEREPR_* constants.
     871             :  *
     872             :  * The SIMD pseudo-module must have been initialized for this to be safe.
     873             :  */
     874             : MOZ_MUST_USE bool GetSimdTypeDescr(JSContext* cx, unsigned argc, Value* vp);
     875             : 
     876             : /*
     877             :  * Usage: Store_int8(targetDatum, targetOffset, value)
     878             :  *        ...
     879             :  *        Store_uint8(targetDatum, targetOffset, value)
     880             :  *        ...
     881             :  *        Store_float32(targetDatum, targetOffset, value)
     882             :  *        Store_float64(targetDatum, targetOffset, value)
     883             :  *
     884             :  * Intrinsic function. Stores `value` into the memory referenced by
     885             :  * `targetDatum` at the offset `targetOffset`.
     886             :  *
     887             :  * Assumes (and asserts) that:
     888             :  * - `targetDatum` is attached
     889             :  * - `targetOffset` is a valid offset within the bounds of `targetDatum`
     890             :  * - `value` is a number
     891             :  */
     892             : #define JS_STORE_SCALAR_CLASS_DEFN(_constant, T, _name)                       \
     893             : class StoreScalar##T {                                                        \
     894             :   public:                                                                     \
     895             :     static MOZ_MUST_USE bool Func(JSContext* cx, unsigned argc, Value* vp);   \
     896             :     static const JSJitInfo JitInfo;                                           \
     897             : };
     898             : 
     899             : /*
     900             :  * Usage: Store_Any(targetDatum, targetOffset, fieldName, value)
     901             :  *        Store_Object(targetDatum, targetOffset, fieldName, value)
     902             :  *        Store_string(targetDatum, targetOffset, fieldName, value)
     903             :  *
     904             :  * Intrinsic function. Stores `value` into the memory referenced by
     905             :  * `targetDatum` at the offset `targetOffset`.
     906             :  *
     907             :  * Assumes (and asserts) that:
     908             :  * - `targetDatum` is attached
     909             :  * - `targetOffset` is a valid offset within the bounds of `targetDatum`
     910             :  * - `value` is an object or null (`Store_Object`) or string (`Store_string`).
     911             :  */
     912             : #define JS_STORE_REFERENCE_CLASS_DEFN(_constant, T, _name)                    \
     913             : class StoreReference##_name {                                                 \
     914             :   private:                                                                    \
     915             :     static MOZ_MUST_USE bool store(JSContext* cx, T* heap, const Value& v,    \
     916             :                                    TypedObject* obj, jsid id);                \
     917             :                                                                               \
     918             :   public:                                                                     \
     919             :     static MOZ_MUST_USE bool Func(JSContext* cx, unsigned argc, Value* vp);   \
     920             :     static const JSJitInfo JitInfo;                                           \
     921             : };
     922             : 
     923             : /*
     924             :  * Usage: LoadScalar(targetDatum, targetOffset, value)
     925             :  *
     926             :  * Intrinsic function. Loads value (which must be an int32 or uint32)
     927             :  * by `scalarTypeRepr` (which must be a type repr obj) and loads the
     928             :  * value at the memory for `targetDatum` at offset `targetOffset`.
     929             :  * `targetDatum` must be attached.
     930             :  */
     931             : #define JS_LOAD_SCALAR_CLASS_DEFN(_constant, T, _name)                        \
     932             : class LoadScalar##T {                                                         \
     933             :   public:                                                                     \
     934             :     static MOZ_MUST_USE bool Func(JSContext* cx, unsigned argc, Value* vp);   \
     935             :     static const JSJitInfo JitInfo;                                           \
     936             : };
     937             : 
     938             : /*
     939             :  * Usage: LoadReference(targetDatum, targetOffset, value)
     940             :  *
     941             :  * Intrinsic function. Stores value (which must be an int32 or uint32)
     942             :  * by `scalarTypeRepr` (which must be a type repr obj) and stores the
     943             :  * value at the memory for `targetDatum` at offset `targetOffset`.
     944             :  * `targetDatum` must be attached.
     945             :  */
     946             : #define JS_LOAD_REFERENCE_CLASS_DEFN(_constant, T, _name)                     \
     947             : class LoadReference##_name {                                                  \
     948             :   private:                                                                    \
     949             :     static void load(T* heap, MutableHandleValue v);                          \
     950             :                                                                               \
     951             :   public:                                                                     \
     952             :     static MOZ_MUST_USE bool Func(JSContext* cx, unsigned argc, Value* vp);   \
     953             :     static const JSJitInfo JitInfo;                                           \
     954             : };
     955             : 
     956             : // I was using templates for this stuff instead of macros, but ran
     957             : // into problems with the Unagi compiler.
     958             : JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_STORE_SCALAR_CLASS_DEFN)
     959             : JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_LOAD_SCALAR_CLASS_DEFN)
     960             : JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_STORE_REFERENCE_CLASS_DEFN)
     961             : JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_DEFN)
     962             : 
     963             : inline bool
     964        7539 : IsTypedObjectClass(const Class* class_)
     965             : {
     966        7539 :     return class_ == &OutlineTransparentTypedObject::class_ ||
     967        7539 :            class_ == &InlineTransparentTypedObject::class_ ||
     968       15078 :            class_ == &OutlineOpaqueTypedObject::class_ ||
     969        7539 :            class_ == &InlineOpaqueTypedObject::class_;
     970             : }
     971             : 
     972             : inline bool
     973           0 : IsOpaqueTypedObjectClass(const Class* class_)
     974             : {
     975           0 :     return class_ == &OutlineOpaqueTypedObject::class_ ||
     976           0 :            class_ == &InlineOpaqueTypedObject::class_;
     977             : }
     978             : 
     979             : inline bool
     980           0 : IsOutlineTypedObjectClass(const Class* class_)
     981             : {
     982           0 :     return class_ == &OutlineOpaqueTypedObject::class_ ||
     983           0 :            class_ == &OutlineTransparentTypedObject::class_;
     984             : }
     985             : 
     986             : inline bool
     987           0 : IsInlineTypedObjectClass(const Class* class_)
     988             : {
     989           0 :     return class_ == &InlineOpaqueTypedObject::class_ ||
     990           0 :            class_ == &InlineTransparentTypedObject::class_;
     991             : }
     992             : 
     993             : inline const Class*
     994           0 : GetOutlineTypedObjectClass(bool opaque)
     995             : {
     996           0 :     return opaque ? &OutlineOpaqueTypedObject::class_ : &OutlineTransparentTypedObject::class_;
     997             : }
     998             : 
     999             : inline bool
    1000         528 : IsSimpleTypeDescrClass(const Class* clasp)
    1001             : {
    1002         528 :     return clasp == &ScalarTypeDescr::class_ ||
    1003         528 :            clasp == &ReferenceTypeDescr::class_;
    1004             : }
    1005             : 
    1006             : inline bool
    1007         528 : IsComplexTypeDescrClass(const Class* clasp)
    1008             : {
    1009         528 :     return clasp == &StructTypeDescr::class_ ||
    1010        1056 :            clasp == &ArrayTypeDescr::class_ ||
    1011         528 :            clasp == &SimdTypeDescr::class_;
    1012             : }
    1013             : 
    1014             : inline bool
    1015         528 : IsTypeDescrClass(const Class* clasp)
    1016             : {
    1017        1056 :     return IsSimpleTypeDescrClass(clasp) ||
    1018        1056 :            IsComplexTypeDescrClass(clasp);
    1019             : }
    1020             : 
    1021             : inline bool
    1022           0 : TypedObject::opaque() const
    1023             : {
    1024           0 :     return IsOpaqueTypedObjectClass(getClass());
    1025             : }
    1026             : 
    1027             : JSObject*
    1028             : InitTypedObjectModuleObject(JSContext* cx, JS::HandleObject obj);
    1029             : 
    1030             : } // namespace js
    1031             : 
    1032             : template <>
    1033             : inline bool
    1034           0 : JSObject::is<js::SimpleTypeDescr>() const
    1035             : {
    1036           0 :     return IsSimpleTypeDescrClass(getClass());
    1037             : }
    1038             : 
    1039             : template <>
    1040             : inline bool
    1041           0 : JSObject::is<js::ComplexTypeDescr>() const
    1042             : {
    1043           0 :     return IsComplexTypeDescrClass(getClass());
    1044             : }
    1045             : 
    1046             : template <>
    1047             : inline bool
    1048         528 : JSObject::is<js::TypeDescr>() const
    1049             : {
    1050         528 :     return IsTypeDescrClass(getClass());
    1051             : }
    1052             : 
    1053             : template <>
    1054             : inline bool
    1055        7384 : JSObject::is<js::TypedObject>() const
    1056             : {
    1057        7384 :     return IsTypedObjectClass(getClass());
    1058             : }
    1059             : 
    1060             : template <>
    1061             : inline bool
    1062        7999 : JSObject::is<js::OutlineTypedObject>() const
    1063             : {
    1064       15998 :     return getClass() == &js::OutlineTransparentTypedObject::class_ ||
    1065       15998 :            getClass() == &js::OutlineOpaqueTypedObject::class_;
    1066             : }
    1067             : 
    1068             : template <>
    1069             : inline bool
    1070       30700 : JSObject::is<js::InlineTypedObject>() const
    1071             : {
    1072       61400 :     return getClass() == &js::InlineTransparentTypedObject::class_ ||
    1073       61400 :            getClass() == &js::InlineOpaqueTypedObject::class_;
    1074             : }
    1075             : 
    1076             : #endif /* builtin_TypedObject_h */

Generated by: LCOV version 1.13