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 */