Bug 851465 - Remove slim wrappers - stop morphing slim wrappers. r=bholley.
authorPeter Van der Beken <peterv@propagandism.org>
Fri, 19 Apr 2013 21:57:15 +0200
changeset 146572 1b34a34b25389bf3a7d92598f473f4589684c093
parent 146571 fb09320a1b30aa5016dfe0aad38804524c99cc90
child 146573 1c5330960d0c49ac16f5d67fa653f93abf58e6a3
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbholley
bugs851465
milestone24.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 851465 - Remove slim wrappers - stop morphing slim wrappers. r=bholley.
content/base/src/nsNodeUtils.cpp
js/xpconnect/src/XPCComponents.cpp
js/xpconnect/src/XPCConvert.cpp
js/xpconnect/src/XPCJSID.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/XPCWrappedNativeJSOps.cpp
js/xpconnect/src/nsXPConnect.cpp
js/xpconnect/src/xpcprivate.h
js/xpconnect/src/xpcpublic.h
js/xpconnect/wrappers/WrapperFactory.cpp
--- a/content/base/src/nsNodeUtils.cpp
+++ b/content/base/src/nsNodeUtils.cpp
@@ -396,23 +396,16 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
   *aResult = nullptr;
 
   // First deal with aNode and walk its attributes (and their children). Then,
   // if aDeep is true, deal with aNode's children (and recurse into their
   // attributes and children).
 
   AutoJSContext cx;
   nsresult rv;
-  JS::RootedObject wrapper(cx);
-  bool isDOMBinding;
-  if (aReparentScope && (wrapper = aNode->GetWrapper()) &&
-      !(isDOMBinding = IsDOMObject(wrapper))) {
-      rv = xpc_MorphSlimWrapper(cx, aNode);
-      NS_ENSURE_SUCCESS(rv, rv);
-  }
 
   nsNodeInfoManager *nodeInfoManager = aNewNodeInfoManager;
 
   // aNode.
   nsINodeInfo *nodeInfo = aNode->mNodeInfo;
   nsCOMPtr<nsINodeInfo> newNodeInfo;
   if (nodeInfoManager) {
 
@@ -518,29 +511,32 @@ nsNodeUtils::CloneAndAdopt(nsINode *aNod
     if (oldDoc != newDoc && oldDoc->MayHaveDOMMutationObservers()) {
       newDoc->SetMayHaveDOMMutationObservers();
     }
 
     if (elem) {
       elem->RecompileScriptEventListeners();
     }
 
-    if (aReparentScope && wrapper) {
-      if (isDOMBinding) {
-        rv = ReparentWrapper(cx, wrapper);
-      } else {
-        nsIXPConnect *xpc = nsContentUtils::XPConnect();
-        if (xpc) {
-          rv = xpc->ReparentWrappedNativeIfFound(cx, wrapper, aReparentScope, aNode);
+    if (aReparentScope) {
+      JS::Rooted<JSObject*> wrapper(cx);
+      if ((wrapper = aNode->GetWrapper())) {
+        if (IsDOMObject(wrapper)) {
+          rv = ReparentWrapper(cx, wrapper);
+        } else {
+          nsIXPConnect *xpc = nsContentUtils::XPConnect();
+          if (xpc) {
+            rv = xpc->ReparentWrappedNativeIfFound(cx, wrapper, aReparentScope, aNode);
+          }
         }
-      }
-      if (NS_FAILED(rv)) {
-        aNode->mNodeInfo.swap(nodeInfo);
+        if (NS_FAILED(rv)) {
+          aNode->mNodeInfo.swap(nodeInfo);
 
-        return rv;
+          return rv;
+        }
       }
     }
   }
 
   // XXX If there are any attribute nodes on this element with UserDataHandlers
   // we should technically adopt/clone/import such attribute nodes and notify
   // those handlers. However we currently don't have code to do so without
   // also notifying when it's not safe so we're not doing that at this time.
--- a/js/xpconnect/src/XPCComponents.cpp
+++ b/js/xpconnect/src/XPCComponents.cpp
@@ -2679,20 +2679,16 @@ nsXPCComponents_Utils::LookupMethod(cons
     if (!obj) {
         JS_ReportError(cx, "Permission denied to unwrap object");
         return NS_ERROR_XPC_BAD_CONVERT_JS;
     }
     {
         // Enter the target compartment.
         JSAutoCompartment ac(cx, obj);
 
-        // Morph slim wrappers.
-        if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
-            return NS_ERROR_FAILURE;
-
         // Now, try to create an Xray wrapper around the object. This won't work
         // if the object isn't Xray-able. In that case, we throw.
         JSObject *xray = WrapperFactory::WrapForSameCompartmentXray(cx, obj);
         if (!xray)
             return NS_ERROR_XPC_BAD_CONVERT_JS;
 
         // Alright, now do the lookup.
         *retval = UndefinedValue();
--- a/js/xpconnect/src/XPCConvert.cpp
+++ b/js/xpconnect/src/XPCConvert.cpp
@@ -882,27 +882,16 @@ XPCConvert::NativeInterface2JSObject(jsv
         // otherwise we'll just return its JSObject in d (which should be
         // rooted in that case).
         if (dest)
             strongWrapper = wrapper;
         if (iface)
             wrapper->FindTearOff(iface, false, &rv);
         else
             rv = NS_OK;
-    } else {
-        NS_ASSERTION(IS_SLIM_WRAPPER(flat),
-                     "What kind of wrapper is this?");
-
-        SLIM_LOG(("***** morphing from XPCConvert::NativeInterface2JSObject"
-                  "(%p)\n",
-                  static_cast<nsISupports*>(xpc_GetJSPrivate(flat))));
-
-        rv = XPCWrappedNative::Morph(flat, iface, cache,
-                                     getter_AddRefs(strongWrapper));
-        wrapper = strongWrapper;
     }
 
     if (NS_FAILED(rv) && pErr)
         *pErr = rv;
 
     // If creating the wrapped native failed, then return early.
     if (NS_FAILED(rv) || !wrapper)
         return false;
--- a/js/xpconnect/src/XPCJSID.cpp
+++ b/js/xpconnect/src/XPCJSID.cpp
@@ -500,49 +500,34 @@ nsJSIID::HasInstance(nsIXPConnectWrapped
     nsresult rv = NS_OK;
 
     if (!JSVAL_IS_PRIMITIVE(val)) {
         // we have a JSObject
         RootedObject obj(cx, JSVAL_TO_OBJECT(val));
 
         NS_ASSERTION(obj, "when is an object not an object?");
 
-        nsISupports *identity = nullptr;
         // is this really a native xpcom object with a wrapper?
         const nsIID* iid;
         mInfo->GetIIDShared(&iid);
 
         obj = FindObjectForHasInstance(cx, obj);
         if (!obj)
             return NS_OK;
 
-        if (IS_SLIM_WRAPPER(obj)) {
-            XPCWrappedNativeProto* proto = GetSlimWrapperProto(obj);
-            if (proto->GetSet()->HasInterfaceWithAncestor(iid)) {
-                *bp = true;
+        if (IsDOMObject(obj)) {
+            // Not all DOM objects implement nsISupports. But if they don't,
+            // there's nothing to do in this HasInstance hook.
+            nsISupports *identity = UnwrapDOMObjectToISupports(obj);
+            if (!identity)
                 return NS_OK;
-            }
-
-#ifdef DEBUG_slimwrappers
-            char foo[NSID_LENGTH];
-            iid->ToProvidedString(foo);
-            SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, foo);
-#endif
-            if (!MorphSlimWrapper(cx, obj))
-                return NS_ERROR_FAILURE;
-        } else if (IsDOMObject(obj)) {
-              // Not all DOM objects implement nsISupports. But if they don't,
-              // there's nothing to do in this HasInstance hook.
-              identity = UnwrapDOMObjectToISupports(obj);
-              if (!identity)
-                  return NS_OK;
-              nsCOMPtr<nsISupports> supp;
-              identity->QueryInterface(*iid, getter_AddRefs(supp));
-              *bp = supp;
-              return NS_OK;
+            nsCOMPtr<nsISupports> supp;
+            identity->QueryInterface(*iid, getter_AddRefs(supp));
+            *bp = supp;
+            return NS_OK;
         }
 
         MOZ_ASSERT(IS_WN_WRAPPER(obj));
         XPCWrappedNative* other_wrapper = XPCWrappedNative::Get(obj);
         if (!other_wrapper)
             return NS_OK;
 
         // We'll trust the interface set of the wrapper if this is known
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -527,25 +527,18 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
         }
 
         // Take the performance hit of checking the hashtable again in case
         // the preCreate call caused the wrapper to get created through some
         // interesting path (the DOM code tends to make this happen sometimes).
 
         if (cache) {
             RootedObject cached(cx, cache->GetWrapper());
-            if (cached) {
-                if (IS_SLIM_WRAPPER_OBJECT(cached)) {
-                    if (NS_FAILED(XPCWrappedNative::Morph(cached,
-                          Interface, cache, getter_AddRefs(wrapper))))
-                        return NS_ERROR_FAILURE;
-                } else {
-                    wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(cached));
-                }
-            }
+            if (cached)
+                wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(cached));
         } else {
             // scoped lock
             XPCAutoLock lock(mapLock);
             wrapper = map->Find(identity);
         }
 
         if (wrapper) {
             if (Interface && !wrapper->FindTearOff(Interface, false, &rv)) {
@@ -708,101 +701,34 @@ FinishCreate(XPCWrappedNativeScope* Scop
 
     DEBUG_CheckClassInfoClaims(wrapper);
     *resultWrapper = wrapper.forget().get();
     return NS_OK;
 }
 
 // static
 nsresult
-XPCWrappedNative::Morph(HandleObject existingJSObject,
-                        XPCNativeInterface* Interface,
-                        nsWrapperCache *cache,
-                        XPCWrappedNative** resultWrapper)
-{
-    AutoJSContext cx;
-    NS_ASSERTION(IS_SLIM_WRAPPER(existingJSObject),
-                 "Trying to morph a JSObject that's not a slim wrapper?");
-
-    nsISupports *identity =
-        static_cast<nsISupports*>(xpc_GetJSPrivate(existingJSObject));
-    XPCWrappedNativeProto *proto = GetSlimWrapperProto(existingJSObject);
-
-#if DEBUG
-    // FIXME Can't assert this until
-    //       https://bugzilla.mozilla.org/show_bug.cgi?id=343141 is fixed.
-#if 0
-    if (proto->GetScriptableInfo()->GetFlags().WantPreCreate()) {
-        JSObject* parent = JS_GetParent(existingJSObject);
-        JSObject* plannedParent = parent;
-        nsresult rv =
-            proto->GetScriptableInfo()->GetCallback()->PreCreate(identity, ccx,
-                                                                 parent,
-                                                                 &parent);
-        if (NS_FAILED(rv))
-            return rv;
-
-        NS_ASSERTION(parent == plannedParent,
-                     "PreCreate returned a different parent");
-    }
-#endif
-#endif
-
-    nsRefPtr<XPCWrappedNative> wrapper = new XPCWrappedNative(dont_AddRef(identity), proto);
-    if (!wrapper)
-        return NS_ERROR_FAILURE;
-
-    NS_ASSERTION(!xpc::WrapperFactory::IsXrayWrapper(js::GetObjectParent(existingJSObject)),
-                 "Xray wrapper being used to parent XPCWrappedNative?");
-
-    // We use an AutoMarkingPtr here because it is possible for JS gc to happen
-    // after we have Init'd the wrapper but *before* we add it to the hashtable.
-    // This would cause the mSet to get collected and we'd later crash. I've
-    // *seen* this happen.
-    AutoMarkingWrappedNativePtr wrapperMarker(cx, wrapper);
-
-    JSAutoCompartment ac(cx, existingJSObject);
-    if (!wrapper->Init(existingJSObject))
-        return NS_ERROR_FAILURE;
-
-    nsresult rv;
-    if (Interface && !wrapper->FindTearOff(Interface, false, &rv)) {
-        NS_ASSERTION(NS_FAILED(rv), "returning NS_OK on failure");
-        return rv;
-    }
-
-    return FinishCreate(wrapper->GetScope(), Interface, cache, wrapper, resultWrapper);
-}
-
-// static
-nsresult
 XPCWrappedNative::GetUsedOnly(nsISupports* Object,
                               XPCWrappedNativeScope* Scope,
                               XPCNativeInterface* Interface,
                               XPCWrappedNative** resultWrapper)
 {
     AutoJSContext cx;
     NS_ASSERTION(Object, "XPCWrappedNative::GetUsedOnly was called with a null Object");
 
     XPCWrappedNative* wrapper;
     nsWrapperCache* cache = nullptr;
     CallQueryInterface(Object, &cache);
     if (cache) {
         RootedObject flat(cx, cache->GetWrapper());
-        if (flat && IS_SLIM_WRAPPER_OBJECT(flat) && !MorphSlimWrapper(cx, flat))
-           return NS_ERROR_FAILURE;
-
-        wrapper = flat ?
-                  static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(flat)) :
-                  nullptr;
-
-        if (!wrapper) {
+        if (!flat) {
             *resultWrapper = nullptr;
             return NS_OK;
         }
+        wrapper = static_cast<XPCWrappedNative*>(xpc_GetJSPrivate(flat));
         NS_ADDREF(wrapper);
     } else {
         nsCOMPtr<nsISupports> identity = do_QueryInterface(Object);
 
         if (!identity) {
             NS_ERROR("This XPCOM object fails in QueryInterface to nsISupports!");
             return NS_ERROR_FAILURE;
         }
@@ -1062,20 +988,16 @@ XPCWrappedNative::GatherScriptableCreate
                      "without also setting it on the class scriptable (if present and shared)");
 
         return sciWrapper;
     }
 
     return sciProto;
 }
 
-#ifdef DEBUG_slimwrappers
-static uint32_t sMorphedSlimWrappers;
-#endif
-
 JSBool
 XPCWrappedNative::Init(HandleObject parent,
                        const XPCNativeScriptableCreateInfo* sci)
 {
     AutoJSContext cx;
     // setup our scriptable info...
 
     if (sci->GetCallback()) {
@@ -1125,42 +1047,21 @@ XPCWrappedNative::Init(HandleObject pare
         return false;
 
     JS_SetPrivate(mFlatJSObject, this);
 
     return FinishInit();
 }
 
 JSBool
-XPCWrappedNative::Init(JSObject *existingJSObject)
-{
-    // Set up the private to point to the WN.
-    JS_SetPrivate(existingJSObject, this);
-
-    // Officially mark us as non-slim.
-    MorphMultiSlot(existingJSObject);
-
-    mScriptableInfo = GetProto()->GetScriptableInfo();
-    mFlatJSObject = existingJSObject;
-
-    SLIM_LOG(("----- %i morphed slim wrapper (mFlatJSObject: %p, %p)\n",
-              ++sMorphedSlimWrappers, mFlatJSObject,
-              static_cast<nsISupports*>(xpc_GetJSPrivate(mFlatJSObject))));
-
-    return FinishInit();
-}
-
-JSBool
 XPCWrappedNative::FinishInit()
 {
     AutoJSContext cx;
 
     // For all WNs, we want to make sure that the multislot starts out as null.
-    // This happens explicitly when morphing a slim wrapper, but we need to
-    // make sure it happens in the other cases too.
     JS_SetReservedSlot(mFlatJSObject, WRAPPER_MULTISLOT, JSVAL_NULL);
 
     // This reference will be released when mFlatJSObject is finalized.
     // Since this reference will push the refcount to 2 it will also root
     // mFlatJSObject;
     NS_ASSERTION(1 == mRefCnt, "unexpected refcount value");
     NS_ADDREF(this);
 
@@ -1688,22 +1589,16 @@ RescueOrphans(HandleObject obj)
             NS_ENSURE_SUCCESS(rv, rv);
         } else {
             MOZ_ASSERT(IsDOMObject(obj));
             const DOMClass* domClass = GetDOMClass(obj);
             parentObj = domClass->mGetParent(cx, obj);
         }
     }
 
-    // Morph any slim wrappers, lest they confuse us.
-    if (IS_SLIM_WRAPPER(parentObj)) {
-        bool ok = MorphSlimWrapper(cx, parentObj);
-        NS_ENSURE_TRUE(ok, NS_ERROR_FAILURE);
-    }
-
     // Recursively fix up orphans on the parent chain.
     rv = RescueOrphans(parentObj);
     NS_ENSURE_SUCCESS(rv, rv);
 
     // Now that we know our parent is in the right place, determine if we've
     // been orphaned. If not, we have nothing to do.
     if (!js::IsCrossCompartmentWrapper(parentObj))
         return NS_OK;
@@ -3548,23 +3443,8 @@ XPCJSObjectHolder*
 XPCJSObjectHolder::newHolder(JSObject* obj)
 {
     if (!obj) {
         NS_ERROR("bad param");
         return nullptr;
     }
     return new XPCJSObjectHolder(obj);
 }
-
-JSBool
-MorphSlimWrapper(JSContext *cx, HandleObject obj)
-{
-    SLIM_LOG(("***** morphing from MorphSlimToWrapper (%p, %p)\n",
-              obj, static_cast<nsISupports*>(xpc_GetJSPrivate(obj))));
-
-    nsISupports* object = static_cast<nsISupports*>(xpc_GetJSPrivate(obj));
-    nsWrapperCache *cache = nullptr;
-    CallQueryInterface(object, &cache);
-    nsRefPtr<XPCWrappedNative> wn;
-    nsresult rv = XPCWrappedNative::Morph(obj, nullptr, cache,
-                                          getter_AddRefs(wn));
-    return NS_SUCCEEDED(rv);
-}
--- a/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeJSOps.cpp
@@ -25,23 +25,16 @@ using namespace JS;
 static JSBool Throw(nsresult errNum, JSContext* cx)
 {
     XPCThrower::Throw(errNum, cx);
     return false;
 }
 
 // Handy macro used in many callback stub below.
 
-#define MORPH_SLIM_WRAPPER(cx, obj)                                           \
-    PR_BEGIN_MACRO                                                            \
-    SLIM_LOG_WILL_MORPH(cx, obj);                                             \
-    if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))                   \
-        return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);                    \
-    PR_END_MACRO
-
 #define THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper)                          \
     PR_BEGIN_MACRO                                                            \
     if (!wrapper)                                                             \
         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);                    \
     if (!wrapper->IsValid())                                                  \
         return Throw(NS_ERROR_XPC_HAS_BEEN_SHUTDOWN, cx);                     \
     PR_END_MACRO
 
@@ -168,17 +161,16 @@ GetDoubleWrappedJSObject(XPCCallContext&
 
 static JSBool
 XPC_WN_DoubleWrappedGetter(JSContext *cx, unsigned argc, jsval *vp)
 {
     RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
     if (!obj)
         return false;
 
-    MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
 
     RootedObject realObject(cx, GetDoubleWrappedJSObject(ccx, wrapper));
     if (!realObject) {
@@ -508,17 +500,16 @@ XPC_WN_CannotModifyStrictPropertyStub(JS
 static JSBool
 XPC_WN_Shared_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
 {
     if (type == JSTYPE_OBJECT) {
         vp.set(OBJECT_TO_JSVAL(obj));
         return true;
     }
 
-    MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     switch (type) {
         case JSTYPE_FUNCTION:
             {
                 if (!ccx.GetTearOff()) {
@@ -561,17 +552,16 @@ XPC_WN_Shared_Convert(JSContext *cx, JSH
     }
     NS_NOTREACHED("huh?");
     return false;
 }
 
 static JSBool
 XPC_WN_Shared_Enumerate(JSContext *cx, JSHandleObject obj)
 {
-    MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     // Since we aren't going to enumerate tearoff names and the prototype
     // handles non-mutated members, we can do this potential short-circuit.
     if (!wrapper->HasMutatedSet())
         return true;
@@ -688,17 +678,16 @@ static void
 XPC_WN_NoHelper_Trace(JSTracer *trc, JSObject *obj)
 {
     MarkWrappedNative(trc, obj);
 }
 
 static JSBool
 XPC_WN_NoHelper_Resolve(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
-    MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), id);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     XPCNativeSet* set = ccx.GetSet();
     if (!set)
         return true;
 
@@ -821,17 +810,16 @@ XPCWrappedNativeJSClass XPC_WN_NoHelper_
 };
 
 
 /***************************************************************************/
 
 static JSBool
 XPC_WN_MaybeResolvingPropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSMutableHandleValue vp)
 {
-    MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     if (ccx.GetResolvingWrapper() == wrapper)
         return true;
     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
 }
@@ -841,36 +829,28 @@ XPC_WN_MaybeResolvingStrictPropertyStub(
                                         JSMutableHandleValue vp)
 {
     return XPC_WN_MaybeResolvingPropertyStub(cx, obj, id, vp);
 }
 
 static JSBool
 XPC_WN_MaybeResolvingDeletePropertyStub(JSContext *cx, JSHandleObject obj, JSHandleId id, JSBool *succeeded)
 {
-    MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     if (ccx.GetResolvingWrapper() == wrapper) {
         *succeeded = true;
         return true;
     }
     return Throw(NS_ERROR_XPC_CANT_MODIFY_PROP_ON_WN, cx);
 }
 
 // macro fun!
-#define PRE_HELPER_STUB_NO_SLIM                                               \
-    XPCWrappedNative* wrapper =                                               \
-        XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(cx, obj);        \
-    THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);                             \
-    bool retval = true;                                                       \
-    nsresult rv = wrapper->GetScriptableCallback()->
-
 #define PRE_HELPER_STUB                                                       \
     XPCWrappedNative* wrapper;                                                \
     nsIXPCScriptable* si;                                                     \
     JSObject *unwrapped = js::CheckedUnwrap(obj, false);                \
     if (!unwrapped) {                                                         \
         JS_ReportError(cx, "Permission denied to operate on object.");        \
         return false;                                                         \
     }                                                                         \
@@ -929,18 +909,17 @@ XPC_WN_Helper_SetProperty(JSContext *cx,
     PRE_HELPER_STUB
     SetProperty(wrapper, cx, obj, id, vp.address(), &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
 XPC_WN_Helper_Convert(JSContext *cx, JSHandleObject obj, JSType type, JSMutableHandleValue vp)
 {
-    SLIM_LOG_WILL_MORPH(cx, obj);
-    PRE_HELPER_STUB_NO_SLIM
+    PRE_HELPER_STUB
     Convert(wrapper, cx, obj, type, vp.address(), &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
 XPC_WN_Helper_CheckAccess(JSContext *cx, JSHandleObject obj, JSHandleId id,
                           JSAccessMode mode, JSMutableHandleValue vp)
 {
@@ -958,18 +937,17 @@ XPC_WN_Helper_Call(JSContext *cx, unsign
 
     XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), JSID_VOIDHANDLE, args.length(),
                        args.array(), args.rval().address());
     if (!ccx.IsValid())
         return false;
 
     MOZ_ASSERT(obj == ccx.GetFlattenedJSObject());
 
-    SLIM_LOG_WILL_MORPH(cx, obj);
-    PRE_HELPER_STUB_NO_SLIM
+    PRE_HELPER_STUB
     Call(wrapper, cx, obj, args, &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
 XPC_WN_Helper_Construct(JSContext *cx, unsigned argc, jsval *vp)
 {
     JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
@@ -979,28 +957,26 @@ XPC_WN_Helper_Construct(JSContext *cx, u
 
     XPCCallContext ccx(JS_CALLER, cx, obj, NullPtr(), JSID_VOIDHANDLE, args.length(),
                        args.array(), args.rval().address());
     if (!ccx.IsValid())
         return false;
 
     MOZ_ASSERT(obj == ccx.GetFlattenedJSObject());
 
-    SLIM_LOG_WILL_MORPH(cx, obj);
-    PRE_HELPER_STUB_NO_SLIM
+    PRE_HELPER_STUB
     Construct(wrapper, cx, obj, args, &retval);
     POST_HELPER_STUB
 }
 
 static JSBool
 XPC_WN_Helper_HasInstance(JSContext *cx, JSHandleObject obj, JSMutableHandleValue valp, JSBool *bp)
 {
-    SLIM_LOG_WILL_MORPH(cx, obj);
     bool retval2;
-    PRE_HELPER_STUB_NO_SLIM
+    PRE_HELPER_STUB
     HasInstance(wrapper, cx, obj, valp, &retval2, &retval);
     *bp = retval2;
     POST_HELPER_STUB
 }
 
 static void
 XPC_WN_Helper_Finalize(js::FreeOp *fop, JSObject *obj)
 {
@@ -1153,18 +1129,16 @@ XPC_WN_JSOp_Enumerate(JSContext *cx, JSH
     if (!IS_WRAPPER_CLASS(clazz) || clazz == &XPC_WN_NoHelper_JSClass.base) {
         // obj must be a prototype object or a wrapper w/o a
         // helper. Short circuit this call to the default
         // implementation.
 
         return JS_EnumerateState(cx, obj, enum_op, statep, idp);
     }
 
-    MORPH_SLIM_WRAPPER(cx, obj);
-
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     XPCNativeScriptableInfo* si = wrapper->GetScriptableInfo();
     if (!si)
         return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
 
@@ -1448,28 +1422,16 @@ XPC_WN_CallMethod(JSContext *cx, unsigne
 {
     NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
     RootedObject funobj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
 
     RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
     if (!obj)
         return false;
 
-#ifdef DEBUG_slimwrappers
-    {
-        JSFunction* fun = funobj->getFunctionPrivate();
-        JSString *funid = JS_GetFunctionDisplayId(fun);
-        JSAutoByteString bytes;
-        const char *funname = !funid ? "" : bytes.encodeLatin1(cx, funid) ? bytes.ptr() : "<error>";
-        SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
-    }
-#endif
-    if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
-        return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
-
     obj = FixUpThisIfBroken(obj, funobj);
     XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOIDHANDLE, argc,
                        JS_ARGV(cx, vp), vp);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     XPCNativeInterface* iface;
     XPCNativeMember*    member;
@@ -1485,31 +1447,16 @@ XPC_WN_GetterSetter(JSContext *cx, unsig
 {
     NS_ASSERTION(JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION, "bad function");
     RootedObject funobj(cx, JSVAL_TO_OBJECT(JS_CALLEE(cx, vp)));
 
     RootedObject obj(cx, JS_THIS_OBJECT(cx, vp));
     if (!obj)
         return false;
 
-#ifdef DEBUG_slimwrappers
-    {
-        const char* funname = nullptr;
-        JSAutoByteString bytes;
-        if (JS_TypeOfValue(cx, JS_CALLEE(cx, vp)) == JSTYPE_FUNCTION) {
-            JSString *funid = JS_GetFunctionDisplayId(funobj->getFunctionPrivate());
-            funname = !funid ? "" : bytes.encodeLatin1(cx, funid) ? bytes.ptr() : "<error>";
-        }
-        SLIM_LOG_WILL_MORPH_FOR_PROP(cx, obj, funname);
-    }
-#endif
-    if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
-        return Throw(NS_ERROR_XPC_BAD_OP_ON_WN_PROTO, cx);
-
-
     obj = FixUpThisIfBroken(obj, funobj);
     XPCCallContext ccx(JS_CALLER, cx, obj, funobj, JSID_VOIDHANDLE, argc,
                        JS_ARGV(cx, vp), vp);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     XPCNativeInterface* iface;
     XPCNativeMember*    member;
@@ -1782,17 +1729,16 @@ js::Class XPC_WN_NoMods_NoCall_Proto_JSC
     XPC_WN_NoCall_ObjectOps
 };
 
 /***************************************************************************/
 
 static JSBool
 XPC_WN_TearOff_Enumerate(JSContext *cx, JSHandleObject obj)
 {
-    MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     XPCWrappedNativeTearOff* to = ccx.GetTearOff();
     XPCNativeInterface* iface;
 
     if (!to || nullptr == (iface = to->GetInterface()))
@@ -1805,17 +1751,16 @@ XPC_WN_TearOff_Enumerate(JSContext *cx, 
     }
 
     return true;
 }
 
 static JSBool
 XPC_WN_TearOff_Resolve(JSContext *cx, JSHandleObject obj, JSHandleId id)
 {
-    MORPH_SLIM_WRAPPER(cx, obj);
     XPCCallContext ccx(JS_CALLER, cx, obj);
     XPCWrappedNative* wrapper = ccx.GetWrapper();
     THROW_AND_RETURN_IF_BAD_WRAPPER(cx, wrapper);
 
     XPCWrappedNativeTearOff* to = ccx.GetTearOff();
     XPCNativeInterface* iface;
 
     if (!to || nullptr == (iface = to->GetInterface()))
--- a/js/xpconnect/src/nsXPConnect.cpp
+++ b/js/xpconnect/src/nsXPConnect.cpp
@@ -1075,31 +1075,16 @@ nsXPConnect::InitClassesWithNewWrappedGl
         !DOMErrorBinding::GetConstructorObject(aJSContext, global)) {
         return UnexpectedFailure(NS_ERROR_FAILURE);
     }
 
     wrappedGlobal.forget(_retval);
     return NS_OK;
 }
 
-nsresult
-xpc_MorphSlimWrapper(JSContext *cx, nsISupports *tomorph)
-{
-    nsWrapperCache *cache;
-    CallQueryInterface(tomorph, &cache);
-    if (!cache)
-        return NS_OK;
-
-    RootedObject obj(cx, cache->GetWrapper());
-    if (!obj || !IS_SLIM_WRAPPER(obj))
-        return NS_OK;
-    NS_ENSURE_STATE(MorphSlimWrapper(cx, obj));
-    return NS_OK;
-}
-
 static nsresult
 NativeInterface2JSObject(HandleObject aScope,
                          nsISupports *aCOMObj,
                          nsWrapperCache *aCache,
                          const nsIID * aIID,
                          bool aAllowWrapping,
                          jsval *aVal,
                          nsIXPConnectJSObjectHolder **aHolder)
@@ -1231,22 +1216,19 @@ nsXPConnect::GetWrappedNativeOfJSObject(
                                         JSObject * aJSObjArg,
                                         nsIXPConnectWrappedNative **_retval)
 {
     NS_ASSERTION(aJSContext, "bad param");
     NS_ASSERTION(aJSObjArg, "bad param");
     NS_ASSERTION(_retval, "bad param");
 
     RootedObject aJSObj(aJSContext, aJSObjArg);
-    SLIM_LOG_WILL_MORPH(aJSContext, aJSObj);
-    nsIXPConnectWrappedNative* wrapper =
-        XPCWrappedNative::GetAndMorphWrappedNativeOfJSObject(aJSContext, aJSObj);
-    if (wrapper) {
-        NS_ADDREF(wrapper);
-        *_retval = wrapper;
+    aJSObj = js::CheckedUnwrap(aJSObj, /* stopAtOuter = */ false);
+    if (aJSObj && IS_WN_WRAPPER(aJSObj)) {
+        NS_IF_ADDREF(*_retval = XPCWrappedNative::Get(aJSObj));
         return NS_OK;
     }
 
     // else...
     *_retval = nullptr;
     return NS_ERROR_FAILURE;
 }
 
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -299,26 +299,16 @@ inline void SetSlimWrapperProto(JSObject
 
 inline XPCWrappedNativeProto* GetSlimWrapperProto(JSObject *obj)
 {
     MOZ_ASSERT(IS_SLIM_WRAPPER(obj));
     const JS::Value &v = js::GetReservedSlot(obj, WRAPPER_MULTISLOT);
     return static_cast<XPCWrappedNativeProto*>(v.toPrivate());
 }
 
-// A slim wrapper is identified by having a native pointer in its reserved slot.
-// This function, therefore, does the official transition from a slim wrapper to
-// a non-slim wrapper.
-inline void MorphMultiSlot(JSObject *obj)
-{
-    MOZ_ASSERT(IS_SLIM_WRAPPER(obj));
-    JS_SetReservedSlot(obj, WRAPPER_MULTISLOT, JSVAL_NULL);
-    MOZ_ASSERT(!IS_SLIM_WRAPPER(obj));
-}
-
 inline void SetWNExpandoChain(JSObject *obj, JSObject *chain)
 {
     MOZ_ASSERT(IS_WN_WRAPPER(obj));
     JS_SetReservedSlot(obj, WRAPPER_MULTISLOT, JS::ObjectOrNullValue(chain));
 }
 
 inline JSObject* GetWNExpandoChain(JSObject *obj)
 {
@@ -2236,18 +2226,16 @@ private:
     JS::ObjectPtr            mJSProtoObject;
     nsCOMPtr<nsIClassInfo>   mClassInfo;
     uint32_t                 mClassInfoFlags;
     XPCNativeSet*            mSet;
     void*                    mSecurityInfo;
     XPCNativeScriptableInfo* mScriptableInfo;
 };
 
-extern JSBool MorphSlimWrapper(JSContext *cx, JS::HandleObject obj);
-
 /***********************************************/
 // XPCWrappedNativeTearOff represents the info needed to make calls to one
 // interface on the underlying native object of a XPCWrappedNative.
 
 class XPCWrappedNativeTearOff
 {
 public:
     JSBool IsAvailable() const {return mInterface == nullptr;}
@@ -2484,32 +2472,16 @@ public:
 
 public:
     static nsresult
     GetUsedOnly(nsISupports* Object,
                 XPCWrappedNativeScope* Scope,
                 XPCNativeInterface* Interface,
                 XPCWrappedNative** wrapper);
 
-    static XPCWrappedNative*
-    GetAndMorphWrappedNativeOfJSObject(JSContext* cx, JSObject* obj_)
-    {
-        JS::RootedObject obj(cx, obj_);
-        obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false);
-        if (!obj)
-            return nullptr;
-        if (!IS_WRAPPER_CLASS(js::GetObjectClass(obj)))
-            return nullptr;
-
-        if (IS_SLIM_WRAPPER_OBJECT(obj) && !MorphSlimWrapper(cx, obj))
-            return nullptr;
-        MOZ_ASSERT(IS_WN_WRAPPER(obj));
-        return XPCWrappedNative::Get(obj);
-    }
-
     static nsresult
     ReparentWrapperIfFound(XPCWrappedNativeScope* aOldScope,
                            XPCWrappedNativeScope* aNewScope,
                            JS::HandleObject aNewParent,
                            nsISupports* aCOMObj);
 
     nsresult RescueOrphans();
 
@@ -2663,17 +2635,16 @@ private:
         NEEDS_SOW = JS_BIT(0),
         NEEDS_COW = JS_BIT(1),
         FLAG_MASK = JS_BITMASK(3)
     };
 
 private:
 
     JSBool Init(JS::HandleObject parent, const XPCNativeScriptableCreateInfo* sci);
-    JSBool Init(JSObject *existingJSObject);
     JSBool FinishInit();
 
     JSBool ExtendSet(XPCNativeInterface* aInterface);
 
     nsresult InitTearOff(XPCWrappedNativeTearOff* aTearOff,
                          XPCNativeInterface* aInterface,
                          JSBool needJSObject);
 
--- a/js/xpconnect/src/xpcpublic.h
+++ b/js/xpconnect/src/xpcpublic.h
@@ -77,19 +77,16 @@ void
 TraceXPCGlobal(JSTracer *trc, JSObject *obj);
 
 // XXX These should be moved into XPCJSRuntime!
 NS_EXPORT_(bool)
 xpc_LocalizeRuntime(JSRuntime *rt);
 NS_EXPORT_(void)
 xpc_DelocalizeRuntime(JSRuntime *rt);
 
-nsresult
-xpc_MorphSlimWrapper(JSContext *cx, nsISupports *tomorph);
-
 static inline bool IS_WRAPPER_CLASS(js::Class* clazz)
 {
     return clazz->ext.isWrappedNative;
 }
 
 // If IS_WRAPPER_CLASS for the JSClass of an object is true, the object can be
 // a slim wrapper, holding a native in its private slot, or a wrappednative
 // wrapper, holding the XPCWrappedNative in its private slot. A slim wrapper
--- a/js/xpconnect/wrappers/WrapperFactory.cpp
+++ b/js/xpconnect/wrappers/WrapperFactory.cpp
@@ -147,21 +147,16 @@ WrapperFactory::PrepareForWrapping(JSCon
     // this case first to allow us to assert against wrappers below.
     if (js::IsOuterObject(obj))
         return DoubleWrap(cx, obj, flags);
 
     // Here are the rules for wrapping:
     // We should never get a proxy here (the JS engine unwraps those for us).
     MOZ_ASSERT(!IsWrapper(obj));
 
-    // As soon as an object is wrapped in a security wrapper, it morphs to be
-    // a fat wrapper. (see also: bug XXX).
-    if (IS_SLIM_WRAPPER(obj) && !MorphSlimWrapper(cx, obj))
-        return nullptr;
-
     // If the object being wrapped is a prototype for a standard class and the
     // wrapper does not subsumes the wrappee, use the one from the content
     // compartment. This is generally safer all-around, and in the COW case this
     // lets us safely take advantage of things like .forEach() via the
     // ChromeObjectWrapper machinery.
     //
     // If the prototype chain of chrome object |obj| looks like this:
     //