js/src/builtin/TypedObject.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
michael@0 2 * vim: set ts=8 sts=4 et sw=4 tw=99:
michael@0 3 * This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #ifndef builtin_TypedObject_h
michael@0 8 #define builtin_TypedObject_h
michael@0 9
michael@0 10 #include "jsobj.h"
michael@0 11
michael@0 12 #include "builtin/TypedObjectConstants.h"
michael@0 13 #include "vm/ArrayBufferObject.h"
michael@0 14
michael@0 15 /*
michael@0 16 * -------------
michael@0 17 * Typed Objects
michael@0 18 * -------------
michael@0 19 *
michael@0 20 * Typed objects are a special kind of JS object where the data is
michael@0 21 * given well-structured form. To use a typed object, users first
michael@0 22 * create *type objects* (no relation to the type objects used in TI)
michael@0 23 * that define the type layout. For example, a statement like:
michael@0 24 *
michael@0 25 * var PointType = new StructType({x: uint8, y: uint8});
michael@0 26 *
michael@0 27 * would create a type object PointType that is a struct with
michael@0 28 * two fields, each of uint8 type.
michael@0 29 *
michael@0 30 * This comment typically assumes familiary with the API. For more
michael@0 31 * info on the API itself, see the Harmony wiki page at
michael@0 32 * http://wiki.ecmascript.org/doku.php?id=harmony:typed_objects or the
michael@0 33 * ES6 spec (not finalized at the time of this writing).
michael@0 34 *
michael@0 35 * - Initialization:
michael@0 36 *
michael@0 37 * Currently, all "globals" related to typed objects are packaged
michael@0 38 * within a single "module" object `TypedObject`. This module has its
michael@0 39 * own js::Class and when that class is initialized, we also create
michael@0 40 * and define all other values (in `js_InitTypedObjectModuleClass()`).
michael@0 41 *
michael@0 42 * - Type objects, meta type objects, and type representations:
michael@0 43 *
michael@0 44 * There are a number of pre-defined type objects, one for each
michael@0 45 * scalar type (`uint8` etc). Each of these has its own class_,
michael@0 46 * defined in `DefineNumericClass()`.
michael@0 47 *
michael@0 48 * There are also meta type objects (`ArrayType`, `StructType`).
michael@0 49 * These constructors are not themselves type objects but rather the
michael@0 50 * means for the *user* to construct new typed objects.
michael@0 51 *
michael@0 52 * Each type object is associated with a *type representation* (see
michael@0 53 * TypeRepresentation.h). Type representations are canonical versions
michael@0 54 * of type objects. We attach them to TI type objects and (eventually)
michael@0 55 * use them for shape guards etc. They are purely internal to the
michael@0 56 * engine and are not exposed to end users (though self-hosted code
michael@0 57 * sometimes accesses them).
michael@0 58 *
michael@0 59 * - Typed objects:
michael@0 60 *
michael@0 61 * A typed object is an instance of a *type object* (note the past
michael@0 62 * participle). There is one class for *transparent* typed objects and
michael@0 63 * one for *opaque* typed objects. These classes are equivalent in
michael@0 64 * basically every way, except that requesting the backing buffer of
michael@0 65 * an opaque typed object yields null. We use distinct js::Classes to
michael@0 66 * avoid the need for an extra slot in every typed object.
michael@0 67 *
michael@0 68 * Note that whether a typed object is opaque is not directly
michael@0 69 * connected to its type. That is, opaque types are *always*
michael@0 70 * represented by opaque typed objects, but you may have opaque typed
michael@0 71 * objects for transparent types too. This can occur for two reasons:
michael@0 72 * (1) a transparent type may be embedded within an opaque type or (2)
michael@0 73 * users can choose to convert transparent typed objects into opaque
michael@0 74 * ones to avoid giving access to the buffer itself.
michael@0 75 *
michael@0 76 * Typed objects (no matter their class) are non-native objects that
michael@0 77 * fully override the property accessors etc. The overridden accessor
michael@0 78 * methods are the same in each and are defined in methods of
michael@0 79 * TypedObject.
michael@0 80 *
michael@0 81 * Typed objects may be attached or unattached. An unattached typed
michael@0 82 * object has no memory associated with it; it is basically a null
michael@0 83 * pointer. When first created, objects are always attached, but they
michael@0 84 * can become unattached if their buffer is neutered (note that this
michael@0 85 * implies that typed objects of opaque types can never be unattached).
michael@0 86 *
michael@0 87 * When a new typed object instance is created, fresh memory is
michael@0 88 * allocated and set as that typed object's private field. The object
michael@0 89 * is then considered the *owner* of that memory: when the object is
michael@0 90 * collected, its finalizer will free the memory. The fact that an
michael@0 91 * object `o` owns its memory is indicated by setting its reserved
michael@0 92 * slot JS_TYPEDOBJ_SLOT_OWNER to `o` (a trivial cycle, in other
michael@0 93 * words).
michael@0 94 *
michael@0 95 * Later, *derived* typed objects can be created, typically via an
michael@0 96 * access like `o.f` where `f` is some complex (non-scalar) type, but
michael@0 97 * also explicitly via Handle objects. In those cases, the memory
michael@0 98 * pointer of the derived object is set to alias the owner's memory
michael@0 99 * pointer, and the owner slot for the derived object is set to the
michael@0 100 * owner object, thus ensuring that the owner is not collected while
michael@0 101 * the derived object is alive. We always maintain the invariant that
michael@0 102 * JS_TYPEDOBJ_SLOT_OWNER is the true owner of the memory, meaning
michael@0 103 * that there is a shallow tree. This prevents an access pattern like
michael@0 104 * `a.b.c.d` from keeping all the intermediate objects alive.
michael@0 105 */
michael@0 106
michael@0 107 namespace js {
michael@0 108
michael@0 109 /*
michael@0 110 * Helper method for converting a double into other scalar
michael@0 111 * types in the same way that JavaScript would. In particular,
michael@0 112 * simple C casting from double to int32_t gets things wrong
michael@0 113 * for values like 0xF0000000.
michael@0 114 */
michael@0 115 template <typename T>
michael@0 116 static T ConvertScalar(double d)
michael@0 117 {
michael@0 118 if (TypeIsFloatingPoint<T>()) {
michael@0 119 return T(d);
michael@0 120 } else if (TypeIsUnsigned<T>()) {
michael@0 121 uint32_t n = ToUint32(d);
michael@0 122 return T(n);
michael@0 123 } else {
michael@0 124 int32_t n = ToInt32(d);
michael@0 125 return T(n);
michael@0 126 }
michael@0 127 }
michael@0 128
michael@0 129 /*
michael@0 130 * The prototype for a typed object. Currently, carries a link to the
michael@0 131 * type descriptor. Eventually will carry most of the type information
michael@0 132 * we want.
michael@0 133 */
michael@0 134 class TypedProto : public JSObject
michael@0 135 {
michael@0 136 public:
michael@0 137 static const Class class_;
michael@0 138
michael@0 139 inline void initTypeDescrSlot(TypeDescr &descr);
michael@0 140
michael@0 141 TypeDescr &typeDescr() const {
michael@0 142 return getReservedSlot(JS_TYPROTO_SLOT_DESCR).toObject().as<TypeDescr>();
michael@0 143 }
michael@0 144 };
michael@0 145
michael@0 146 class TypeDescr : public JSObject
michael@0 147 {
michael@0 148 public:
michael@0 149 // This is *intentionally* not defined so as to produce link
michael@0 150 // errors if a is<FooTypeDescr>() etc goes wrong. Otherwise, the
michael@0 151 // default implementation resolves this to a reference to
michael@0 152 // FooTypeDescr::class_ which resolves to
michael@0 153 // JSObject::class_. Debugging the resulting errors leads to much
michael@0 154 // fun and rejoicing.
michael@0 155 static const Class class_;
michael@0 156
michael@0 157 enum Kind {
michael@0 158 Scalar = JS_TYPEREPR_SCALAR_KIND,
michael@0 159 Reference = JS_TYPEREPR_REFERENCE_KIND,
michael@0 160 X4 = JS_TYPEREPR_X4_KIND,
michael@0 161 Struct = JS_TYPEREPR_STRUCT_KIND,
michael@0 162 SizedArray = JS_TYPEREPR_SIZED_ARRAY_KIND,
michael@0 163 UnsizedArray = JS_TYPEREPR_UNSIZED_ARRAY_KIND,
michael@0 164 };
michael@0 165
michael@0 166 static bool isSized(Kind kind) {
michael@0 167 return kind > JS_TYPEREPR_MAX_UNSIZED_KIND;
michael@0 168 }
michael@0 169
michael@0 170 JSAtom &stringRepr() const {
michael@0 171 return getReservedSlot(JS_DESCR_SLOT_STRING_REPR).toString()->asAtom();
michael@0 172 }
michael@0 173
michael@0 174 TypeDescr::Kind kind() const {
michael@0 175 return (TypeDescr::Kind) getReservedSlot(JS_DESCR_SLOT_KIND).toInt32();
michael@0 176 }
michael@0 177
michael@0 178 bool opaque() const {
michael@0 179 return getReservedSlot(JS_DESCR_SLOT_OPAQUE).toBoolean();
michael@0 180 }
michael@0 181
michael@0 182 bool transparent() const {
michael@0 183 return !opaque();
michael@0 184 }
michael@0 185
michael@0 186 int32_t alignment() {
michael@0 187 return getReservedSlot(JS_DESCR_SLOT_ALIGNMENT).toInt32();
michael@0 188 }
michael@0 189 };
michael@0 190
michael@0 191 typedef Handle<TypeDescr*> HandleTypeDescr;
michael@0 192
michael@0 193 class SizedTypeDescr : public TypeDescr
michael@0 194 {
michael@0 195 public:
michael@0 196 int32_t size() {
michael@0 197 return getReservedSlot(JS_DESCR_SLOT_SIZE).toInt32();
michael@0 198 }
michael@0 199
michael@0 200 void initInstances(const JSRuntime *rt, uint8_t *mem, size_t length);
michael@0 201 void traceInstances(JSTracer *trace, uint8_t *mem, size_t length);
michael@0 202 };
michael@0 203
michael@0 204 typedef Handle<SizedTypeDescr*> HandleSizedTypeDescr;
michael@0 205
michael@0 206 class SimpleTypeDescr : public SizedTypeDescr
michael@0 207 {
michael@0 208 };
michael@0 209
michael@0 210 // Type for scalar type constructors like `uint8`. All such type
michael@0 211 // constructors share a common js::Class and JSFunctionSpec. Scalar
michael@0 212 // types are non-opaque (their storage is visible unless combined with
michael@0 213 // an opaque reference type.)
michael@0 214 class ScalarTypeDescr : public SimpleTypeDescr
michael@0 215 {
michael@0 216 public:
michael@0 217 // Must match order of JS_FOR_EACH_SCALAR_TYPE_REPR below
michael@0 218 enum Type {
michael@0 219 TYPE_INT8 = JS_SCALARTYPEREPR_INT8,
michael@0 220 TYPE_UINT8 = JS_SCALARTYPEREPR_UINT8,
michael@0 221 TYPE_INT16 = JS_SCALARTYPEREPR_INT16,
michael@0 222 TYPE_UINT16 = JS_SCALARTYPEREPR_UINT16,
michael@0 223 TYPE_INT32 = JS_SCALARTYPEREPR_INT32,
michael@0 224 TYPE_UINT32 = JS_SCALARTYPEREPR_UINT32,
michael@0 225 TYPE_FLOAT32 = JS_SCALARTYPEREPR_FLOAT32,
michael@0 226 TYPE_FLOAT64 = JS_SCALARTYPEREPR_FLOAT64,
michael@0 227
michael@0 228 /*
michael@0 229 * Special type that's a uint8_t, but assignments are clamped to 0 .. 255.
michael@0 230 * Treat the raw data type as a uint8_t.
michael@0 231 */
michael@0 232 TYPE_UINT8_CLAMPED = JS_SCALARTYPEREPR_UINT8_CLAMPED,
michael@0 233 };
michael@0 234 static const int32_t TYPE_MAX = TYPE_UINT8_CLAMPED + 1;
michael@0 235
michael@0 236 static const TypeDescr::Kind Kind = TypeDescr::Scalar;
michael@0 237 static const bool Opaque = false;
michael@0 238 static int32_t size(Type t);
michael@0 239 static int32_t alignment(Type t);
michael@0 240 static const char *typeName(Type type);
michael@0 241
michael@0 242 static const Class class_;
michael@0 243 static const JSFunctionSpec typeObjectMethods[];
michael@0 244
michael@0 245 ScalarTypeDescr::Type type() const {
michael@0 246 return (ScalarTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
michael@0 247 }
michael@0 248
michael@0 249 static bool call(JSContext *cx, unsigned argc, Value *vp);
michael@0 250 };
michael@0 251
michael@0 252 // Enumerates the cases of ScalarTypeDescr::Type which have
michael@0 253 // unique C representation. In particular, omits Uint8Clamped since it
michael@0 254 // is just a Uint8.
michael@0 255 #define JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_) \
michael@0 256 macro_(ScalarTypeDescr::TYPE_INT8, int8_t, int8) \
michael@0 257 macro_(ScalarTypeDescr::TYPE_UINT8, uint8_t, uint8) \
michael@0 258 macro_(ScalarTypeDescr::TYPE_INT16, int16_t, int16) \
michael@0 259 macro_(ScalarTypeDescr::TYPE_UINT16, uint16_t, uint16) \
michael@0 260 macro_(ScalarTypeDescr::TYPE_INT32, int32_t, int32) \
michael@0 261 macro_(ScalarTypeDescr::TYPE_UINT32, uint32_t, uint32) \
michael@0 262 macro_(ScalarTypeDescr::TYPE_FLOAT32, float, float32) \
michael@0 263 macro_(ScalarTypeDescr::TYPE_FLOAT64, double, float64)
michael@0 264
michael@0 265 // Must be in same order as the enum ScalarTypeDescr::Type:
michael@0 266 #define JS_FOR_EACH_SCALAR_TYPE_REPR(macro_) \
michael@0 267 JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(macro_) \
michael@0 268 macro_(ScalarTypeDescr::TYPE_UINT8_CLAMPED, uint8_t, uint8Clamped)
michael@0 269
michael@0 270 // Type for reference type constructors like `Any`, `String`, and
michael@0 271 // `Object`. All such type constructors share a common js::Class and
michael@0 272 // JSFunctionSpec. All these types are opaque.
michael@0 273 class ReferenceTypeDescr : public SimpleTypeDescr
michael@0 274 {
michael@0 275 public:
michael@0 276 // Must match order of JS_FOR_EACH_REFERENCE_TYPE_REPR below
michael@0 277 enum Type {
michael@0 278 TYPE_ANY = JS_REFERENCETYPEREPR_ANY,
michael@0 279 TYPE_OBJECT = JS_REFERENCETYPEREPR_OBJECT,
michael@0 280 TYPE_STRING = JS_REFERENCETYPEREPR_STRING,
michael@0 281 };
michael@0 282 static const int32_t TYPE_MAX = TYPE_STRING + 1;
michael@0 283 static const char *typeName(Type type);
michael@0 284
michael@0 285 static const TypeDescr::Kind Kind = TypeDescr::Reference;
michael@0 286 static const bool Opaque = true;
michael@0 287 static const Class class_;
michael@0 288 static int32_t size(Type t);
michael@0 289 static int32_t alignment(Type t);
michael@0 290 static const JSFunctionSpec typeObjectMethods[];
michael@0 291
michael@0 292 ReferenceTypeDescr::Type type() const {
michael@0 293 return (ReferenceTypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
michael@0 294 }
michael@0 295
michael@0 296 const char *typeName() const {
michael@0 297 return typeName(type());
michael@0 298 }
michael@0 299
michael@0 300 static bool call(JSContext *cx, unsigned argc, Value *vp);
michael@0 301 };
michael@0 302
michael@0 303 #define JS_FOR_EACH_REFERENCE_TYPE_REPR(macro_) \
michael@0 304 macro_(ReferenceTypeDescr::TYPE_ANY, HeapValue, Any) \
michael@0 305 macro_(ReferenceTypeDescr::TYPE_OBJECT, HeapPtrObject, Object) \
michael@0 306 macro_(ReferenceTypeDescr::TYPE_STRING, HeapPtrString, string)
michael@0 307
michael@0 308 // Type descriptors whose instances are objects and hence which have
michael@0 309 // an associated `prototype` property.
michael@0 310 class ComplexTypeDescr : public SizedTypeDescr
michael@0 311 {
michael@0 312 public:
michael@0 313 // Returns the prototype that instances of this type descriptor
michael@0 314 // will have.
michael@0 315 TypedProto &instancePrototype() const {
michael@0 316 return getReservedSlot(JS_DESCR_SLOT_TYPROTO).toObject().as<TypedProto>();
michael@0 317 }
michael@0 318 };
michael@0 319
michael@0 320 /*
michael@0 321 * Type descriptors `float32x4` and `int32x4`
michael@0 322 */
michael@0 323 class X4TypeDescr : public ComplexTypeDescr
michael@0 324 {
michael@0 325 public:
michael@0 326 enum Type {
michael@0 327 TYPE_INT32 = JS_X4TYPEREPR_INT32,
michael@0 328 TYPE_FLOAT32 = JS_X4TYPEREPR_FLOAT32,
michael@0 329 };
michael@0 330
michael@0 331 static const TypeDescr::Kind Kind = TypeDescr::X4;
michael@0 332 static const bool Opaque = false;
michael@0 333 static const Class class_;
michael@0 334 static int32_t size(Type t);
michael@0 335 static int32_t alignment(Type t);
michael@0 336
michael@0 337 X4TypeDescr::Type type() const {
michael@0 338 return (X4TypeDescr::Type) getReservedSlot(JS_DESCR_SLOT_TYPE).toInt32();
michael@0 339 }
michael@0 340
michael@0 341 static bool call(JSContext *cx, unsigned argc, Value *vp);
michael@0 342 static bool is(const Value &v);
michael@0 343 };
michael@0 344
michael@0 345 #define JS_FOR_EACH_X4_TYPE_REPR(macro_) \
michael@0 346 macro_(X4TypeDescr::TYPE_INT32, int32_t, int32) \
michael@0 347 macro_(X4TypeDescr::TYPE_FLOAT32, float, float32)
michael@0 348
michael@0 349 bool IsTypedObjectClass(const Class *clasp); // Defined below
michael@0 350 bool IsTypedObjectArray(JSObject& obj);
michael@0 351
michael@0 352 bool CreateUserSizeAndAlignmentProperties(JSContext *cx, HandleTypeDescr obj);
michael@0 353
michael@0 354 /*
michael@0 355 * Properties and methods of the `ArrayType` meta type object. There
michael@0 356 * is no `class_` field because `ArrayType` is just a native
michael@0 357 * constructor function.
michael@0 358 */
michael@0 359 class ArrayMetaTypeDescr : public JSObject
michael@0 360 {
michael@0 361 private:
michael@0 362 friend class UnsizedArrayTypeDescr;
michael@0 363
michael@0 364 // Helper for creating a new ArrayType object, either sized or unsized.
michael@0 365 // The template parameter `T` should be either `UnsizedArrayTypeDescr`
michael@0 366 // or `SizedArrayTypeDescr`.
michael@0 367 //
michael@0 368 // - `arrayTypePrototype` - prototype for the new object to be created,
michael@0 369 // either ArrayType.prototype or
michael@0 370 // unsizedArrayType.__proto__ depending on
michael@0 371 // whether this is a sized or unsized array
michael@0 372 // - `elementType` - type object for the elements in the array
michael@0 373 // - `stringRepr` - canonical string representation for the array
michael@0 374 // - `size` - length of the array (0 if unsized)
michael@0 375 template<class T>
michael@0 376 static T *create(JSContext *cx,
michael@0 377 HandleObject arrayTypePrototype,
michael@0 378 HandleSizedTypeDescr elementType,
michael@0 379 HandleAtom stringRepr,
michael@0 380 int32_t size);
michael@0 381
michael@0 382 public:
michael@0 383 // Properties and methods to be installed on ArrayType.prototype,
michael@0 384 // and hence inherited by all array type objects:
michael@0 385 static const JSPropertySpec typeObjectProperties[];
michael@0 386 static const JSFunctionSpec typeObjectMethods[];
michael@0 387
michael@0 388 // Properties and methods to be installed on ArrayType.prototype.prototype,
michael@0 389 // and hence inherited by all array *typed* objects:
michael@0 390 static const JSPropertySpec typedObjectProperties[];
michael@0 391 static const JSFunctionSpec typedObjectMethods[];
michael@0 392
michael@0 393 // This is the function that gets called when the user
michael@0 394 // does `new ArrayType(elem)`. It produces an array type object.
michael@0 395 static bool construct(JSContext *cx, unsigned argc, Value *vp);
michael@0 396 };
michael@0 397
michael@0 398 /*
michael@0 399 * Type descriptor created by `new ArrayType(typeObj)`
michael@0 400 *
michael@0 401 * These have a prototype, and hence *could* be a subclass of
michael@0 402 * `ComplexTypeDescr`, but it would require some reshuffling of the
michael@0 403 * hierarchy, and it's not worth the trouble since they will be going
michael@0 404 * away as part of bug 973238.
michael@0 405 */
michael@0 406 class UnsizedArrayTypeDescr : public TypeDescr
michael@0 407 {
michael@0 408 public:
michael@0 409 static const Class class_;
michael@0 410 static const TypeDescr::Kind Kind = TypeDescr::UnsizedArray;
michael@0 411
michael@0 412 // This is the sized method on unsized array type objects. It
michael@0 413 // produces a sized variant.
michael@0 414 static bool dimension(JSContext *cx, unsigned int argc, jsval *vp);
michael@0 415
michael@0 416 SizedTypeDescr &elementType() {
michael@0 417 return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>();
michael@0 418 }
michael@0 419 };
michael@0 420
michael@0 421 /*
michael@0 422 * Type descriptor created by `unsizedArrayTypeObj.dimension()`
michael@0 423 */
michael@0 424 class SizedArrayTypeDescr : public ComplexTypeDescr
michael@0 425 {
michael@0 426 public:
michael@0 427 static const Class class_;
michael@0 428 static const TypeDescr::Kind Kind = TypeDescr::SizedArray;
michael@0 429
michael@0 430 SizedTypeDescr &elementType() {
michael@0 431 return getReservedSlot(JS_DESCR_SLOT_ARRAY_ELEM_TYPE).toObject().as<SizedTypeDescr>();
michael@0 432 }
michael@0 433
michael@0 434 int32_t length() {
michael@0 435 return getReservedSlot(JS_DESCR_SLOT_SIZED_ARRAY_LENGTH).toInt32();
michael@0 436 }
michael@0 437 };
michael@0 438
michael@0 439 /*
michael@0 440 * Properties and methods of the `StructType` meta type object. There
michael@0 441 * is no `class_` field because `StructType` is just a native
michael@0 442 * constructor function.
michael@0 443 */
michael@0 444 class StructMetaTypeDescr : public JSObject
michael@0 445 {
michael@0 446 private:
michael@0 447 static JSObject *create(JSContext *cx, HandleObject structTypeGlobal,
michael@0 448 HandleObject fields);
michael@0 449
michael@0 450 public:
michael@0 451 // Properties and methods to be installed on StructType.prototype,
michael@0 452 // and hence inherited by all struct type objects:
michael@0 453 static const JSPropertySpec typeObjectProperties[];
michael@0 454 static const JSFunctionSpec typeObjectMethods[];
michael@0 455
michael@0 456 // Properties and methods to be installed on StructType.prototype.prototype,
michael@0 457 // and hence inherited by all struct *typed* objects:
michael@0 458 static const JSPropertySpec typedObjectProperties[];
michael@0 459 static const JSFunctionSpec typedObjectMethods[];
michael@0 460
michael@0 461 // This is the function that gets called when the user
michael@0 462 // does `new StructType(...)`. It produces a struct type object.
michael@0 463 static bool construct(JSContext *cx, unsigned argc, Value *vp);
michael@0 464 };
michael@0 465
michael@0 466 class StructTypeDescr : public ComplexTypeDescr
michael@0 467 {
michael@0 468 public:
michael@0 469 static const Class class_;
michael@0 470
michael@0 471 // Returns the number of fields defined in this struct.
michael@0 472 size_t fieldCount();
michael@0 473
michael@0 474 // Set `*out` to the index of the field named `id` and returns true,
michael@0 475 // or return false if no such field exists.
michael@0 476 bool fieldIndex(jsid id, size_t *out);
michael@0 477
michael@0 478 // Return the name of the field at index `index`.
michael@0 479 JSAtom &fieldName(size_t index);
michael@0 480
michael@0 481 // Return the type descr of the field at index `index`.
michael@0 482 SizedTypeDescr &fieldDescr(size_t index);
michael@0 483
michael@0 484 // Return the offset of the field at index `index`.
michael@0 485 int32_t fieldOffset(size_t index);
michael@0 486 };
michael@0 487
michael@0 488 typedef Handle<StructTypeDescr*> HandleStructTypeDescr;
michael@0 489
michael@0 490 /*
michael@0 491 * This object exists in order to encapsulate the typed object types
michael@0 492 * somewhat, rather than sticking them all into the global object.
michael@0 493 * Eventually it will go away and become a module.
michael@0 494 */
michael@0 495 class TypedObjectModuleObject : public JSObject {
michael@0 496 public:
michael@0 497 enum Slot {
michael@0 498 ArrayTypePrototype,
michael@0 499 StructTypePrototype,
michael@0 500 SlotCount
michael@0 501 };
michael@0 502
michael@0 503 static const Class class_;
michael@0 504 };
michael@0 505
michael@0 506 /*
michael@0 507 * Base type for typed objects and handles. Basically any type whose
michael@0 508 * contents consist of typed memory.
michael@0 509 */
michael@0 510 class TypedObject : public ArrayBufferViewObject
michael@0 511 {
michael@0 512 private:
michael@0 513 static const bool IsTypedObjectClass = true;
michael@0 514
michael@0 515 template<class T>
michael@0 516 static bool obj_getArrayElement(JSContext *cx,
michael@0 517 Handle<TypedObject*> typedObj,
michael@0 518 Handle<TypeDescr*> typeDescr,
michael@0 519 uint32_t index,
michael@0 520 MutableHandleValue vp);
michael@0 521
michael@0 522 template<class T>
michael@0 523 static bool obj_setArrayElement(JSContext *cx,
michael@0 524 Handle<TypedObject*> typedObj,
michael@0 525 Handle<TypeDescr*> typeDescr,
michael@0 526 uint32_t index,
michael@0 527 MutableHandleValue vp);
michael@0 528
michael@0 529 protected:
michael@0 530 static void obj_trace(JSTracer *trace, JSObject *object);
michael@0 531
michael@0 532 static bool obj_lookupGeneric(JSContext *cx, HandleObject obj,
michael@0 533 HandleId id, MutableHandleObject objp,
michael@0 534 MutableHandleShape propp);
michael@0 535
michael@0 536 static bool obj_lookupProperty(JSContext *cx, HandleObject obj,
michael@0 537 HandlePropertyName name,
michael@0 538 MutableHandleObject objp,
michael@0 539 MutableHandleShape propp);
michael@0 540
michael@0 541 static bool obj_lookupElement(JSContext *cx, HandleObject obj,
michael@0 542 uint32_t index, MutableHandleObject objp,
michael@0 543 MutableHandleShape propp);
michael@0 544
michael@0 545 static bool obj_defineGeneric(JSContext *cx, HandleObject obj, HandleId id, HandleValue v,
michael@0 546 PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
michael@0 547
michael@0 548 static bool obj_defineProperty(JSContext *cx, HandleObject obj,
michael@0 549 HandlePropertyName name, HandleValue v,
michael@0 550 PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
michael@0 551
michael@0 552 static bool obj_defineElement(JSContext *cx, HandleObject obj, uint32_t index, HandleValue v,
michael@0 553 PropertyOp getter, StrictPropertyOp setter, unsigned attrs);
michael@0 554
michael@0 555 static bool obj_getGeneric(JSContext *cx, HandleObject obj, HandleObject receiver,
michael@0 556 HandleId id, MutableHandleValue vp);
michael@0 557
michael@0 558 static bool obj_getProperty(JSContext *cx, HandleObject obj, HandleObject receiver,
michael@0 559 HandlePropertyName name, MutableHandleValue vp);
michael@0 560
michael@0 561 static bool obj_getElement(JSContext *cx, HandleObject obj, HandleObject receiver,
michael@0 562 uint32_t index, MutableHandleValue vp);
michael@0 563
michael@0 564 static bool obj_getUnsizedArrayElement(JSContext *cx, HandleObject obj, HandleObject receiver,
michael@0 565 uint32_t index, MutableHandleValue vp);
michael@0 566
michael@0 567 static bool obj_setGeneric(JSContext *cx, HandleObject obj, HandleId id,
michael@0 568 MutableHandleValue vp, bool strict);
michael@0 569 static bool obj_setProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
michael@0 570 MutableHandleValue vp, bool strict);
michael@0 571 static bool obj_setElement(JSContext *cx, HandleObject obj, uint32_t index,
michael@0 572 MutableHandleValue vp, bool strict);
michael@0 573
michael@0 574 static bool obj_getGenericAttributes(JSContext *cx, HandleObject obj,
michael@0 575 HandleId id, unsigned *attrsp);
michael@0 576 static bool obj_setGenericAttributes(JSContext *cx, HandleObject obj,
michael@0 577 HandleId id, unsigned *attrsp);
michael@0 578
michael@0 579 static bool obj_deleteProperty(JSContext *cx, HandleObject obj, HandlePropertyName name,
michael@0 580 bool *succeeded);
michael@0 581 static bool obj_deleteElement(JSContext *cx, HandleObject obj, uint32_t index,
michael@0 582 bool *succeeded);
michael@0 583
michael@0 584 static bool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
michael@0 585 MutableHandleValue statep, MutableHandleId idp);
michael@0 586
michael@0 587 public:
michael@0 588 static size_t offsetOfOwnerSlot();
michael@0 589
michael@0 590 // Each typed object contains a void* pointer pointing at the
michael@0 591 // binary data that it represents. (That data may be owned by this
michael@0 592 // object or this object may alias data owned by someone else.)
michael@0 593 // This function returns the offset in bytes within the object
michael@0 594 // where the `void*` pointer can be found. It is intended for use
michael@0 595 // by the JIT.
michael@0 596 static size_t offsetOfDataSlot();
michael@0 597
michael@0 598 // Offset of the byte offset slot.
michael@0 599 static size_t offsetOfByteOffsetSlot();
michael@0 600
michael@0 601 // Helper for createUnattached()
michael@0 602 static TypedObject *createUnattachedWithClass(JSContext *cx,
michael@0 603 const Class *clasp,
michael@0 604 HandleTypeDescr type,
michael@0 605 int32_t length);
michael@0 606
michael@0 607 // Creates an unattached typed object or handle (depending on the
michael@0 608 // type parameter T). Note that it is only legal for unattached
michael@0 609 // handles to escape to the end user; for non-handles, the caller
michael@0 610 // should always invoke one of the `attach()` methods below.
michael@0 611 //
michael@0 612 // Arguments:
michael@0 613 // - type: type object for resulting object
michael@0 614 // - length: 0 unless this is an array, otherwise the length
michael@0 615 static TypedObject *createUnattached(JSContext *cx, HandleTypeDescr type,
michael@0 616 int32_t length);
michael@0 617
michael@0 618 // Creates a typedObj that aliases the memory pointed at by `owner`
michael@0 619 // at the given offset. The typedObj will be a handle iff type is a
michael@0 620 // handle and a typed object otherwise.
michael@0 621 static TypedObject *createDerived(JSContext *cx,
michael@0 622 HandleSizedTypeDescr type,
michael@0 623 Handle<TypedObject*> typedContents,
michael@0 624 int32_t offset);
michael@0 625
michael@0 626 // Creates a new typed object whose memory is freshly allocated
michael@0 627 // and initialized with zeroes (or, in the case of references, an
michael@0 628 // appropriate default value).
michael@0 629 static TypedObject *createZeroed(JSContext *cx,
michael@0 630 HandleTypeDescr typeObj,
michael@0 631 int32_t length);
michael@0 632
michael@0 633 // User-accessible constructor (`new TypeDescriptor(...)`)
michael@0 634 // used for sized types. Note that the callee here is the *type descriptor*,
michael@0 635 // not the typedObj.
michael@0 636 static bool constructSized(JSContext *cx, unsigned argc, Value *vp);
michael@0 637
michael@0 638 // As `constructSized`, but for unsized array types.
michael@0 639 static bool constructUnsized(JSContext *cx, unsigned argc, Value *vp);
michael@0 640
michael@0 641 // Use this method when `buffer` is the owner of the memory.
michael@0 642 void attach(ArrayBufferObject &buffer, int32_t offset);
michael@0 643
michael@0 644 // Otherwise, use this to attach to memory referenced by another typedObj.
michael@0 645 void attach(TypedObject &typedObj, int32_t offset);
michael@0 646
michael@0 647 // Invoked when array buffer is transferred elsewhere
michael@0 648 void neuter(void *newData);
michael@0 649
michael@0 650 int32_t offset() const {
michael@0 651 return getReservedSlot(JS_TYPEDOBJ_SLOT_BYTEOFFSET).toInt32();
michael@0 652 }
michael@0 653
michael@0 654 ArrayBufferObject &owner() const {
michael@0 655 return getReservedSlot(JS_TYPEDOBJ_SLOT_OWNER).toObject().as<ArrayBufferObject>();
michael@0 656 }
michael@0 657
michael@0 658 TypeDescr &typeDescr() const {
michael@0 659 return getReservedSlot(JS_TYPEDOBJ_SLOT_TYPE_DESCR).toObject().as<TypeDescr>();
michael@0 660 }
michael@0 661
michael@0 662 uint8_t *typedMem() const {
michael@0 663 return (uint8_t*) getPrivate();
michael@0 664 }
michael@0 665
michael@0 666 int32_t byteLength() const {
michael@0 667 return getReservedSlot(JS_TYPEDOBJ_SLOT_BYTELENGTH).toInt32();
michael@0 668 }
michael@0 669
michael@0 670 int32_t length() const {
michael@0 671 return getReservedSlot(JS_TYPEDOBJ_SLOT_LENGTH).toInt32();
michael@0 672 }
michael@0 673
michael@0 674 int32_t size() const {
michael@0 675 switch (typeDescr().kind()) {
michael@0 676 case TypeDescr::Scalar:
michael@0 677 case TypeDescr::X4:
michael@0 678 case TypeDescr::Reference:
michael@0 679 case TypeDescr::Struct:
michael@0 680 case TypeDescr::SizedArray:
michael@0 681 return typeDescr().as<SizedTypeDescr>().size();
michael@0 682
michael@0 683 case TypeDescr::UnsizedArray: {
michael@0 684 SizedTypeDescr &elementType = typeDescr().as<UnsizedArrayTypeDescr>().elementType();
michael@0 685 return elementType.size() * length();
michael@0 686 }
michael@0 687 }
michael@0 688 MOZ_ASSUME_UNREACHABLE("unhandled typerepresentation kind");
michael@0 689 }
michael@0 690
michael@0 691 uint8_t *typedMem(size_t offset) const {
michael@0 692 // It seems a bit surprising that one might request an offset
michael@0 693 // == size(), but it can happen when taking the "address of" a
michael@0 694 // 0-sized value. (In other words, we maintain the invariant
michael@0 695 // that `offset + size <= size()` -- this is always checked in
michael@0 696 // the caller's side.)
michael@0 697 JS_ASSERT(offset <= (size_t) size());
michael@0 698 return typedMem() + offset;
michael@0 699 }
michael@0 700 };
michael@0 701
michael@0 702 typedef Handle<TypedObject*> HandleTypedObject;
michael@0 703
michael@0 704 class TransparentTypedObject : public TypedObject
michael@0 705 {
michael@0 706 public:
michael@0 707 static const Class class_;
michael@0 708 };
michael@0 709
michael@0 710 typedef Handle<TransparentTypedObject*> HandleTransparentTypedObject;
michael@0 711
michael@0 712 class OpaqueTypedObject : public TypedObject
michael@0 713 {
michael@0 714 public:
michael@0 715 static const Class class_;
michael@0 716 static const JSFunctionSpec handleStaticMethods[];
michael@0 717 };
michael@0 718
michael@0 719 /*
michael@0 720 * Usage: NewOpaqueTypedObject(typeObj)
michael@0 721 *
michael@0 722 * Constructs a new, unattached instance of `Handle`.
michael@0 723 */
michael@0 724 bool NewOpaqueTypedObject(JSContext *cx, unsigned argc, Value *vp);
michael@0 725
michael@0 726 /*
michael@0 727 * Usage: NewDerivedTypedObject(typeObj, owner, offset)
michael@0 728 *
michael@0 729 * Constructs a new, unattached instance of `Handle`.
michael@0 730 */
michael@0 731 bool NewDerivedTypedObject(JSContext *cx, unsigned argc, Value *vp);
michael@0 732
michael@0 733 /*
michael@0 734 * Usage: AttachTypedObject(typedObj, newDatum, newOffset)
michael@0 735 *
michael@0 736 * Moves `typedObj` to point at the memory referenced by `newDatum` with
michael@0 737 * the offset `newOffset`.
michael@0 738 */
michael@0 739 bool AttachTypedObject(ThreadSafeContext *cx, unsigned argc, Value *vp);
michael@0 740 extern const JSJitInfo AttachTypedObjectJitInfo;
michael@0 741
michael@0 742 /*
michael@0 743 * Usage: SetTypedObjectOffset(typedObj, offset)
michael@0 744 *
michael@0 745 * Changes the offset for `typedObj` within its buffer to `offset`.
michael@0 746 * `typedObj` must already be attached.
michael@0 747 */
michael@0 748 bool intrinsic_SetTypedObjectOffset(JSContext *cx, unsigned argc, Value *vp);
michael@0 749 bool SetTypedObjectOffset(ThreadSafeContext *, unsigned argc, Value *vp);
michael@0 750 extern const JSJitInfo intrinsic_SetTypedObjectOffsetJitInfo;
michael@0 751
michael@0 752 /*
michael@0 753 * Usage: ObjectIsTypeDescr(obj)
michael@0 754 *
michael@0 755 * True if `obj` is a type object.
michael@0 756 */
michael@0 757 bool ObjectIsTypeDescr(ThreadSafeContext *cx, unsigned argc, Value *vp);
michael@0 758 extern const JSJitInfo ObjectIsTypeDescrJitInfo;
michael@0 759
michael@0 760 /*
michael@0 761 * Usage: ObjectIsTypedObject(obj)
michael@0 762 *
michael@0 763 * True if `obj` is a transparent or opaque typed object.
michael@0 764 */
michael@0 765 bool ObjectIsTypedObject(ThreadSafeContext *cx, unsigned argc, Value *vp);
michael@0 766 extern const JSJitInfo ObjectIsTypedObjectJitInfo;
michael@0 767
michael@0 768 /*
michael@0 769 * Usage: ObjectIsOpaqueTypedObject(obj)
michael@0 770 *
michael@0 771 * True if `obj` is an opaque typed object.
michael@0 772 */
michael@0 773 bool ObjectIsOpaqueTypedObject(ThreadSafeContext *cx, unsigned argc, Value *vp);
michael@0 774 extern const JSJitInfo ObjectIsOpaqueTypedObjectJitInfo;
michael@0 775
michael@0 776 /*
michael@0 777 * Usage: ObjectIsTransparentTypedObject(obj)
michael@0 778 *
michael@0 779 * True if `obj` is a transparent typed object.
michael@0 780 */
michael@0 781 bool ObjectIsTransparentTypedObject(ThreadSafeContext *cx, unsigned argc, Value *vp);
michael@0 782 extern const JSJitInfo ObjectIsTransparentTypedObjectJitInfo;
michael@0 783
michael@0 784 /* Predicates on type descriptor objects. In all cases, 'obj' must be a type descriptor. */
michael@0 785
michael@0 786 bool TypeDescrIsSimpleType(ThreadSafeContext *, unsigned argc, Value *vp);
michael@0 787 extern const JSJitInfo TypeDescrIsSimpleTypeJitInfo;
michael@0 788
michael@0 789 bool TypeDescrIsArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
michael@0 790 extern const JSJitInfo TypeDescrIsArrayTypeJitInfo;
michael@0 791
michael@0 792 bool TypeDescrIsSizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
michael@0 793 extern const JSJitInfo TypeDescrIsSizedArrayTypeJitInfo;
michael@0 794
michael@0 795 bool TypeDescrIsUnsizedArrayType(ThreadSafeContext *, unsigned argc, Value *vp);
michael@0 796 extern const JSJitInfo TypeDescrIsUnsizedArrayTypeJitInfo;
michael@0 797
michael@0 798 /*
michael@0 799 * Usage: TypedObjectIsAttached(obj)
michael@0 800 *
michael@0 801 * Given a TypedObject `obj`, returns true if `obj` is
michael@0 802 * "attached" (i.e., its data pointer is nullptr).
michael@0 803 */
michael@0 804 bool TypedObjectIsAttached(ThreadSafeContext *cx, unsigned argc, Value *vp);
michael@0 805 extern const JSJitInfo TypedObjectIsAttachedJitInfo;
michael@0 806
michael@0 807 /*
michael@0 808 * Usage: ClampToUint8(v)
michael@0 809 *
michael@0 810 * Same as the C function ClampDoubleToUint8. `v` must be a number.
michael@0 811 */
michael@0 812 bool ClampToUint8(ThreadSafeContext *cx, unsigned argc, Value *vp);
michael@0 813 extern const JSJitInfo ClampToUint8JitInfo;
michael@0 814
michael@0 815 /*
michael@0 816 * Usage: Memcpy(targetDatum, targetOffset,
michael@0 817 * sourceDatum, sourceOffset,
michael@0 818 * size)
michael@0 819 *
michael@0 820 * Intrinsic function. Copies size bytes from the data for
michael@0 821 * `sourceDatum` at `sourceOffset` into the data for
michael@0 822 * `targetDatum` at `targetOffset`.
michael@0 823 *
michael@0 824 * Both `sourceDatum` and `targetDatum` must be attached.
michael@0 825 */
michael@0 826 bool Memcpy(ThreadSafeContext *cx, unsigned argc, Value *vp);
michael@0 827 extern const JSJitInfo MemcpyJitInfo;
michael@0 828
michael@0 829 /*
michael@0 830 * Usage: GetTypedObjectModule()
michael@0 831 *
michael@0 832 * Returns the global "typed object" module, which provides access
michael@0 833 * to the various builtin type descriptors. These are currently
michael@0 834 * exported as immutable properties so it is safe for self-hosted code
michael@0 835 * to access them; eventually this should be linked into the module
michael@0 836 * system.
michael@0 837 */
michael@0 838 bool GetTypedObjectModule(JSContext *cx, unsigned argc, Value *vp);
michael@0 839
michael@0 840 /*
michael@0 841 * Usage: GetFloat32x4TypeDescr()
michael@0 842 *
michael@0 843 * Returns the float32x4 type object. SIMD pseudo-module must have
michael@0 844 * been initialized for this to be safe.
michael@0 845 */
michael@0 846 bool GetFloat32x4TypeDescr(JSContext *cx, unsigned argc, Value *vp);
michael@0 847
michael@0 848 /*
michael@0 849 * Usage: GetInt32x4TypeDescr()
michael@0 850 *
michael@0 851 * Returns the int32x4 type object. SIMD pseudo-module must have
michael@0 852 * been initialized for this to be safe.
michael@0 853 */
michael@0 854 bool GetInt32x4TypeDescr(JSContext *cx, unsigned argc, Value *vp);
michael@0 855
michael@0 856 /*
michael@0 857 * Usage: Store_int8(targetDatum, targetOffset, value)
michael@0 858 * ...
michael@0 859 * Store_uint8(targetDatum, targetOffset, value)
michael@0 860 * ...
michael@0 861 * Store_float32(targetDatum, targetOffset, value)
michael@0 862 * Store_float64(targetDatum, targetOffset, value)
michael@0 863 *
michael@0 864 * Intrinsic function. Stores `value` into the memory referenced by
michael@0 865 * `targetDatum` at the offset `targetOffset`.
michael@0 866 *
michael@0 867 * Assumes (and asserts) that:
michael@0 868 * - `targetDatum` is attached
michael@0 869 * - `targetOffset` is a valid offset within the bounds of `targetDatum`
michael@0 870 * - `value` is a number
michael@0 871 */
michael@0 872 #define JS_STORE_SCALAR_CLASS_DEFN(_constant, T, _name) \
michael@0 873 class StoreScalar##T { \
michael@0 874 public: \
michael@0 875 static bool Func(ThreadSafeContext *cx, unsigned argc, Value *vp); \
michael@0 876 static const JSJitInfo JitInfo; \
michael@0 877 };
michael@0 878
michael@0 879 /*
michael@0 880 * Usage: Store_Any(targetDatum, targetOffset, value)
michael@0 881 * Store_Object(targetDatum, targetOffset, value)
michael@0 882 * Store_string(targetDatum, targetOffset, value)
michael@0 883 *
michael@0 884 * Intrinsic function. Stores `value` into the memory referenced by
michael@0 885 * `targetDatum` at the offset `targetOffset`.
michael@0 886 *
michael@0 887 * Assumes (and asserts) that:
michael@0 888 * - `targetDatum` is attached
michael@0 889 * - `targetOffset` is a valid offset within the bounds of `targetDatum`
michael@0 890 * - `value` is an object (`Store_Object`) or string (`Store_string`).
michael@0 891 */
michael@0 892 #define JS_STORE_REFERENCE_CLASS_DEFN(_constant, T, _name) \
michael@0 893 class StoreReference##T { \
michael@0 894 private: \
michael@0 895 static void store(T* heap, const Value &v); \
michael@0 896 \
michael@0 897 public: \
michael@0 898 static bool Func(ThreadSafeContext *cx, unsigned argc, Value *vp); \
michael@0 899 static const JSJitInfo JitInfo; \
michael@0 900 };
michael@0 901
michael@0 902 /*
michael@0 903 * Usage: LoadScalar(targetDatum, targetOffset, value)
michael@0 904 *
michael@0 905 * Intrinsic function. Loads value (which must be an int32 or uint32)
michael@0 906 * by `scalarTypeRepr` (which must be a type repr obj) and loads the
michael@0 907 * value at the memory for `targetDatum` at offset `targetOffset`.
michael@0 908 * `targetDatum` must be attached.
michael@0 909 */
michael@0 910 #define JS_LOAD_SCALAR_CLASS_DEFN(_constant, T, _name) \
michael@0 911 class LoadScalar##T { \
michael@0 912 public: \
michael@0 913 static bool Func(ThreadSafeContext *cx, unsigned argc, Value *vp); \
michael@0 914 static const JSJitInfo JitInfo; \
michael@0 915 };
michael@0 916
michael@0 917 /*
michael@0 918 * Usage: LoadReference(targetDatum, targetOffset, value)
michael@0 919 *
michael@0 920 * Intrinsic function. Stores value (which must be an int32 or uint32)
michael@0 921 * by `scalarTypeRepr` (which must be a type repr obj) and stores the
michael@0 922 * value at the memory for `targetDatum` at offset `targetOffset`.
michael@0 923 * `targetDatum` must be attached.
michael@0 924 */
michael@0 925 #define JS_LOAD_REFERENCE_CLASS_DEFN(_constant, T, _name) \
michael@0 926 class LoadReference##T { \
michael@0 927 private: \
michael@0 928 static void load(T* heap, MutableHandleValue v); \
michael@0 929 \
michael@0 930 public: \
michael@0 931 static bool Func(ThreadSafeContext *cx, unsigned argc, Value *vp); \
michael@0 932 static const JSJitInfo JitInfo; \
michael@0 933 };
michael@0 934
michael@0 935 // I was using templates for this stuff instead of macros, but ran
michael@0 936 // into problems with the Unagi compiler.
michael@0 937 JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_STORE_SCALAR_CLASS_DEFN)
michael@0 938 JS_FOR_EACH_UNIQUE_SCALAR_TYPE_REPR_CTYPE(JS_LOAD_SCALAR_CLASS_DEFN)
michael@0 939 JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_STORE_REFERENCE_CLASS_DEFN)
michael@0 940 JS_FOR_EACH_REFERENCE_TYPE_REPR(JS_LOAD_REFERENCE_CLASS_DEFN)
michael@0 941
michael@0 942 inline bool
michael@0 943 IsTypedObjectClass(const Class *class_)
michael@0 944 {
michael@0 945 return class_ == &TransparentTypedObject::class_ ||
michael@0 946 class_ == &OpaqueTypedObject::class_;
michael@0 947 }
michael@0 948
michael@0 949 inline bool
michael@0 950 IsSimpleTypeDescrClass(const Class* clasp)
michael@0 951 {
michael@0 952 return clasp == &ScalarTypeDescr::class_ ||
michael@0 953 clasp == &ReferenceTypeDescr::class_;
michael@0 954 }
michael@0 955
michael@0 956 inline bool
michael@0 957 IsComplexTypeDescrClass(const Class* clasp)
michael@0 958 {
michael@0 959 return clasp == &StructTypeDescr::class_ ||
michael@0 960 clasp == &SizedArrayTypeDescr::class_ ||
michael@0 961 clasp == &X4TypeDescr::class_;
michael@0 962 }
michael@0 963
michael@0 964 inline bool
michael@0 965 IsSizedTypeDescrClass(const Class* clasp)
michael@0 966 {
michael@0 967 return IsSimpleTypeDescrClass(clasp) ||
michael@0 968 IsComplexTypeDescrClass(clasp);
michael@0 969 }
michael@0 970
michael@0 971 inline bool
michael@0 972 IsTypeDescrClass(const Class* clasp)
michael@0 973 {
michael@0 974 return IsSizedTypeDescrClass(clasp) ||
michael@0 975 clasp == &UnsizedArrayTypeDescr::class_;
michael@0 976 }
michael@0 977
michael@0 978 } // namespace js
michael@0 979
michael@0 980 JSObject *
michael@0 981 js_InitTypedObjectModuleObject(JSContext *cx, JS::HandleObject obj);
michael@0 982
michael@0 983 template <>
michael@0 984 inline bool
michael@0 985 JSObject::is<js::SimpleTypeDescr>() const
michael@0 986 {
michael@0 987 return IsSimpleTypeDescrClass(getClass());
michael@0 988 }
michael@0 989
michael@0 990 template <>
michael@0 991 inline bool
michael@0 992 JSObject::is<js::SizedTypeDescr>() const
michael@0 993 {
michael@0 994 return IsSizedTypeDescrClass(getClass());
michael@0 995 }
michael@0 996
michael@0 997 template <>
michael@0 998 inline bool
michael@0 999 JSObject::is<js::ComplexTypeDescr>() const
michael@0 1000 {
michael@0 1001 return IsComplexTypeDescrClass(getClass());
michael@0 1002 }
michael@0 1003
michael@0 1004 template <>
michael@0 1005 inline bool
michael@0 1006 JSObject::is<js::TypeDescr>() const
michael@0 1007 {
michael@0 1008 return IsTypeDescrClass(getClass());
michael@0 1009 }
michael@0 1010
michael@0 1011 template <>
michael@0 1012 inline bool
michael@0 1013 JSObject::is<js::TypedObject>() const
michael@0 1014 {
michael@0 1015 return IsTypedObjectClass(getClass());
michael@0 1016 }
michael@0 1017
michael@0 1018 template<>
michael@0 1019 inline bool
michael@0 1020 JSObject::is<js::SizedArrayTypeDescr>() const
michael@0 1021 {
michael@0 1022 return getClass() == &js::SizedArrayTypeDescr::class_;
michael@0 1023 }
michael@0 1024
michael@0 1025 template<>
michael@0 1026 inline bool
michael@0 1027 JSObject::is<js::UnsizedArrayTypeDescr>() const
michael@0 1028 {
michael@0 1029 return getClass() == &js::UnsizedArrayTypeDescr::class_;
michael@0 1030 }
michael@0 1031
michael@0 1032 inline void
michael@0 1033 js::TypedProto::initTypeDescrSlot(TypeDescr &descr)
michael@0 1034 {
michael@0 1035 initReservedSlot(JS_TYPROTO_SLOT_DESCR, ObjectValue(descr));
michael@0 1036 }
michael@0 1037
michael@0 1038 #endif /* builtin_TypedObject_h */

mercurial