Bug 773962 - Add some asserts in the brain transplant code. r=billm
authorBobby Holley <bobbyholley@gmail.com>
Mon, 23 Jul 2012 15:51:18 +0200
changeset 100127 451e63f9381ccff00af0ef5c66c01e187ba6e9cb
parent 100126 a501733bc7b5124e6b94492914260d56a84bcc38
child 100128 712a40509486a36ca782d50cbdbf369ed817cbf9
push id12343
push userbobbyholley@gmail.com
push dateMon, 23 Jul 2012 13:51:47 +0000
treeherdermozilla-inbound@195065ccf37b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbillm
bugs773962
milestone17.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 773962 - Add some asserts in the brain transplant code. r=billm This catches the crash when the naughtiness happens, rather than later on.
js/src/jswrapper.cpp
--- a/js/src/jswrapper.cpp
+++ b/js/src/jswrapper.cpp
@@ -1090,44 +1090,57 @@ js::NukeCrossCompartmentWrappers(JSConte
 
 // Given a cross-compartment wrapper |wobj|, update it to point to
 // |newTarget|. This recomputes the wrapper with JS_WrapValue, and thus can be
 // useful even if wrapper already points to newTarget.
 bool
 js::RemapWrapper(JSContext *cx, JSObject *wobj, JSObject *newTarget)
 {
     JS_ASSERT(IsCrossCompartmentWrapper(wobj));
+    JS_ASSERT(!IsCrossCompartmentWrapper(newTarget));
     JSObject *origTarget = Wrapper::wrappedObject(wobj);
     JS_ASSERT(origTarget);
     Value origv = ObjectValue(*origTarget);
     JSCompartment *wcompartment = wobj->compartment();
     WrapperMap &pmap = wcompartment->crossCompartmentWrappers;
 
+    // If we're mapping to a different target (as opposed to just recomputing
+    // for the same target), we must not have an existing wrapper for the new
+    // target, otherwise this will break.
+    JS_ASSERT_IF(origTarget != newTarget, !pmap.has(ObjectValue(*newTarget)));
+
+    // The old value should still be in the cross-compartment wrapper map, and
+    // the lookup should return wobj.
+    JS_ASSERT(&pmap.lookup(origv)->value.toObject() == wobj);
+    pmap.remove(origv);
+
     // When we remove origv from the wrapper map, its wrapper, wobj, must
     // immediately cease to be a cross-compartment wrapper. Neuter it.
-    JS_ASSERT(pmap.lookup(origv));
-    pmap.remove(origv);
     NukeCrossCompartmentWrapper(wobj);
 
     // First, we wrap it in the new compartment. This will return
     // a new wrapper.
     AutoCompartment ac(cx, wobj);
     JSObject *tobj = newTarget;
     if (!ac.enter() || !wcompartment->wrap(cx, &tobj))
         return false;
 
     // Now, because we need to maintain object identity, we do a
     // brain transplant on the old object. At the same time, we
     // update the entry in the compartment's wrapper map to point
     // to the old wrapper.
     JS_ASSERT(tobj != wobj);
     if (!wobj->swap(cx, tobj))
         return false;
+
+    // Before swapping, this wrapper came out of wrap(), which enforces the
+    // invariant that the wrapper in the map points directly to the key.
+    JS_ASSERT(Wrapper::wrappedObject(wobj) == newTarget);
+
     pmap.put(ObjectValue(*newTarget), ObjectValue(*wobj));
-
     return true;
 }
 
 // Remap all cross-compartment wrappers pointing to |oldTarget| to point to
 // |newTarget|. All wrappers are recomputed.
 bool
 js::RemapAllWrappersForObject(JSContext *cx, JSObject *oldTarget,
                               JSObject *newTarget)