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

--HG--
extra : rebase_source : 8358a73a0f8f81081661538d4a7c9a31b1aa7a56
This commit is contained in:
Andrew McCreight 2018-03-12 13:36:15 -07:00
Родитель 40c8743812
Коммит da728cc408
6 изменённых файлов: 27 добавлений и 47 удалений

Просмотреть файл

@ -17,7 +17,7 @@
template<typename T> class nsCOMArray;
class nsIMemoryReporter;
struct XPTInterfaceDirectoryEntry;
struct XPTInterfaceDescriptor;
class xptiInterfaceEntry;
class xptiInterfaceInfo;
class xptiTypelibGuts;
@ -55,7 +55,7 @@ private:
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);

Просмотреть файл

@ -16,32 +16,32 @@
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

Просмотреть файл

@ -85,7 +85,7 @@ XPTInterfaceInfoManager::XPTInterfaceInfoManager()
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);
}
}
@ -104,18 +104,21 @@ XPTInterfaceInfoManager::InitMemoryReporter()
}
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;

Просмотреть файл

@ -42,7 +42,7 @@ xptiTypelibGuts::GetEntryAt(uint16_t i)
if (r)
return r;
const XPTInterfaceDirectoryEntry* iface = XPTHeader::kInterfaceDirectory + i;
const XPTInterfaceDescriptor* iface = XPTHeader::kInterfaces + i;
XPTInterfaceInfoManager::xptiWorkingSet& set =
XPTInterfaceInfoManager::GetSingleton()->mWorkingSet;
@ -66,7 +66,7 @@ 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();
}

Просмотреть файл

@ -147,7 +147,7 @@ private:
class xptiInterfaceEntry
{
public:
static xptiInterfaceEntry* Create(const XPTInterfaceDirectoryEntry* aEntry,
static xptiInterfaceEntry* Create(const XPTInterfaceDescriptor* aIface,
xptiTypelibGuts* aTypelib);
enum {
@ -243,7 +243,7 @@ public:
nsresult GetIIDForParamNoAlloc(uint16_t methodIndex, const nsXPTParamInfo * param, nsIID *iid);
private:
xptiInterfaceEntry(const XPTInterfaceDirectoryEntry* aDescriptor,
xptiInterfaceEntry(const XPTInterfaceDescriptor* aIface,
xptiTypelibGuts* aTypelib);
~xptiInterfaceEntry();

Просмотреть файл

@ -16,7 +16,6 @@
#include <stdint.h>
#include "mozilla/Assertions.h"
struct XPTInterfaceDirectoryEntry;
struct XPTInterfaceDescriptor;
struct XPTConstDescriptor;
struct XPTMethodDescriptor;
@ -26,7 +25,6 @@ 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[];
@ -38,22 +36,6 @@ struct XPTHeader {
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.
@ -69,12 +51,15 @@ struct XPTInterfaceDescriptor {
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;
@ -232,18 +217,10 @@ struct XPTMethodDescriptor {
};
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];