Bug 1089665 - Fixup dictionary objects earlier after swapping them, r=billm.
authorBrian Hackett <bhackett1024@gmail.com>
Tue, 04 Nov 2014 18:44:03 -0700
changeset 214044 fd04ca4a868dbc364906ea59fdf3ee784bfcb86f
parent 214043 38ca6211d1d4ae7571b1cbc26ae4371b960006c1
child 214045 fca5cc8130369e86140bb9f9715a1a2bcaa95250
push id27771
push userryanvm@gmail.com
push dateWed, 05 Nov 2014 19:04:24 +0000
treeherdermozilla-central@305b4fecce99 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs1089665
milestone36.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 1089665 - Fixup dictionary objects earlier after swapping them, r=billm.
js/src/jsobj.cpp
js/src/jsobj.h
--- a/js/src/jsobj.cpp
+++ b/js/src/jsobj.cpp
@@ -2382,16 +2382,25 @@ NativeObject::fillInAfterSwap(JSContext 
         if (!slots_)
             CrashAtUnhandlableOOM("fillInAfterSwap");
         Debug_SetSlotRangeToCrashOnTouch(slots_, ndynamic);
     }
 
     initSlotRange(0, values.begin(), values.length());
 }
 
+void
+JSObject::fixDictionaryShapeAfterSwap()
+{
+    // Dictionary shapes can point back to their containing objects, so after
+    // swapping the guts of those objects fix the pointers up.
+    if (isNative() && as<NativeObject>().inDictionaryMode())
+        shape_->listp = &shape_;
+}
+
 /* Use this method with extreme caution. It trades the guts of two objects. */
 bool
 JSObject::swap(JSContext *cx, HandleObject a, HandleObject b)
 {
     // Ensure swap doesn't cause a finalizer to not be run.
     MOZ_ASSERT(IsBackgroundFinalized(a->asTenured().getAllocKind()) ==
                IsBackgroundFinalized(b->asTenured().getAllocKind()));
     MOZ_ASSERT(a->compartment() == b->compartment());
@@ -2436,16 +2445,19 @@ JSObject::swap(JSContext *cx, HandleObje
         size_t size = a->tenuredSizeOfThis();
 
         char tmp[mozilla::tl::Max<sizeof(JSFunction), sizeof(JSObject_Slots16)>::value];
         MOZ_ASSERT(size <= sizeof(tmp));
 
         js_memcpy(tmp, a, size);
         js_memcpy(a, b, size);
         js_memcpy(b, tmp, size);
+
+        a->fixDictionaryShapeAfterSwap();
+        b->fixDictionaryShapeAfterSwap();
     } else {
         // Avoid GC in here to avoid confusing the tracing code with our
         // intermediate state.
         AutoSuppressGC suppress(cx);
 
         // When the objects have different sizes, they will have different
         // numbers of fixed slots before and after the swap, so the slots for
         // native objects will need to be rearranged.
@@ -2473,29 +2485,25 @@ JSObject::swap(JSContext *cx, HandleObje
         }
 
         // Swap the main fields of the objects, whether they are native objects or proxies.
         char tmp[sizeof(JSObject_Slots0)];
         js_memcpy(&tmp, a, sizeof tmp);
         js_memcpy(a, b, sizeof tmp);
         js_memcpy(b, &tmp, sizeof tmp);
 
+        a->fixDictionaryShapeAfterSwap();
+        b->fixDictionaryShapeAfterSwap();
+
         if (na)
             b->as<NativeObject>().fillInAfterSwap(cx, avals, apriv);
         if (nb)
             a->as<NativeObject>().fillInAfterSwap(cx, bvals, bpriv);
     }
 
-    // Dictionary shapes can point back to their containing objects, so fix
-    // those pointers up.
-    if (a->isNative() && a->as<NativeObject>().inDictionaryMode())
-        a->lastProperty()->listp = &a->shape_;
-    if (b->isNative() && b->as<NativeObject>().inDictionaryMode())
-        b->lastProperty()->listp = &b->shape_;
-
     // Swapping the contents of two objects invalidates type sets which contain
     // either of the objects, so mark all such sets as unknown.
     MarkTypeObjectUnknownProperties(cx, a->type(), !a->hasSingletonType());
     MarkTypeObjectUnknownProperties(cx, b->type(), !b->hasSingletonType());
 
 #ifdef JSGC_INCREMENTAL
     /*
      * We need a write barrier here. If |a| was marked and |b| was not, then
--- a/js/src/jsobj.h
+++ b/js/src/jsobj.h
@@ -700,16 +700,20 @@ class JSObject : public js::gc::Cell
             return op(cx, obj);
         return obj;
     }
 
     static bool thisObject(JSContext *cx, const js::Value &v, js::Value *vp);
 
     static bool swap(JSContext *cx, JS::HandleObject a, JS::HandleObject b);
 
+  private:
+    void fixDictionaryShapeAfterSwap();
+
+  public:
     inline void initArrayClass();
 
     /*
      * In addition to the generic object interface provided by JSObject,
      * specific types of objects may provide additional operations. To access,
      * these addition operations, callers should use the pattern:
      *
      *   if (obj.is<XObject>()) {