hoist arrays to XPTHeader draft
authorAndrew McCreight <continuation@gmail.com>
Wed, 28 Feb 2018 15:12:07 -0800
changeset 762247 dea496e2d271796a8b7b4d3ff27263086c3d4d21
parent 762246 38d785af0f0d3d82e5e2f11cac1462d2185edde7
child 762248 79f5d8b4d20a16fee8a3ded4162871e9470719be
push id101107
push userbmo:continuation@gmail.com
push dateThu, 01 Mar 2018 22:22:59 +0000
milestone60.0a1
hoist arrays to XPTHeader MozReview-Commit-ID: 5rgwaEBvDYl
xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
xpcom/typelib/xpt/xpt_struct.h
--- a/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
@@ -298,17 +298,17 @@ xptiInterfaceEntry::GetInterfaceIndexFor
     {
         NS_ERROR("bad param");
         return NS_ERROR_INVALID_ARG;
     }
 
     const XPTTypeDescriptor *td = &param->type;
 
     while (td->Tag() == TD_ARRAY) {
-        td = &mDescriptor->additional_types[td->u.array.additional_type];
+        td = &mHeader->Type(td->u.array.additional_type);
     }
 
     if (td->Tag() != TD_INTERFACE_TYPE) {
         NS_ERROR("not an interface");
         return NS_ERROR_INVALID_ARG;
     }
 
     *interfaceIndex = (td->u.iface.iface_hi8 << 8) | td->u.iface.iface_lo8;
@@ -433,25 +433,23 @@ xptiInterfaceEntry::GetIIDForParamNoAllo
 nsresult
 xptiInterfaceEntry::GetTypeInArray(const nsXPTParamInfo* param,
                                   uint16_t dimension,
                                   const XPTTypeDescriptor** type)
 {
     NS_ASSERTION(IsFullyResolved(), "bad state");
 
     const XPTTypeDescriptor *td = &param->type;
-    const XPTTypeDescriptor *additional_types =
-                mDescriptor->additional_types;
 
     for (uint16_t i = 0; i < dimension; i++) {
         if (td->Tag() != TD_ARRAY) {
             NS_ERROR("bad dimension");
             return NS_ERROR_INVALID_ARG;
         }
-        td = &additional_types[td->u.array.additional_type];
+        td = &mHeader->Type(td->u.array.additional_type);
     }
 
     *type = td;
     return NS_OK;
 }
 
 nsresult
 xptiInterfaceEntry::GetTypeForParam(uint16_t methodIndex,
@@ -551,17 +549,17 @@ xptiInterfaceEntry::GetInterfaceIsArgNum
     {
         NS_ERROR("bad index");
         return NS_ERROR_INVALID_ARG;
     }
 
     const XPTTypeDescriptor *td = &param->type;
 
     while (td->Tag() == TD_ARRAY) {
-        td = &mDescriptor->additional_types[td->u.array.additional_type];
+        td = &mHeader->Type(td->u.array.additional_type);
     }
 
     if (td->Tag() != TD_INTERFACE_IS_TYPE) {
         NS_ERROR("not an iid_is");
         return NS_ERROR_INVALID_ARG;
     }
 
     *argnum = td->u.interface_is.argnum;
--- a/xpcom/typelib/xpt/xpt_struct.h
+++ b/xpcom/typelib/xpt/xpt_struct.h
@@ -19,32 +19,44 @@ struct XPTInterfaceDirectoryEntry;
 struct XPTInterfaceDescriptor;
 struct XPTConstDescriptor;
 struct XPTMethodDescriptor;
 struct XPTParamDescriptor;
 struct XPTTypeDescriptor;
 struct XPTTypeDescriptorPrefix;
 
 struct XPTHeader {
+  inline const XPTTypeDescriptor& Type(size_t aIndex) const;
+
   const XPTInterfaceDirectoryEntry* mEntries;
   uint16_t mNumEntries;
+
+  const XPTInterfaceDescriptor* mInterfaces;
+  const XPTTypeDescriptor* mTypes;
+  const XPTParamDescriptor* mParams;
+  const XPTMethodDescriptor* mMethods;
+  const XPTConstDescriptor* mConsts;
+
+  // All of the strings for this header, concanated into a single
+  // string. This includes null terminators.
+  const char* mStrings;
 };
 
 /*
  * 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 XPTHeader* aHeader) const;
   inline const char* Name(const XPTHeader* aHeader) const;
 
   nsID mIID;
-  const char* mName;
-  const XPTInterfaceDescriptor* mInterfaceDescriptor;
+  uint32_t mName; // Index into XPTHeader::mStrings.
+  uint32_t mInterfaceDescriptor; // 1-based index into XPTHeader::mInterfaces.
 };
 
 /*
  * An InterfaceDescriptor describes a single XPCOM interface, including all of
  * its methods.
  */
 struct XPTInterfaceDescriptor {
   static const uint8_t kScriptableMask =                0x80;
@@ -58,24 +70,22 @@ struct XPTInterfaceDescriptor {
   bool IsMainProcessScriptableOnly() const { return !!(mFlags & kMainProcessScriptableOnlyMask); }
 
   inline const XPTMethodDescriptor& Method(const XPTHeader* aHeader, size_t aIndex) const;
   inline const XPTConstDescriptor& Const(const XPTHeader* aHeader, size_t aIndex) const;
 
   /*
    * This field ordering minimizes the size of this struct.
    */
-  const XPTMethodDescriptor* mMethodDescriptors;
-  const XPTConstDescriptor* mConstDescriptors;
-  const XPTTypeDescriptor* additional_types;
+  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;
-  uint8_t num_additional_types;
 };
 
 /*
  * A TypeDescriptor is a union used to identify the type of a method
  * argument or return value.
  *
  * There are three types of TypeDescriptors:
  *
@@ -149,17 +159,17 @@ struct XPTTypeDescriptor {
     // Used for TD_PSTRING_SIZE_IS, TD_PWSTRING_SIZE_IS.
     struct {
       uint8_t argnum;
     } pstring_is;
 
     // Used for TD_ARRAY.
     struct {
       uint8_t argnum;
-      uint8_t additional_type;
+      uint8_t additional_type; // XXX is uint8_t still enough given module-level merging?
     } array;
 
     // Used for TD_INTERFACE_TYPE.
     struct {
       // We store the 16-bit iface value as two 8-bit values in order to
       // avoid 16-bit alignment requirements for XPTTypeDescriptor, which
       // reduces its size and also the size of XPTParamDescriptor.
       uint8_t iface_hi8;
@@ -180,20 +190,20 @@ union XPTConstValue {
   int16_t i16;
   uint16_t ui16;
   int32_t i32;
   uint32_t ui32;
 };
 
 struct XPTConstDescriptor {
   const char* Name(const XPTHeader* aHeader) const {
-    return mName;
+    return &aHeader->mStrings[mName];
   }
 
-  const char* mName;
+  uint32_t mName; // Index into XPTHeader::mStrings.
   XPTTypeDescriptor mType;
   union XPTConstValue mValue;
 };
 
 /*
  * A ParamDescriptor is used to describe either a single argument to a method or
  * a method's result.
  */
@@ -202,41 +212,49 @@ struct XPTParamDescriptor {
   XPTTypeDescriptor type;
 };
 
 /*
  * A MethodDescriptor is used to describe a single interface method.
  */
 struct XPTMethodDescriptor {
   const char* Name(const XPTHeader* aHeader) const {
-    return mName;
+    return &aHeader->mStrings[mName];
   }
   const XPTParamDescriptor& Param(const XPTHeader* aHeader, uint8_t aIndex) const {
-    return mParams[aIndex];
+    return aHeader->mParams[aIndex];
   }
 
-  const char* mName;
-  const XPTParamDescriptor* mParams;
+  uint32_t mName; // Index into XPTHeader::mStrings.
+  uint32_t mParams; // Index into XPTHeader::mParams.
   uint8_t mFlags;
   uint8_t mNumArgs;
 };
 
+const XPTTypeDescriptor&
+XPTHeader::Type(size_t aIndex) const {
+  return mTypes[aIndex];
+}
+
 const char*
 XPTInterfaceDirectoryEntry::Name(const XPTHeader* aHeader) const {
-  return mName;
+  return &aHeader->mStrings[mName];
 }
 
 const XPTInterfaceDescriptor*
 XPTInterfaceDirectoryEntry::InterfaceDescriptor(const XPTHeader* aHeader) const {
-  return mInterfaceDescriptor;
+  if (mInterfaceDescriptor == 0) {
+    return nullptr;
+  }
+  return &aHeader->mInterfaces[mInterfaceDescriptor - 1];
 }
 
 const XPTMethodDescriptor&
 XPTInterfaceDescriptor::Method(const XPTHeader* aHeader, size_t aIndex) const {
-  return mMethodDescriptors[aIndex];
+  return aHeader->mMethods[mMethodDescriptors + aIndex];
 }
 
 const XPTConstDescriptor&
 XPTInterfaceDescriptor::Const(const XPTHeader* aHeader, size_t aIndex) const {
-  return mConstDescriptors[aIndex];
+  return aHeader->mConsts[mConstDescriptors + aIndex];
 }
 
 #endif /* xpt_struct_h */