Bug 1438688, part 5 - Merge XPTInterfaceDirectoryEntry and XPTInterfaceDescriptor. r=njn
☠☠ backed out by 70400746eb53 ☠ ☠
authorAndrew McCreight <continuation@gmail.com>
Mon, 12 Mar 2018 13:36:15 -0700
changeset 776472 e05ec1e08b46732b5552a48fe48d32108f9cca4c
parent 776471 4c437ba9d9841597038e36a6244f428b8cf01816
child 776473 8786eabb61a41e1b83b69bf8f1f30d135184c404
push id104888
push userbmo:emilio@crisal.io
push dateTue, 03 Apr 2018 07:00:14 +0000
reviewersnjn
bugs1438688
milestone61.0a1
Bug 1438688, part 5 - Merge XPTInterfaceDirectoryEntry and XPTInterfaceDescriptor. r=njn With fully linked XPT data, there is exactly one directory entry per descriptor, plus one per unresolved interface. There are 1200 of the former and 40 of the latter. By merging them, we save a 32 bit int per directory entry, at the cost of 11 bytes per unresolved interface. This will make VerifyAndAddEntryIfNew slightly slower because it has to do an nsID equality check rather than a null check, but I can't imagine that will matter. My main goal for this patch is to reduce the size of the executable, to avoid a regression with my static XPT information patches, but it should reduce memory a little bit, too. MozReview-Commit-ID: L35YdOuAyF4
xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h
xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
xpcom/reflect/xptinfo/xptiTypelibGuts.cpp
xpcom/reflect/xptinfo/xptiprivate.h
xpcom/typelib/xpt/xpt_struct.h
--- a/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h
+++ b/xpcom/reflect/xptinfo/XPTInterfaceInfoManager.h
@@ -12,17 +12,17 @@
 
 #include "mozilla/MemoryReporting.h"
 #include "mozilla/Mutex.h"
 #include "mozilla/ReentrantMonitor.h"
 #include "nsDataHashtable.h"
 
 template<typename T> class nsCOMArray;
 class nsIMemoryReporter;
-struct XPTInterfaceDirectoryEntry;
+struct XPTInterfaceDescriptor;
 class xptiInterfaceEntry;
 class xptiInterfaceInfo;
 class xptiTypelibGuts;
 
 namespace mozilla {
 
 class XPTInterfaceInfoManager final
     : public nsIInterfaceInfoManager
@@ -50,17 +50,17 @@ public:
 
 private:
     XPTInterfaceInfoManager();
     ~XPTInterfaceInfoManager();
 
     void InitMemoryReporter();
 
     // idx is the index of this interface in the XPTHeader
-    void VerifyAndAddEntryIfNew(const XPTInterfaceDirectoryEntry* iface,
+    void VerifyAndAddEntryIfNew(const XPTInterfaceDescriptor* iface,
                                 uint16_t idx,
                                 xptiTypelibGuts* typelib);
 
 private:
 
     class xptiWorkingSet
     {
     public:
--- a/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
@@ -11,42 +11,42 @@
 #include "mozilla/DebugOnly.h"
 #include "mozilla/XPTInterfaceInfoManager.h"
 #include "mozilla/PodOperations.h"
 #include "jsapi.h"
 
 using namespace mozilla;
 
 /* static */ xptiInterfaceEntry*
-xptiInterfaceEntry::Create(const XPTInterfaceDirectoryEntry* aEntry,
+xptiInterfaceEntry::Create(const XPTInterfaceDescriptor* aIface,
                            xptiTypelibGuts* aTypelib)
 {
     void* place = XPT_CALLOC8(gXPTIStructArena, sizeof(xptiInterfaceEntry));
     if (!place) {
         return nullptr;
     }
-    return new (place) xptiInterfaceEntry(aEntry, aTypelib);
+    return new (place) xptiInterfaceEntry(aIface, aTypelib);
 }
 
-xptiInterfaceEntry::xptiInterfaceEntry(const XPTInterfaceDirectoryEntry* aEntry,
+xptiInterfaceEntry::xptiInterfaceEntry(const XPTInterfaceDescriptor* aIface,
                                        xptiTypelibGuts* aTypelib)
-    : mIID(aEntry->mIID)
-    , mDescriptor(aEntry->InterfaceDescriptor())
+    : mIID(aIface->mIID)
+    , mDescriptor(aIface)
     , mTypelib(aTypelib)
     , mParent(nullptr)
     , mInfo(nullptr)
     , mMethodBaseIndex(0)
     , mConstantBaseIndex(0)
     , mFlags(0)
-    , mName(aEntry->Name())
+    , mName(aIface->Name())
 {
     SetResolvedState(PARTIALLY_RESOLVED);
-    SetScriptableFlag(mDescriptor->IsScriptable());
-    SetBuiltinClassFlag(mDescriptor->IsBuiltinClass());
-    SetMainProcessScriptableOnlyFlag(mDescriptor->IsMainProcessScriptableOnly());
+    SetScriptableFlag(aIface->IsScriptable());
+    SetBuiltinClassFlag(aIface->IsBuiltinClass());
+    SetMainProcessScriptableOnlyFlag(aIface->IsMainProcessScriptableOnly());
 }
 
 bool
 xptiInterfaceEntry::Resolve()
 {
     MutexAutoLock lock(XPTInterfaceInfoManager::GetResolveLock());
     return ResolveLocked();
 }
--- a/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfoManager.cpp
@@ -80,17 +80,17 @@ XPTInterfaceInfoManager::FreeInterfaceIn
 XPTInterfaceInfoManager::XPTInterfaceInfoManager()
     :   mWorkingSet(),
         mResolveLock("XPTInterfaceInfoManager.mResolveLock")
 {
     xptiTypelibGuts* typelib = xptiTypelibGuts::Create();
 
     ReentrantMonitorAutoEnter monitor(mWorkingSet.mTableReentrantMonitor);
     for (uint16_t k = 0; k < XPTHeader::kNumInterfaces; k++) {
-        VerifyAndAddEntryIfNew(XPTHeader::kInterfaceDirectory + k, k, typelib);
+        VerifyAndAddEntryIfNew(XPTHeader::kInterfaces + k, k, typelib);
     }
 }
 
 XPTInterfaceInfoManager::~XPTInterfaceInfoManager()
 {
     // We only do this on shutdown of the service.
     mWorkingSet.InvalidateInterfaceInfos();
 
@@ -99,28 +99,31 @@ XPTInterfaceInfoManager::~XPTInterfaceIn
 
 void
 XPTInterfaceInfoManager::InitMemoryReporter()
 {
     RegisterWeakMemoryReporter(this);
 }
 
 void
-XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(const XPTInterfaceDirectoryEntry* iface,
+XPTInterfaceInfoManager::VerifyAndAddEntryIfNew(const XPTInterfaceDescriptor* iface,
                                                 uint16_t idx,
                                                 xptiTypelibGuts* typelib)
 {
-    if (!iface->InterfaceDescriptor())
+    static const nsID zeroIID =
+        { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
+
+    if (iface->mIID.Equals(zeroIID)) {
         return;
+    }
 
     // The number of maximum methods is not arbitrary. It is the same value as
     // in xpcom/reflect/xptcall/genstubs.pl; do not change this value
     // without changing that one or you WILL see problems.
-    if (iface->InterfaceDescriptor()->mNumMethods > 250 &&
-            !iface->InterfaceDescriptor()->IsBuiltinClass()) {
+    if (iface->mNumMethods > 250 && !iface->IsBuiltinClass()) {
         NS_ASSERTION(0, "Too many methods to handle for the stub, cannot load");
         fprintf(stderr, "ignoring too large interface: %s\n", iface->Name());
         return;
     }
 
     mWorkingSet.mTableReentrantMonitor.AssertCurrentThreadIn();
     xptiInterfaceEntry* entry = mWorkingSet.mIIDTable.Get(iface->mIID);
     if (entry) {
--- a/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp
+++ b/xpcom/reflect/xptinfo/xptiTypelibGuts.cpp
@@ -37,17 +37,17 @@ xptiTypelibGuts::GetEntryAt(uint16_t i)
         { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 } };
 
     NS_ASSERTION(i < GetEntryCount(), "bad index");
 
     xptiInterfaceEntry* r = mEntryArray[i];
     if (r)
         return r;
 
-    const XPTInterfaceDirectoryEntry* iface = XPTHeader::kInterfaceDirectory + i;
+    const XPTInterfaceDescriptor* iface = XPTHeader::kInterfaces + i;
 
     XPTInterfaceInfoManager::xptiWorkingSet& set =
         XPTInterfaceInfoManager::GetSingleton()->mWorkingSet;
 
     {
         ReentrantMonitorAutoEnter monitor(set.mTableReentrantMonitor);
         if (iface->mIID.Equals(zeroIID))
             r = set.mNameTable.Get(iface->Name());
@@ -61,12 +61,12 @@ xptiTypelibGuts::GetEntryAt(uint16_t i)
     return r;
 }
 
 const char*
 xptiTypelibGuts::GetEntryNameAt(uint16_t i)
 {
     NS_ASSERTION(i < GetEntryCount(), "bad index");
 
-    const XPTInterfaceDirectoryEntry* iface = XPTHeader::kInterfaceDirectory + i;
+    const XPTInterfaceDescriptor* iface = XPTHeader::kInterfaces + i;
 
     return iface->Name();
 }
--- a/xpcom/reflect/xptinfo/xptiprivate.h
+++ b/xpcom/reflect/xptinfo/xptiprivate.h
@@ -142,17 +142,17 @@ private:
 
 // No virtual methods.
 // We always create in the struct arena and construct using "placement new".
 // No members need dtor calls.
 
 class xptiInterfaceEntry
 {
 public:
-    static xptiInterfaceEntry* Create(const XPTInterfaceDirectoryEntry* aEntry,
+    static xptiInterfaceEntry* Create(const XPTInterfaceDescriptor* aIface,
                                       xptiTypelibGuts* aTypelib);
 
     enum {
         PARTIALLY_RESOLVED    = 1,
         FULLY_RESOLVED        = 2,
         RESOLVE_FAILED        = 3
     };
 
@@ -238,17 +238,17 @@ public:
     nsresult IsIID(const nsIID * IID, bool *_retval);
     nsresult GetNameShared(const char **name);
     nsresult GetIIDShared(const nsIID * *iid);
     nsresult IsFunction(bool *_retval);
     nsresult HasAncestor(const nsIID * iid, bool *_retval);
     nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid);
 
 private:
-    xptiInterfaceEntry(const XPTInterfaceDirectoryEntry* aDescriptor,
+    xptiInterfaceEntry(const XPTInterfaceDescriptor* aIface,
                        xptiTypelibGuts* aTypelib);
     ~xptiInterfaceEntry();
 
     void SetResolvedState(int state)
         {mFlags.SetState(uint8_t(state));}
 
     bool Resolve();
 
--- a/xpcom/typelib/xpt/xpt_struct.h
+++ b/xpcom/typelib/xpt/xpt_struct.h
@@ -11,75 +11,60 @@
 
 #ifndef xpt_struct_h
 #define xpt_struct_h
 
 #include "nsID.h"
 #include <stdint.h>
 #include "mozilla/Assertions.h"
 
-struct XPTInterfaceDirectoryEntry;
 struct XPTInterfaceDescriptor;
 struct XPTConstDescriptor;
 struct XPTMethodDescriptor;
 struct XPTParamDescriptor;
 struct XPTTypeDescriptor;
 struct XPTTypeDescriptorPrefix;
 
 struct XPTHeader {
   static const uint16_t kNumInterfaces;
-  static const XPTInterfaceDirectoryEntry kInterfaceDirectory[];
   static const XPTInterfaceDescriptor kInterfaces[];
   static const XPTTypeDescriptor kTypes[];
   static const XPTParamDescriptor kParams[];
   static const XPTMethodDescriptor kMethods[];
   static const XPTConstDescriptor kConsts[];
 
   // All of the strings for this header, including their null
   // terminators, concatenated into a single string.
   static const char kStrings[];
 };
 
 /*
- * An array of directory entries is used to quickly locate an interface
- * description using its IID. No interface should appear more than once in the
- * array.
- */
-struct XPTInterfaceDirectoryEntry {
-  inline const XPTInterfaceDescriptor* InterfaceDescriptor() const;
-  inline const char* Name() const;
-
-  nsID mIID;
-  uint32_t mName; // Index into XPTHeader::mStrings.
-  // mInterfaceDescriptor is a 1-based index into XPTHeader::mInterfaces. The
-  // value 0 is used to indicate unresolved interfaces.
-  uint32_t mInterfaceDescriptor;
-};
-
-/*
  * An InterfaceDescriptor describes a single XPCOM interface, including all of
  * its methods.
  */
 struct XPTInterfaceDescriptor {
   static const uint8_t kScriptableMask =                0x80;
   static const uint8_t kFunctionMask =                  0x40;
   static const uint8_t kBuiltinClassMask =              0x20;
   static const uint8_t kMainProcessScriptableOnlyMask = 0x10;
 
   bool IsScriptable() const { return !!(mFlags & kScriptableMask); }
   bool IsFunction() const { return !!(mFlags & kFunctionMask); }
   bool IsBuiltinClass() const { return !!(mFlags & kBuiltinClassMask); }
   bool IsMainProcessScriptableOnly() const { return !!(mFlags & kMainProcessScriptableOnlyMask); }
 
+  inline const char* Name() const;
   inline const XPTMethodDescriptor& Method(size_t aIndex) const;
   inline const XPTConstDescriptor& Const(size_t aIndex) const;
 
   /*
    * This field ordering minimizes the size of this struct.
    */
+  nsID mIID;
+  uint32_t mName; // Index into XPTHeader::mStrings.
   uint16_t mMethodDescriptors; // Index into XPTHeader::mMethods.
   uint16_t mConstDescriptors; // Index into XPTHeader::mConsts.
   uint16_t mParentInterface;
   uint16_t mNumMethods;
   uint16_t mNumConstants;
   uint8_t mFlags;
 };
 
@@ -227,28 +212,20 @@ struct XPTMethodDescriptor {
 
   uint32_t mName; // Index into XPTHeader::mStrings.
   uint32_t mParams; // Index into XPTHeader::mParams.
   uint8_t mFlags;
   uint8_t mNumArgs;
 };
 
 const char*
-XPTInterfaceDirectoryEntry::Name() const {
+XPTInterfaceDescriptor::Name() const {
   return &XPTHeader::kStrings[mName];
 }
 
-const XPTInterfaceDescriptor*
-XPTInterfaceDirectoryEntry::InterfaceDescriptor() const {
-  if (mInterfaceDescriptor == 0) {
-    return nullptr;
-  }
-  return &XPTHeader::kInterfaces[mInterfaceDescriptor - 1];
-}
-
 const XPTMethodDescriptor&
 XPTInterfaceDescriptor::Method(size_t aIndex) const {
   return XPTHeader::kMethods[mMethodDescriptors + aIndex];
 }
 
 const XPTConstDescriptor&
 XPTInterfaceDescriptor::Const(size_t aIndex) const {
   return XPTHeader::kConsts[mConstDescriptors + aIndex];