Bug 1396931 - Simplify sweeping of dictionary mode objects allocated in the nursery r=sfink
authorJon Coppeard <jcoppeard@mozilla.com>
Wed, 06 Sep 2017 09:07:09 +0100
changeset 428779 eb00a7039454986b07be0caab31063e7876dea57
parent 428778 f80146e7ec85b8fd309b7b42f51032304136d835
child 428780 8d1a2ad4d81160488a7ec54cb0ed3abfa369ba77
push id7761
push userjlund@mozilla.com
push dateFri, 15 Sep 2017 00:19:52 +0000
treeherdermozilla-beta@c38455951db4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssfink
bugs1396931
milestone57.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 1396931 - Simplify sweeping of dictionary mode objects allocated in the nursery r=sfink
js/src/gc/Marking.cpp
js/src/gc/Nursery.cpp
js/src/jsobjinlines.h
js/src/vm/NativeObject.h
--- a/js/src/gc/Marking.cpp
+++ b/js/src/gc/Marking.cpp
@@ -2970,22 +2970,18 @@ js::TenuringTracer::moveObjectToTenured(
 
     // Move the slots and elements, if we need to.
     if (src->isNative()) {
         NativeObject* ndst = &dst->as<NativeObject>();
         NativeObject* nsrc = &src->as<NativeObject>();
         tenuredSize += moveSlotsToTenured(ndst, nsrc, dstKind);
         tenuredSize += moveElementsToTenured(ndst, nsrc, dstKind);
 
-        // The shape's list head may point into the old object. This can only
-        // happen for dictionaries, which are native objects.
-        if (&nsrc->shape_ == ndst->shape_->listp) {
-            MOZ_ASSERT(nsrc->shape_->inDictionary());
-            ndst->shape_->listp = &ndst->shape_;
-        }
+        // There is a pointer into a dictionary mode object from the head of its
+        // shape list. This is updated in Nursery::sweepDictionaryModeObjects().
     }
 
     if (src->is<InlineTypedObject>()) {
         InlineTypedObject::objectMovedDuringMinorGC(this, dst, src);
     } else if (src->is<TypedArrayObject>()) {
         tenuredSize += TypedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
     } else if (src->is<UnboxedArrayObject>()) {
         tenuredSize += UnboxedArrayObject::objectMovedDuringMinorGC(this, dst, src, dstKind);
--- a/js/src/gc/Nursery.cpp
+++ b/js/src/gc/Nursery.cpp
@@ -1074,11 +1074,13 @@ js::Nursery::queueDictionaryModeObjectTo
 }
 
 void
 js::Nursery::sweepDictionaryModeObjects()
 {
     for (auto obj : dictionaryModeObjects_) {
         if (!IsForwarded(obj))
             obj->sweepDictionaryListPointer();
+        else
+            Forwarded(obj)->updateDictionaryListPointerAfterMinorGC(obj);
     }
     dictionaryModeObjects_.clear();
 }
--- a/js/src/jsobjinlines.h
+++ b/js/src/jsobjinlines.h
@@ -138,16 +138,27 @@ js::NativeObject::sweepDictionaryListPoi
     // For dictionary objects (which must be native), it's possible that
     // unreachable shapes may be marked whose listp points into this object.  In
     // case this happens, null out the shape's pointer so that a moving GC will
     // not try to access the dead object.
     if (shape_->listp == &shape_)
         shape_->listp = nullptr;
 }
 
+MOZ_ALWAYS_INLINE void
+js::NativeObject::updateDictionaryListPointerAfterMinorGC(NativeObject* old)
+{
+    MOZ_ASSERT(this == Forwarded(old));
+
+    // Dictionary objects can be allocated in the nursery and when they are
+    // tenured the shape's pointer into the object needs to be updated.
+    if (shape_->listp == &old->shape_)
+        shape_->listp = &shape_;
+}
+
 /* static */ inline bool
 JSObject::setSingleton(JSContext* cx, js::HandleObject obj)
 {
     MOZ_ASSERT(!IsInsideNursery(obj));
 
     js::ObjectGroup* group = js::ObjectGroup::lazySingletonGroup(cx, obj->getClass(),
                                                                  obj->taggedProto());
     if (!group)
--- a/js/src/vm/NativeObject.h
+++ b/js/src/vm/NativeObject.h
@@ -1339,16 +1339,17 @@ class NativeObject : public ShapedObject
     }
 
     static inline NativeObject*
     copy(JSContext* cx, gc::AllocKind kind, gc::InitialHeap heap,
          HandleNativeObject templateObject);
 
     void updateShapeAfterMovingGC();
     void sweepDictionaryListPointer();
+    void updateDictionaryListPointerAfterMinorGC(NativeObject* old);
 
     /* JIT Accessors */
     static size_t offsetOfElements() { return offsetof(NativeObject, elements_); }
     static size_t offsetOfFixedElements() {
         return sizeof(NativeObject) + sizeof(ObjectElements);
     }
 
     static size_t getFixedSlotOffset(size_t slot) {