Bug 1002864 - Ignore the change-data/same-data argument to neuter() and JS_NeuterArrayBuffer when the buffer being neutered doesn't support the given data disposition. r=sfink, a=sylvestre
authorJeff Walden <jwalden@mit.edu>
Wed, 30 Apr 2014 17:15:14 -0700
changeset 200293 90c1b5961d6bd03cf1fb753c58f42322e9e47aa8
parent 200292 d66cfabe38e50e5ea5e5536ac1449a2075dc09be
child 200294 42d103fc89938e885d42a6075173e17902669ee4
push id486
push userasasaki@mozilla.com
push dateMon, 14 Jul 2014 18:39:42 +0000
treeherdermozilla-release@d33428174ff1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink, sylvestre
bugs1002864
milestone31.0a2
Bug 1002864 - Ignore the change-data/same-data argument to neuter() and JS_NeuterArrayBuffer when the buffer being neutered doesn't support the given data disposition. r=sfink, a=sylvestre
js/src/jit-test/tests/asm.js/testNeuter.js
js/src/jsfriendapi.h
js/src/vm/ArrayBufferObject.cpp
--- a/js/src/jit-test/tests/asm.js/testNeuter.js
+++ b/js/src/jit-test/tests/asm.js/testNeuter.js
@@ -21,16 +21,17 @@ var i32 = new Int32Array(1024);
 var buffer = i32.buffer;
 var {get, set} = f(this, null, buffer);
 if (isAsmJSCompilationAvailable())
     assertEq(isAsmJSFunction(get) && isAsmJSFunction(set), true);
 
 set(4, 42);
 assertEq(get(4), 42);
 
+neuter(buffer, "change-data");
 neuter(buffer, "same-data");
 
 // These operations may throw internal errors
 try {
     assertEq(get(4), 0);
     set(0, 42);
     assertEq(get(0), 0);
 } catch (e) {
@@ -56,16 +57,22 @@ var buffer = i32.buffer;
 var threw = false;
 function ffi() {
     try {
         neuter(buffer, "same-data");
     } catch (e) {
         assertEq(String(e).indexOf("InternalError"), 0);
         threw = true;
     }
+    try {
+        neuter(buffer, "change-data");
+    } catch (e) {
+        assertEq(String(e).indexOf("InternalError"), 0);
+        threw = true;
+    }
 }
 var inner = f2(this, {ffi:ffi}, buffer);
 if (isAsmJSCompilationAvailable())
     assertEq(isAsmJSFunction(inner), true);
 i32[2] = 13;
 var result = inner(8);
 if (threw)
     assertEq(result, 13);
--- a/js/src/jsfriendapi.h
+++ b/js/src/jsfriendapi.h
@@ -1448,16 +1448,22 @@ JS_GetArrayBufferViewBuffer(JSContext *c
 
 typedef enum {
     ChangeData,
     KeepData
 } NeuterDataDisposition;
 
 /*
  * Set an ArrayBuffer's length to 0 and neuter all of its views.
+ *
+ * The |changeData| argument is a hint to inform internal behavior with respect
+ * to the internal pointer to the ArrayBuffer's data after being neutered.
+ * There is no guarantee it will be respected.  But if it is respected, the
+ * ArrayBuffer's internal data pointer will, or will not, have changed
+ * accordingly.
  */
 extern JS_FRIEND_API(bool)
 JS_NeuterArrayBuffer(JSContext *cx, JS::HandleObject obj,
                      NeuterDataDisposition changeData);
 
 /*
  * Check whether obj supports JS_GetDataView* APIs.
  */
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -1025,17 +1025,17 @@ JS_NeuterArrayBuffer(JSContext *cx, Hand
     Rooted<ArrayBufferObject*> buffer(cx, &obj->as<ArrayBufferObject>());
 
     if (!buffer->canNeuter(cx)) {
         js_ReportOverRecursed(cx);
         return false;
     }
 
     void *newData;
-    if (changeData == ChangeData) {
+    if (changeData == ChangeData && buffer->hasStealableContents()) {
         newData = AllocateArrayBufferContents(cx, buffer->byteLength());
         if (!newData)
             return false;
     } else {
         newData = buffer->dataPointer();
     }
 
     ArrayBufferObject::neuter(cx, buffer, newData);