Bug 1517823 - Part 1: Store out of line TypedArray data in ArrayBuffer malloc-arena. r=sfink
authorAndré Bargull <andre.bargull@gmail.com>
Mon, 07 Jan 2019 05:46:34 -0800
changeset 510011 3d09512072a5b37eb90f38a9490f89264be90356
parent 510010 14e4487e1c6b6fbee0e3c617219d1dae18a15bdb
child 510012 752c683e631d73518b21da4b0924ac80ce1f6d5f
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1517823
milestone66.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 1517823 - Part 1: Store out of line TypedArray data in ArrayBuffer malloc-arena. r=sfink
js/src/gc/Nursery.cpp
js/src/gc/Nursery.h
js/src/jit/MacroAssembler.cpp
js/src/vm/MallocProvider.h
js/src/vm/TypedArrayObject.cpp
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -451,43 +451,45 @@ void* js::Nursery::allocateBufferSameLoc
 
   if (!IsInsideNursery(obj)) {
     return obj->zone()->pod_malloc<uint8_t>(nbytes);
   }
 
   return allocate(nbytes);
 }
 
-void* js::Nursery::allocateZeroedBuffer(Zone* zone, size_t nbytes) {
+void* js::Nursery::allocateZeroedBuffer(
+    Zone* zone, size_t nbytes, arena_id_t arena /*= js::MallocArena*/) {
   MOZ_ASSERT(nbytes > 0);
 
   if (nbytes <= MaxNurseryBufferSize) {
     void* buffer = allocate(nbytes);
     if (buffer) {
       memset(buffer, 0, nbytes);
       return buffer;
     }
   }
 
-  void* buffer = zone->pod_calloc<uint8_t>(nbytes);
+  void* buffer = zone->pod_calloc<uint8_t>(nbytes, arena);
   if (buffer && !registerMallocedBuffer(buffer)) {
     js_free(buffer);
     return nullptr;
   }
   return buffer;
 }
 
-void* js::Nursery::allocateZeroedBuffer(JSObject* obj, size_t nbytes) {
+void* js::Nursery::allocateZeroedBuffer(
+    JSObject* obj, size_t nbytes, arena_id_t arena /*= js::MallocArena*/) {
   MOZ_ASSERT(obj);
   MOZ_ASSERT(nbytes > 0);
 
   if (!IsInsideNursery(obj)) {
-    return obj->zone()->pod_calloc<uint8_t>(nbytes);
+    return obj->zone()->pod_calloc<uint8_t>(nbytes, arena);
   }
-  return allocateZeroedBuffer(obj->zone(), nbytes);
+  return allocateZeroedBuffer(obj->zone(), nbytes, arena);
 }
 
 void* js::Nursery::reallocateBuffer(JSObject* obj, void* oldBuffer,
                                     size_t oldBytes, size_t newBytes) {
   if (!IsInsideNursery(obj)) {
     return obj->zone()->pod_realloc<uint8_t>((uint8_t*)oldBuffer, oldBytes,
                                              newBytes);
   }
--- a/js/src/gc/Nursery.h
+++ b/js/src/gc/Nursery.h
@@ -239,25 +239,29 @@ class Nursery {
   /*
    * Allocate a buffer for a given object, always using the nursery if obj is
    * in the nursery. The requested size must be less than or equal to
    * MaxNurseryBufferSize.
    */
   void* allocateBufferSameLocation(JSObject* obj, size_t nbytes);
 
   /* Allocate a zero-initialized buffer for a given zone, using the nursery if
-   * possible.
+   * possible. If the buffer isn't allocated in the nursery, the given arena is
+   * used.
    */
-  void* allocateZeroedBuffer(JS::Zone* zone, size_t nbytes);
+  void* allocateZeroedBuffer(JS::Zone* zone, size_t nbytes,
+                             arena_id_t arena = js::MallocArena);
 
   /*
    * Allocate a zero-initialized buffer for a given object, using the nursery if
-   * possible and obj is in the nursery.
+   * possible and obj is in the nursery. If the buffer isn't allocated in the
+   * nursery, the given arena is used.
    */
-  void* allocateZeroedBuffer(JSObject* obj, size_t nbytes);
+  void* allocateZeroedBuffer(JSObject* obj, size_t nbytes,
+                             arena_id_t arena = js::MallocArena);
 
   /* Resize an existing object buffer. */
   void* reallocateBuffer(JSObject* obj, void* oldBuffer, size_t oldBytes,
                          size_t newBytes);
 
   /* Free an object buffer. */
   void freeBuffer(void* buffer);
 
--- a/js/src/jit/MacroAssembler.cpp
+++ b/js/src/jit/MacroAssembler.cpp
@@ -1175,17 +1175,18 @@ static void AllocateObjectBufferWithInit
   }
 
   obj->setFixedSlot(TypedArrayObject::LENGTH_SLOT, Int32Value(count));
 
   size_t nbytes = count * obj->bytesPerElement();
   MOZ_ASSERT((CheckedUint32(nbytes) + sizeof(Value)).isValid());
 
   nbytes = JS_ROUNDUP(nbytes, sizeof(Value));
-  void* buf = cx->nursery().allocateZeroedBuffer(obj, nbytes);
+  void* buf = cx->nursery().allocateZeroedBuffer(obj, nbytes,
+                                                 js::ArrayBufferContentsArena);
   if (buf) {
     obj->initPrivate(buf);
   }
 }
 
 void MacroAssembler::initTypedArraySlots(Register obj, Register temp,
                                          Register lengthReg,
                                          LiveRegisterSet liveRegs, Label* fail,
--- a/js/src/vm/MallocProvider.h
+++ b/js/src/vm/MallocProvider.h
@@ -44,18 +44,18 @@
 #include "js/UniquePtr.h"
 #include "js/Utility.h"
 
 namespace js {
 
 template <class Client>
 struct MallocProvider {
   template <class T>
-  T* maybe_pod_malloc(size_t numElems) {
-    T* p = js_pod_malloc<T>(numElems);
+  T* maybe_pod_malloc(size_t numElems, arena_id_t arena = js::MallocArena) {
+    T* p = js_pod_arena_malloc<T>(arena, numElems);
     if (MOZ_LIKELY(p)) {
       client()->updateMallocCounter(numElems * sizeof(T));
     }
     return p;
   }
 
   template <class T>
   T* maybe_pod_calloc(size_t numElems, arena_id_t arena = js::MallocArena) {
@@ -80,18 +80,18 @@ struct MallocProvider {
   }
 
   template <class T>
   T* pod_malloc() {
     return pod_malloc<T>(1);
   }
 
   template <class T>
-  T* pod_malloc(size_t numElems) {
-    T* p = maybe_pod_malloc<T>(numElems);
+  T* pod_malloc(size_t numElems, arena_id_t arena = js::MallocArena) {
+    T* p = maybe_pod_malloc<T>(numElems, arena);
     if (MOZ_LIKELY(p)) {
       return p;
     }
     size_t bytes;
     if (MOZ_UNLIKELY(!CalculateAllocSize<T>(numElems, &bytes))) {
       client()->reportAllocationOverflow();
       return nullptr;
     }
--- a/js/src/vm/TypedArrayObject.cpp
+++ b/js/src/vm/TypedArrayObject.cpp
@@ -187,17 +187,18 @@ void TypedArrayObject::finalize(FreeOp* 
       output[0] = ZeroLengthArrayData;
     }
 #endif
     newObj->setInlineElements();
   } else {
     MOZ_ASSERT(!oldObj->hasInlineElements());
     AutoEnterOOMUnsafeRegion oomUnsafe;
     nbytes = JS_ROUNDUP(nbytes, sizeof(Value));
-    void* data = newObj->zone()->pod_malloc<uint8_t>(nbytes);
+    void* data = newObj->zone()->pod_malloc<uint8_t>(
+        nbytes, js::ArrayBufferContentsArena);
     if (!data) {
       oomUnsafe.crash(
           "Failed to allocate typed array elements while tenuring.");
     }
     MOZ_ASSERT(!nursery.isInside(data));
     newObj->initPrivate(data);
   }
 
@@ -523,17 +524,17 @@ class TypedArrayObjectTemplate : public 
     RootedObjectGroup group(cx, templateObj->group());
     MOZ_ASSERT(group->clasp() == instanceClass());
 
     NewObjectKind newKind = TenuredObject;
 
     UniquePtr<void, JS::FreePolicy> buf;
     if (!fitsInline) {
       MOZ_ASSERT(len > 0);
-      buf.reset(cx->pod_calloc<uint8_t>(nbytes));
+      buf.reset(cx->pod_calloc<uint8_t>(nbytes, js::ArrayBufferContentsArena));
       if (!buf) {
         return nullptr;
       }
     }
 
     TypedArrayObject* obj =
         NewObjectWithGroup<TypedArrayObject>(cx, group, allocKind, newKind);
     if (!obj) {