JS_ArenaAllocate(JSArenaPool *pool, size_t nb) { JSArena **ap, *a, *b; jsuword extra, hdrsz, gross; void *p; /* * Search pool from current forward till we find or make enough space. * * NB: subtract nb from a->limit in the loop condition, instead of adding * nb to a->avail, to avoid overflowing a 32-bit address space (possible * when running a 32-bit program on a 64-bit system where the kernel maps * the heap up against the top of the 32-bit address space). * * Thanks to Juergen Kreileder <*****@*****.**>, who brought this up in * https://bugzilla.mozilla.org/show_bug.cgi?id=279273. */ JS_ASSERT((nb & pool->mask) == 0); for (a = pool->current; nb > a->limit || a->avail > a->limit - nb; pool->current = a) { ap = &a->next; if (!*ap) { /* Not enough space in pool, so we must malloc. */ extra = (nb > pool->arenasize) ? HEADER_SIZE(pool) : 0; hdrsz = sizeof *a + extra + pool->mask; gross = hdrsz + JS_MAX(nb, pool->arenasize); if (gross < nb) return NULL; if (pool->quotap) { if (gross > *pool->quotap) return NULL; b = (JSArena *) js_malloc(gross); if (!b) return NULL; *pool->quotap -= gross; } else { b = (JSArena *) js_malloc(gross); if (!b) return NULL; } b->next = NULL; b->limit = (jsuword)b + gross; JS_COUNT_ARENA(pool,++); COUNT(pool, nmallocs); /* If oversized, store ap in the header, just before a->base. */ *ap = a = b; JS_ASSERT(gross <= JS_UPTRDIFF(a->limit, a)); if (extra) { a->base = a->avail = ((jsuword)a + hdrsz) & ~HEADER_BASE_MASK(pool); SET_HEADER(pool, a, ap); } else { a->base = a->avail = JS_ARENA_ALIGN(pool, a + 1); } continue; } a = *ap; /* move to next arena */ }
JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size, size_t align, size_t *quotap) { if (align == 0) align = JS_ARENA_DEFAULT_ALIGN; pool->mask = JS_BITMASK(JS_CeilingLog2(align)); pool->first.next = NULL; pool->first.base = pool->first.avail = pool->first.limit = JS_ARENA_ALIGN(pool, &pool->first + 1); pool->current = &pool->first; pool->arenasize = size; pool->quotap = quotap; #ifdef JS_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 }
JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size, size_t align) { #ifdef JS_THREADSAFE /* Must come through here once in primordial thread to init safely! */ if (!arena_freelist_lock) { arena_freelist_lock = JS_NEW_LOCK(); JS_ASSERT(arena_freelist_lock); } #endif if (align == 0) align = JS_ARENA_DEFAULT_ALIGN; pool->mask = JS_BITMASK(JS_CeilingLog2(align)); pool->first.next = NULL; pool->first.base = pool->first.avail = pool->first.limit = JS_ARENA_ALIGN(pool, &pool->first + 1); pool->current = &pool->first; pool->arenasize = size; #ifdef JS_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 }
JS_ArenaAllocate(JSArenaPool *pool, size_t nb) { JSArena **ap, **bp, *a, *b; jsuword extra, hdrsz, gross, sz; void *p; /* * Search pool from current forward till we find or make enough space. * * NB: subtract nb from a->limit in the loop condition, instead of adding * nb to a->avail, to avoid overflowing a 32-bit address space (possible * when running a 32-bit program on a 64-bit system where the kernel maps * the heap up against the top of the 32-bit address space). * * Thanks to Juergen Kreileder <*****@*****.**>, who brought this up in * https://bugzilla.mozilla.org/show_bug.cgi?id=279273. */ JS_ASSERT((nb & pool->mask) == 0); for (a = pool->current; nb > a->limit || a->avail > a->limit - nb; pool->current = a) { ap = &a->next; if (!*ap) { /* Not enough space in pool -- try to reclaim a free arena. */ extra = (nb > pool->arenasize) ? HEADER_SIZE(pool) : 0; hdrsz = sizeof *a + extra + pool->mask; gross = hdrsz + JS_MAX(nb, pool->arenasize); if (gross < nb) return NULL; bp = &arena_freelist; JS_ACQUIRE_LOCK(arena_freelist_lock); while ((b = *bp) != NULL) { /* * Insist on exact arenasize match to avoid leaving alloc'able * space after an oversized allocation as it grows. */ sz = JS_UPTRDIFF(b->limit, b); if (sz == gross) { *bp = b->next; JS_RELEASE_LOCK(arena_freelist_lock); b->next = NULL; COUNT(pool, nreclaims); goto claim; } bp = &b->next; } /* Nothing big enough on the freelist, so we must malloc. */ JS_RELEASE_LOCK(arena_freelist_lock); b = (JSArena *) malloc(gross); if (!b) return NULL; b->next = NULL; b->limit = (jsuword)b + gross; JS_COUNT_ARENA(pool,++); COUNT(pool, nmallocs); claim: /* If oversized, store ap in the header, just before a->base. */ *ap = a = b; JS_ASSERT(gross <= JS_UPTRDIFF(a->limit, a)); if (extra) { a->base = a->avail = ((jsuword)a + hdrsz) & ~HEADER_BASE_MASK(pool); SET_HEADER(pool, a, ap); } else { a->base = a->avail = JS_ARENA_ALIGN(pool, a + 1); } continue; } a = *ap; /* move to next arena */ }