PR_IMPLEMENT(void) PL_InitArenaPool( PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align) { /* * Look-up table of PR_BITMASK(PR_CeilingLog2(align)) values for * align = 1 to 32. */ static const PRUint8 pmasks[33] = { 0, /* not used */ 0, 1, 3, 3, 7, 7, 7, 7,15,15,15,15,15,15,15,15, /* 1 ... 16 */ 31,31,31,31,31,31,31,31,31,31,31,31,31,31,31,31}; /* 17 ... 32 */ if (align == 0) align = PL_ARENA_DEFAULT_ALIGN; if (align < sizeof(pmasks)/sizeof(pmasks[0])) pool->mask = pmasks[align]; else pool->mask = PR_BITMASK(PR_CeilingLog2(align)); pool->first.next = NULL; pool->first.base = pool->first.avail = pool->first.limit = (PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1); pool->current = &pool->first; pool->arenasize = size; #ifdef PL_ARENAMETER memset(&pool->stats, 0, sizeof pool->stats); pool->stats.name = strdup(name); pool->stats.next = arena_stats_list; arena_stats_list = &pool->stats; #endif }
PR_IMPLEMENT(void) PL_InitArenaPool( PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align) { #if defined(XP_MAC) #pragma unused (name) #endif if (align == 0) align = PL_ARENA_DEFAULT_ALIGN; pool->mask = PR_BITMASK(PR_CeilingLog2(align)); pool->first.next = NULL; /* Set all three addresses in pool->first to the same dummy value. * These addresses are only compared with each other, but never * dereferenced. */ pool->first.base = pool->first.avail = pool->first.limit = (PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1); pool->current = &pool->first; pool->arenasize = size; #ifdef PL_ARENAMETER memset(&pool->stats, 0, sizeof pool->stats); pool->stats.name = strdup(name); pool->stats.next = arena_stats_list; arena_stats_list = &pool->stats; #endif }
void* nsPresArena::Allocate(uint32_t aCode, size_t aSize) { NS_ABORT_IF_FALSE(aSize > 0, "PresArena cannot allocate zero bytes"); // We only hand out aligned sizes aSize = PL_ARENA_ALIGN(&mPool, aSize); // If there is no free-list entry for this type already, we have // to create one now, to record its size. FreeList* list = mFreeLists.PutEntry(aCode); nsTArray<void*>::index_type len = list->mEntries.Length(); if (list->mEntrySize == 0) { NS_ABORT_IF_FALSE(len == 0, "list with entries but no recorded size"); list->mEntrySize = aSize; } else { NS_ABORT_IF_FALSE(list->mEntrySize == aSize, "different sizes for same object type code"); } void* result; if (len > 0) { // LIFO behavior for best cache utilization result = list->mEntries.ElementAt(len - 1); list->mEntries.RemoveElementAt(len - 1); #if defined(DEBUG) { MOZ_MAKE_MEM_DEFINED(result, list->mEntrySize); char* p = reinterpret_cast<char*>(result); char* limit = p + list->mEntrySize; for (; p < limit; p += sizeof(uintptr_t)) { uintptr_t val = *reinterpret_cast<uintptr_t*>(p); NS_ABORT_IF_FALSE(val == mozPoisonValue(), nsPrintfCString("PresArena: poison overwritten; " "wanted %.16llx " "found %.16llx " "errors in bits %.16llx", uint64_t(mozPoisonValue()), uint64_t(val), uint64_t(mozPoisonValue() ^ val) ).get()); } } #endif MOZ_MAKE_MEM_UNDEFINED(result, list->mEntrySize); return result; } // Allocate a new chunk from the arena list->mEntriesEverAllocated++; PL_ARENA_ALLOCATE(result, &mPool, aSize); if (!result) { NS_ABORT_OOM(aSize); } return result; }
void* Allocate(PRUint32 aCode, size_t aSize) { NS_ABORT_IF_FALSE(aSize > 0, "PresArena cannot allocate zero bytes"); // We only hand out aligned sizes aSize = PL_ARENA_ALIGN(&mPool, aSize); // If there is no free-list entry for this type already, we have // to create one now, to record its size. FreeList* list = mFreeLists.PutEntry(aCode); if (!list) { return nsnull; } nsTArray<void*>::index_type len = list->mEntries.Length(); if (list->mEntrySize == 0) { NS_ABORT_IF_FALSE(len == 0, "list with entries but no recorded size"); list->mEntrySize = aSize; } else { NS_ABORT_IF_FALSE(list->mEntrySize == aSize, "different sizes for same object type code"); } void* result; if (len > 0) { // LIFO behavior for best cache utilization result = list->mEntries.ElementAt(len - 1); list->mEntries.RemoveElementAt(len - 1); #ifdef DEBUG { char* p = reinterpret_cast<char*>(result); char* limit = p + list->mEntrySize; for (; p < limit; p += sizeof(PRUword)) { NS_ABORT_IF_FALSE(*reinterpret_cast<PRUword*>(p) == ARENA_POISON, "PresArena: poison overwritten"); } } #endif return result; } // Allocate a new chunk from the arena PL_ARENA_ALLOCATE(result, &mPool, aSize); return result; }
PR_IMPLEMENT(void) PL_InitArenaPool( PLArenaPool *pool, const char *name, PRUint32 size, PRUint32 align) { #if !defined (__GNUC__) #pragma unused (name) #endif if (align == 0) align = PL_ARENA_DEFAULT_ALIGN; pool->mask = PR_BITMASK(PR_CeilingLog2(align)); pool->first.next = NULL; pool->first.base = pool->first.avail = pool->first.limit = (PRUword)PL_ARENA_ALIGN(pool, &pool->first + 1); pool->current = &pool->first; pool->arenasize = size; #ifdef PL_ARENAMETER memset(&pool->stats, 0, sizeof pool->stats); pool->stats.name = strdup(name); pool->stats.next = arena_stats_list; arena_stats_list = &pool->stats; #endif }
PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb) { PLArena *a; char *rp; /* returned pointer */ PR_ASSERT((nb & pool->mask) == 0); nb = (PRUword)PL_ARENA_ALIGN(pool, nb); /* force alignment */ /* attempt to allocate from arenas at pool->current */ { a = pool->current; do { if ( a->avail +nb <= a->limit ) { pool->current = a; rp = (char *)a->avail; a->avail += nb; return rp; } } while( NULL != (a = a->next) ); } /* attempt to allocate from arena_freelist */ { PLArena *p; /* previous pointer, for unlinking from freelist */ /* lock the arena_freelist. Make access to the freelist MT-Safe */ if ( PR_FAILURE == LockArena()) return(0); for ( a = arena_freelist, p = NULL; a != NULL ; p = a, a = a->next ) { if ( a->base +nb <= a->limit ) { if ( p == NULL ) arena_freelist = a->next; else p->next = a->next; UnlockArena(); a->avail = a->base; rp = (char *)a->avail; a->avail += nb; /* the newly allocated arena is linked after pool->current * and becomes pool->current */ a->next = pool->current->next; pool->current->next = a; pool->current = a; if ( NULL == pool->first.next ) pool->first.next = a; return(rp); } } UnlockArena(); } /* attempt to allocate from the heap */ { PRUint32 sz = PR_MAX(pool->arenasize, nb); sz += sizeof *a + pool->mask; /* header and alignment slop */ a = (PLArena*)PR_MALLOC(sz); if ( NULL != a ) { a->limit = (PRUword)a + sz; a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1); rp = (char *)a->avail; a->avail += nb; /* the newly allocated arena is linked after pool->current * and becomes pool->current */ a->next = pool->current->next; pool->current->next = a; pool->current = a; if ( NULL == pool->first.next ) pool->first.next = a; PL_COUNT_ARENA(pool,++); COUNT(pool, nmallocs); return(rp); } }
PR_IMPLEMENT(void *) PL_ArenaAllocate(PLArenaPool *pool, PRUint32 nb) { PLArena *a; char *rp; /* returned pointer */ PR_ASSERT((nb & pool->mask) == 0); #ifdef __APPLE__ nb = PL_ARENA_ALIGN(pool, nb); /* force alignment, cast is useless/causes warning. */ #else nb = (PRUword)PL_ARENA_ALIGN(pool, nb); /* force alignment */ #endif /* attempt to allocate from arenas at pool->current */ { a = pool->current; do { if ( nb <= a->limit - a->avail ) { pool->current = a; rp = (char *)a->avail; a->avail += nb; return rp; } } while( NULL != (a = a->next) ); } /* attempt to allocate from the heap */ { PRUint32 sz = PR_MAX(pool->arenasize, nb); if (PR_UINT32_MAX - sz < sizeof *a + pool->mask) { a = NULL; } else { sz += sizeof *a + pool->mask; /* header and alignment slop */ a = (PLArena*)PR_MALLOC(sz); } #ifdef __APPLE__ // Check for integer overflow on a->avail += nb PRUword a_avail_tmp=(PRUword)PL_ARENA_ALIGN(pool, a + 1); if (a_avail_tmp + nb < a_avail_tmp) { PR_FREEIF(a); // Set a back to NULL } #endif if ( NULL != a ) { a->limit = (PRUword)a + sz; #ifdef __APPLE__ a->base = a->avail = a_avail_tmp; #else a->base = a->avail = (PRUword)PL_ARENA_ALIGN(pool, a + 1); #endif rp = (char *)a->avail; a->avail += nb; /* the newly allocated arena is linked after pool->current * and becomes pool->current */ a->next = pool->current->next; pool->current->next = a; pool->current = a; if ( NULL == pool->first.next ) pool->first.next = a; PL_COUNT_ARENA(pool,++); COUNT(pool, nmallocs); return(rp); } }