Bug 1496378 part 6 - Remove TypedObject to ArrayBufferViewObject static_cast hackery. r=jwalden
authorJan de Mooij <jdemooij@mozilla.com>
Mon, 15 Oct 2018 11:43:36 +0000
changeset 499724 8886fad423dc0f7de57b96512b5680eecc2733ba
parent 499723 b449c4991dc4153716f7d53173a14f7a29284616
child 499725 942ccac42c5e7e0ef48f5ef3f1b3d18f1cf47750
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1496378
milestone64.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 1496378 part 6 - Remove TypedObject to ArrayBufferViewObject static_cast hackery. r=jwalden Depends on D7727 Differential Revision: https://phabricator.services.mozilla.com/D7728
js/src/vm/ArrayBufferObject.cpp
js/src/vm/ArrayBufferObject.h
js/src/vm/ArrayBufferViewObject.cpp
--- a/js/src/vm/ArrayBufferObject.cpp
+++ b/js/src/vm/ArrayBufferObject.cpp
@@ -504,33 +504,32 @@ ArrayBufferObject::detach(JSContext* cx,
             oomUnsafe.crash("ArrayBufferObject::detach");
         }
         MarkObjectGroupFlags(cx, cx->global(), OBJECT_FLAG_TYPED_OBJECT_HAS_DETACHED_BUFFER);
         cx->zone()->detachedTypedObjects = 1;
     }
 
     // Update all views of the buffer to account for the buffer having been
     // detached, and clear the buffer's data and list of views.
+    //
+    // Typed object buffers are not exposed and cannot be detached.
 
     auto& innerViews = ObjectRealm::get(buffer).innerViews.get();
     if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(buffer)) {
         for (size_t i = 0; i < views->length(); i++) {
-            NoteViewBufferWasDetached((*views)[i], newContents, cx);
+            JSObject* view = (*views)[i];
+            NoteViewBufferWasDetached(&view->as<ArrayBufferViewObject>(), newContents, cx);
         }
         innerViews.removeViews(buffer);
     }
-    if (buffer->firstView()) {
-        if (buffer->forInlineTypedObject()) {
-            // The buffer points to inline data in its first view, so to keep
-            // this pointer alive we don't clear out the first view.
-            MOZ_ASSERT(buffer->firstView()->is<InlineTransparentTypedObject>());
-        } else {
-            NoteViewBufferWasDetached(buffer->firstView(), newContents, cx);
-            buffer->setFirstView(nullptr);
-        }
+    if (JSObject* view = buffer->firstView()) {
+        MOZ_ASSERT(!buffer->forInlineTypedObject(),
+                   "Typed object buffers cannot be detached");
+        NoteViewBufferWasDetached(&view->as<ArrayBufferViewObject>(), newContents, cx);
+        buffer->setFirstView(nullptr);
     }
 
     if (newContents.data() != buffer->dataPointer()) {
         buffer->setNewData(cx->runtime()->defaultFreeOp(), newContents, OwnsData);
     }
 
     buffer->setByteLength(0);
     buffer->setIsDetached();
@@ -585,21 +584,23 @@ ArrayBufferObject::changeContents(JSCont
     // Change buffer contents.
     uint8_t* oldDataPointer = dataPointer();
     setNewData(cx->runtime()->defaultFreeOp(), newContents, ownsState);
 
     // Update all views.
     auto& innerViews = ObjectRealm::get(this).innerViews.get();
     if (InnerViewTable::ViewVector* views = innerViews.maybeViewsUnbarriered(this)) {
         for (size_t i = 0; i < views->length(); i++) {
-            changeViewContents(cx, (*views)[i], oldDataPointer, newContents);
+            JSObject* view = (*views)[i];
+            changeViewContents(cx, &view->as<ArrayBufferViewObject>(), oldDataPointer,
+                               newContents);
         }
     }
-    if (firstView()) {
-        changeViewContents(cx, firstView(), oldDataPointer, newContents);
+    if (JSObject* view = firstView()) {
+        changeViewContents(cx, &view->as<ArrayBufferViewObject>(), oldDataPointer, newContents);
     }
 }
 
 /*
  * [SMDOC] WASM Linear Memory structure
  *
  * Wasm Raw Buf Linear Memory Structure
  *
@@ -1476,54 +1477,53 @@ ArrayBufferObject::objectMoved(JSObject*
     // Fix up possible inline data pointer.
     if (src.hasInlineData()) {
         dst.setFixedSlot(DATA_SLOT, PrivateValue(dst.inlineDataPointer()));
     }
 
     return 0;
 }
 
-ArrayBufferViewObject*
+JSObject*
 ArrayBufferObject::firstView()
 {
     return getFixedSlot(FIRST_VIEW_SLOT).isObject()
-        ? static_cast<ArrayBufferViewObject*>(&getFixedSlot(FIRST_VIEW_SLOT).toObject())
+        ? &getFixedSlot(FIRST_VIEW_SLOT).toObject()
         : nullptr;
 }
 
 void
-ArrayBufferObject::setFirstView(ArrayBufferViewObject* view)
+ArrayBufferObject::setFirstView(JSObject* view)
 {
+    MOZ_ASSERT_IF(view,
+                  view->is<ArrayBufferViewObject>() || view->is<TypedObject>());
     setFixedSlot(FIRST_VIEW_SLOT, ObjectOrNullValue(view));
 }
 
 bool
-ArrayBufferObject::addView(JSContext* cx, JSObject* viewArg)
+ArrayBufferObject::addView(JSContext* cx, JSObject* view)
 {
-    // Note: we don't pass in an ArrayBufferViewObject as the argument due to
-    // tricky inheritance in the various view classes. View classes do not
-    // inherit from ArrayBufferViewObject so won't be upcast automatically.
-    MOZ_ASSERT(viewArg->is<ArrayBufferViewObject>() || viewArg->is<TypedObject>());
-    ArrayBufferViewObject* view = static_cast<ArrayBufferViewObject*>(viewArg);
+    MOZ_ASSERT(view->is<ArrayBufferViewObject>() || view->is<TypedObject>());
 
     if (!firstView()) {
         setFirstView(view);
         return true;
     }
+
     return ObjectRealm::get(this).innerViews.get().addView(cx, this, view);
 }
 
 /*
  * InnerViewTable
  */
 
 constexpr size_t VIEW_LIST_MAX_LENGTH = 500;
 
 bool
-InnerViewTable::addView(JSContext* cx, ArrayBufferObject* buffer, ArrayBufferViewObject* view)
+InnerViewTable::addView(JSContext* cx, ArrayBufferObject* buffer, JSObject* view)
 {
     // ArrayBufferObject entries are only added when there are multiple views.
     MOZ_ASSERT(buffer->firstView());
 
     Map::AddPtr p = map.lookupForAdd(buffer);
 
     MOZ_ASSERT(!gc::IsInsideNursery(buffer));
     bool addToNursery = nurseryKeysValid && gc::IsInsideNursery(view);
--- a/js/src/vm/ArrayBufferObject.h
+++ b/js/src/vm/ArrayBufferObject.h
@@ -321,32 +321,32 @@ class ArrayBufferObject : public ArrayBu
     static void addSizeOfExcludingThis(JSObject* obj, mozilla::MallocSizeOf mallocSizeOf,
                                        JS::ClassInfo* info);
 
     // ArrayBufferObjects (strongly) store the first view added to them, while
     // later views are (weakly) stored in the compartment's InnerViewTable
     // below. Buffers usually only have one view, so this slot optimizes for
     // the common case. Avoiding entries in the InnerViewTable saves memory and
     // non-incrementalized sweep time.
-    ArrayBufferViewObject* firstView();
+    JSObject* firstView();
 
     bool addView(JSContext* cx, JSObject* view);
 
     void setNewData(FreeOp* fop, BufferContents newContents, OwnsState ownsState);
     void changeContents(JSContext* cx, BufferContents newContents, OwnsState ownsState);
 
     // Detach this buffer from its original memory.  (This necessarily makes
     // views of this buffer unusable for modifying that original memory.)
     static void
     detach(JSContext* cx, Handle<ArrayBufferObject*> buffer, BufferContents newContents);
 
   private:
     void changeViewContents(JSContext* cx, ArrayBufferViewObject* view,
                             uint8_t* oldDataPointer, BufferContents newContents);
-    void setFirstView(ArrayBufferViewObject* view);
+    void setFirstView(JSObject* view);
 
     uint8_t* inlineDataPointer() const;
 
     struct FreeInfo {
         JS::BufferContentsFreeFunc freeFunc;
         void* freeUserData;
     };
     FreeInfo* freeInfo() const;
@@ -557,17 +557,17 @@ template<> inline bool TypeIsUnsigned<ui
 template<> inline bool TypeIsUnsigned<uint16_t>() { return true; }
 template<> inline bool TypeIsUnsigned<uint32_t>() { return true; }
 
 // Per-compartment table that manages the relationship between array buffers
 // and the views that use their storage.
 class InnerViewTable
 {
   public:
-    typedef Vector<ArrayBufferViewObject*, 1, SystemAllocPolicy> ViewVector;
+    typedef Vector<JSObject*, 1, SystemAllocPolicy> ViewVector;
 
     friend class ArrayBufferObject;
 
   private:
     struct MapGCPolicy {
         static bool needsSweep(JSObject** key, ViewVector* value) {
             return InnerViewTable::sweepEntry(key, *value);
         }
@@ -599,17 +599,17 @@ class InnerViewTable
     Vector<JSObject*, 0, SystemAllocPolicy> nurseryKeys;
 
     // Whether nurseryKeys is a complete list.
     bool nurseryKeysValid;
 
     // Sweep an entry during GC, returning whether the entry should be removed.
     static bool sweepEntry(JSObject** pkey, ViewVector& views);
 
-    bool addView(JSContext* cx, ArrayBufferObject* obj, ArrayBufferViewObject* view);
+    bool addView(JSContext* cx, ArrayBufferObject* buffer, JSObject* view);
     ViewVector* maybeViewsUnbarriered(ArrayBufferObject* obj);
     void removeViews(ArrayBufferObject* obj);
 
   public:
     InnerViewTable()
       : nurseryKeysValid(true)
     {}
 
--- a/js/src/vm/ArrayBufferViewObject.cpp
+++ b/js/src/vm/ArrayBufferViewObject.cpp
@@ -147,19 +147,17 @@ JS_GetArrayBufferViewBuffer(JSContext* c
     AssertHeapIsIdle();
     CHECK_THREAD(cx);
     cx->check(objArg);
 
     JSObject* obj = CheckedUnwrap(objArg);
     if (!obj) {
         return nullptr;
     }
-    MOZ_ASSERT(obj->is<ArrayBufferViewObject>());
-
-    Rooted<ArrayBufferViewObject*> viewObject(cx, static_cast<ArrayBufferViewObject*>(obj));
+    Rooted<ArrayBufferViewObject*> viewObject(cx, &obj->as<ArrayBufferViewObject>());
     ArrayBufferObjectMaybeShared* buffer = ArrayBufferViewObject::bufferObject(cx, viewObject);
     *isSharedMemory = buffer->is<SharedArrayBufferObject>();
     return buffer;
 }
 
 JS_FRIEND_API(uint32_t)
 JS_GetArrayBufferViewByteLength(JSObject* obj)
 {