Bug 1295034 - Assertion failure when sorting TypedArrays constructed under JIT; r?mrrrgn draft
authorSumit Tiwari <sumi29@gmail.com>
Tue, 23 Aug 2016 22:04:14 -0400
changeset 404881 fda220337d675cbc9f1a61c3e0a767703bf0c56c
parent 404651 bd7645928990649c84609d3f531e803c2d41f269
child 406350 0ee53958c641842607f72dfa2f393d87f23f772f
push id27347
push userbmo:sumi29@gmail.com
push dateWed, 24 Aug 2016 12:08:48 +0000
reviewersmrrrgn
bugs1295034
milestone51.0a1
Bug 1295034 - Assertion failure when sorting TypedArrays constructed under JIT; r?mrrrgn MozReview-Commit-ID: L5T2uuCrG7d
js/src/builtin/Sorting.js
js/src/tests/ecma_6/TypedArray/sort_jit_array.js
js/src/vm/SelfHosting.cpp
js/src/vm/TypedArrayObject.cpp
js/src/vm/TypedArrayObject.h
--- a/js/src/builtin/Sorting.js
+++ b/js/src/builtin/Sorting.js
@@ -96,29 +96,34 @@ function SortByColumn(array, len, aux, c
 function RadixSort(array, len, buffer, nbytes, signed, floating, comparefn) {
 
     // Determined by performance testing.
     if (len < 128) {
         QuickSort(array, len, comparefn);
         return array;
     }
 
-    // Verify that the buffer is non-null
-    assert(buffer !== null, "Attached data buffer should be reified when array length is >= 128.");
-
     let aux = new List();
     for (let i = 0; i < len; i++) {
         aux[i] = 0;
     }
 
     let view = array;
     let signMask = 1 << nbytes * 8 - 1;
 
     // Preprocess
     if (floating) {
+        // This happens if the array object is constructed under JIT
+        if (buffer === null) {
+            buffer = callFunction(std_TypedArray_buffer, array);
+        }
+
+        // Verify that the buffer is non-null
+        assert(buffer !== null, "Attached data buffer should be reified when array length is >= 128.");
+
         view = new Int32Array(buffer);
 
         // Flip sign bit for positive numbers; flip all bits for negative
         // numbers
         for (let i = 0; i < len; i++) {
             if (view[i] & signMask) {
                 view[i] ^= 0xFFFFFFFF;
             } else {
new file mode 100644
--- /dev/null
+++ b/js/src/tests/ecma_6/TypedArray/sort_jit_array.js
@@ -0,0 +1,22 @@
+const constructors = [
+    Int8Array,
+    Uint8Array,
+    Uint8ClampedArray,
+    Int16Array,
+    Uint16Array,
+    Int32Array,
+    Uint32Array,
+    Float32Array,
+    Float64Array ];
+
+// Ensure that when creating TypedArrays under JIT
+// the sort() method works as expected (bug 1295034).
+for (var ctor of constructors) {
+  for (var _ of Array(1024)) {
+    var testArray = new ctor(1024);
+    testArray.sort();
+  }
+}
+
+if (typeof reportCompare === "function")
+    reportCompare(true, true);
\ No newline at end of file
--- a/js/src/vm/SelfHosting.cpp
+++ b/js/src/vm/SelfHosting.cpp
@@ -2333,17 +2333,18 @@ static const JSFunctionSpec intrinsic_fu
     JS_FN("std_String_toLocaleLowerCase",        str_toLocaleLowerCase,        0,0),
     JS_FN("std_String_toLocaleUpperCase",        str_toLocaleUpperCase,        0,0),
 #if !EXPOSE_INTL_API
     JS_FN("std_String_localeCompare",            str_localeCompare,            1,0),
 #else
     JS_FN("std_String_normalize",                str_normalize,                0,0),
 #endif
     JS_FN("std_String_concat",                   str_concat,                   1,0),
-
+    
+    JS_FN("std_TypedArray_buffer",               js::TypedArray_bufferGetter,  1,0),
 
     JS_FN("std_WeakMap_has",                     WeakMap_has,                  1,0),
     JS_FN("std_WeakMap_get",                     WeakMap_get,                  2,0),
     JS_FN("std_WeakMap_set",                     WeakMap_set,                  2,0),
     JS_FN("std_WeakMap_delete",                  WeakMap_delete,               1,0),
 
     JS_FN("std_SIMD_Int8x16_extractLane",        simd_int8x16_extractLane,     2,0),
     JS_FN("std_SIMD_Int16x8_extractLane",        simd_int16x8_extractLane,     2,0),
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -1321,18 +1321,18 @@ BufferGetterImpl(JSContext* cx, const Ca
     MOZ_ASSERT(TypedArrayObject::is(args.thisv()));
     Rooted<TypedArrayObject*> tarray(cx, &args.thisv().toObject().as<TypedArrayObject>());
     if (!TypedArrayObject::ensureHasBuffer(cx, tarray))
         return false;
     args.rval().set(TypedArrayObject::bufferValue(tarray));
     return true;
 }
 
-static bool
-TypedArray_bufferGetter(JSContext* cx, unsigned argc, Value* vp)
+/*static*/ bool
+js::TypedArray_bufferGetter(JSContext* cx, unsigned argc, Value* vp)
 {
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<TypedArrayObject::is, BufferGetterImpl>(cx, args);
 }
 
 /* static */ const JSPropertySpec
 TypedArrayObject::protoAccessors[] = {
     JS_PSG("length", TypedArray_lengthGetter, 0),
--- a/js/src/vm/TypedArrayObject.h
+++ b/js/src/vm/TypedArrayObject.h
@@ -289,16 +289,18 @@ class TypedArrayObject : public NativeOb
 
     /* Accessors and functions */
 
     static bool is(HandleValue v);
 
     static bool set(JSContext* cx, unsigned argc, Value* vp);
 };
 
+MOZ_MUST_USE bool TypedArray_bufferGetter(JSContext* cx, unsigned argc, Value* vp);
+
 extern TypedArrayObject*
 TypedArrayCreateWithTemplate(JSContext* cx, HandleObject templateObj, int32_t len);
 
 inline bool
 IsTypedArrayClass(const Class* clasp)
 {
     return &TypedArrayObject::classes[0] <= clasp &&
            clasp < &TypedArrayObject::classes[Scalar::MaxTypedArrayViewType];