Bug 1438688, part 4 - Hoist arrays to XPTHeader. r=njn
To allow XPT information to be shared between processes, it needs to
not contain any pointers, because they cause relocations. I've
eliminated pointers by hoisting all of the variable length data
structures to XPTHeader, into a single array for each type of
data. These data structures now use an index into these arrays to find
their first element. Strings are similar, but they are mashed into a
single giant string, including embedded null terminators. Modifying
the accessor methods to support this is easy, because there is only a
single global instance of each of these arrays in XPTHeader.
MozReview-Commit-ID: 5rgwaEBvDYl
--- a/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
+++ b/xpcom/reflect/xptinfo/xptiInterfaceInfo.cpp
@@ -296,17 +296,17 @@ xptiInterfaceEntry::GetInterfaceIndexFor
{
NS_ERROR("bad param");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = ¶m->mType;
while (td->Tag() == TD_ARRAY) {
- td = td->ArrayElementType(mDescriptor);
+ td = td->ArrayElementType();
}
if (td->Tag() != TD_INTERFACE_TYPE) {
NS_ERROR("not an interface");
return NS_ERROR_INVALID_ARG;
}
*interfaceIndex = td->InterfaceIndex();
return NS_OK;
@@ -436,17 +436,17 @@ xptiInterfaceEntry::GetTypeInArray(const
const XPTTypeDescriptor *td = ¶m->mType;
for (uint16_t i = 0; i < dimension; i++) {
if (td->Tag() != TD_ARRAY) {
NS_ERROR("bad dimension");
return NS_ERROR_INVALID_ARG;
}
- td = td->ArrayElementType(mDescriptor);
+ td = td->ArrayElementType();
}
*type = td;
return NS_OK;
}
nsresult
xptiInterfaceEntry::GetTypeForParam(uint16_t methodIndex,
@@ -544,17 +544,17 @@ xptiInterfaceEntry::GetInterfaceIsArgNum
{
NS_ERROR("bad index");
return NS_ERROR_INVALID_ARG;
}
const XPTTypeDescriptor *td = ¶m->mType;
while (td->Tag() == TD_ARRAY) {
- td = td->ArrayElementType(mDescriptor);
+ td = td->ArrayElementType();
}
if (td->Tag() != TD_INTERFACE_IS_TYPE) {
NS_ERROR("not an iid_is");
return NS_ERROR_INVALID_ARG;
}
*argnum = td->ArgNum();
--- a/xpcom/typelib/xpt/xpt_struct.h
+++ b/xpcom/typelib/xpt/xpt_struct.h
@@ -22,30 +22,41 @@ 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;
- const char* mName;
- const XPTInterfaceDescriptor* mInterfaceDescriptor;
+ 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;
@@ -59,24 +70,22 @@ struct XPTInterfaceDescriptor {
bool IsMainProcessScriptableOnly() const { return !!(mFlags & kMainProcessScriptableOnlyMask); }
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.
*/
- const XPTMethodDescriptor* mMethodDescriptors;
- const XPTConstDescriptor* mConstDescriptors;
- const XPTTypeDescriptor* mAdditionalTypes;
+ 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 mNumAdditionalTypes;
};
/*
* A TypeDescriptor is a union used to identify the type of a method
* argument or return value.
*
* There are three types of TypeDescriptors:
*
@@ -142,19 +151,19 @@ struct XPTTypeDescriptor {
uint8_t ArgNum() const {
MOZ_ASSERT(Tag() == TD_INTERFACE_IS_TYPE ||
Tag() == TD_PSTRING_SIZE_IS ||
Tag() == TD_PWSTRING_SIZE_IS ||
Tag() == TD_ARRAY);
return mData1;
}
- const XPTTypeDescriptor* ArrayElementType(const XPTInterfaceDescriptor* aDescriptor) const {
+ const XPTTypeDescriptor* ArrayElementType() const {
MOZ_ASSERT(Tag() == TD_ARRAY);
- return &aDescriptor->mAdditionalTypes[mData2];
+ return &XPTHeader::kTypes[mData2];
}
// 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.
uint16_t InterfaceIndex() const {
MOZ_ASSERT(Tag() == TD_INTERFACE_TYPE);
return (mData1 << 8) | mData2;
@@ -183,20 +192,20 @@ union XPTConstValue {
int16_t i16;
uint16_t ui16;
int32_t i32;
uint32_t ui32;
};
struct XPTConstDescriptor {
const char* Name() const {
- return mName;
+ return &XPTHeader::kStrings[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.
*/
@@ -205,41 +214,44 @@ struct XPTParamDescriptor {
XPTTypeDescriptor mType;
};
/*
* A MethodDescriptor is used to describe a single interface method.
*/
struct XPTMethodDescriptor {
const char* Name() const {
- return mName;
+ return &XPTHeader::kStrings[mName];
}
const XPTParamDescriptor& Param(uint8_t aIndex) const {
- return mParams[aIndex];
+ return XPTHeader::kParams[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 char*
XPTInterfaceDirectoryEntry::Name() const {
- return mName;
+ return &XPTHeader::kStrings[mName];
}
const XPTInterfaceDescriptor*
XPTInterfaceDirectoryEntry::InterfaceDescriptor() const {
- return mInterfaceDescriptor;
+ if (mInterfaceDescriptor == 0) {
+ return nullptr;
+ }
+ return &XPTHeader::kInterfaces[mInterfaceDescriptor - 1];
}
const XPTMethodDescriptor&
XPTInterfaceDescriptor::Method(size_t aIndex) const {
- return mMethodDescriptors[aIndex];
+ return XPTHeader::kMethods[mMethodDescriptors + aIndex];
}
const XPTConstDescriptor&
XPTInterfaceDescriptor::Const(size_t aIndex) const {
- return mConstDescriptors[aIndex];
+ return XPTHeader::kConsts[mConstDescriptors + aIndex];
}
#endif /* xpt_struct_h */