Bug 671630 - Make initializing the various typed arrays (but not ArrayBuffer) non-generic. r=mrbkap
authorJeff Walden <jwalden@mit.edu>
Wed, 04 May 2011 16:54:23 -0400
changeset 73864 1e291b76d689b7d363243e4281e4f6011d3e6e43
parent 73863 64ca7770ab496d0c354c7704532fa54c335e5282
child 73865 0079dfa0cd2376900b52480cfb941e1eec084f0c
push id2
push userbsmedberg@mozilla.com
push dateFri, 19 Aug 2011 14:38:13 +0000
reviewersmrbkap
bugs671630
milestone8.0a1
Bug 671630 - Make initializing the various typed arrays (but not ArrayBuffer) non-generic. r=mrbkap
js/src/jstracer.cpp
js/src/jstypedarray.cpp
js/src/jstypedarray.h
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -11572,17 +11572,17 @@ TraceRecorder::callNative(uintN argc, JS
         JS_ASSERT(((jsuword) clasp & 3) == 0);
 
         // Abort on |new Function|. (FIXME: This restriction might not
         // unnecessary now that the constructor creates the new function object
         // itself.)
         if (clasp == &js_FunctionClass)
             RETURN_STOP("new Function");
 
-        if (!clasp->isNative())
+        if (!IsFastTypedArrayClass(clasp) && !clasp->isNative())
             RETURN_STOP("new with non-native ops");
 
         // Don't trace |new Math.sin(0)|.
         if (!fun->isConstructor())
             RETURN_STOP("new with non-constructor native function");
 
         vp[1].setMagicWithObjectOrNullPayload(NULL);
         newobj_ins = w.immpMagicNull();
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -58,16 +58,18 @@
 #include "jsnum.h"
 #include "jsobj.h"
 #include "jsstaticcheck.h"
 #include "jsbit.h"
 #include "jsvector.h"
 #include "jstypedarray.h"
 #include "jsutil.h"
 
+#include "vm/GlobalObject.h"
+
 #include "jsobjinlines.h"
 #include "jstypedarrayinlines.h"
 
 using namespace js;
 using namespace js::gc;
 
 /* slots can only be upto 255 */
 static const uint8 ARRAYBUFFER_RESERVED_SLOTS = 16;
@@ -682,16 +684,18 @@ class TypedArrayTemplate
 {
   public:
     typedef NativeType ThisType;
     typedef TypedArrayTemplate<NativeType> ThisTypeArray;
     static const int ArrayTypeID() { return TypeIDOfType<NativeType>(); }
     static const bool ArrayTypeIsUnsigned() { return TypeIsUnsigned<NativeType>(); }
     static const bool ArrayTypeIsFloatingPoint() { return TypeIsFloatingPoint<NativeType>(); }
 
+    static const size_t BYTES_PER_ELEMENT = sizeof(ThisType);
+
     static inline Class *slowClass()
     {
         return &TypedArray::slowClasses[ArrayTypeID()];
     }
 
     static inline Class *fastClass()
     {
         return &TypedArray::fastClasses[ArrayTypeID()];
@@ -1509,56 +1513,65 @@ class TypedArrayTemplate
         int32 bytelen = size * count;
         return ArrayBuffer::create(cx, bytelen);
     }
 };
 
 class Int8Array : public TypedArrayTemplate<int8> {
   public:
     enum { ACTUAL_TYPE = TYPE_INT8 };
+    static const JSProtoKey key = JSProto_Int8Array;
     static JSFunctionSpec jsfuncs[];
 };
 class Uint8Array : public TypedArrayTemplate<uint8> {
   public:
     enum { ACTUAL_TYPE = TYPE_UINT8 };
+    static const JSProtoKey key = JSProto_Uint8Array;
     static JSFunctionSpec jsfuncs[];
 };
 class Int16Array : public TypedArrayTemplate<int16> {
   public:
     enum { ACTUAL_TYPE = TYPE_INT16 };
+    static const JSProtoKey key = JSProto_Int16Array;
     static JSFunctionSpec jsfuncs[];
 };
 class Uint16Array : public TypedArrayTemplate<uint16> {
   public:
     enum { ACTUAL_TYPE = TYPE_UINT16 };
+    static const JSProtoKey key = JSProto_Uint16Array;
     static JSFunctionSpec jsfuncs[];
 };
 class Int32Array : public TypedArrayTemplate<int32> {
   public:
     enum { ACTUAL_TYPE = TYPE_INT32 };
+    static const JSProtoKey key = JSProto_Int32Array;
     static JSFunctionSpec jsfuncs[];
 };
 class Uint32Array : public TypedArrayTemplate<uint32> {
   public:
     enum { ACTUAL_TYPE = TYPE_UINT32 };
+    static const JSProtoKey key = JSProto_Uint32Array;
     static JSFunctionSpec jsfuncs[];
 };
 class Float32Array : public TypedArrayTemplate<float> {
   public:
     enum { ACTUAL_TYPE = TYPE_FLOAT32 };
+    static const JSProtoKey key = JSProto_Float32Array;
     static JSFunctionSpec jsfuncs[];
 };
 class Float64Array : public TypedArrayTemplate<double> {
   public:
     enum { ACTUAL_TYPE = TYPE_FLOAT64 };
+    static const JSProtoKey key = JSProto_Float64Array;
     static JSFunctionSpec jsfuncs[];
 };
 class Uint8ClampedArray : public TypedArrayTemplate<uint8_clamped> {
   public:
     enum { ACTUAL_TYPE = TYPE_UINT8_CLAMPED };
+    static const JSProtoKey key = JSProto_Uint8ClampedArray;
     static JSFunctionSpec jsfuncs[];
 };
 
 // this default implementation is only valid for integer types
 // less than 32-bits in size.
 template<typename NativeType>
 void
 TypedArrayTemplate<NativeType>::copyIndexToValue(JSContext *cx, JSObject *tarray, uint32 index, Value *vp)
@@ -1775,37 +1788,47 @@ template<> JSFunctionSpec _typedArray::j
         NULL,       /* clear           */                                      \
     }                                                                          \
 }
 
 template<class ArrayType>
 static inline JSObject *
 InitTypedArrayClass(JSContext *cx, GlobalObject *global)
 {
-    JSObject *proto = js_InitClass(cx, global, NULL,
-                                   &ArrayType::slowClasses[ArrayType::ACTUAL_TYPE],
-                                   ArrayType::class_constructor, 3,
-                                   ArrayType::jsprops,
-                                   ArrayType::jsfuncs,
-                                   NULL, NULL);
+    JSObject *proto = global->createBlankPrototype(cx, ArrayType::slowClass());
     if (!proto)
         return NULL;
-    JSObject *ctor = JS_GetConstructor(cx, proto);
-    if (!ctor ||
-        !JS_DefineProperty(cx, ctor, "BYTES_PER_ELEMENT",
-                           INT_TO_JSVAL(sizeof(typename ArrayType::ThisType)),
-                           JS_PropertyStub, JS_StrictPropertyStub,
-                           JSPROP_PERMANENT | JSPROP_READONLY) ||
-        !JS_DefineProperty(cx, proto, "BYTES_PER_ELEMENT",
-                           INT_TO_JSVAL(sizeof(typename ArrayType::ThisType)),
-                           JS_PropertyStub, JS_StrictPropertyStub,
-                           JSPROP_PERMANENT | JSPROP_READONLY))
+
+    JSFunction *ctor =
+        global->createConstructor(cx, ArrayType::class_constructor, ArrayType::fastClass(),
+                                  cx->runtime->atomState.classAtoms[ArrayType::key], 3);
+    if (!ctor)
+        return NULL;
+
+    if (!LinkConstructorAndPrototype(cx, ctor, proto))
+        return NULL;
+
+    if (!ctor->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.BYTES_PER_ELEMENTAtom),
+                              Int32Value(ArrayType::BYTES_PER_ELEMENT),
+                              PropertyStub, StrictPropertyStub,
+                              JSPROP_PERMANENT | JSPROP_READONLY) ||
+        !proto->defineProperty(cx, ATOM_TO_JSID(cx->runtime->atomState.BYTES_PER_ELEMENTAtom),
+                               Int32Value(ArrayType::BYTES_PER_ELEMENT),
+                               PropertyStub, StrictPropertyStub,
+                               JSPROP_PERMANENT | JSPROP_READONLY))
     {
         return NULL;
     }
+
+    if (!DefinePropertiesAndBrand(cx, proto, ArrayType::jsprops, ArrayType::jsfuncs))
+        return NULL;
+
+    if (!DefineConstructorAndPrototype(cx, global, ArrayType::key, ctor, proto))
+        return NULL;
+
     return proto;
 }
 
 IMPL_TYPED_ARRAY_STATICS(Int8Array);
 IMPL_TYPED_ARRAY_STATICS(Uint8Array);
 IMPL_TYPED_ARRAY_STATICS(Int16Array);
 IMPL_TYPED_ARRAY_STATICS(Uint16Array);
 IMPL_TYPED_ARRAY_STATICS(Int32Array);
@@ -1885,16 +1908,27 @@ js_InitTypedArrayClasses(JSContext *cx, 
 
 JS_FRIEND_API(JSBool)
 js_IsArrayBuffer(JSObject *obj)
 {
     JS_ASSERT(obj);
     return obj->getClass() == &ArrayBuffer::fastClass;
 }
 
+namespace js {
+
+bool
+IsFastTypedArrayClass(const Class *clasp)
+{
+    return &TypedArray::fastClasses[0] <= clasp &&
+           clasp < &TypedArray::fastClasses[TypedArray::TYPE_MAX];
+}
+
+} // namespace js
+
 JSUint32
 JS_GetArrayBufferByteLength(JSObject *obj)
 {
     return ArrayBuffer::getByteLength(obj);
 }
 
 uint8 *
 JS_GetArrayBufferData(JSObject *obj)
@@ -1902,18 +1936,17 @@ JS_GetArrayBufferData(JSObject *obj)
     return ArrayBuffer::getDataOffset(obj);
 }
 
 JS_FRIEND_API(JSBool)
 js_IsTypedArray(JSObject *obj)
 {
     JS_ASSERT(obj);
     Class *clasp = obj->getClass();
-    return clasp >= &TypedArray::fastClasses[0] &&
-           clasp <  &TypedArray::fastClasses[TypedArray::TYPE_MAX];
+    return IsFastTypedArrayClass(clasp);
 }
 
 JS_FRIEND_API(JSObject *)
 js_CreateArrayBuffer(JSContext *cx, jsuint nbytes)
 {
     return ArrayBuffer::create(cx, nbytes);
 }
 
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -204,16 +204,19 @@ struct JS_FRIEND_API(TypedArray) {
             return 8;
           default:
             JS_NOT_REACHED("invalid typed array");
             return 0;
         }
     }
 };
 
+extern bool
+IsFastTypedArrayClass(const Class *clasp);
+
 } // namespace js
 
 /* Friend API methods */
 
 JS_FRIEND_API(JSObject *)
 js_InitTypedArrayClasses(JSContext *cx, JSObject *obj);
 
 JS_FRIEND_API(JSBool)