js/src/builtin/TypedObject.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/js/src/builtin/TypedObject.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1038 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     1.5 + * vim: set ts=8 sts=4 et sw=4 tw=99:
     1.6 + * This Source Code Form is subject to the terms of the Mozilla Public
     1.7 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.8 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.9 +
    1.10 +#ifndef builtin_TypedObject_h
    1.11 +#define builtin_TypedObject_h
    1.12 +
    1.13 +#include "jsobj.h"
    1.14 +
    1.15 +#include "builtin/TypedObjectConstants.h"
    1.16 +#include "vm/ArrayBufferObject.h"
    1.17 +
    1.18 +/*
    1.19 + * -------------
    1.20 + * Typed Objects
    1.21 + * -------------
    1.22 + *
    1.23 + * Typed objects are a special kind of JS object where the data is
    1.24 + * given well-structured form. To use a typed object, users first
    1.25 + * create *type objects* (no relation to the type objects used in TI)
    1.26 + * that define the type layout. For example, a statement like:
    1.27 + *
    1.28 + *    var PointType = new StructType({x: uint8, y: uint8});
    1.29 + *
    1.30 + * would create a type object PointType that is a struct with
    1.31 + * two fields, each of uint8 type.
    1.32 + *
    1.33 + * This comment typically assumes familiary with the API.  For more
    1.34 + * info on the API itself, see the Harmony wiki page at
    1.35 + * http://wiki.ecmascript.org/doku.php?id=harmony:typed_objects or the
    1.36 + * ES6 spec (not finalized at the time of this writing).
    1.37 + *
    1.38 + * - Initialization:
    1.39 + *
    1.40 + * Currently, all "globals" related to typed objects are packaged
    1.41 + * within a single "module" object `TypedObject`. This module has its
    1.42 + * own js::Class and when that class is initialized, we also create
    1.43 + * and define all other values (in `js_InitTypedObjectModuleClass()`).
    1.44 + *
    1.45 + * - Type objects, meta type objects, and type representations:
    1.46 + *
    1.47 + * There are a number of pre-defined type objects, one for each
    1.48 + * scalar type (`uint8` etc). Each of these has its own class_,
    1.49 + * defined in `DefineNumericClass()`.
    1.50 + *
    1.51 + * There are also meta type objects (`ArrayType`, `StructType`).
    1.52 + * These constructors are not themselves type objects but rather the
    1.53 + * means for the *user* to construct new typed objects.
    1.54 + *
    1.55 + * Each type object is associated with a *type representation* (see
    1.56 + * TypeRepresentation.h). Type representations are canonical versions
    1.57 + * of type objects. We attach them to TI type objects and (eventually)
    1.58 + * use them for shape guards etc. They are purely internal to the
    1.59 + * engine and are not exposed to end users (though self-hosted code
    1.60 + * sometimes accesses them).
    1.61 + *
    1.62 + * - Typed objects:
    1.63 + *
    1.64 + * A typed object is an instance of a *type object* (note the past
    1.65 + * participle). There is one class for *transparent* typed objects and
    1.66 + * one for *opaque* typed objects. These classes are equivalent in
    1.67 + * basically every way, except that requesting the backing buffer of
    1.68 + * an opaque typed object yields null. We use distinct js::Classes to
    1.69 + * avoid the need for an extra slot in every typed object.
    1.70 + *
    1.71 + * Note that whether a typed object is opaque is not directly
    1.72 + * connected to its type. That is, opaque types are *always*
    1.73 + * represented by opaque typed objects, but you may have opaque typed
    1.74 + * objects for transparent types too. This can occur for two reasons:
    1.75 + * (1) a transparent type may be embedded within an opaque type or (2)
    1.76 + * users can choose to convert transparent typed objects into opaque
    1.77 + * ones to avoid giving access to the buffer itself.
    1.78 + *
    1.79 + * Typed objects (no matter their class) are non-native objects that
    1.80 + * fully override the property accessors etc. The overridden accessor
    1.81 + * methods are the same in each and are defined in methods of
    1.82 + * TypedObject.
    1.83 + *
    1.84 + * Typed objects may be attached or unattached. An unattached typed
    1.85 + * object has no memory associated with it; it is basically a null
    1.86 + * pointer. When first created, objects are always attached, but they
    1.87 + * can become unattached if their buffer is neutered (note that this
    1.88 + * implies that typed objects of opaque types can never be unattached).
    1.89 + *
    1.90 + * When a new typed object instance is created, fresh memory is
    1.91 + * allocated and set as that typed object's private field. The object
    1.92 + * is then considered the *owner* of that memory: when the object is
    1.93 + * collected, its finalizer will free the memory. The fact that an
    1.94 + * object `o` owns its memory is indicated by setting its reserved
    1.95 + * slot JS_TYPEDOBJ_SLOT_OWNER to `o` (a trivial cycle, in other
    1.96 + * words).
    1.97 + *
    1.98 + * Later, *derived* typed objects can be created, typically via an
    1.99 + * access like `o.f` where `f` is some complex (non-scalar) type, but
   1.100 + * also explicitly via Handle objects. In those cases, the memory
   1.101 + * pointer of the derived object is set to alias the owner's memory
   1.102 + * pointer, and the owner slot for the derived object is set to the
   1.103 + * owner object, thus ensuring that the owner is not collected while
   1.104 + * the derived object is alive. We always maintain the invariant that
   1.105 + * JS_TYPEDOBJ_SLOT_OWNER is the true owner of the memory, meaning
   1.106 + * that there is a shallow tree. This prevents an access pattern like
   1.107 + * `a.b.c.d` from keeping all the intermediate objects alive.
   1.108 + */
   1.109 +
   1.110 +namespace js {
   1.111 +
   1.112 +/*
   1.113 + * Helper method for converting a double into other scalar
   1.114 + * types in the same way that JavaScript would. In particular,
   1.115 + * simple C casting from double to int32_t gets things wrong
   1.116 + * for values like 0xF0000000.
   1.117 + */
   1.118 +template <typename T>
   1.119 +static T ConvertScalar(double d)
   1.120 +{
   1.121 +    if (TypeIsFloatingPoint<T>()) {
   1.122 +        return T(d);
   1.123 +    } else if (TypeIsUnsigned<T>()) {
   1.124 +        uint32_t n = ToUint32(d);
   1.125 +        return T(n);
   1.126 +    } else {
   1.127 +        int32_t n = ToInt32(d);
   1.128 +        return T(n);
   1.129 +    }
   1.130 +}
   1.131 +
   1.132 +/*
   1.133 + * The prototype for a typed object. Currently, carries a link to the
   1.134 + * type descriptor. Eventually will carry most of the type information
   1.135 + * we want.
   1.136 + */
   1.137 +class TypedProto : public JSObject
   1.138 +{
   1.139 +  public:
   1.140 +    static const Class class_;
   1.141 +
   1.142 +    inline void initTypeDescrSlot(TypeDescr &descr);
   1.143 +
   1.144 +    TypeDescr &typeDescr() const {
   1.145 +        return getReservedSlot(JS_TYPROTO_SLOT_DESCR).toObject().as<TypeDescr>();
   1.146 +    }
   1.147 +};
   1.148 +
   1.149 +class TypeDescr : public JSObject
   1.150 +{
   1.151 +  public:
   1.152 +    // This is *intentionally* not defined so as to produce link
   1.153 +    // errors if a is<FooTypeDescr>() etc goes wrong. Otherwise, the
   1.154 +    // default implementation resolves this to a reference to
   1.155 +    // FooTypeDescr::class_ which resolves to
   1.156 +    // JSObject::class_. Debugging the resulting errors leads to much
   1.157 +    // fun and rejoicing.
   1.158 +    static const Class class_;
   1.159 +
   1.160 +    enum Kind {
   1.161 +        Scalar = JS_TYPEREPR_SCALAR_KIND,
   1.162 +        Reference = JS_TYPEREPR_REFERENCE_KIND,
   1.163 +        X4 = JS_TYPEREPR_X4_KIND,
   1.164 +        Struct = JS_TYPEREPR_STRUCT_KIND,
   1.165 +        SizedArray = JS_TYPEREPR_SIZED_ARRAY_KIND,
   1.166 +        UnsizedArray = JS_TYPEREPR_UNSIZED_ARRAY_KIND,
   1.167 +    };
   1.168 +
   1.169 +    static bool isSized(Kind kind) {
   1.170 +        return kind > JS_TYPEREPR_MAX_UNSIZED_KIND;
   1.171 +    }
   1.172 +
   1.173 +    JSAtom &stringRepr() const {
   1.174 +        return getReservedSlot(JS_DESCR_SLOT_STRING_REPR).toString()->asAtom();
   1.175 +    }
   1.176 +
   1.177 +    TypeDescr::Kind kind() const {
   1.178 +        return (TypeDescr::Kind) getReservedSlot(JS_DESCR_SLOT_KIND).toInt32();
   1.179 +    }
   1.180 +
   1.181 +    bool opaque() const {
   1.182 +        return getReservedSlot(JS_DESCR_SLOT_OPAQUE).toBoolean();
   1.183 +    }
   1.184 +
   1.185 +    bool transparent() const {
   1.186 +        return !opaque();
   1.187 +    }
   1.188 +
   1.189 +    int32_t alignment() {
   1.190 +        return getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
   1.191 +    }
   1.192 +};
   1.193 +
   1.194 +typedef Handle<TypeDescr*> HandleTypeDescr;
   1.195 +
   1.196 +class SizedTypeDescr : public TypeDescr
   1.197 +{
   1.198 +  public:
   1.199 +    int32_t size() {
   1.200 +        return getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
   1.201 +    }
   1.202 +
   1.203 +    void initInstances(const JSRuntime *rt, uint8_t *mem, size_t length);
   1.204 +    void traceInstances(JSTracer *trace, uint8_t *mem, size_t length);
   1.205 +};
   1.206 +
   1.207 +typedef Handle<SizedTypeDescr*> HandleSizedTypeDescr;
   1.208 +
   1.209 +class SimpleTypeDescr : public SizedTypeDescr
   1.210 +{
   1.211 +};
   1.212 +
   1.213 +// Type for scalar type constructors like `uint8`. All such type
   1.214 +// constructors share a common js::Class and JSFunctionSpec. Scalar
   1.215 +// types are non-opaque (their storage is visible unless combined with
   1.216 +// an opaque reference type.)
   1.217 +class ScalarTypeDescr : public SimpleTypeDescr
   1.218 +{
   1.219 +  public:
   1.220 +    // Must match order of JS_FOR_EACH_SCALAR_TYPE_REPR below
   1.221 +    enum Type {
   1.222 +        TYPE_INT8 = JS_SCALARTYPEREPR_INT8,
   1.223 +        TYPE_UINT8 = JS_SCALARTYPEREPR_UINT8,
   1.224 +        TYPE_INT16 = JS_SCALARTYPEREPR_INT16,
   1.225 +        TYPE_UINT16 = JS_SCALARTYPEREPR_UINT16,
   1.226 +        TYPE_INT32 = JS_SCALARTYPEREPR_INT32,
   1.227 +        TYPE_UINT32 = JS_SCALARTYPEREPR_UINT32,
   1.228 +        TYPE_FLOAT32 = JS_SCALARTYPEREPR_FLOAT32,
   1.229 +        TYPE_FLOAT64 = JS_SCALARTYPEREPR_FLOAT64,
   1.230 +
   1.231 +        /*
   1.232 +         * Special type that's a uint8_t, but assignments are clamped to 0 .. 255.
   1.233 +         * Treat the raw data type as a uint8_t.
   1.234 +         */
   1.235 +        TYPE_UINT8_CLAMPED = JS_SCALARTYPEREPR_UINT8_CLAMPED,
   1.236 +    };
   1.237 +    static const int32_t TYPE_MAX = TYPE_UINT8_CLAMPED + 1;
   1.238 +
   1.239 +    static const TypeDescr::Kind Kind = TypeDescr::Scalar;
   1.240 +    static const bool Opaque = false;
   1.241 +    static int32_t size(Type t);
   1.242 +    static int32_t alignment(Type t);
   1.243 +    static const char *typeName(Type type);
   1.244 +
   1.245 +    static const Class class_;
   1.246 +    static const JSFunctionSpec typeObjectMethods[];
   1.247 +
   1.248 +    ScalarTypeDescr::Type type() const {
   1.249 +        return (ScalarTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
   1.250 +    }
   1.251 +
   1.252 +    static bool call(JSContext *cx, unsigned argc, Value *vp);
   1.253 +};
   1.254 +
   1.255 +// Enumerates the cases of ScalarTypeDescr::Type which have
   1.256 +// unique C representation. In particular, omits Uint8Clamped since it
   1.257 +// is just a Uint8.
   1.258 +#define JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_)                     \
   1.259 +    macro_(ScalarTypeDescr::TYPE_INT8,    int8_t,   int8)            \
   1.260 +    macro_(ScalarTypeDescr::TYPE_UINT8,   uint8_t,  uint8)           \
   1.261 +    macro_(ScalarTypeDescr::TYPE_INT16,   int16_t,  int16)           \
   1.262 +    macro_(ScalarTypeDescr::TYPE_UINT16,  uint16_t, uint16)          \
   1.263 +    macro_(ScalarTypeDescr::TYPE_INT32,   int32_t,  int32)           \
   1.264 +    macro_(ScalarTypeDescr::TYPE_UINT32,  uint32_t, uint32)          \
   1.265 +    macro_(ScalarTypeDescr::TYPE_FLOAT32, float,    float32)         \
   1.266 +    macro_(ScalarTypeDescr::TYPE_FLOAT64, double,   float64)
   1.267 +
   1.268 +// Must be in same order as the enum ScalarTypeDescr::Type:
   1.269 +#define JS_FOR_EACH_SCALAR_TYPE_REPR(macro_)                                    \
   1.270 +    JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_)                           \
   1.271 +    macro_(ScalarTypeDescr::TYPE_UINT8_CLAMPED, uint8_t, uint8Clamped)
   1.272 +
   1.273 +// Type for reference type constructors like `Any`, `String`, and
   1.274 +// `Object`. All such type constructors share a common js::Class and
   1.275 +// JSFunctionSpec. All these types are opaque.
   1.276 +class ReferenceTypeDescr : public SimpleTypeDescr
   1.277 +{
   1.278 +  public:
   1.279 +    // Must match order of JS_FOR_EACH_REFERENCE_TYPE_REPR below
   1.280 +    enum Type {
   1.281 +        TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
   1.282 +        TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
   1.283 +        TYPE_STRING = JS_REFERENCETYPEREPR_STRING,
   1.284 +    };
   1.285 +    static const int32_t TYPE_MAX = TYPE_STRING + 1;
   1.286 +    static const char *typeName(Type type);
   1.287 +
   1.288 +    static const TypeDescr::Kind Kind = TypeDescr::Reference;
   1.289 +    static const bool Opaque = true;
   1.290 +    static const Class class_;
   1.291 +    static int32_t size(Type t);
   1.292 +    static int32_t alignment(Type t);
   1.293 +    static const JSFunctionSpec typeObjectMethods[];
   1.294 +
   1.295 +    ReferenceTypeDescr::Type type() const {
   1.296 +        return (ReferenceTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
   1.297 +    }
   1.298 +
   1.299 +    const char *typeName() const {
   1.300 +        return typeName(type());
   1.301 +    }
   1.302 +
   1.303 +    static bool call(JSContext *cx, unsigned argc, Value *vp);
   1.304 +};
   1.305 +
   1.306 +#define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_)                    \
   1.307 +    macro_(ReferenceTypeDescr::TYPE_ANY,    HeapValue, Any)        \
   1.308 +    macro_(ReferenceTypeDescr::TYPE_OBJECT, HeapPtrObject, Object) \
   1.309 +    macro_(ReferenceTypeDescr::TYPE_STRING, HeapPtrString, string)
   1.310 +
   1.311 +// Type descriptors whose instances are objects and hence which have
   1.312 +// an associated `prototype` property.
   1.313 +class ComplexTypeDescr : public SizedTypeDescr
   1.314 +{
   1.315 +  public:
   1.316 +    // Returns the prototype that instances of this type descriptor
   1.317 +    // will have.
   1.318 +    TypedProto &instancePrototype() const {
   1.319 +        return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>();
   1.320 +    }
   1.321 +};
   1.322 +
   1.323 +/*
   1.324 + * Type descriptors `float32x4` and `int32x4`
   1.325 + */
   1.326 +class X4TypeDescr : public ComplexTypeDescr
   1.327 +{
   1.328 +  public:
   1.329 +    enum Type {
   1.330 +        TYPE_INT32 = JS_X4TYPEREPR_INT32,
   1.331 +        TYPE_FLOAT32 = JS_X4TYPEREPR_FLOAT32,
   1.332 +    };
   1.333 +
   1.334 +    static const TypeDescr::Kind Kind = TypeDescr::X4;
   1.335 +    static const bool Opaque = false;
   1.336 +    static const Class class_;
   1.337 +    static int32_t size(Type t);
   1.338 +    static int32_t alignment(Type t);
   1.339 +
   1.340 +    X4TypeDescr::Type type() const {
   1.341 +        return (X4TypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
   1.342 +    }
   1.343 +
   1.344 +    static bool call(JSContext *cx, unsigned argc, Value *vp);
   1.345 +    static bool is(const Value &v);
   1.346 +};
   1.347 +
   1.348 +#define JS_FOR_EACH_X4_TYPE_REPR(macro_)                             \
   1.349 +    macro_(X4TypeDescr::TYPE_INT32, int32_t, int32)                  \
   1.350 +    macro_(X4TypeDescr::TYPE_FLOAT32, float, float32)
   1.351 +
   1.352 +bool IsTypedObjectClass(const Class *clasp); // Defined below
   1.353 +bool IsTypedObjectArray(JSObject& obj);
   1.354 +
   1.355 +bool CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr obj);
   1.356 +
   1.357 +/*
   1.358 + * Properties and methods of the `ArrayType` meta type object. There
   1.359 + * is no `class_` field because `ArrayType` is just a native
   1.360 + * constructor function.
   1.361 + */
   1.362 +class ArrayMetaTypeDescr : public JSObject
   1.363 +{
   1.364 +  private:
   1.365 +    friend class UnsizedArrayTypeDescr;
   1.366 +
   1.367 +    // Helper for creating a new ArrayType object, either sized or unsized.
   1.368 +    // The template parameter `T` should be either `UnsizedArrayTypeDescr`
   1.369 +    // or `SizedArrayTypeDescr`.
   1.370 +    //
   1.371 +    // - `arrayTypePrototype` - prototype for the new object to be created,
   1.372 +    //                          either ArrayType.prototype or
   1.373 +    //                          unsizedArrayType.__proto__ depending on
   1.374 +    //                          whether this is a sized or unsized array
   1.375 +    // - `elementType` - type object for the elements in the array
   1.376 +    // - `stringRepr` - canonical string representation for the array
   1.377 +    // - `size` - length of the array (0 if unsized)
   1.378 +    template<class T>
   1.379 +    static T *create(JSContext *cx,
   1.380 +                     HandleObject arrayTypePrototype,
   1.381 +                     HandleSizedTypeDescr elementType,
   1.382 +                     HandleAtom stringRepr,
   1.383 +                     int32_t size);
   1.384 +
   1.385 +  public:
   1.386 +    // Properties and methods to be installed on ArrayType.prototype,
   1.387 +    // and hence inherited by all array type objects:
   1.388 +    static const JSPropertySpec typeObjectProperties[];
   1.389 +    static const JSFunctionSpec typeObjectMethods[];
   1.390 +
   1.391 +    // Properties and methods to be installed on ArrayType.prototype.prototype,
   1.392 +    // and hence inherited by all array *typed* objects:
   1.393 +    static const JSPropertySpec typedObjectProperties[];
   1.394 +    static const JSFunctionSpec typedObjectMethods[];
   1.395 +
   1.396 +    // This is the function that gets called when the user
   1.397 +    // does `new ArrayType(elem)`. It produces an array type object.
   1.398 +    static bool construct(JSContext *cx, unsigned argc, Value *vp);
   1.399 +};
   1.400 +
   1.401 +/*
   1.402 + * Type descriptor created by `new ArrayType(typeObj)`
   1.403 + *
   1.404 + * These have a prototype, and hence *could* be a subclass of
   1.405 + * `ComplexTypeDescr`, but it would require some reshuffling of the
   1.406 + * hierarchy, and it's not worth the trouble since they will be going
   1.407 + * away as part of bug 973238.
   1.408 + */
   1.409 +class UnsizedArrayTypeDescr : public TypeDescr
   1.410 +{
   1.411 +  public:
   1.412 +    static const Class class_;
   1.413 +    static const TypeDescr::Kind Kind = TypeDescr::UnsizedArray;
   1.414 +
   1.415 +    // This is the sized method on unsized array type objects.  It
   1.416 +    // produces a sized variant.
   1.417 +    static bool dimension(JSContext *cx, unsigned int argc, jsval *vp);
   1.418 +
   1.419 +    SizedTypeDescr &elementType() {
   1.420 +        return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>();
   1.421 +    }
   1.422 +};
   1.423 +
   1.424 +/*
   1.425 + * Type descriptor created by `unsizedArrayTypeObj.dimension()`
   1.426 + */
   1.427 +class SizedArrayTypeDescr : public ComplexTypeDescr
   1.428 +{
   1.429 +  public:
   1.430 +    static const Class class_;
   1.431 +    static const TypeDescr::Kind Kind = TypeDescr::SizedArray;
   1.432 +
   1.433 +    SizedTypeDescr &elementType() {
   1.434 +        return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>();
   1.435 +    }
   1.436 +
   1.437 +    int32_t length() {
   1.438 +        return getReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH).toInt32();
   1.439 +    }
   1.440 +};
   1.441 +
   1.442 +/*
   1.443 + * Properties and methods of the `StructType` meta type object. There
   1.444 + * is no `class_` field because `StructType` is just a native
   1.445 + * constructor function.
   1.446 + */
   1.447 +class StructMetaTypeDescr : public JSObject
   1.448 +{
   1.449 +  private:
   1.450 +    static JSObject *create(JSContext *cx, HandleObject structTypeGlobal,
   1.451 +                            HandleObject fields);
   1.452 +
   1.453 +  public:
   1.454 +    // Properties and methods to be installed on StructType.prototype,
   1.455 +    // and hence inherited by all struct type objects:
   1.456 +    static const JSPropertySpec typeObjectProperties[];
   1.457 +    static const JSFunctionSpec typeObjectMethods[];
   1.458 +
   1.459 +    // Properties and methods to be installed on StructType.prototype.prototype,
   1.460 +    // and hence inherited by all struct *typed* objects:
   1.461 +    static const JSPropertySpec typedObjectProperties[];
   1.462 +    static const JSFunctionSpec typedObjectMethods[];
   1.463 +
   1.464 +    // This is the function that gets called when the user
   1.465 +    // does `new StructType(...)`. It produces a struct type object.
   1.466 +    static bool construct(JSContext *cx, unsigned argc, Value *vp);
   1.467 +};
   1.468 +
   1.469 +class StructTypeDescr : public ComplexTypeDescr
   1.470 +{
   1.471 +  public:
   1.472 +    static const Class class_;
   1.473 +
   1.474 +    // Returns the number of fields defined in this struct.
   1.475 +    size_t fieldCount();
   1.476 +
   1.477 +    // Set `*out` to the index of the field named `id` and returns true,
   1.478 +    // or return false if no such field exists.
   1.479 +    bool fieldIndex(jsid id, size_t *out);
   1.480 +
   1.481 +    // Return the name of the field at index `index`.
   1.482 +    JSAtom &fieldName(size_t index);
   1.483 +
   1.484 +    // Return the type descr of the field at index `index`.
   1.485 +    SizedTypeDescr &fieldDescr(size_t index);
   1.486 +
   1.487 +    // Return the offset of the field at index `index`.
   1.488 +    int32_t fieldOffset(size_t index);
   1.489 +};
   1.490 +
   1.491 +typedef Handle<StructTypeDescr*> HandleStructTypeDescr;
   1.492 +
   1.493 +/*
   1.494 + * This object exists in order to encapsulate the typed object types
   1.495 + * somewhat, rather than sticking them all into the global object.
   1.496 + * Eventually it will go away and become a module.
   1.497 + */
   1.498 +class TypedObjectModuleObject : public JSObject {
   1.499 +  public:
   1.500 +    enum Slot {
   1.501 +        ArrayTypePrototype,
   1.502 +        StructTypePrototype,
   1.503 +        SlotCount
   1.504 +    };
   1.505 +
   1.506 +    static const Class class_;
   1.507 +};
   1.508 +
   1.509 +/*
   1.510 + * Base type for typed objects and handles. Basically any type whose
   1.511 + * contents consist of typed memory.
   1.512 + */
   1.513 +class TypedObject : public ArrayBufferViewObject
   1.514 +{
   1.515 +  private:
   1.516 +    static const bool IsTypedObjectClass = true;
   1.517 +
   1.518 +    template<class T>
   1.519 +    static bool obj_getArrayElement(JSContext *cx,
   1.520 +                                    Handle<TypedObject*> typedObj,
   1.521 +                                    Handle<TypeDescr*> typeDescr,
   1.522 +                                    uint32_t index,
   1.523 +                                    MutableHandleValue vp);
   1.524 +
   1.525 +    template<class T>
   1.526 +    static bool obj_setArrayElement(JSContext *cx,
   1.527 +                                    Handle<TypedObject*> typedObj,
   1.528 +                                    Handle<TypeDescr*> typeDescr,
   1.529 +                                    uint32_t index,
   1.530 +                                    MutableHandleValue vp);
   1.531 +
   1.532 +  protected:
   1.533 +    static void obj_trace(JSTracer *trace, JSObject *object);
   1.534 +
   1.535 +    static bool obj_lookupGeneric(JSContext *cx, HandleObject obj,
   1.536 +                                  HandleId id, MutableHandleObject objp,
   1.537 +                                  MutableHandleShape propp);
   1.538 +
   1.539 +    static bool obj_lookupProperty(JSContext *cx, HandleObject obj,
   1.540 +                                   HandlePropertyName name,
   1.541 +                                   MutableHandleObject objp,
   1.542 +                                   MutableHandleShape propp);
   1.543 +
   1.544 +    static bool obj_lookupElement(JSContext *cx, HandleObject obj,
   1.545 +                                  uint32_t index, MutableHandleObject objp,
   1.546 +                                  MutableHandleShape propp);
   1.547 +
   1.548 +    static bool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
   1.549 +                                  PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
   1.550 +
   1.551 +    static bool obj_defineProperty(JSContext *cx, HandleObject obj,
   1.552 +                                   HandlePropertyName name, HandleValue v,
   1.553 +                                   PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
   1.554 +
   1.555 +    static bool obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
   1.556 +                                  PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
   1.557 +
   1.558 +    static bool obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
   1.559 +                               HandleId id, MutableHandleValue vp);
   1.560 +
   1.561 +    static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
   1.562 +                                HandlePropertyName name, MutableHandleValue vp);
   1.563 +
   1.564 +    static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
   1.565 +                               uint32_t index, MutableHandleValue vp);
   1.566 +
   1.567 +    static bool obj_getUnsizedArrayElement(JSContext *cx, HandleObject obj, HandleObject receiver,
   1.568 +                                         uint32_t index, MutableHandleValue vp);
   1.569 +
   1.570 +    static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
   1.571 +                               MutableHandleValue vp, bool strict);
   1.572 +    static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
   1.573 +                                MutableHandleValue vp, bool strict);
   1.574 +    static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
   1.575 +                               MutableHandleValue vp, bool strict);
   1.576 +
   1.577 +    static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
   1.578 +                                         HandleId id, unsigned *attrsp);
   1.579 +    static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
   1.580 +                                         HandleId id, unsigned *attrsp);
   1.581 +
   1.582 +    static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
   1.583 +                                   bool *succeeded);
   1.584 +    static bool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
   1.585 +                                  bool *succeeded);
   1.586 +
   1.587 +    static bool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
   1.588 +                              MutableHandleValue statep, MutableHandleId idp);
   1.589 +
   1.590 +  public:
   1.591 +    static size_t offsetOfOwnerSlot();
   1.592 +
   1.593 +    // Each typed object contains a void* pointer pointing at the
   1.594 +    // binary data that it represents. (That data may be owned by this
   1.595 +    // object or this object may alias data owned by someone else.)
   1.596 +    // This function returns the offset in bytes within the object
   1.597 +    // where the `void*` pointer can be found. It is intended for use
   1.598 +    // by the JIT.
   1.599 +    static size_t offsetOfDataSlot();
   1.600 +
   1.601 +    // Offset of the byte offset slot.
   1.602 +    static size_t offsetOfByteOffsetSlot();
   1.603 +
   1.604 +    // Helper for createUnattached()
   1.605 +    static TypedObject *createUnattachedWithClass(JSContext *cx,
   1.606 +                                                 const Class *clasp,
   1.607 +                                                 HandleTypeDescr type,
   1.608 +                                                 int32_t length);
   1.609 +
   1.610 +    // Creates an unattached typed object or handle (depending on the
   1.611 +    // type parameter T). Note that it is only legal for unattached
   1.612 +    // handles to escape to the end user; for non-handles, the caller
   1.613 +    // should always invoke one of the `attach()` methods below.
   1.614 +    //
   1.615 +    // Arguments:
   1.616 +    // - type: type object for resulting object
   1.617 +    // - length: 0 unless this is an array, otherwise the length
   1.618 +    static TypedObject *createUnattached(JSContext *cx, HandleTypeDescr type,
   1.619 +                                        int32_t length);
   1.620 +
   1.621 +    // Creates a typedObj that aliases the memory pointed at by `owner`
   1.622 +    // at the given offset. The typedObj will be a handle iff type is a
   1.623 +    // handle and a typed object otherwise.
   1.624 +    static TypedObject *createDerived(JSContext *cx,
   1.625 +                                      HandleSizedTypeDescr type,
   1.626 +                                      Handle<TypedObject*> typedContents,
   1.627 +                                      int32_t offset);
   1.628 +
   1.629 +    // Creates a new typed object whose memory is freshly allocated
   1.630 +    // and initialized with zeroes (or, in the case of references, an
   1.631 +    // appropriate default value).
   1.632 +    static TypedObject *createZeroed(JSContext *cx,
   1.633 +                                     HandleTypeDescr typeObj,
   1.634 +                                     int32_t length);
   1.635 +
   1.636 +    // User-accessible constructor (`new TypeDescriptor(...)`)
   1.637 +    // used for sized types. Note that the callee here is the *type descriptor*,
   1.638 +    // not the typedObj.
   1.639 +    static bool constructSized(JSContext *cx, unsigned argc, Value *vp);
   1.640 +
   1.641 +    // As `constructSized`, but for unsized array types.
   1.642 +    static bool constructUnsized(JSContext *cx, unsigned argc, Value *vp);
   1.643 +
   1.644 +    // Use this method when `buffer` is the owner of the memory.
   1.645 +    void attach(ArrayBufferObject &buffer, int32_t offset);
   1.646 +
   1.647 +    // Otherwise, use this to attach to memory referenced by another typedObj.
   1.648 +    void attach(TypedObject &typedObj, int32_t offset);
   1.649 +
   1.650 +    // Invoked when array buffer is transferred elsewhere
   1.651 +    void neuter(void *newData);
   1.652 +
   1.653 +    int32_t offset() const {
   1.654 +        return getReservedSlot(JS_TYPEDOBJ_SLOT_BYTEOFFSET).toInt32();
   1.655 +    }
   1.656 +
   1.657 +    ArrayBufferObject &owner() const {
   1.658 +        return getReservedSlot(JS_TYPEDOBJ_SLOT_OWNER).toObject().as<ArrayBufferObject>();
   1.659 +    }
   1.660 +
   1.661 +    TypeDescr &typeDescr() const {
   1.662 +        return getReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR).toObject().as<TypeDescr>();
   1.663 +    }
   1.664 +
   1.665 +    uint8_t *typedMem() const {
   1.666 +        return (uint8_t*) getPrivate();
   1.667 +    }
   1.668 +
   1.669 +    int32_t byteLength() const {
   1.670 +        return getReservedSlot(JS_TYPEDOBJ_SLOT_BYTELENGTH).toInt32();
   1.671 +    }
   1.672 +
   1.673 +    int32_t length() const {
   1.674 +        return getReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH).toInt32();
   1.675 +    }
   1.676 +
   1.677 +    int32_t size() const {
   1.678 +        switch (typeDescr().kind()) {
   1.679 +          case TypeDescr::Scalar:
   1.680 +          case TypeDescr::X4:
   1.681 +          case TypeDescr::Reference:
   1.682 +          case TypeDescr::Struct:
   1.683 +          case TypeDescr::SizedArray:
   1.684 +            return typeDescr().as<SizedTypeDescr>().size();
   1.685 +
   1.686 +          case TypeDescr::UnsizedArray: {
   1.687 +            SizedTypeDescr &elementType = typeDescr().as<UnsizedArrayTypeDescr>().elementType();
   1.688 +            return elementType.size() * length();
   1.689 +          }
   1.690 +        }
   1.691 +        MOZ_ASSUME_UNREACHABLE("unhandled typerepresentation kind");
   1.692 +    }
   1.693 +
   1.694 +    uint8_t *typedMem(size_t offset) const {
   1.695 +        // It seems a bit surprising that one might request an offset
   1.696 +        // == size(), but it can happen when taking the "address of" a
   1.697 +        // 0-sized value. (In other words, we maintain the invariant
   1.698 +        // that `offset + size <= size()` -- this is always checked in
   1.699 +        // the caller's side.)
   1.700 +        JS_ASSERT(offset <= (size_t) size());
   1.701 +        return typedMem() + offset;
   1.702 +    }
   1.703 +};
   1.704 +
   1.705 +typedef Handle<TypedObject*> HandleTypedObject;
   1.706 +
   1.707 +class TransparentTypedObject : public TypedObject
   1.708 +{
   1.709 +  public:
   1.710 +    static const Class class_;
   1.711 +};
   1.712 +
   1.713 +typedef Handle<TransparentTypedObject*> HandleTransparentTypedObject;
   1.714 +
   1.715 +class OpaqueTypedObject : public TypedObject
   1.716 +{
   1.717 +  public:
   1.718 +    static const Class class_;
   1.719 +    static const JSFunctionSpec handleStaticMethods[];
   1.720 +};
   1.721 +
   1.722 +/*
   1.723 + * Usage: NewOpaqueTypedObject(typeObj)
   1.724 + *
   1.725 + * Constructs a new, unattached instance of `Handle`.
   1.726 + */
   1.727 +bool NewOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp);
   1.728 +
   1.729 +/*
   1.730 + * Usage: NewDerivedTypedObject(typeObj, owner, offset)
   1.731 + *
   1.732 + * Constructs a new, unattached instance of `Handle`.
   1.733 + */
   1.734 +bool NewDerivedTypedObject(JSContext *cx, unsigned argc, Value *vp);
   1.735 +
   1.736 +/*
   1.737 + * Usage: AttachTypedObject(typedObj, newDatum, newOffset)
   1.738 + *
   1.739 + * Moves `typedObj` to point at the memory referenced by `newDatum` with
   1.740 + * the offset `newOffset`.
   1.741 + */
   1.742 +bool AttachTypedObject(ThreadSafeContext *cx, unsigned argc, Value *vp);
   1.743 +extern const JSJitInfo AttachTypedObjectJitInfo;
   1.744 +
   1.745 +/*
   1.746 + * Usage: SetTypedObjectOffset(typedObj, offset)
   1.747 + *
   1.748 + * Changes the offset for `typedObj` within its buffer to `offset`.
   1.749 + * `typedObj` must already be attached.
   1.750 + */
   1.751 +bool intrinsic_SetTypedObjectOffset(JSContext *cx, unsigned argc, Value *vp);
   1.752 +bool SetTypedObjectOffset(ThreadSafeContext *, unsigned argc, Value *vp);
   1.753 +extern const JSJitInfo intrinsic_SetTypedObjectOffsetJitInfo;
   1.754 +
   1.755 +/*
   1.756 + * Usage: ObjectIsTypeDescr(obj)
   1.757 + *
   1.758 + * True if `obj` is a type object.
   1.759 + */
   1.760 +bool ObjectIsTypeDescr(ThreadSafeContext *cx, unsigned argc, Value *vp);
   1.761 +extern const JSJitInfo ObjectIsTypeDescrJitInfo;
   1.762 +
   1.763 +/*
   1.764 + * Usage: ObjectIsTypedObject(obj)
   1.765 + *
   1.766 + * True if `obj` is a transparent or opaque typed object.
   1.767 + */
   1.768 +bool ObjectIsTypedObject(ThreadSafeContext *cx, unsigned argc, Value *vp);
   1.769 +extern const JSJitInfo ObjectIsTypedObjectJitInfo;
   1.770 +
   1.771 +/*
   1.772 + * Usage: ObjectIsOpaqueTypedObject(obj)
   1.773 + *
   1.774 + * True if `obj` is an opaque typed object.
   1.775 + */
   1.776 +bool ObjectIsOpaqueTypedObject(ThreadSafeContext *cx, unsigned argc, Value *vp);
   1.777 +extern const JSJitInfo ObjectIsOpaqueTypedObjectJitInfo;
   1.778 +
   1.779 +/*
   1.780 + * Usage: ObjectIsTransparentTypedObject(obj)
   1.781 + *
   1.782 + * True if `obj` is a transparent typed object.
   1.783 + */
   1.784 +bool ObjectIsTransparentTypedObject(ThreadSafeContext *cx, unsigned argc, Value *vp);
   1.785 +extern const JSJitInfo ObjectIsTransparentTypedObjectJitInfo;
   1.786 +
   1.787 +/* Predicates on type descriptor objects.  In all cases, 'obj' must be a type descriptor. */
   1.788 +
   1.789 +bool TypeDescrIsSimpleType(ThreadSafeContext *, unsigned argc, Value *vp);
   1.790 +extern const JSJitInfo TypeDescrIsSimpleTypeJitInfo;
   1.791 +
   1.792 +bool TypeDescrIsArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
   1.793 +extern const JSJitInfo TypeDescrIsArrayTypeJitInfo;
   1.794 +
   1.795 +bool TypeDescrIsSizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
   1.796 +extern const JSJitInfo TypeDescrIsSizedArrayTypeJitInfo;
   1.797 +
   1.798 +bool TypeDescrIsUnsizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
   1.799 +extern const JSJitInfo TypeDescrIsUnsizedArrayTypeJitInfo;
   1.800 +
   1.801 +/*
   1.802 + * Usage: TypedObjectIsAttached(obj)
   1.803 + *
   1.804 + * Given a TypedObject `obj`, returns true if `obj` is
   1.805 + * "attached" (i.e., its data pointer is nullptr).
   1.806 + */
   1.807 +bool TypedObjectIsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp);
   1.808 +extern const JSJitInfo TypedObjectIsAttachedJitInfo;
   1.809 +
   1.810 +/*
   1.811 + * Usage: ClampToUint8(v)
   1.812 + *
   1.813 + * Same as the C function ClampDoubleToUint8. `v` must be a number.
   1.814 + */
   1.815 +bool ClampToUint8(ThreadSafeContext *cx, unsigned argc, Value *vp);
   1.816 +extern const JSJitInfo ClampToUint8JitInfo;
   1.817 +
   1.818 +/*
   1.819 + * Usage: Memcpy(targetDatum, targetOffset,
   1.820 + *               sourceDatum, sourceOffset,
   1.821 + *               size)
   1.822 + *
   1.823 + * Intrinsic function. Copies size bytes from the data for
   1.824 + * `sourceDatum` at `sourceOffset` into the data for
   1.825 + * `targetDatum` at `targetOffset`.
   1.826 + *
   1.827 + * Both `sourceDatum` and `targetDatum` must be attached.
   1.828 + */
   1.829 +bool Memcpy(ThreadSafeContext *cx, unsigned argc, Value *vp);
   1.830 +extern const JSJitInfo MemcpyJitInfo;
   1.831 +
   1.832 +/*
   1.833 + * Usage: GetTypedObjectModule()
   1.834 + *
   1.835 + * Returns the global "typed object" module, which provides access
   1.836 + * to the various builtin type descriptors. These are currently
   1.837 + * exported as immutable properties so it is safe for self-hosted code
   1.838 + * to access them; eventually this should be linked into the module
   1.839 + * system.
   1.840 + */
   1.841 +bool GetTypedObjectModule(JSContext *cx, unsigned argc, Value *vp);
   1.842 +
   1.843 +/*
   1.844 + * Usage: GetFloat32x4TypeDescr()
   1.845 + *
   1.846 + * Returns the float32x4 type object. SIMD pseudo-module must have
   1.847 + * been initialized for this to be safe.
   1.848 + */
   1.849 +bool GetFloat32x4TypeDescr(JSContext *cx, unsigned argc, Value *vp);
   1.850 +
   1.851 +/*
   1.852 + * Usage: GetInt32x4TypeDescr()
   1.853 + *
   1.854 + * Returns the int32x4 type object. SIMD pseudo-module must have
   1.855 + * been initialized for this to be safe.
   1.856 + */
   1.857 +bool GetInt32x4TypeDescr(JSContext *cx, unsigned argc, Value *vp);
   1.858 +
   1.859 +/*
   1.860 + * Usage: Store_int8(targetDatum, targetOffset, value)
   1.861 + *        ...
   1.862 + *        Store_uint8(targetDatum, targetOffset, value)
   1.863 + *        ...
   1.864 + *        Store_float32(targetDatum, targetOffset, value)
   1.865 + *        Store_float64(targetDatum, targetOffset, value)
   1.866 + *
   1.867 + * Intrinsic function. Stores `value` into the memory referenced by
   1.868 + * `targetDatum` at the offset `targetOffset`.
   1.869 + *
   1.870 + * Assumes (and asserts) that:
   1.871 + * - `targetDatum` is attached
   1.872 + * - `targetOffset` is a valid offset within the bounds of `targetDatum`
   1.873 + * - `value` is a number
   1.874 + */
   1.875 +#define JS_STORE_SCALAR_CLASS_DEFN(_constant, T, _name)                       \
   1.876 +class StoreScalar##T {                                                        \
   1.877 +  public:                                                                     \
   1.878 +    static bool Func(ThreadSafeContext *cx, unsigned argc, Value *vp);        \
   1.879 +    static const JSJitInfo JitInfo;                                           \
   1.880 +};
   1.881 +
   1.882 +/*
   1.883 + * Usage: Store_Any(targetDatum, targetOffset, value)
   1.884 + *        Store_Object(targetDatum, targetOffset, value)
   1.885 + *        Store_string(targetDatum, targetOffset, value)
   1.886 + *
   1.887 + * Intrinsic function. Stores `value` into the memory referenced by
   1.888 + * `targetDatum` at the offset `targetOffset`.
   1.889 + *
   1.890 + * Assumes (and asserts) that:
   1.891 + * - `targetDatum` is attached
   1.892 + * - `targetOffset` is a valid offset within the bounds of `targetDatum`
   1.893 + * - `value` is an object (`Store_Object`) or string (`Store_string`).
   1.894 + */
   1.895 +#define JS_STORE_REFERENCE_CLASS_DEFN(_constant, T, _name)                    \
   1.896 +class StoreReference##T {                                                     \
   1.897 +  private:                                                                    \
   1.898 +    static void store(T* heap, const Value &v);                               \
   1.899 +                                                                              \
   1.900 +  public:                                                                     \
   1.901 +    static bool Func(ThreadSafeContext *cx, unsigned argc, Value *vp);        \
   1.902 +    static const JSJitInfo JitInfo;                                           \
   1.903 +};
   1.904 +
   1.905 +/*
   1.906 + * Usage: LoadScalar(targetDatum, targetOffset, value)
   1.907 + *
   1.908 + * Intrinsic function. Loads value (which must be an int32 or uint32)
   1.909 + * by `scalarTypeRepr` (which must be a type repr obj) and loads the
   1.910 + * value at the memory for `targetDatum` at offset `targetOffset`.
   1.911 + * `targetDatum` must be attached.
   1.912 + */
   1.913 +#define JS_LOAD_SCALAR_CLASS_DEFN(_constant, T, _name)                        \
   1.914 +class LoadScalar##T {                                                         \
   1.915 +  public:                                                                     \
   1.916 +    static bool Func(ThreadSafeContext *cx, unsigned argc, Value *vp);        \
   1.917 +    static const JSJitInfo JitInfo;                                           \
   1.918 +};
   1.919 +
   1.920 +/*
   1.921 + * Usage: LoadReference(targetDatum, targetOffset, value)
   1.922 + *
   1.923 + * Intrinsic function. Stores value (which must be an int32 or uint32)
   1.924 + * by `scalarTypeRepr` (which must be a type repr obj) and stores the
   1.925 + * value at the memory for `targetDatum` at offset `targetOffset`.
   1.926 + * `targetDatum` must be attached.
   1.927 + */
   1.928 +#define JS_LOAD_REFERENCE_CLASS_DEFN(_constant, T, _name)                     \
   1.929 +class LoadReference##T {                                                      \
   1.930 +  private:                                                                    \
   1.931 +    static void load(T* heap, MutableHandleValue v);                          \
   1.932 +                                                                              \
   1.933 +  public:                                                                     \
   1.934 +    static bool Func(ThreadSafeContext *cx, unsigned argc, Value *vp);        \
   1.935 +    static const JSJitInfo JitInfo;                                           \
   1.936 +};
   1.937 +
   1.938 +// I was using templates for this stuff instead of macros, but ran
   1.939 +// into problems with the Unagi compiler.
   1.940 +JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_STORE_SCALAR_CLASS_DEFN)
   1.941 +JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_LOAD_SCALAR_CLASS_DEFN)
   1.942 +JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_STORE_REFERENCE_CLASS_DEFN)
   1.943 +JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_DEFN)
   1.944 +
   1.945 +inline bool
   1.946 +IsTypedObjectClass(const Class *class_)
   1.947 +{
   1.948 +    return class_ == &TransparentTypedObject::class_ ||
   1.949 +           class_ == &OpaqueTypedObject::class_;
   1.950 +}
   1.951 +
   1.952 +inline bool
   1.953 +IsSimpleTypeDescrClass(const Class* clasp)
   1.954 +{
   1.955 +    return clasp == &ScalarTypeDescr::class_ ||
   1.956 +           clasp == &ReferenceTypeDescr::class_;
   1.957 +}
   1.958 +
   1.959 +inline bool
   1.960 +IsComplexTypeDescrClass(const Class* clasp)
   1.961 +{
   1.962 +    return clasp == &StructTypeDescr::class_ ||
   1.963 +           clasp == &SizedArrayTypeDescr::class_ ||
   1.964 +           clasp == &X4TypeDescr::class_;
   1.965 +}
   1.966 +
   1.967 +inline bool
   1.968 +IsSizedTypeDescrClass(const Class* clasp)
   1.969 +{
   1.970 +    return IsSimpleTypeDescrClass(clasp) ||
   1.971 +           IsComplexTypeDescrClass(clasp);
   1.972 +}
   1.973 +
   1.974 +inline bool
   1.975 +IsTypeDescrClass(const Class* clasp)
   1.976 +{
   1.977 +    return IsSizedTypeDescrClass(clasp) ||
   1.978 +           clasp == &UnsizedArrayTypeDescr::class_;
   1.979 +}
   1.980 +
   1.981 +} // namespace js
   1.982 +
   1.983 +JSObject *
   1.984 +js_InitTypedObjectModuleObject(JSContext *cx, JS::HandleObject obj);
   1.985 +
   1.986 +template <>
   1.987 +inline bool
   1.988 +JSObject::is<js::SimpleTypeDescr>() const
   1.989 +{
   1.990 +    return IsSimpleTypeDescrClass(getClass());
   1.991 +}
   1.992 +
   1.993 +template <>
   1.994 +inline bool
   1.995 +JSObject::is<js::SizedTypeDescr>() const
   1.996 +{
   1.997 +    return IsSizedTypeDescrClass(getClass());
   1.998 +}
   1.999 +
  1.1000 +template <>
  1.1001 +inline bool
  1.1002 +JSObject::is<js::ComplexTypeDescr>() const
  1.1003 +{
  1.1004 +    return IsComplexTypeDescrClass(getClass());
  1.1005 +}
  1.1006 +
  1.1007 +template <>
  1.1008 +inline bool
  1.1009 +JSObject::is<js::TypeDescr>() const
  1.1010 +{
  1.1011 +    return IsTypeDescrClass(getClass());
  1.1012 +}
  1.1013 +
  1.1014 +template <>
  1.1015 +inline bool
  1.1016 +JSObject::is<js::TypedObject>() const
  1.1017 +{
  1.1018 +    return IsTypedObjectClass(getClass());
  1.1019 +}
  1.1020 +
  1.1021 +template<>
  1.1022 +inline bool
  1.1023 +JSObject::is<js::SizedArrayTypeDescr>() const
  1.1024 +{
  1.1025 +    return getClass() == &js::SizedArrayTypeDescr::class_;
  1.1026 +}
  1.1027 +
  1.1028 +template<>
  1.1029 +inline bool
  1.1030 +JSObject::is<js::UnsizedArrayTypeDescr>() const
  1.1031 +{
  1.1032 +    return getClass() == &js::UnsizedArrayTypeDescr::class_;
  1.1033 +}
  1.1034 +
  1.1035 +inline void
  1.1036 +js::TypedProto::initTypeDescrSlot(TypeDescr &descr)
  1.1037 +{
  1.1038 +    initReservedSlot(JS_TYPROTO_SLOT_DESCR, ObjectValue(descr));
  1.1039 +}
  1.1040 +
  1.1041 +#endif /* builtin_TypedObject_h */

mercurial