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
--- 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];