Bug 982974 - Back out the previous fix-attempt for non-trivial issues. r=orange, a=orange
authorJeff Walden <jwalden@mit.edu>
Sat, 15 Mar 2014 01:08:30 -0700
changeset 120025 f20eb0241d17b8e72b09c9e9cf1dee037bdaaa2d
parent 120024 53ede23e8515be5cd93a819909c4e90aacbe0837
child 120026 ed12abe9e1180e9a44770c032f7a091ed7fc0f03
push id1152
push userjwalden@mit.edu
push dateSat, 15 Mar 2014 08:09:46 +0000
reviewersorange, orange
bugs982974
milestone18.1
Bug 982974 - Back out the previous fix-attempt for non-trivial issues. r=orange, a=orange
js/src/jstypedarray.cpp
js/src/jstypedarray.h
js/src/jstypedarrayinlines.h
js/src/vm/ObjectImpl.h
--- a/js/src/jstypedarray.cpp
+++ b/js/src/jstypedarray.cpp
@@ -457,18 +457,16 @@ ArrayBufferObject::createDataViewForThis
     CallArgs args = CallArgsFromVp(argc, vp);
     return CallNonGenericMethod<IsArrayBuffer, createDataViewForThisImpl>(cx, args);
 }
 
 bool
 ArrayBufferObject::stealContents(JSContext *cx, JSObject *obj, void **contents,
                                  uint8_t **data)
 {
-    MOZ_ASSERT(cx);
-
     ArrayBufferObject &buffer = obj->asArrayBuffer();
     JSObject *views = *GetViewList(&buffer);
 
     // remove buffer from the list of buffers with > 1 view
     if (views && NextView(views) && BufferLink(*GetViewList(&buffer)) != UNSET_BUFFER_LINK)
     {
         ArrayBufferObject *prev = &cx->runtime->liveArrayBuffers->asArrayBuffer();
         if (prev == &buffer) {
@@ -482,57 +480,44 @@ ArrayBufferObject::stealContents(JSConte
                     SetBufferLink(*GetViewList(prev), BufferLink(*GetViewList(buf)));
                     break;
                 }
                 prev = buf;
             }
         }
     }
 
-    uint32_t byteLen = buffer.byteLength();
-
-    js::ObjectElements *oldHeader = buffer.getElementsHeader();
-    js::ObjectElements *newHeader;
-
-    // If the ArrayBuffer's elements are transferrable, transfer ownership
-    // directly.  Otherwise we have to copy the data into new elements.
-    bool stolen = buffer.hasStealableContents();
-    if (stolen) {
-        newHeader = AllocateArrayBufferContents(cx, byteLen, NULL);
-        if (!newHeader)
-            return false;
-
+    js::ObjectElements *header = js::ObjectElements::fromElements((js::HeapSlot*)buffer.dataPointer());
+    if (buffer.hasDynamicElements()) {
         *GetViewList(&buffer) = NULL;
-        *contents = oldHeader;
+        *contents = header;
         *data = buffer.dataPointer();
 
-        buffer.elements = newHeader->elements();
+        buffer.setFixedElements();
+        header = js::ObjectElements::fromElements((js::HeapSlot*)buffer.dataPointer());
     } else {
-        js::ObjectElements *headerCopy =
-            AllocateArrayBufferContents(cx, byteLen, buffer.dataPointer());
-        if (!headerCopy)
+        uint32_t length = buffer.byteLength();
+        js::ObjectElements *newheader =
+            AllocateArrayBufferContents(cx, length, buffer.dataPointer());
+        if (!newheader) {
+            js_ReportOutOfMemory(cx);
             return false;
-
-        ArrayBufferObject::setElementsHeader(headerCopy, byteLen);
-        *contents = headerCopy;
-        *data = reinterpret_cast<uint8_t *>(headerCopy + 1);
-
-        // Keep using the current elements.
-        newHeader = oldHeader;
+        }
+
+        ArrayBufferObject::setElementsHeader(newheader, length);
+        *contents = newheader;
+        *data = reinterpret_cast<uint8_t *>(newheader + 1);
     }
 
     // Neuter the donor ArrayBuffer and all views of it
-    uint32_t flags = newHeader->flags;
-    ArrayBufferObject::setElementsHeader(newHeader, 0);
-    newHeader->flags = flags;
+    ArrayBufferObject::setElementsHeader(header, 0);
     *GetViewList(&buffer) = views;
     for (JSObject *view = views; view; view = NextView(view))
         TypedArray::neuter(view);
 
-    newHeader->setIsNeuteredBuffer();
     return true;
 }
 
 void
 ArrayBufferObject::obj_trace(JSTracer *trc, RawObject obj)
 {
     /*
      * If this object changes, it will get marked via the private data barrier,
--- a/js/src/jstypedarray.h
+++ b/js/src/jstypedarray.h
@@ -127,29 +127,16 @@ class ArrayBufferObject : public JSObjec
                                     HandleSpecialId sid, MutableHandleValue rval,
                                     JSBool strict);
 
     static JSBool obj_enumerate(JSContext *cx, HandleObject obj, JSIterateOp enum_op,
                                 MutableHandleValue statep, MutableHandleId idp);
 
     static void sweepAll(JSRuntime *rt);
 
-    bool hasStealableContents() const {
-        // Inline elements strictly adhere to the corresponding buffer.
-        if (!hasDynamicElements())
-            return false;
-
-        // Neutered contents aren't transferrable because we want a neutered
-        // array's contents to be backed by zeroed memory equal in length to
-        // the original buffer contents.  Transferring these contents would
-        // allocate new ones based on the current byteLength, which is 0 for a
-        // neutered array -- not the original byteLength.
-        return !isNeutered();
-    }
-
     static bool stealContents(JSContext *cx, JSObject *obj, void **contents,
                               uint8_t **data);
 
     static inline void setElementsHeader(js::ObjectElements *header, uint32_t bytes);
 
     void addView(RawObject view);
 
     bool allocateSlots(JSContext *cx, uint32_t size, uint8_t *contents = NULL);
@@ -165,19 +152,16 @@ class ArrayBufferObject : public JSObjec
     inline uint8_t * dataPointer() const;
 
    /*
      * Check if the arrayBuffer contains any data. This will return false for
      * ArrayBuffer.prototype and neutered ArrayBuffers.
      */
     inline bool hasData() const;
 
-    bool isNeutered() const {
-        return getElementsHeader()->isNeuteredBuffer();
-    }
 };
 
 /*
  * BufferView
  *
  * Common definitions shared by all ArrayBufferViews. (The name ArrayBufferView
  * is currently being used for a namespace in jsfriendapi.h.)
  */
--- a/js/src/jstypedarrayinlines.h
+++ b/js/src/jstypedarrayinlines.h
@@ -23,17 +23,17 @@ js::ArrayBufferObject::setElementsHeader
     /*
      * Note that |bytes| may not be a multiple of |sizeof(Value)|, so
      * |capacity * sizeof(Value)| may underestimate the size by up to
      * |sizeof(Value) - 1| bytes.
      */
     header->capacity = bytes / sizeof(js::Value);
     header->initializedLength = bytes;
     header->length = 0;
-    header->flags = 0;
+    header->unused = 0;
 }
 
 inline uint32_t
 js::ArrayBufferObject::byteLength() const
 {
     JS_ASSERT(isArrayBuffer());
     return getElementsHeader()->initializedLength;
 }
--- a/js/src/vm/ObjectImpl.h
+++ b/js/src/vm/ObjectImpl.h
@@ -857,49 +857,42 @@ ElementsHeader::asArrayBufferElements()
  */
 class ArrayBufferObject;
 class ObjectElements
 {
     friend struct ::JSObject;
     friend class ObjectImpl;
     friend class ArrayBufferObject;
 
-    enum Flags {
-        NEUTERED_BUFFER = 0x1
-    };
-
     /* Number of allocated slots. */
     uint32_t capacity;
 
     /*
      * Number of initialized elements. This is <= the capacity, and for arrays
      * is <= the length. Memory for elements above the initialized length is
      * uninitialized, but values between the initialized length and the proper
      * length are conceptually holes.
      */
     uint32_t initializedLength;
 
-    /*
-     * 'length' property of array objects, views for ArrayBuffer objects,
-     * unused for other objects.
-     */
+    /* 'length' property of array objects, unused for other objects. */
     uint32_t length;
 
     /* :XXX: bug 586842 store state about sparse slots. */
-    uint32_t flags;
+    uint32_t unused;
 
     void staticAsserts() {
         MOZ_STATIC_ASSERT(sizeof(ObjectElements) == VALUES_PER_HEADER * sizeof(Value),
                           "Elements size and values-per-Elements mismatch");
     }
 
   public:
 
     ObjectElements(uint32_t capacity, uint32_t length)
-      : capacity(capacity), initializedLength(0), length(length), flags(0)
+      : capacity(capacity), initializedLength(0), length(length)
     {}
 
     HeapSlot *elements() { return (HeapSlot *)(uintptr_t(this) + sizeof(ObjectElements)); }
     static ObjectElements * fromElements(HeapSlot *elems) {
         return (ObjectElements *)(uintptr_t(elems) - sizeof(ObjectElements));
     }
 
     static int offsetOfCapacity() {
@@ -908,23 +901,16 @@ class ObjectElements
     static int offsetOfInitializedLength() {
         return (int)offsetof(ObjectElements, initializedLength) - (int)sizeof(ObjectElements);
     }
     static int offsetOfLength() {
         return (int)offsetof(ObjectElements, length) - (int)sizeof(ObjectElements);
     }
 
     static const size_t VALUES_PER_HEADER = 2;
-
-    bool isNeuteredBuffer() const {
-        return flags & NEUTERED_BUFFER;
-    }
-    void setIsNeuteredBuffer() {
-        flags |= NEUTERED_BUFFER;
-    }
 };
 
 /* Shared singleton for objects with no elements. */
 extern HeapSlot *emptyObjectElements;
 
 struct Class;
 struct GCMarker;
 struct ObjectOps;