Bug 1529298 - Make ArrayBufferObject::wasmGrowToSizeInPlace do its work *not* using ArrayBufferObject::stealContents, rather using the exact operations desired, far more simply. r=sfink
authorJeff Walden <jwalden@mit.edu>
Wed, 20 Feb 2019 13:33:16 -0800
changeset 519487 a9638eeea75714425a28e5bcd9edb9ae55dd13b9
parent 519486 715e9b139ebbd407ac64b5ee8737d0f042f74b4c
child 519488 5f4cc2c4551793656ade258587b3d83caae29b3e
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1529298
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1529298 - Make ArrayBufferObject::wasmGrowToSizeInPlace do its work *not* using ArrayBufferObject::stealContents, rather using the exact operations desired, far more simply. r=sfink
js/src/vm/ArrayBufferObject.cpp
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -1106,44 +1106,66 @@ Maybe<uint32_t> ArrayBufferObject::wasmM
 Maybe<uint32_t> js::WasmArrayBufferMaxSize(
     const ArrayBufferObjectMaybeShared* buf) {
   if (buf->is<ArrayBufferObject>()) {
     return buf->as<ArrayBufferObject>().wasmMaxSize();
   }
   return buf->as<SharedArrayBufferObject>().wasmMaxSize();
 }
 
+static void CheckStealPreconditions(Handle<ArrayBufferObject*> buffer,
+                                    JSContext* cx) {
+  cx->check(buffer);
+
+  MOZ_ASSERT(!buffer->isDetached(), "can't steal from a detached buffer");
+  MOZ_ASSERT(!buffer->isPreparedForAsmJS(),
+             "asm.js-prepared buffers don't have detachable/stealable data");
+}
+
 /* static */ bool ArrayBufferObject::wasmGrowToSizeInPlace(
     uint32_t newSize, HandleArrayBufferObject oldBuf,
     MutableHandleArrayBufferObject newBuf, JSContext* cx) {
+  CheckStealPreconditions(oldBuf, cx);
+
+  MOZ_ASSERT(oldBuf->isWasm());
+
   // On failure, do not throw and ensure that the original buffer is
   // unmodified and valid. After WasmArrayRawBuffer::growToSizeInPlace(), the
   // wasm-visible length of the buffer has been increased so it must be the
   // last fallible operation.
 
   if (newSize > ArrayBufferObject::MaxBufferByteLength) {
     return false;
   }
 
   newBuf.set(ArrayBufferObject::createEmpty(cx));
   if (!newBuf) {
     cx->clearPendingException();
     return false;
   }
 
+  MOZ_ASSERT(newBuf->isNoData());
+
   if (!oldBuf->contents().wasmBuffer()->growToSizeInPlace(oldBuf->byteLength(),
                                                           newSize)) {
     return false;
   }
 
-  bool hasStealableContents = true;
-  BufferContents contents =
-      ArrayBufferObject::stealContents(cx, oldBuf, hasStealableContents);
-  MOZ_ASSERT(contents);
-  newBuf->initialize(newSize, contents, OwnsData);
+  // Extract the grown contents from |oldBuf|.
+  BufferContents oldContents = oldBuf->contents();
+
+  // Overwrite |oldBuf|'s data pointer *without* releasing old data.
+  BufferContents detachedContents = BufferContents::createNoData();
+  oldBuf->setDataPointer(detachedContents, OwnsData);
+
+  // Detach |oldBuf| now that doing so won't release |oldContents|.
+  ArrayBufferObject::detach(cx, oldBuf, detachedContents);
+
+  // Set |newBuf|'s contents to |oldBuf|'s original contents.
+  newBuf->initialize(newSize, oldContents, OwnsData);
   return true;
 }
 
 #ifndef WASM_HUGE_MEMORY
 /* static */ bool ArrayBufferObject::wasmMovingGrowToSize(
     uint32_t newSize, HandleArrayBufferObject oldBuf,
     MutableHandleArrayBufferObject newBuf, JSContext* cx) {
   // On failure, do not throw and ensure that the original buffer is
@@ -1368,25 +1390,16 @@ ArrayBufferObject* ArrayBufferObject::cr
   auto contents = BufferContents::createWasm(rawBuffer->dataPointer());
   buffer->setDataPointer(contents, OwnsData);
 
   cx->updateMallocCounter(initialSize);
 
   return buffer;
 }
 
-static void CheckStealPreconditions(Handle<ArrayBufferObject*> buffer,
-                                    JSContext* cx) {
-  cx->check(buffer);
-
-  MOZ_ASSERT(!buffer->isDetached(), "can't steal from a detached buffer");
-  MOZ_ASSERT(!buffer->isPreparedForAsmJS(),
-             "asm.js-prepared buffers don't have detachable/stealable data");
-}
-
 /* static */ uint8_t* ArrayBufferObject::stealMallocedContents(
     JSContext* cx, Handle<ArrayBufferObject*> buffer) {
   CheckStealPreconditions(buffer, cx);
 
   switch (buffer->bufferKind()) {
     case MALLOCED:
       if (buffer->ownsData()) {
         uint8_t* stolenData = buffer->dataPointer();