Bug 877654 - Remove thisptr offset tables - Remove thisptr table support from XPConnect. r=Ms2ger.
authorPeter Van der Beken <peterv@propagandism.org>
Tue, 21 May 2013 21:59:30 +0200
changeset 134217 dcb08e602abd838ccd9a16252122e90eb5fcb54f
parent 134216 1cb64629a1c993d841b05535d1127e1d6bfbf41d
child 134218 ccf704fa6fddaeca0e854a7fa8eebe9b91e9f8a0
push id29102
push userpvanderbeken@mozilla.com
push dateThu, 06 Jun 2013 07:43:30 +0000
treeherdermozilla-inbound@dcb08e602abd [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersMs2ger
bugs877654
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 877654 - Remove thisptr offset tables - Remove thisptr table support from XPConnect. r=Ms2ger.
js/xpconnect/src/XPCQuickStubs.cpp
js/xpconnect/src/XPCWrappedNative.cpp
js/xpconnect/src/XPCWrappedNativeProto.cpp
js/xpconnect/src/xpcprivate.h
xpcom/components/nsIClassInfo.idl
--- a/js/xpconnect/src/XPCQuickStubs.cpp
+++ b/js/xpconnect/src/XPCQuickStubs.cpp
@@ -13,35 +13,16 @@
 #include "XPCQuickStubs.h"
 #include "mozilla/dom/BindingUtils.h"
 
 using namespace mozilla;
 using namespace JS;
 
 extern const char* xpc_qsStringTable;
 
-static inline QITableEntry *
-GetOffsets(nsISupports *identity, XPCWrappedNativeProto* proto)
-{
-    QITableEntry* offsets = proto ? proto->GetOffsets() : nullptr;
-    if (!offsets) {
-        static NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
-        identity->QueryInterface(kThisPtrOffsetsSID, (void**)&offsets);
-    }
-    return offsets;
-}
-
-static inline QITableEntry *
-GetOffsetsFromSlimWrapper(JSObject *obj)
-{
-    NS_ASSERTION(IS_SLIM_WRAPPER(obj), "What kind of object is this?");
-    return GetOffsets(static_cast<nsISupports*>(xpc_GetJSPrivate(obj)),
-                      GetSlimWrapperProto(obj));
-}
-
 static const xpc_qsHashEntry *
 LookupEntry(uint32_t tableSize, const xpc_qsHashEntry *table, const nsID &iid)
 {
     size_t i;
     const xpc_qsHashEntry *p;
 
     i = iid.m0 % tableSize;
     do
@@ -504,53 +485,40 @@ xpc_qsAUTF8String::xpc_qsAUTF8String(JSC
     }
 
     new(mBuf) implementation_type(chars, len);
     mValid = true;
 }
 
 static nsresult
 getNative(nsISupports *idobj,
-          QITableEntry* entries,
           HandleObject obj,
           const nsIID &iid,
           void **ppThis,
           nsISupports **pThisRef,
           jsval *vp)
 {
-    // Try using the QITableEntry to avoid the extra AddRef and Release.
-    if (entries) {
-        for (QITableEntry* e = entries; e->iid; e++) {
-            if (e->iid->Equals(iid)) {
-                *ppThis = (char*) idobj + e->offset - entries[0].offset;
-                *vp = OBJECT_TO_JSVAL(obj);
-                *pThisRef = nullptr;
-                return NS_OK;
-            }
-        }
-    }
-
     nsresult rv = idobj->QueryInterface(iid, ppThis);
     *pThisRef = static_cast<nsISupports*>(*ppThis);
     if (NS_SUCCEEDED(rv))
         *vp = OBJECT_TO_JSVAL(obj);
     return rv;
 }
 
 inline nsresult
 getNativeFromWrapper(JSContext *cx,
                      XPCWrappedNative *wrapper,
                      const nsIID &iid,
                      void **ppThis,
                      nsISupports **pThisRef,
                      jsval *vp)
 {
     RootedObject obj(cx, wrapper->GetFlatJSObject());
-    return getNative(wrapper->GetIdentityObject(), wrapper->GetOffsets(),
-                     obj, iid, ppThis, pThisRef, vp);
+    return getNative(wrapper->GetIdentityObject(), obj, iid, ppThis, pThisRef,
+                     vp);
 }
 
 
 nsresult
 getWrapper(JSContext *cx,
            JSObject *obj,
            XPCWrappedNative **wrapper,
            JSObject **cur,
@@ -623,28 +591,26 @@ castNative(JSContext *cx,
     if (wrapper) {
         nsresult rv = getNativeFromWrapper(cx,wrapper, iid, ppThis, pThisRef,
                                            vp);
 
         if (rv != NS_ERROR_NO_INTERFACE)
             return rv;
     } else if (cur) {
         nsISupports *native;
-        QITableEntry *entries;
-        if ((native = mozilla::dom::UnwrapDOMObjectToISupports(cur))) {
-            entries = nullptr;
-        } else if (IS_SLIM_WRAPPER(cur)) {
-            native = static_cast<nsISupports*>(xpc_GetJSPrivate(cur));
-            entries = GetOffsetsFromSlimWrapper(cur);
-        } else {
-            *pThisRef = nullptr;
-            return NS_ERROR_ILLEGAL_VALUE;
+        if (!(native = mozilla::dom::UnwrapDOMObjectToISupports(cur))) {
+            if (IS_SLIM_WRAPPER(cur)) {
+                native = static_cast<nsISupports*>(xpc_GetJSPrivate(cur));
+            } else {
+                *pThisRef = nullptr;
+                return NS_ERROR_ILLEGAL_VALUE;
+            }
         }
 
-        if (NS_SUCCEEDED(getNative(native, entries, cur, iid, ppThis, pThisRef, vp))) {
+        if (NS_SUCCEEDED(getNative(native, cur, iid, ppThis, pThisRef, vp))) {
             return NS_OK;
         }
     }
 
     *pThisRef = nullptr;
     return NS_ERROR_XPC_BAD_OP_ON_WN_PROTO;
 }
 
@@ -716,18 +682,17 @@ xpc_qsUnwrapThisFromCcxImpl(XPCCallConte
                             nsISupports **pThisRef,
                             jsval *vp)
 {
     nsISupports *native = ccx.GetIdentityObject();
     if (!native)
         return xpc_qsThrow(ccx.GetJSContext(), NS_ERROR_XPC_HAS_BEEN_SHUTDOWN);
 
     RootedObject obj(ccx, ccx.GetFlattenedJSObject());
-    nsresult rv = getNative(native, GetOffsets(native, ccx.GetProto()),
-                            obj, iid, ppThis, pThisRef, vp);
+    nsresult rv = getNative(native, obj, iid, ppThis, pThisRef, vp);
     if (NS_FAILED(rv))
         return xpc_qsThrow(ccx.GetJSContext(), rv);
     return true;
 }
 
 nsresult
 xpc_qsUnwrapArgImpl(JSContext *cx,
                     jsval v,
--- a/js/xpconnect/src/XPCWrappedNative.cpp
+++ b/js/xpconnect/src/XPCWrappedNative.cpp
@@ -327,20 +327,19 @@ XPCWrappedNative::WrapNewGlobal(xpcObjec
     // If requested, initialize the standard classes on the global.
     if (initStandardClasses && ! JS_InitStandardClasses(cx, global))
         return NS_ERROR_FAILURE;
 
     // Make a proto.
     XPCWrappedNativeProto *proto =
         XPCWrappedNativeProto::GetNewOrUsed(scope,
                                             nativeHelper.GetClassInfo(), &sciProto,
-                                            UNKNOWN_OFFSETS, /* callPostCreatePrototype = */ false);
+                                            /* callPostCreatePrototype = */ false);
     if (!proto)
         return NS_ERROR_FAILURE;
-    proto->CacheOffsets(identity);
 
     // Set up the prototype on the global.
     MOZ_ASSERT(proto->GetJSProtoObject());
     bool success = JS_SplicePrototype(cx, global, proto->GetJSProtoObject());
     if (!success)
         return NS_ERROR_FAILURE;
 
     // Construct the wrapper, which takes over the strong reference to the
@@ -577,18 +576,16 @@ XPCWrappedNative::GetNewOrUsed(xpcObject
     // Note that the security check happens inside FindTearOff - after the
     // wrapper is actually created, but before JS code can see it.
 
     if (info && !isClassInfo) {
         proto = XPCWrappedNativeProto::GetNewOrUsed(Scope, info, &sciProto);
         if (!proto)
             return NS_ERROR_FAILURE;
 
-        proto->CacheOffsets(identity);
-
         wrapper = new XPCWrappedNative(helper.forgetCanonical(), proto);
     } else {
         AutoMarkingNativeInterfacePtr iface(cx, Interface);
         if (!iface)
             iface = XPCNativeInterface::GetISupports();
 
         AutoMarkingNativeSetPtr set(cx);
         set = XPCNativeSet::GetNewOrUsed(nullptr, iface, 0);
@@ -1469,17 +1466,17 @@ XPCWrappedNative::ReparentWrapperIfFound
             oldProto = wrapper->GetProto();
 
         if (oldProto) {
             XPCNativeScriptableInfo *info = oldProto->GetScriptableInfo();
             XPCNativeScriptableCreateInfo ci(*info);
             newProto =
                 XPCWrappedNativeProto::GetNewOrUsed(aNewScope,
                                                     oldProto->GetClassInfo(),
-                                                    &ci, oldProto->GetOffsetsMasked());
+                                                    &ci);
             if (!newProto) {
                 return NS_ERROR_FAILURE;
             }
         }
 
         if (wrapper) {
 
             // First, the clone of the reflector, get a copy of its
@@ -3646,18 +3643,16 @@ ConstructSlimWrapper(xpcObjectHelper &aH
     XPCNativeScriptableCreateInfo
         sciProto(aHelper.forgetXPCClassInfo(), flags, interfacesBitmap);
 
     AutoMarkingWrappedNativeProtoPtr xpcproto(cx);
     xpcproto = XPCWrappedNativeProto::GetNewOrUsed(xpcScope, classInfoHelper, &sciProto);
     if (!xpcproto)
         return false;
 
-    xpcproto->CacheOffsets(identityObj);
-
     XPCNativeScriptableInfo* si = xpcproto->GetScriptableInfo();
     JSClass* jsclazz = si->GetSlimJSClass();
     if (!jsclazz)
         return false;
 
     wrapper = JS_NewObject(cx, jsclazz, xpcproto->GetJSProtoObject(), parent);
     if (!wrapper)
         return false;
--- a/js/xpconnect/src/XPCWrappedNativeProto.cpp
+++ b/js/xpconnect/src/XPCWrappedNativeProto.cpp
@@ -13,26 +13,24 @@ using namespace mozilla;
 
 #if defined(DEBUG_xpc_hacker) || defined(DEBUG)
 int32_t XPCWrappedNativeProto::gDEBUG_LiveProtoCount = 0;
 #endif
 
 XPCWrappedNativeProto::XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
                                              nsIClassInfo* ClassInfo,
                                              uint32_t ClassInfoFlags,
-                                             XPCNativeSet* Set,
-                                             QITableEntry* offsets)
+                                             XPCNativeSet* Set)
     : mScope(Scope),
       mJSProtoObject(nullptr),
       mClassInfo(ClassInfo),
       mClassInfoFlags(ClassInfoFlags),
       mSet(Set),
       mSecurityInfo(nullptr),
-      mScriptableInfo(nullptr),
-      mOffsets(offsets)
+      mScriptableInfo(nullptr)
 {
     // This native object lives as long as its associated JSObject - killed
     // by finalization of the JSObject (or explicitly if Init fails).
 
     MOZ_COUNT_CTOR(XPCWrappedNativeProto);
     MOZ_ASSERT(mScope);
 
 #ifdef DEBUG
@@ -172,17 +170,16 @@ XPCWrappedNativeProto::SystemIsBeingShut
     }
 }
 
 // static
 XPCWrappedNativeProto*
 XPCWrappedNativeProto::GetNewOrUsed(XPCWrappedNativeScope* scope,
                                     nsIClassInfo* classInfo,
                                     const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
-                                    QITableEntry* offsets,
                                     bool callPostCreatePrototype)
 {
     AutoJSContext cx;
     NS_ASSERTION(scope, "bad param");
     NS_ASSERTION(classInfo, "bad param");
 
     AutoMarkingWrappedNativeProtoPtr proto(cx);
     ClassInfo2WrappedNativeProtoMap* map = nullptr;
@@ -202,17 +199,17 @@ XPCWrappedNativeProto::GetNewOrUsed(XPCW
             return proto;
     }
 
     AutoMarkingNativeSetPtr set(cx);
     set = XPCNativeSet::GetNewOrUsed(classInfo);
     if (!set)
         return nullptr;
 
-    proto = new XPCWrappedNativeProto(scope, classInfo, ciFlags, set, offsets);
+    proto = new XPCWrappedNativeProto(scope, classInfo, ciFlags, set);
 
     if (!proto || !proto->Init(scriptableCreateInfo, callPostCreatePrototype)) {
         delete proto.get();
         return nullptr;
     }
 
     {   // scoped lock
         XPCAutoLock al(lock);
--- a/js/xpconnect/src/xpcprivate.h
+++ b/js/xpconnect/src/xpcprivate.h
@@ -2120,26 +2120,23 @@ private:
     XPCNativeScriptableFlags    mFlags;
     uint32_t                    mInterfacesBitmap;
 };
 
 /***********************************************/
 // XPCWrappedNativeProto hold the additional shared wrapper data
 // for XPCWrappedNative whose native objects expose nsIClassInfo.
 
-#define UNKNOWN_OFFSETS ((QITableEntry*)1)
-
 class XPCWrappedNativeProto
 {
 public:
     static XPCWrappedNativeProto*
     GetNewOrUsed(XPCWrappedNativeScope* scope,
                  nsIClassInfo* classInfo,
                  const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
-                 QITableEntry* offsets = UNKNOWN_OFFSETS,
                  bool callPostCreatePrototype = true);
 
     XPCWrappedNativeScope*
     GetScope()   const {return mScope;}
 
     XPCJSRuntime*
     GetRuntime() const {return mScope->GetRuntime();}
 
@@ -2156,50 +2153,16 @@ public:
     GetScriptableInfo()   {return mScriptableInfo;}
 
     void**
     GetSecurityInfoAddr() {return &mSecurityInfo;}
 
     uint32_t
     GetClassInfoFlags() const {return mClassInfoFlags;}
 
-    QITableEntry*
-    GetOffsets()
-    {
-        return InitedOffsets() ? mOffsets : nullptr;
-    }
-    QITableEntry*
-    GetOffsetsMasked()
-    {
-        return mOffsets;
-    }
-    void
-    CacheOffsets(nsISupports* identity)
-    {
-        static NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
-
-#ifdef DEBUG
-        if (InitedOffsets() && mOffsets) {
-            QITableEntry* offsets;
-            identity->QueryInterface(kThisPtrOffsetsSID, (void**)&offsets);
-            NS_ASSERTION(offsets == mOffsets,
-                         "We can't deal with objects that have the same "
-                         "classinfo but different offset tables.");
-        }
-#endif
-
-        if (!InitedOffsets()) {
-            if (mClassInfoFlags & nsIClassInfo::CONTENT_NODE) {
-                identity->QueryInterface(kThisPtrOffsetsSID, (void**)&mOffsets);
-            } else {
-                mOffsets = nullptr;
-            }
-        }
-    }
-
 #ifdef GET_IT
 #undef GET_IT
 #endif
 #define GET_IT(f_) const {return !!(mClassInfoFlags & nsIClassInfo:: f_ );}
 
     JSBool ClassIsSingleton()           GET_IT(SINGLETON)
     JSBool ClassIsThreadSafe()          GET_IT(THREADSAFE)
     JSBool ClassIsMainThreadOnly()      GET_IT(MAIN_THREAD_ONLY)
@@ -2265,42 +2228,34 @@ protected:
     // disable copy ctor and assignment
     XPCWrappedNativeProto(const XPCWrappedNativeProto& r); // not implemented
     XPCWrappedNativeProto& operator= (const XPCWrappedNativeProto& r); // not implemented
 
     // hide ctor
     XPCWrappedNativeProto(XPCWrappedNativeScope* Scope,
                           nsIClassInfo* ClassInfo,
                           uint32_t ClassInfoFlags,
-                          XPCNativeSet* Set,
-                          QITableEntry* offsets);
+                          XPCNativeSet* Set);
 
     JSBool Init(const XPCNativeScriptableCreateInfo* scriptableCreateInfo,
                 bool callPostCreatePrototype);
 
 private:
 #if defined(DEBUG_xpc_hacker) || defined(DEBUG)
     static int32_t gDEBUG_LiveProtoCount;
 #endif
 
 private:
-    bool
-    InitedOffsets()
-    {
-        return mOffsets != UNKNOWN_OFFSETS;
-    }
-
     XPCWrappedNativeScope*   mScope;
     JS::ObjectPtr            mJSProtoObject;
     nsCOMPtr<nsIClassInfo>   mClassInfo;
     uint32_t                 mClassInfoFlags;
     XPCNativeSet*            mSet;
     void*                    mSecurityInfo;
     XPCNativeScriptableInfo* mScriptableInfo;
-    QITableEntry*            mOffsets;
 };
 
 class xpcObjectHelper;
 extern JSBool ConstructSlimWrapper(xpcObjectHelper &aHelper,
                                    XPCWrappedNativeScope* xpcScope,
                                    JS::MutableHandleValue rval);
 extern JSBool MorphSlimWrapper(JSContext *cx, JS::HandleObject obj);
 
@@ -2696,30 +2651,16 @@ public:
     // mFlatJSObject otherwise.
     //
     // This takes care of checking mWrapperWord to see if we already have such
     // a wrapper.
     JSObject *GetSameCompartmentSecurityWrapper(JSContext *cx);
 
     void NoteTearoffs(nsCycleCollectionTraversalCallback& cb);
 
-    QITableEntry* GetOffsets()
-    {
-        if (!HasProto() || !GetProto()->ClassIsDOMObject())
-            return nullptr;
-
-        XPCWrappedNativeProto* proto = GetProto();
-        QITableEntry* offsets = proto->GetOffsets();
-        if (!offsets) {
-            static NS_DEFINE_IID(kThisPtrOffsetsSID, NS_THISPTROFFSETS_SID);
-            mIdentity->QueryInterface(kThisPtrOffsetsSID, (void**)&offsets);
-        }
-        return offsets;
-    }
-
     // Make ctor and dtor protected (rather than private) to placate nsCOMPtr.
 protected:
     XPCWrappedNative(); // not implemented
 
     // This ctor is used if this object will have a proto.
     XPCWrappedNative(already_AddRefed<nsISupports> aIdentity,
                      XPCWrappedNativeProto* aProto);
 
--- a/xpcom/components/nsIClassInfo.idl
+++ b/xpcom/components/nsIClassInfo.idl
@@ -1,28 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  *
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 
-%{C++
-/**
- * Calling QueryInterface with this special IID will return a null-terminated
- * table of QITableEntry's. Not all objects support this.
- * Note that this breaks XPCOM rules a bit (the table doesn't derive from
- * nsISupports).
- */
-#define NS_THISPTROFFSETS_SID \
-    { 0x23e017cc, 0x5d6f, 0x430c, \
-      { 0xb3, 0xe6, 0x9d, 0x32, 0x65, 0x70, 0xd6, 0xb8 } }
-%}
-
 /**
  * Provides information about a specific implementation class.  If you want
  * your class to implement nsIClassInfo, see nsIClassInfoImpl.h for
  * instructions--you most likely do not want to inherit from nsIClassInfo.
  */
 
 [scriptable, uuid(986c11d0-f340-11d4-9075-0010a4e73d9a)]
 interface nsIClassInfo : nsISupports