mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 15:23:51 +00:00
Bug 1249174 (part 7.5) - Avoid wasted space around XPT strings. r=khuey.
This patch: - Removes XPTArena's ability to support arbitrary alignments. - Hardwires two sub-arenas into XPTArena, one with alignment of 8 and one with alignment of 1. - Uses the first sub-arena for most allocations and the second sub-arena for C string allocations. These changes reduce "xpti-working-set" by 56 KiB. The patch also renames all the used of "malloc" in XPT identifiers with "calloc", to make clearer that the result is always zeroed. --HG-- extra : rebase_source : 8e6cc42644621a7f3c80593006734e25420c7229
This commit is contained in:
parent
941e0d3432
commit
2ddfe18454
@ -48,9 +48,10 @@ xptiInterfaceEntry::Create(const char* name, const nsID& iid,
|
||||
xptiTypelibGuts* aTypelib)
|
||||
{
|
||||
int namelen = strlen(name);
|
||||
return new (XPT_MALLOC(gXPTIStructArena,
|
||||
sizeof(xptiInterfaceEntry) + namelen))
|
||||
xptiInterfaceEntry(name, namelen, iid, aDescriptor, aTypelib);
|
||||
void* place =
|
||||
XPT_CALLOC8(gXPTIStructArena, sizeof(xptiInterfaceEntry) + namelen);
|
||||
return new (place) xptiInterfaceEntry(name, namelen, iid, aDescriptor,
|
||||
aTypelib);
|
||||
}
|
||||
|
||||
xptiInterfaceEntry::xptiInterfaceEntry(const char* name,
|
||||
|
@ -52,7 +52,7 @@ XPTInterfaceInfoManager::CollectReports(nsIHandleReportCallback* aHandleReport,
|
||||
// Measure gXPTIStructArena here, too. This is a bit grotty because it
|
||||
// doesn't belong to the XPTIInterfaceInfoManager, but there's no
|
||||
// obviously better place to measure it.
|
||||
amount += XPT_SizeOfArena(gXPTIStructArena, XPTIMallocSizeOf);
|
||||
amount += XPT_SizeOfArenaIncludingThis(gXPTIStructArena, XPTIMallocSizeOf);
|
||||
|
||||
return MOZ_COLLECT_REPORT(
|
||||
"explicit/xpti-working-set", KIND_HEAP, UNITS_BYTES, amount,
|
||||
|
@ -22,11 +22,10 @@ xptiTypelibGuts*
|
||||
xptiTypelibGuts::Create(XPTHeader* aHeader)
|
||||
{
|
||||
NS_ASSERTION(aHeader, "bad param");
|
||||
void* place = XPT_MALLOC(gXPTIStructArena,
|
||||
sizeof(xptiTypelibGuts) +
|
||||
(sizeof(xptiInterfaceEntry*) *
|
||||
(aHeader->num_interfaces - 1)));
|
||||
if(!place)
|
||||
size_t n = sizeof(xptiTypelibGuts) +
|
||||
sizeof(xptiInterfaceEntry*) * (aHeader->num_interfaces - 1);
|
||||
void* place = XPT_CALLOC8(gXPTIStructArena, n);
|
||||
if (!place)
|
||||
return nullptr;
|
||||
return new(place) xptiTypelibGuts(aHeader);
|
||||
}
|
||||
|
@ -13,8 +13,10 @@
|
||||
|
||||
using namespace mozilla;
|
||||
|
||||
#define XPTI_STRUCT_ARENA_BLOCK_SIZE (1024 * 16)
|
||||
#define XPTI_HASHTABLE_LENGTH 1024
|
||||
static const size_t XPTI_ARENA8_BLOCK_SIZE = 16 * 1024;
|
||||
static const size_t XPTI_ARENA1_BLOCK_SIZE = 8 * 1024;
|
||||
|
||||
static const uint32_t XPTI_HASHTABLE_LENGTH = 1024;
|
||||
|
||||
XPTInterfaceInfoManager::xptiWorkingSet::xptiWorkingSet()
|
||||
: mTableReentrantMonitor("xptiWorkingSet::mTableReentrantMonitor")
|
||||
@ -23,8 +25,8 @@ XPTInterfaceInfoManager::xptiWorkingSet::xptiWorkingSet()
|
||||
{
|
||||
MOZ_COUNT_CTOR(xptiWorkingSet);
|
||||
|
||||
gXPTIStructArena =
|
||||
XPT_NewArena(XPTI_STRUCT_ARENA_BLOCK_SIZE, sizeof(double));
|
||||
gXPTIStructArena = XPT_NewArena(XPTI_ARENA8_BLOCK_SIZE,
|
||||
XPTI_ARENA1_BLOCK_SIZE);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -29,49 +29,55 @@ struct BLK_HDR
|
||||
/* XXX this is lame. Should clone the code to do this bitwise */
|
||||
#define ALIGN_RND(s,a) ((a)==1?(s):((((s)+(a)-1)/(a))*(a)))
|
||||
|
||||
struct XPTArena
|
||||
struct XPTSubArena
|
||||
{
|
||||
BLK_HDR *first;
|
||||
uint8_t *next;
|
||||
size_t space;
|
||||
size_t alignment;
|
||||
size_t block_size;
|
||||
};
|
||||
|
||||
XPT_PUBLIC_API(XPTArena *)
|
||||
XPT_NewArena(uint32_t block_size, size_t alignment)
|
||||
struct XPTArena
|
||||
{
|
||||
XPTArena *arena = (XPTArena*)calloc(1, sizeof(XPTArena));
|
||||
// We have one sub-arena with 8-byte alignment for most allocations, and
|
||||
// one with 1-byte alignment for C string allocations. The latter sub-arena
|
||||
// avoids significant amounts of unnecessary padding between C strings.
|
||||
XPTSubArena subarena8;
|
||||
XPTSubArena subarena1;
|
||||
};
|
||||
|
||||
XPT_PUBLIC_API(XPTArena *)
|
||||
XPT_NewArena(size_t block_size8, size_t block_size1)
|
||||
{
|
||||
XPTArena *arena = static_cast<XPTArena*>(calloc(1, sizeof(XPTArena)));
|
||||
if (arena) {
|
||||
XPT_ASSERT(alignment);
|
||||
if (alignment > sizeof(double))
|
||||
alignment = sizeof(double);
|
||||
arena->alignment = alignment;
|
||||
if (block_size8 < XPT_MIN_BLOCK_SIZE)
|
||||
block_size8 = XPT_MIN_BLOCK_SIZE;
|
||||
arena->subarena8.block_size = ALIGN_RND(block_size8, 8);
|
||||
|
||||
if (block_size < XPT_MIN_BLOCK_SIZE)
|
||||
block_size = XPT_MIN_BLOCK_SIZE;
|
||||
arena->block_size = ALIGN_RND(block_size, alignment);
|
||||
|
||||
/* must have room for at least one item! */
|
||||
XPT_ASSERT(arena->block_size >=
|
||||
ALIGN_RND(sizeof(BLK_HDR), alignment) +
|
||||
ALIGN_RND(1, alignment));
|
||||
if (block_size1 < XPT_MIN_BLOCK_SIZE)
|
||||
block_size1 = XPT_MIN_BLOCK_SIZE;
|
||||
arena->subarena1.block_size = block_size1;
|
||||
}
|
||||
return arena;
|
||||
}
|
||||
|
||||
static void
|
||||
DestroySubArena(XPTSubArena *subarena)
|
||||
{
|
||||
BLK_HDR* cur = subarena->first;
|
||||
while (cur) {
|
||||
BLK_HDR* next = cur->next;
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
return arena;
|
||||
}
|
||||
|
||||
XPT_PUBLIC_API(void)
|
||||
XPT_DestroyArena(XPTArena *arena)
|
||||
{
|
||||
BLK_HDR* cur;
|
||||
BLK_HDR* next;
|
||||
|
||||
cur = arena->first;
|
||||
while (cur) {
|
||||
next = cur->next;
|
||||
free(cur);
|
||||
cur = next;
|
||||
}
|
||||
DestroySubArena(&arena->subarena8);
|
||||
DestroySubArena(&arena->subarena1);
|
||||
free(arena);
|
||||
}
|
||||
|
||||
@ -81,11 +87,8 @@ XPT_DestroyArena(XPTArena *arena)
|
||||
*/
|
||||
|
||||
XPT_PUBLIC_API(void *)
|
||||
XPT_ArenaMalloc(XPTArena *arena, size_t size)
|
||||
XPT_ArenaCalloc(XPTArena *arena, size_t size, size_t alignment)
|
||||
{
|
||||
uint8_t *cur;
|
||||
size_t bytes;
|
||||
|
||||
if (!size)
|
||||
return NULL;
|
||||
|
||||
@ -94,55 +97,66 @@ XPT_ArenaMalloc(XPTArena *arena, size_t size)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bytes = ALIGN_RND(size, arena->alignment);
|
||||
XPTSubArena *subarena;
|
||||
if (alignment == 8) {
|
||||
subarena = &arena->subarena8;
|
||||
} else if (alignment == 1) {
|
||||
subarena = &arena->subarena1;
|
||||
} else {
|
||||
XPT_ASSERT(0);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (bytes > arena->space) {
|
||||
size_t bytes = ALIGN_RND(size, alignment);
|
||||
|
||||
if (bytes > subarena->space) {
|
||||
BLK_HDR* new_block;
|
||||
size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), arena->alignment);
|
||||
size_t new_space = arena->block_size;
|
||||
|
||||
while (bytes > new_space - block_header_size)
|
||||
new_space += arena->block_size;
|
||||
size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), alignment);
|
||||
size_t new_space = subarena->block_size;
|
||||
|
||||
new_block = (BLK_HDR*) calloc(new_space/arena->alignment,
|
||||
arena->alignment);
|
||||
while (bytes > new_space - block_header_size)
|
||||
new_space += subarena->block_size;
|
||||
|
||||
new_block =
|
||||
static_cast<BLK_HDR*>(calloc(new_space / alignment, alignment));
|
||||
if (!new_block) {
|
||||
arena->next = NULL;
|
||||
arena->space = 0;
|
||||
subarena->next = NULL;
|
||||
subarena->space = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* link block into the list of blocks for use when we destroy */
|
||||
new_block->next = arena->first;
|
||||
arena->first = new_block;
|
||||
new_block->next = subarena->first;
|
||||
subarena->first = new_block;
|
||||
|
||||
/* set info for current block */
|
||||
arena->next = ((uint8_t*)new_block) + block_header_size;
|
||||
arena->space = new_space - block_header_size;
|
||||
subarena->next =
|
||||
reinterpret_cast<uint8_t*>(new_block) + block_header_size;
|
||||
subarena->space = new_space - block_header_size;
|
||||
|
||||
#ifdef DEBUG
|
||||
/* mark block for corruption check */
|
||||
memset(arena->next, 0xcd, arena->space);
|
||||
memset(subarena->next, 0xcd, subarena->space);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
{
|
||||
/* do corruption check */
|
||||
size_t i;
|
||||
for (i = 0; i < bytes; ++i) {
|
||||
XPT_ASSERT(arena->next[i] == 0xcd);
|
||||
XPT_ASSERT(subarena->next[i] == 0xcd);
|
||||
}
|
||||
/* we guarantee that the block will be filled with zeros */
|
||||
memset(arena->next, 0, bytes);
|
||||
}
|
||||
memset(subarena->next, 0, bytes);
|
||||
}
|
||||
#endif
|
||||
|
||||
cur = arena->next;
|
||||
arena->next += bytes;
|
||||
arena->space -= bytes;
|
||||
|
||||
return cur;
|
||||
uint8_t* p = subarena->next;
|
||||
subarena->next += bytes;
|
||||
subarena->space -= bytes;
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
/***************************************************************************/
|
||||
@ -157,12 +171,12 @@ XPT_AssertFailed(const char *s, const char *file, uint32_t lineno)
|
||||
}
|
||||
#endif
|
||||
|
||||
XPT_PUBLIC_API(size_t)
|
||||
XPT_SizeOfArena(XPTArena *arena, MozMallocSizeOf mallocSizeOf)
|
||||
static size_t
|
||||
SizeOfSubArenaExcludingThis(XPTSubArena *subarena, MozMallocSizeOf mallocSizeOf)
|
||||
{
|
||||
size_t n = mallocSizeOf(arena);
|
||||
size_t n = 0;
|
||||
|
||||
BLK_HDR* cur = arena->first;
|
||||
BLK_HDR* cur = subarena->first;
|
||||
while (cur) {
|
||||
BLK_HDR* next = cur->next;
|
||||
n += mallocSizeOf(cur);
|
||||
@ -171,3 +185,12 @@ XPT_SizeOfArena(XPTArena *arena, MozMallocSizeOf mallocSizeOf)
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
XPT_PUBLIC_API(size_t)
|
||||
XPT_SizeOfArenaIncludingThis(XPTArena *arena, MozMallocSizeOf mallocSizeOf)
|
||||
{
|
||||
size_t n = mallocSizeOf(arena);
|
||||
n += SizeOfSubArenaExcludingThis(&arena->subarena8, mallocSizeOf);
|
||||
n += SizeOfSubArenaExcludingThis(&arena->subarena1, mallocSizeOf);
|
||||
return n;
|
||||
}
|
||||
|
@ -35,24 +35,22 @@ extern "C" {
|
||||
typedef struct XPTArena XPTArena;
|
||||
|
||||
XPT_PUBLIC_API(XPTArena *)
|
||||
XPT_NewArena(uint32_t block_size, size_t alignment);
|
||||
XPT_NewArena(size_t block_size8, size_t block_size1);
|
||||
|
||||
XPT_PUBLIC_API(void)
|
||||
XPT_DestroyArena(XPTArena *arena);
|
||||
|
||||
XPT_PUBLIC_API(void *)
|
||||
XPT_ArenaMalloc(XPTArena *arena, size_t size);
|
||||
XPT_ArenaCalloc(XPTArena *arena, size_t size, size_t alignment);
|
||||
|
||||
XPT_PUBLIC_API(size_t)
|
||||
XPT_SizeOfArena(XPTArena *arena, MozMallocSizeOf mallocSizeOf);
|
||||
XPT_SizeOfArenaIncludingThis(XPTArena *arena, MozMallocSizeOf mallocSizeOf);
|
||||
|
||||
/* --------------------------------------------------------- */
|
||||
|
||||
#define XPT_MALLOC(_arena, _bytes) \
|
||||
XPT_ArenaMalloc((_arena), (_bytes))
|
||||
|
||||
#define XPT_CALLOC(_arena, _size) XPT_MALLOC((_arena), (_size))
|
||||
#define XPT_NEW(_arena, _struct) ((_struct *) XPT_MALLOC((_arena), sizeof(_struct)))
|
||||
#define XPT_CALLOC8(_arena, _bytes) XPT_ArenaCalloc((_arena), (_bytes), 8)
|
||||
#define XPT_CALLOC1(_arena, _bytes) XPT_ArenaCalloc((_arena), (_bytes), 1)
|
||||
#define XPT_NEW(_arena, _struct) ((_struct *) XPT_CALLOC8((_arena), sizeof(_struct)))
|
||||
#define XPT_NEWZAP(_arena, _struct) XPT_NEW((_arena), _struct)
|
||||
|
||||
/* --------------------------------------------------------- */
|
||||
|
@ -108,9 +108,9 @@ XPT_DoHeader(XPTArena *arena, XPTCursor *cursor, XPTHeader **headerp)
|
||||
XPT_SetDataOffset(cursor->state, data_pool);
|
||||
|
||||
if (header->num_interfaces) {
|
||||
header->interface_directory =
|
||||
(XPTInterfaceDirectoryEntry*)XPT_CALLOC(arena, header->num_interfaces *
|
||||
sizeof(XPTInterfaceDirectoryEntry));
|
||||
size_t n = header->num_interfaces * sizeof(XPTInterfaceDirectoryEntry);
|
||||
header->interface_directory =
|
||||
static_cast<XPTInterfaceDirectoryEntry*>(XPT_CALLOC8(arena, n));
|
||||
if (!header->interface_directory)
|
||||
return PR_FALSE;
|
||||
}
|
||||
@ -174,7 +174,7 @@ XPT_InterfaceDescriptorAddTypes(XPTArena *arena, XPTInterfaceDescriptor *id,
|
||||
size_t new_size = (num * sizeof(XPTTypeDescriptor)) + old_size;
|
||||
|
||||
/* XXX should grow in chunks to minimize alloc overhead */
|
||||
new_ = (XPTTypeDescriptor*)XPT_CALLOC(arena, new_size);
|
||||
new_ = static_cast<XPTTypeDescriptor*>(XPT_CALLOC8(arena, new_size));
|
||||
if (!new_)
|
||||
return PR_FALSE;
|
||||
if (old) {
|
||||
@ -213,8 +213,9 @@ DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer,
|
||||
}
|
||||
|
||||
if (id->num_methods) {
|
||||
id->method_descriptors = (XPTMethodDescriptor*)XPT_CALLOC(arena, id->num_methods *
|
||||
sizeof(XPTMethodDescriptor));
|
||||
size_t n = id->num_methods * sizeof(XPTMethodDescriptor);
|
||||
id->method_descriptors =
|
||||
static_cast<XPTMethodDescriptor*>(XPT_CALLOC8(arena, n));
|
||||
if (!id->method_descriptors)
|
||||
return PR_FALSE;
|
||||
}
|
||||
@ -229,8 +230,9 @@ DoInterfaceDescriptor(XPTArena *arena, XPTCursor *outer,
|
||||
}
|
||||
|
||||
if (id->num_constants) {
|
||||
id->const_descriptors = (XPTConstDescriptor*)XPT_CALLOC(arena, id->num_constants *
|
||||
sizeof(XPTConstDescriptor));
|
||||
size_t n = id->num_constants * sizeof(XPTConstDescriptor);
|
||||
id->const_descriptors =
|
||||
static_cast<XPTConstDescriptor*>(XPT_CALLOC8(arena, n));
|
||||
if (!id->const_descriptors)
|
||||
return PR_FALSE;
|
||||
}
|
||||
@ -313,7 +315,8 @@ DoMethodDescriptor(XPTArena *arena, XPTCursor *cursor, XPTMethodDescriptor *md,
|
||||
return PR_FALSE;
|
||||
|
||||
if (md->num_args) {
|
||||
md->params = (XPTParamDescriptor*)XPT_CALLOC(arena, md->num_args * sizeof(XPTParamDescriptor));
|
||||
size_t n = md->num_args * sizeof(XPTParamDescriptor);
|
||||
md->params = static_cast<XPTParamDescriptor*>(XPT_CALLOC8(arena, n));
|
||||
if (!md->params)
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ XPT_DoCString(XPTArena *arena, XPTCursor *cursor, char **identp, bool ignore)
|
||||
XPT_ASSERT(len > 0);
|
||||
|
||||
if (!ignore) {
|
||||
char *ident = (char*)XPT_MALLOC(arena, len + 1u);
|
||||
char *ident = (char*)XPT_CALLOC1(arena, len + 1u);
|
||||
if (!ident)
|
||||
return PR_FALSE;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user