diff --git a/js/src/jsapi.cpp b/js/src/jsapi.cpp index de7e536d9d3d..f84b6b364f54 100644 --- a/js/src/jsapi.cpp +++ b/js/src/jsapi.cpp @@ -2442,8 +2442,8 @@ JS_GC(JSContext *cx) LeaveTrace(cx); /* Don't nuke active arenas if executing or compiling. */ - if (cx->tempPool.current == &cx->tempPool.first) - JS_FinishArenaPool(&cx->tempPool); + if (cx->tempPool.currentIsFirst()) + cx->tempPool.finish(); js_GC(cx, GC_NORMAL); } @@ -4131,7 +4131,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent) JSUpvarArray *uva = fun->u.i.script->upvars(); JS_ASSERT(uva->length <= size_t(clone->dslots[-1])); - void *mark = JS_ARENA_MARK(&cx->tempPool); + void *mark = cx->tempPool.getMark(); jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool); if (!names) return NULL; @@ -4155,7 +4155,7 @@ JS_CloneFunctionObject(JSContext *cx, JSObject *funobj, JSObject *parent) } break2: - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); if (i < n) return NULL; } diff --git a/js/src/jsarena.cpp b/js/src/jsarena.cpp index b6f661c602ab..b53188d9fcba 100644 --- a/js/src/jsarena.cpp +++ b/js/src/jsarena.cpp @@ -47,37 +47,32 @@ #include "jstypes.h" #include "jsstdint.h" #include "jsbit.h" -#include "jsarena.h" /* Added by JSIFY */ -#include "jsutil.h" /* Added by JSIFY */ +#include "jsarenainlines.h" +#include "jsutil.h" -#ifdef JS_ARENAMETER +#ifdef DEBUG static JSArenaStats *arena_stats_list; - #define COUNT(pool,what) (pool)->stats.what++ #else #define COUNT(pool,what) /* nothing */ -#endif +#endif /* DEBUG */ #define JS_ARENA_DEFAULT_ALIGN sizeof(double) -JS_PUBLIC_API(void) -JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size, - size_t align, size_t *quotap) +void +JSArenaPool::init(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; + mask = JS_BITMASK(JS_CeilingLog2(align)); + first.next = NULL; + first.base = first.avail = first.limit = this->align(jsuword(&first + 1)); + current = &first; + arenasize = size; + this->quotap = quotap; +#ifdef DEBUG + stats.init(name, arena_stats_list); + arena_stats_list = &stats; #endif } @@ -104,37 +99,30 @@ JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size, * boundary. Given powers of two M and P as above, the extra space needed * when M < P is P-M or POINTER_MASK - pool->mask. * - * The size of a header including padding is given by the HEADER_SIZE macro, - * below, for any pool (for any value of M). - * - * The mask to align a->base for any pool is (pool->mask | POINTER_MASK), or - * HEADER_BASE_MASK(pool). - * - * PTR_TO_HEADER computes the address of the back-pointer, given an oversized - * allocation at p. By definition, p must be a->base for the arena a that - * contains p. GET_HEADER and SET_HEADER operate on an oversized arena a, in - * the case of SET_HEADER with back-pointer ap. + * The size of a header including padding is given by the headerSize method + * for any pool (for any value of M). */ -#define POINTER_MASK ((jsuword)(JS_ALIGN_OF_POINTER - 1)) -#define HEADER_SIZE(pool) (sizeof(JSArena **) \ - + (((pool)->mask < POINTER_MASK) \ - ? POINTER_MASK - (pool)->mask \ - : 0)) -#define HEADER_BASE_MASK(pool) ((pool)->mask | POINTER_MASK) -#define PTR_TO_HEADER(pool,p) (JS_ASSERT(((jsuword)(p) \ - & HEADER_BASE_MASK(pool)) \ - == 0), \ - (JSArena ***)(p) - 1) -#define GET_HEADER(pool,a) (*PTR_TO_HEADER(pool, (a)->base)) -#define SET_HEADER(pool,a,ap) (*PTR_TO_HEADER(pool, (a)->base) = (ap)) -JS_PUBLIC_API(void *) -JS_ArenaAllocate(JSArenaPool *pool, size_t nb) +void * +JSArenaPool::allocate(size_t nb, bool limitCheck) { - JSArena **ap, *a, *b; - jsuword extra, hdrsz, gross; - void *p; + countAllocation(nb); + size_t alignedNB = align(nb); + jsuword p = current->avail; + /* + * NB: always subtract nb from limit rather than adding nb to p to avoid overflowing a + * 32-bit address space. See bug 279273. + */ + if ((limitCheck && alignedNB > current->limit) || p > current->limit - alignedNB) + p = jsuword(allocateInternal(alignedNB)); + else + current->avail = p + alignedNB; + return (void *) p; +} +void * +JSArenaPool::allocateInternal(size_t nb) +{ /* * Search pool from current forward till we find or make enough space. * @@ -146,24 +134,25 @@ JS_ArenaAllocate(JSArenaPool *pool, size_t nb) * 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; + JS_ASSERT((nb & mask) == 0); + JSArena *a; + for (a = current; nb > a->limit || a->avail > a->limit - nb; current = a) { + JSArena **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); + jsuword extra = (nb > arenasize) ? headerSize() : 0; + jsuword hdrsz = sizeof *a + extra + mask; + jsuword gross = hdrsz + JS_MAX(nb, arenasize); if (gross < nb) return NULL; - if (pool->quotap) { - if (gross > *pool->quotap) + JSArena *b; + if (quotap) { + if (gross > *quotap) return NULL; b = (JSArena *) js_malloc(gross); if (!b) return NULL; - *pool->quotap -= gross; + *quotap -= gross; } else { b = (JSArena *) js_malloc(gross); if (!b) @@ -172,32 +161,32 @@ JS_ArenaAllocate(JSArenaPool *pool, size_t nb) b->next = NULL; b->limit = (jsuword)b + gross; - JS_COUNT_ARENA(pool,++); - COUNT(pool, nmallocs); + incArenaCount(); + COUNT(this, 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); + ((jsuword)a + hdrsz) & ~headerBaseMask(); + setHeader(a, ap); } else { - a->base = a->avail = JS_ARENA_ALIGN(pool, a + 1); + a->base = a->avail = align(jsuword(a + 1)); } continue; } a = *ap; /* move to next arena */ } - p = (void *)a->avail; + void *p = (void *) a->avail; a->avail += nb; JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); return p; } -JS_PUBLIC_API(void *) -JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr) +void * +JSArenaPool::reallocInternal(void *p, size_t size, size_t incr) { JSArena **ap, *a, *b; jsuword boff, aoff, extra, hdrsz, gross, growth; @@ -206,160 +195,78 @@ JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr) * Use the oversized-single-allocation header to avoid searching for ap. * See JS_ArenaAllocate, the SET_HEADER call. */ - if (size > pool->arenasize) { - ap = *PTR_TO_HEADER(pool, p); + if (size > arenasize) { + ap = *ptrToHeader(p); a = *ap; } else { - ap = &pool->first.next; - while ((a = *ap) != pool->current) + ap = &first.next; + while ((a = *ap) != current) ap = &a->next; } JS_ASSERT(a->base == (jsuword)p); boff = JS_UPTRDIFF(a->base, a); - aoff = JS_ARENA_ALIGN(pool, size + incr); - JS_ASSERT(aoff > pool->arenasize); - extra = HEADER_SIZE(pool); /* oversized header holds ap */ - hdrsz = sizeof *a + extra + pool->mask; /* header and alignment slop */ + aoff = align(size + incr); + JS_ASSERT(aoff > arenasize); + extra = headerSize(); /* oversized header holds ap */ + hdrsz = sizeof *a + extra + mask; /* header and alignment slop */ gross = hdrsz + aoff; JS_ASSERT(gross > aoff); - if (pool->quotap) { + if (quotap) { growth = gross - (a->limit - (jsuword) a); - if (growth > *pool->quotap) + if (growth > *quotap) return NULL; a = (JSArena *) js_realloc(a, gross); if (!a) return NULL; - *pool->quotap -= growth; + *quotap -= growth; } else { a = (JSArena *) js_realloc(a, gross); if (!a) return NULL; } -#ifdef JS_ARENAMETER - pool->stats.nreallocs++; -#endif + incReallocCount(); if (a != *ap) { /* Oops, realloc moved the allocation: update other pointers to a. */ - if (pool->current == *ap) - pool->current = a; + if (current == *ap) + current = a; b = a->next; - if (b && b->avail - b->base > pool->arenasize) { - JS_ASSERT(GET_HEADER(pool, b) == &(*ap)->next); - SET_HEADER(pool, b, &a->next); + if (b && b->avail - b->base > arenasize) { + JS_ASSERT(getHeader(b) == &(*ap)->next); + setHeader(b, &a->next); } /* Now update *ap, the next link of the arena before a. */ *ap = a; } - a->base = ((jsuword)a + hdrsz) & ~HEADER_BASE_MASK(pool); + a->base = ((jsuword)a + hdrsz) & ~headerBaseMask(); a->limit = (jsuword)a + gross; a->avail = a->base + aoff; JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); /* Check whether realloc aligned differently, and copy if necessary. */ if (boff != JS_UPTRDIFF(a->base, a)) - memmove((void *)a->base, (char *)a + boff, size); + memmove((void *) a->base, (char *) a + boff, size); /* Store ap in the oversized-load arena header. */ - SET_HEADER(pool, a, ap); - return (void *)a->base; + setHeader(a, ap); + return (void *) a->base; } -JS_PUBLIC_API(void *) -JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr) +void +JSArenaPool::finish() { - void *newp; - - /* - * If p points to an oversized allocation, it owns an entire arena, so we - * can simply realloc the arena. - */ - if (size > pool->arenasize) - return JS_ArenaRealloc(pool, p, size, incr); - - JS_ARENA_ALLOCATE(newp, pool, size + incr); - if (newp) - memcpy(newp, p, size); - return newp; -} - -/* - * Free tail arenas linked after head, which may not be the true list head. - * Reset pool->current to point to head in case it pointed at a tail arena. - */ -static void -FreeArenaList(JSArenaPool *pool, JSArena *head) -{ - JSArena **ap, *a; - - ap = &head->next; - a = *ap; - if (!a) - return; - + freeArenaList(&first); #ifdef DEBUG - do { - JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); - a->avail = a->base; - JS_CLEAR_UNUSED(a); - } while ((a = a->next) != NULL); - a = *ap; -#endif - - do { - *ap = a->next; - if (pool->quotap) - *pool->quotap += a->limit - (jsuword) a; - JS_CLEAR_ARENA(a); - JS_COUNT_ARENA(pool,--); - js_free(a); - } while ((a = *ap) != NULL); - - pool->current = head; -} - -JS_PUBLIC_API(void) -JS_ArenaRelease(JSArenaPool *pool, char *mark) -{ - JSArena *a; - - for (a = &pool->first; a; a = a->next) { - JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); - - if (JS_ARENA_MARK_MATCH(a, mark)) { - a->avail = JS_ARENA_ALIGN(pool, mark); - JS_ASSERT(a->avail <= a->limit); - FreeArenaList(pool, a); - return; - } - } -} - -JS_PUBLIC_API(void) -JS_FreeArenaPool(JSArenaPool *pool) -{ - FreeArenaList(pool, &pool->first); - COUNT(pool, ndeallocs); -} - -JS_PUBLIC_API(void) -JS_FinishArenaPool(JSArenaPool *pool) -{ - FreeArenaList(pool, &pool->first); -#ifdef JS_ARENAMETER { JSArenaStats *stats, **statsp; - if (pool->stats.name) { - js_free(pool->stats.name); - pool->stats.name = NULL; - } + this->stats.finish(); for (statsp = &arena_stats_list; (stats = *statsp) != 0; statsp = &stats->next) { - if (stats == &pool->stats) { + if (stats == &this->stats) { *statsp = stats->next; return; } @@ -368,83 +275,82 @@ JS_FinishArenaPool(JSArenaPool *pool) #endif } -JS_PUBLIC_API(void) -JS_ArenaFinish() +#ifdef DEBUG +void +JSArenaPool::countAllocation(size_t nb) { + stats.nallocs++; + stats.nbytes += nb; + if (nb > stats.maxalloc) + stats.maxalloc = nb; + stats.variance += nb * nb; } -JS_PUBLIC_API(void) -JS_ArenaShutDown(void) +void +JSArenaPool::countGrowth(size_t size, size_t incr) { -} - -#ifdef JS_ARENAMETER -JS_PUBLIC_API(void) -JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb) -{ - pool->stats.nallocs++; - pool->stats.nbytes += nb; - if (nb > pool->stats.maxalloc) - pool->stats.maxalloc = nb; - pool->stats.variance += nb * nb; -} - -JS_PUBLIC_API(void) -JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr) -{ - pool->stats.ninplace++; -} - -JS_PUBLIC_API(void) -JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr) -{ - pool->stats.ngrows++; - pool->stats.nbytes += incr; - pool->stats.variance -= size * size; + stats.ngrows++; + stats.nbytes += incr; + stats.variance -= size * size; size += incr; - if (size > pool->stats.maxalloc) - pool->stats.maxalloc = size; - pool->stats.variance += size * size; + if (size > stats.maxalloc) + stats.maxalloc = size; + stats.variance += size * size; } -JS_PUBLIC_API(void) -JS_ArenaCountRelease(JSArenaPool *pool, char *mark) +JS_FRIEND_API(void) +JS_DumpArenaStats() { - pool->stats.nreleases++; + const char *filename = getenv("JS_ARENA_STATFILE"); + if (!filename) + return; + FILE *arenaStatFile = strcmp(filename, "stdout") + ? stdout : strcmp(filename, "stderr") + ? stderr : fopen(filename, "w"); + for (const JSArenaStats *stats = arena_stats_list; stats; stats = stats->getNext()) + stats->dump(arenaStatFile); + fclose(arenaStatFile); } -JS_PUBLIC_API(void) -JS_ArenaCountRetract(JSArenaPool *pool, char *mark) +void +JSArenaStats::dump(FILE *fp) const { - pool->stats.nfastrels++; + double sigma; + double mean = JS_MeanAndStdDev(nallocs, nbytes, variance, &sigma); + + fprintf(fp, "\n%s allocation statistics:\n", name); + fprintf(fp, " number of arenas: %u\n", narenas); + fprintf(fp, " number of allocations: %u\n", nallocs); + fprintf(fp, " number of malloc calls: %u\n", nmallocs); + fprintf(fp, " number of deallocations: %u\n", ndeallocs); + fprintf(fp, " number of allocation growths: %u\n", ngrows); + fprintf(fp, " number of in-place growths: %u\n", ninplace); + fprintf(fp, " number of realloc'ing growths: %u\n", nreallocs); + fprintf(fp, "number of released allocations: %u\n", nreleases); + fprintf(fp, " number of fast releases: %u\n", nfastrels); + fprintf(fp, " total bytes allocated: %u\n", unsigned(nbytes)); + fprintf(fp, " mean allocation size: %g\n", mean); + fprintf(fp, " standard deviation: %g\n", sigma); + fprintf(fp, " maximum allocation size: %u\n", unsigned(maxalloc)); } +#endif /* DEBUG */ -#include +/* Backwards compatibility. */ -JS_PUBLIC_API(void) -JS_DumpArenaStats(FILE *fp) +JS_FRIEND_API(void *) +JS_ARENA_MARK(const JSArenaPool *pool) { - JSArenaStats *stats; - double mean, sigma; - - for (stats = arena_stats_list; stats; stats = stats->next) { - mean = JS_MeanAndStdDev(stats->nallocs, stats->nbytes, stats->variance, - &sigma); - - fprintf(fp, "\n%s allocation statistics:\n", stats->name); - fprintf(fp, " number of arenas: %u\n", stats->narenas); - fprintf(fp, " number of allocations: %u\n", stats->nallocs); - fprintf(fp, " number of malloc calls: %u\n", stats->nmallocs); - fprintf(fp, " number of deallocations: %u\n", stats->ndeallocs); - fprintf(fp, " number of allocation growths: %u\n", stats->ngrows); - fprintf(fp, " number of in-place growths: %u\n", stats->ninplace); - fprintf(fp, " number of realloc'ing growths: %u\n", stats->nreallocs); - fprintf(fp, "number of released allocations: %u\n", stats->nreleases); - fprintf(fp, " number of fast releases: %u\n", stats->nfastrels); - fprintf(fp, " total bytes allocated: %u\n", stats->nbytes); - fprintf(fp, " mean allocation size: %g\n", mean); - fprintf(fp, " standard deviation: %g\n", sigma); - fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc); - } + return pool->getMark(); +} + +JS_FRIEND_API(void) +JS_ARENA_RELEASE(JSArenaPool *pool, void *mark) +{ + pool->release(mark); +} + +JS_FRIEND_API(void *) +JS_ARENA_ALLOCATE_COMMON_SANE(jsuword p, JSArenaPool *pool, size_t nb, bool limitCheck) +{ + return pool->allocate(nb, limitCheck); } -#endif /* JS_ARENAMETER */ diff --git a/js/src/jsarena.h b/js/src/jsarena.h index ad2abd19ac6d..7498f22657e0 100644 --- a/js/src/jsarena.h +++ b/js/src/jsarena.h @@ -47,25 +47,67 @@ * Also supports LIFO allocation (JS_ARENA_MARK/JS_ARENA_RELEASE). */ #include +#include +#ifdef DEBUG +#include +#endif #include "jstypes.h" #include "jscompat.h" +#include "jsutil.h" -JS_BEGIN_EXTERN_C +#ifdef DEBUG +const uint8_t JS_FREE_PATTERN = 0xDA; +#endif -typedef struct JSArena JSArena; -typedef struct JSArenaPool JSArenaPool; +#define JS_UPTRDIFF(p,q) (jsuword(p) - jsuword(q)) -struct JSArena { +struct JSArena +{ JSArena *next; /* next arena for this lifetime */ jsuword base; /* aligned base address, follows this header */ jsuword limit; /* one beyond last byte in arena */ jsuword avail; /* points to next available byte */ + + public: + jsuword getBase() const { return base; } + jsuword getLimit() const { return limit; } + jsuword getAvail() const { return avail; } + void setAvail(jsuword newAvail) { avail = newAvail; } + const JSArena *getNext() const { return next; } + JSArena *getNext() { return next; } + void munge(JSArena *next) { this-> next = next; } + void munge(JSArena *next, jsuword base, jsuword avail, jsuword limit) { + this->next = next; + this->base = base; + this->avail = avail; + this->limit = limit; + } + + /* + * Check if the mark is inside arena's allocated area. + */ + bool markMatch(void *mark) const { + return JS_UPTRDIFF(mark, base) <= JS_UPTRDIFF(avail, base); + } + +#ifdef DEBUG + void clear() { memset(this, JS_FREE_PATTERN, limit - jsuword(this)); } + + void clearUnused() { + JS_ASSERT(avail <= limit); + memset((void *) avail, JS_FREE_PATTERN, limit - avail); + } +#else + void clear() {} + void clearUnused() {} +#endif + + friend class JSArenaPool; }; -#ifdef JS_ARENAMETER -typedef struct JSArenaStats JSArenaStats; - -struct JSArenaStats { +#ifdef DEBUG +class JSArenaStats +{ JSArenaStats *next; /* next in arenaStats list */ char *name; /* name for debugging */ uint32 narenas; /* number of arenas in pool */ @@ -80,209 +122,263 @@ struct JSArenaStats { size_t nbytes; /* total bytes allocated */ size_t maxalloc; /* maximum allocation size in bytes */ double variance; /* size variance accumulator */ -}; -#endif -struct JSArenaPool { + public: + void init(const char *name, JSArenaStats *next) { + memset(this, 0, sizeof *this); + this->name = strdup(name); + this->next = next; + } + void finish() { free(name); name = 0; } + void dump(FILE *fp) const; + const JSArenaStats *getNext() const { return next; } + + friend class JSArenaPool; +}; + +JS_FRIEND_API(void) +JS_DumpArenaStats(); +#endif /* DEBUG */ + +class JSArenaPool +{ JSArena first; /* first arena in pool list */ JSArena *current; /* arena from which to allocate space */ size_t arenasize; /* net exact size of a new arena */ jsuword mask; /* alignment mask (power-of-2 - 1) */ size_t *quotap; /* pointer to the quota on pool allocation size or null if pool is unlimited */ -#ifdef JS_ARENAMETER +#ifdef DEBUG JSArenaStats stats; #endif + + public: + /* + * Initialize an arena pool with a minimum size per arena of size bytes. + */ + void init(const char *name, size_t size, size_t align, size_t *quotap); + + /* + * Free the arenas in pool and finish using it altogether. + */ + void finish(); + + /* + * Free the arenas in pool. The user may continue to allocate from pool + * after calling this function. There is no need to call |init| + * again unless JS_FinishArenaPool(pool) has been called. + */ + void free() { + freeArenaList(&first); + incDeallocCount(); + } + + void *getMark() const { return (void *) current->avail; } + jsuword align(jsuword n) const { return (n + mask) & ~mask; } + jsuword align(void *n) const { return align(jsuword(n)); } + bool currentIsFirst() const { return current == &first; } + const JSArena *getFirst() const { return &first; } + const JSArena *getSecond() const { return first.next; } + const JSArena *getCurrent() const { return current; } + JSArena *getFirst() { return &first; } + JSArena *getSecond() { return first.next; } + JSArena *getCurrent() { return current; } + + void *allocate(size_t nb, bool limitCheck); + + template + void allocateCast(T &p, size_t nb) { + p = (T) allocate(nb, true); + } + + template + void allocateType(T *&p) { + p = (T *) allocate(sizeof(T), false); + } + + void allocate(void *&p, size_t nb) { allocateCast(p, nb); } + + void *grow(jsuword p, size_t size, size_t incr); + + template + void growCast(T &p, size_t size, size_t incr) { + p = (T) grow(jsuword(p), size, incr); + } + + void release(void *mark) { + if (current != &first && current->markMatch(mark)) { + current->avail = jsuword(align(mark)); + JS_ASSERT(current->avail <= current->limit); + current->clearUnused(); + countRetract(mark); + } else { + releaseInternal(mark); + } + countRelease(mark); + } + + JSArena *destroy(JSArena *&a) { + decArenaCount(); + if (current == a) + current = &first; + JSArena *next = a->next; + a->clear(); + ::free(a); + a = NULL; + return next; + } + + class ScopedExtension { + JSArenaPool * const parent; + JSArena * const prevTop; + JSArena * const pushed; + public: + ScopedExtension(JSArenaPool *parent, JSArena *toPush) + : parent(parent), prevTop(parent->getCurrent()), pushed(toPush) { + JS_ASSERT(!prevTop->getNext()); + JS_ASSERT(!toPush->getNext()); + JS_ASSERT(prevTop != toPush); + parent->current = prevTop->next = toPush; + } + ~ScopedExtension() { + JS_ASSERT(!pushed->next); + JS_ASSERT(prevTop->next == pushed); + JS_ASSERT(parent->getCurrent() == pushed); + parent->current = prevTop; + prevTop->next = NULL; + } + }; + + private: + static const jsuword POINTER_MASK; + + /* + * The mask to align |base|. + */ + jsuword headerBaseMask() const; + + jsuword headerSize() const; + + /* + * Compute the address of the back-pointer, given an oversized allocation at |p|. + * |p| must be |a->base| for the arena |a| that contains |p|. + */ + JSArena ***ptrToHeader(void *p) const { + JS_ASSERT((jsuword(p) & headerBaseMask()) == 0); + return (JSArena ***)(p) - 1; + } + JSArena ***ptrToHeader(jsuword p) const { return ptrToHeader((void *) p); } + + /* + * |getHeader| and |setHeader| operate on an oversized arena. + */ + JSArena **getHeader(const JSArena *a) const { return *ptrToHeader(a->base); } + JSArena **setHeader(JSArena *a, JSArena **ap) const { return *ptrToHeader(a->base) = ap; } + + void *allocateInternal(size_t nb); + void *reallocInternal(void *p, size_t size, size_t incr); + + void releaseInternal(void *mark) { + for (JSArena *a = &first; a; a = a->next) { + JS_ASSERT(a->base <= a->avail && a->avail <= a->limit); + + if (a->markMatch(mark)) { + a->avail = align(mark); + JS_ASSERT(a->avail <= a->limit); + freeArenaList(a); + return; + } + } + } + + void *growInternal(void *p, size_t size, size_t incr) { + /* + * If p points to an oversized allocation, it owns an entire arena, so we + * can simply realloc the arena. + */ + if (size > arenasize) + return reallocInternal(p, size, incr); + + void *newp = allocate(size + incr, true); + if (newp) + memcpy(newp, p, size); + return newp; + } + + /* + * Free tail arenas linked after head, which may not be the true list head. + * Reset current to point to head in case it pointed at a tail arena. + */ + void freeArenaList(JSArena *head) { + JSArena **ap = &head->next; + JSArena *a = *ap; + if (!a) + return; + +#ifdef DEBUG + do { + JS_ASSERT(a->base <= a->avail); + JS_ASSERT(a->avail <= a->limit); + a->avail = a->base; + a->clearUnused(); + } while ((a = a->next) != NULL); + a = *ap; +#endif + + do { + *ap = a->next; + if (quotap) + *quotap += a->limit - (jsuword) a; + a->clear(); + decArenaCount(); + js_free(a); + } while ((a = *ap) != NULL); + + current = head; + } + + /* Counters. */ +#ifdef DEBUG + void countAllocation(size_t nb); + void countInplaceGrowth(size_t size, size_t incr) { stats.ninplace++; } + void countGrowth(size_t size, size_t incr); + void countRelease(void *mark) { stats.nreleases++; } + void countRetract(void *mark) { stats.nfastrels++; } + void incArenaCount() { stats.narenas++; } + void decArenaCount() { stats.narenas--; } + void incDeallocCount() { stats.ndeallocs++; } + void incReallocCount() { stats.nreallocs++; } +#else + void countAllocation(size_t nb) {} + void countInplaceGrowth(size_t size, size_t incr) {} + void countGrowth(size_t size, size_t incr) {} + void countRelease(void *mark) {} + void countRetract(void *mark) {} + void incArenaCount() {} + void decArenaCount() {} + void incDeallocCount() {} + void incReallocCount() {} +#endif }; -#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + (pool)->mask) & ~(pool)->mask) +/* Backwards compatibility. */ -#define JS_ARENA_ALLOCATE(p, pool, nb) \ - JS_ARENA_ALLOCATE_CAST(p, void *, pool, nb) +JS_BEGIN_EXTERN_C -#define JS_ARENA_ALLOCATE_TYPE(p, type, pool) \ - JS_ARENA_ALLOCATE_COMMON(p, type *, pool, sizeof(type), 0) +JS_FRIEND_API(void *) +JS_ARENA_MARK(const JSArenaPool *pool); -#define JS_ARENA_ALLOCATE_CAST(p, type, pool, nb) \ - JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, _nb > _a->limit) +JS_FRIEND_API(void) +JS_ARENA_RELEASE(JSArenaPool *pool, void *mark); -/* - * NB: In JS_ARENA_ALLOCATE_CAST and JS_ARENA_GROW_CAST, always subtract _nb - * from a->limit rather than adding _nb to _p, 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. - */ -#define JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, guard) \ - JS_BEGIN_MACRO \ - JSArena *_a = (pool)->current; \ - size_t _nb = JS_ARENA_ALIGN(pool, nb); \ - jsuword _p = _a->avail; \ - if ((guard) || _p > _a->limit - _nb) \ - _p = (jsuword)JS_ArenaAllocate(pool, _nb); \ - else \ - _a->avail = _p + _nb; \ - p = (type) _p; \ - JS_ArenaCountAllocation(pool, nb); \ +JS_FRIEND_API(void *) +JS_ARENA_ALLOCATE_COMMON_SANE(jsuword p, JSArenaPool *pool, size_t nb, bool limitCheck); + +#define JS_ARENA_ALLOCATE_CAST(p, type, pool, nb) \ + JS_BEGIN_MACRO \ + (p) = (type) JS_ARENA_ALLOCATE_COMMON_SANE(jsuword(p), (pool), (nb), true); \ JS_END_MACRO - -#define JS_ARENA_GROW(p, pool, size, incr) \ - JS_ARENA_GROW_CAST(p, void *, pool, size, incr) - -#define JS_ARENA_GROW_CAST(p, type, pool, size, incr) \ - JS_BEGIN_MACRO \ - JSArena *_a = (pool)->current; \ - if (_a->avail == (jsuword)(p) + JS_ARENA_ALIGN(pool, size)) { \ - size_t _nb = (size) + (incr); \ - _nb = JS_ARENA_ALIGN(pool, _nb); \ - if (_a->limit >= _nb && (jsuword)(p) <= _a->limit - _nb) { \ - _a->avail = (jsuword)(p) + _nb; \ - JS_ArenaCountInplaceGrowth(pool, size, incr); \ - } else if ((jsuword)(p) == _a->base) { \ - p = (type) JS_ArenaRealloc(pool, p, size, incr); \ - } else { \ - p = (type) JS_ArenaGrow(pool, p, size, incr); \ - } \ - } else { \ - p = (type) JS_ArenaGrow(pool, p, size, incr); \ - } \ - JS_ArenaCountGrowth(pool, size, incr); \ - JS_END_MACRO - -#define JS_ARENA_MARK(pool) ((void *) (pool)->current->avail) -#define JS_UPTRDIFF(p,q) ((jsuword)(p) - (jsuword)(q)) - -/* - * Check if the mark is inside arena's allocated area. - */ -#define JS_ARENA_MARK_MATCH(a, mark) \ - (JS_UPTRDIFF(mark, (a)->base) <= JS_UPTRDIFF((a)->avail, (a)->base)) - -#ifdef DEBUG -#define JS_FREE_PATTERN 0xDA -#define JS_CLEAR_UNUSED(a) (JS_ASSERT((a)->avail <= (a)->limit), \ - memset((void*)(a)->avail, JS_FREE_PATTERN, \ - (a)->limit - (a)->avail)) -#define JS_CLEAR_ARENA(a) memset((void*)(a), JS_FREE_PATTERN, \ - (a)->limit - (jsuword)(a)) -#else -#define JS_CLEAR_UNUSED(a) /* nothing */ -#define JS_CLEAR_ARENA(a) /* nothing */ -#endif - -#define JS_ARENA_RELEASE(pool, mark) \ - JS_BEGIN_MACRO \ - char *_m = (char *)(mark); \ - JSArena *_a = (pool)->current; \ - if (_a != &(pool)->first && JS_ARENA_MARK_MATCH(_a, _m)) { \ - _a->avail = (jsuword)JS_ARENA_ALIGN(pool, _m); \ - JS_ASSERT(_a->avail <= _a->limit); \ - JS_CLEAR_UNUSED(_a); \ - JS_ArenaCountRetract(pool, _m); \ - } else { \ - JS_ArenaRelease(pool, _m); \ - } \ - JS_ArenaCountRelease(pool, _m); \ - JS_END_MACRO - -#ifdef JS_ARENAMETER -#define JS_COUNT_ARENA(pool,op) ((pool)->stats.narenas op) -#else -#define JS_COUNT_ARENA(pool,op) -#endif - -#define JS_ARENA_DESTROY(pool, a, pnext) \ - JS_BEGIN_MACRO \ - JS_COUNT_ARENA(pool,--); \ - if ((pool)->current == (a)) (pool)->current = &(pool)->first; \ - *(pnext) = (a)->next; \ - JS_CLEAR_ARENA(a); \ - js_free(a); \ - (a) = NULL; \ - JS_END_MACRO - -/* - * Initialize an arena pool with a minimum size per arena of size bytes. - */ -extern JS_PUBLIC_API(void) -JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size, - size_t align, size_t *quotap); - -/* - * Free the arenas in pool. The user may continue to allocate from pool - * after calling this function. There is no need to call JS_InitArenaPool() - * again unless JS_FinishArenaPool(pool) has been called. - */ -extern JS_PUBLIC_API(void) -JS_FreeArenaPool(JSArenaPool *pool); - -/* - * Free the arenas in pool and finish using it altogether. - */ -extern JS_PUBLIC_API(void) -JS_FinishArenaPool(JSArenaPool *pool); - -/* - * Deprecated do-nothing function. - */ -extern JS_PUBLIC_API(void) -JS_ArenaFinish(void); - -/* - * Deprecated do-nothing function. - */ -extern JS_PUBLIC_API(void) -JS_ArenaShutDown(void); - -/* - * Friend functions used by the JS_ARENA_*() macros. - */ -extern JS_PUBLIC_API(void *) -JS_ArenaAllocate(JSArenaPool *pool, size_t nb); - -extern JS_PUBLIC_API(void *) -JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr); - -extern JS_PUBLIC_API(void *) -JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr); - -extern JS_PUBLIC_API(void) -JS_ArenaRelease(JSArenaPool *pool, char *mark); - -#ifdef JS_ARENAMETER - -#include - -extern JS_PUBLIC_API(void) -JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb); - -extern JS_PUBLIC_API(void) -JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr); - -extern JS_PUBLIC_API(void) -JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr); - -extern JS_PUBLIC_API(void) -JS_ArenaCountRelease(JSArenaPool *pool, char *mark); - -extern JS_PUBLIC_API(void) -JS_ArenaCountRetract(JSArenaPool *pool, char *mark); - -extern JS_PUBLIC_API(void) -JS_DumpArenaStats(FILE *fp); - -#else /* !JS_ARENAMETER */ - -#define JS_ArenaCountAllocation(ap, nb) /* nothing */ -#define JS_ArenaCountInplaceGrowth(ap, size, incr) /* nothing */ -#define JS_ArenaCountGrowth(ap, size, incr) /* nothing */ -#define JS_ArenaCountRelease(ap, mark) /* nothing */ -#define JS_ArenaCountRetract(ap, mark) /* nothing */ - -#endif /* !JS_ARENAMETER */ + JS_END_EXTERN_C diff --git a/js/src/jsarenainlines.h b/js/src/jsarenainlines.h new file mode 100644 index 000000000000..72378452fb20 --- /dev/null +++ b/js/src/jsarenainlines.h @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * vim: set ts=8 sw=4 et tw=99 ft=cpp: + * + * ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.1 + * + * The contents of this file are subject to the Mozilla Public License Version + * 1.1 (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Mozilla SpiderMonkey JavaScript 1.9 code, released + * June 12, 2009. + * + * The Initial Developer of the Original Code is + * the Mozilla Corporation. + * + * Contributor(s): + * Chris Leary + * + * Alternatively, the contents of this file may be used under the terms of + * either of the GNU General Public License Version 2 or later (the "GPL"), + * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#ifndef jsarenainlines_h___ +#define jsarenainlines_h___ + +#include "jsarena.h" + +const jsuword JSArenaPool::POINTER_MASK = jsuword(JS_ALIGN_OF_POINTER - 1); + +jsuword +JSArenaPool::headerBaseMask() const +{ + return mask | POINTER_MASK; +} + +jsuword +JSArenaPool::headerSize() const +{ + return sizeof(JSArena **) + ((mask < POINTER_MASK) ? POINTER_MASK - mask : 0); +} + +void * +JSArenaPool::grow(jsuword p, size_t size, size_t incr) +{ + countGrowth(size, incr); + if (current->avail == p + align(size)) { + size_t nb = align(size + incr); + if (current->limit >= nb && p <= current->limit - nb) { + current->avail = p + nb; + countInplaceGrowth(size, incr); + } else if (p == current->base) { + p = jsuword(reallocInternal((void *) p, size, incr)); + } else { + p = jsuword(growInternal((void *) p, size, incr)); + } + } else { + p = jsuword(growInternal((void *) p, size, incr)); + } + return (void *) p; +} + +#endif diff --git a/js/src/jsatom.cpp b/js/src/jsatom.cpp index 072e55ed40b6..f5ef7893dc20 100644 --- a/js/src/jsatom.cpp +++ b/js/src/jsatom.cpp @@ -1004,7 +1004,7 @@ js_alloc_temp_space(void *priv, size_t size) } } - JS_ARENA_ALLOCATE(space, &parser->context->tempPool, size); + parser->context->tempPool.allocate(space, size); if (!space) js_ReportOutOfScriptQuota(parser->context); return space; @@ -1036,7 +1036,7 @@ js_alloc_temp_entry(void *priv, const void *key) return &ale->entry; } - JS_ARENA_ALLOCATE_TYPE(ale, JSAtomListElement, &parser->context->tempPool); + parser->context->tempPool.allocateType(ale); if (!ale) { js_ReportOutOfScriptQuota(parser->context); return NULL; diff --git a/js/src/jscntxt.cpp b/js/src/jscntxt.cpp index 1e178b162764..6401d5618109 100644 --- a/js/src/jscntxt.cpp +++ b/js/src/jscntxt.cpp @@ -823,8 +823,7 @@ js_NewContext(JSRuntime *rt, size_t stackChunkSize) JS_ASSERT(cx->version == JSVERSION_DEFAULT); VOUCH_DOES_NOT_REQUIRE_STACK(); - JS_InitArenaPool(&cx->tempPool, "temp", TEMP_POOL_CHUNK_SIZE, sizeof(jsdouble), - &cx->scriptStackQuota); + cx->tempPool.init("temp", TEMP_POOL_CHUNK_SIZE, sizeof(jsdouble), &cx->scriptStackQuota); js_InitRegExpStatics(cx); JS_ASSERT(cx->resolveFlags == 0); @@ -1178,7 +1177,7 @@ FreeContext(JSContext *cx) /* Free the stuff hanging off of cx. */ js_FreeRegExpStatics(cx); VOUCH_DOES_NOT_REQUIRE_STACK(); - JS_FinishArenaPool(&cx->tempPool); + cx->tempPool.finish(); if (cx->lastMessage) js_free(cx->lastMessage); @@ -2218,11 +2217,11 @@ JSContext::isConstructing() inline void FreeOldArenas(JSRuntime *rt, JSArenaPool *pool) { - JSArena *a = pool->current; - if (a == pool->first.next && a->avail == a->base + sizeof(int64)) { - int64 age = JS_Now() - *(int64 *) a->base; + const JSArena *a = pool->getCurrent(); + if (a == pool->getSecond() && a->getAvail() == a->getBase() + sizeof(int64)) { + int64 age = JS_Now() - *(int64 *) a->getBase(); if (age > int64(rt->gcEmptyArenaPoolLifespan) * 1000) - JS_FreeArenaPool(pool); + pool->free(); } } diff --git a/js/src/jsemit.cpp b/js/src/jsemit.cpp index 9776cedb49a7..e695a49abf9c 100644 --- a/js/src/jsemit.cpp +++ b/js/src/jsemit.cpp @@ -93,7 +93,7 @@ JSCodeGenerator::JSCodeGenerator(Parser *parser, uintN lineno) : JSTreeContext(parser), codePool(cpool), notePool(npool), - codeMark(JS_ARENA_MARK(cpool)), noteMark(JS_ARENA_MARK(npool)), + codeMark(cpool->getMark()), noteMark(npool->getMark()), stackDepth(0), maxStackDepth(0), ntrynotes(0), lastTryNode(NULL), spanDeps(NULL), jumpTargets(NULL), jtFreeList(NULL), @@ -118,8 +118,8 @@ bool JSCodeGenerator::init() JSCodeGenerator::~JSCodeGenerator() { - JS_ARENA_RELEASE(codePool, codeMark); - JS_ARENA_RELEASE(notePool, noteMark); + codePool->release(codeMark); + notePool->release(noteMark); /* NB: non-null only after OOM. */ if (spanDeps) @@ -147,11 +147,11 @@ EmitCheck(JSContext *cx, JSCodeGenerator *cg, JSOp op, ptrdiff_t delta) : JS_BIT(JS_CeilingLog2(length)); incr = BYTECODE_SIZE(length); if (!base) { - JS_ARENA_ALLOCATE_CAST(base, jsbytecode *, cg->codePool, incr); + cg->codePool->allocateCast(base, incr); } else { size = BYTECODE_SIZE(limit - base); incr -= size; - JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr); + cg->codePool->growCast(base, size, incr); } if (!base) { js_ReportOutOfScriptQuota(cx); @@ -464,8 +464,7 @@ AddJumpTarget(AddJumpTargetArgs *args, JSJumpTarget **jtp) if (jt) { cg->jtFreeList = jt->kids[JT_LEFT]; } else { - JS_ARENA_ALLOCATE_CAST(jt, JSJumpTarget *, &args->cx->tempPool, - sizeof *jt); + args->cx->tempPool.allocateCast(jt, sizeof *jt); if (!jt) { js_ReportOutOfScriptQuota(args->cx); return 0; @@ -923,7 +922,7 @@ OptimizeSpanDeps(JSContext *cx, JSCodeGenerator *cg) JS_ASSERT(length > BYTECODE_CHUNK); size = BYTECODE_SIZE(limit - base); incr = BYTECODE_SIZE(length) - size; - JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr); + cg->codePool->growCast(base, size, incr); if (!base) { js_ReportOutOfScriptQuota(cx); return JS_FALSE; @@ -4370,9 +4369,9 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) FUN_KIND(fun) == JSFUN_INTERPRETED); /* Generate code for the function's body. */ - void *cg2mark = JS_ARENA_MARK(cg->codePool); - void *cg2space; - JS_ARENA_ALLOCATE_TYPE(cg2space, JSCodeGenerator, cg->codePool); + void *cg2mark = cg->codePool->getMark(); + JSCodeGenerator *cg2space; + cg->codePool->allocateType(cg2space); if (!cg2space) { js_ReportOutOfScriptQuota(cx); return JS_FALSE; @@ -4411,7 +4410,7 @@ js_EmitTree(JSContext *cx, JSCodeGenerator *cg, JSParseNode *pn) pn = NULL; cg2->~JSCodeGenerator(); - JS_ARENA_RELEASE(cg->codePool, cg2mark); + cg->codePool->release(cg2mark); cg2 = NULL; if (!pn) return JS_FALSE; @@ -6962,10 +6961,10 @@ AllocSrcNote(JSContext *cx, JSCodeGenerator *cg) size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1); if (!CG_NOTES(cg)) { /* Allocate the first note array lazily; leave noteMask alone. */ - JS_ARENA_ALLOCATE_CAST(CG_NOTES(cg), jssrcnote *, pool, size); + pool->allocateCast(CG_NOTES(cg), size); } else { /* Grow by doubling note array size; update noteMask on success. */ - JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size); + pool->growCast(CG_NOTES(cg), size, size); if (CG_NOTES(cg)) CG_NOTE_MASK(cg) = (CG_NOTE_MASK(cg) << 1) | 1; } @@ -7066,7 +7065,7 @@ GrowSrcNotes(JSContext *cx, JSCodeGenerator *cg) /* Grow by doubling note array size; update noteMask on success. */ pool = cg->notePool; size = SRCNOTE_SIZE(CG_NOTE_MASK(cg) + 1); - JS_ARENA_GROW_CAST(CG_NOTES(cg), jssrcnote *, pool, size, size); + pool->growCast(CG_NOTES(cg), size, size); if (!CG_NOTES(cg)) { js_ReportOutOfScriptQuota(cx); return JS_FALSE; @@ -7304,7 +7303,7 @@ NewTryNote(JSContext *cx, JSCodeGenerator *cg, JSTryNoteKind kind, JS_ASSERT((size_t)(uint32)start == start); JS_ASSERT((size_t)(uint32)end == end); - JS_ARENA_ALLOCATE_TYPE(tryNode, JSTryNode, &cx->tempPool); + cx->tempPool.allocateType(tryNode); if (!tryNode) { js_ReportOutOfScriptQuota(cx); return JS_FALSE; diff --git a/js/src/jsfun.cpp b/js/src/jsfun.cpp index da50d36ec622..cb609747d89e 100644 --- a/js/src/jsfun.cpp +++ b/js/src/jsfun.cpp @@ -339,7 +339,7 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSObject *funobj, JSFunctio wfun->atom = fun->atom; if (fun->hasLocalNames()) { - void *mark = JS_ARENA_MARK(&cx->tempPool); + void *mark = cx->tempPool.getMark(); jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool); if (!names) return NULL; @@ -361,7 +361,7 @@ WrapEscapingClosure(JSContext *cx, JSStackFrame *fp, JSObject *funobj, JSFunctio break; } - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); if (!ok) return NULL; JS_ASSERT(wfun->nargs == fun->nargs); @@ -956,7 +956,7 @@ call_enumerate(JSContext *cx, JSObject *obj) if (n == 0) return JS_TRUE; - mark = JS_ARENA_MARK(&cx->tempPool); + mark = cx->tempPool.getMark(); MUST_FLOW_THROUGH("out"); names = js_GetLocalNameArray(cx, fun, &cx->tempPool); @@ -990,7 +990,7 @@ call_enumerate(JSContext *cx, JSObject *obj) ok = JS_TRUE; out: - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); return ok; } @@ -1602,16 +1602,13 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp) /* do arguments and local vars */ n = nargs + nvars + nupvars; if (n != 0) { - void *mark; + JSArenaPool &tempPool = xdr->cx->tempPool; + void *mark = tempPool.getMark(); uintN i; - uintN bitmapLength; - uint32 *bitmap; jsuword *names; JSAtom *name; JSLocalKind localKind; - bool ok = true; - mark = JS_ARENA_MARK(&xdr->cx->tempPool); /* * From this point the control must flow via the label release_mark. @@ -1624,16 +1621,16 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp) * name is declared as const, not as ordinary var. * */ MUST_FLOW_THROUGH("release_mark"); - bitmapLength = JS_HOWMANY(n, JS_BITS_PER_UINT32); - JS_ARENA_ALLOCATE_CAST(bitmap, uint32 *, &xdr->cx->tempPool, - bitmapLength * sizeof *bitmap); + uintN bitmapLength = JS_HOWMANY(n, JS_BITS_PER_UINT32); + uint32 *bitmap; + tempPool.allocateCast(bitmap, bitmapLength * sizeof *bitmap); if (!bitmap) { js_ReportOutOfScriptQuota(xdr->cx); ok = false; goto release_mark; } if (xdr->mode == JSXDR_ENCODE) { - names = js_GetLocalNameArray(xdr->cx, fun, &xdr->cx->tempPool); + names = js_GetLocalNameArray(xdr->cx, fun, &tempPool); if (!names) { ok = false; goto release_mark; @@ -1692,7 +1689,7 @@ js_XDRFunctionObject(JSXDRState *xdr, JSObject **objp) } release_mark: - JS_ARENA_RELEASE(&xdr->cx->tempPool, mark); + tempPool.release(mark); if (!ok) return false; @@ -2263,9 +2260,8 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) * for a terminating 0. Mark cx->tempPool for later release, to free * collected_args and its tokenstream in one swoop. */ - mark = JS_ARENA_MARK(&cx->tempPool); - JS_ARENA_ALLOCATE_CAST(cp, jschar *, &cx->tempPool, - (args_length+1) * sizeof(jschar)); + mark = cx->tempPool.getMark(); + cx->tempPool.allocateCast(cp, (args_length + 1) * sizeof(jschar)); if (!cp) { js_ReportOutOfScriptQuota(cx); return JS_FALSE; @@ -2287,7 +2283,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) /* Initialize a tokenstream that reads from the given string. */ if (!ts.init(collected_args, args_length, NULL, filename, lineno)) { - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); return JS_FALSE; } @@ -2347,7 +2343,7 @@ Function(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval) JSMSG_BAD_FORMAL); } ts.close(); - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); if (state != OK) return JS_FALSE; } @@ -2956,7 +2952,7 @@ js_GetLocalNameArray(JSContext *cx, JSFunction *fun, JSArenaPool *pool) * No need to check for overflow of the allocation size as we are making a * copy of already allocated data. As such it must fit size_t. */ - JS_ARENA_ALLOCATE_CAST(names, jsuword *, pool, (size_t) n * sizeof *names); + pool->allocateCast(names, (size_t) n * sizeof *names); if (!names) { js_ReportOutOfScriptQuota(cx); return NULL; diff --git a/js/src/jsgc.cpp b/js/src/jsgc.cpp index 144ac4f69e24..2199051eff35 100644 --- a/js/src/jsgc.cpp +++ b/js/src/jsgc.cpp @@ -1511,8 +1511,8 @@ CheckLeakedRoots(JSRuntime *rt); void js_FinishGC(JSRuntime *rt) { -#ifdef JS_ARENAMETER - JS_DumpArenaStats(stdout); +#ifdef DEBUG + JS_DumpArenaStats(); #endif #ifdef JS_GCMETER if (JS_WANT_GC_METER_PRINT) diff --git a/js/src/jsopcode.cpp b/js/src/jsopcode.cpp index ee045c9fe310..e6fea2222675 100644 --- a/js/src/jsopcode.cpp +++ b/js/src/jsopcode.cpp @@ -558,9 +558,9 @@ SprintEnsureBuffer(Sprinter *sp, size_t len) return JS_TRUE; base = sp->base; if (!base) { - JS_ARENA_ALLOCATE_CAST(base, char *, sp->pool, nb); + sp->pool->allocateCast(base, nb); } else { - JS_ARENA_GROW_CAST(base, char *, sp->pool, sp->size, nb); + sp->pool->growCast(base, sp->size, nb); } if (!base) { js_ReportOutOfScriptQuota(sp->context); @@ -736,11 +736,11 @@ js_QuoteString(JSContext *cx, JSString *str, jschar quote) char *bytes; JSString *escstr; - mark = JS_ARENA_MARK(&cx->tempPool); + mark = cx->tempPool.getMark(); INIT_SPRINTER(cx, &sprinter, &cx->tempPool, 0); bytes = QuoteString(&sprinter, str, quote); escstr = bytes ? JS_NewStringCopyZ(cx, bytes) : NULL; - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); return escstr; } @@ -770,7 +770,7 @@ js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun, if (!jp) return NULL; INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0); - JS_InitArenaPool(&jp->pool, name, 256, 1, &cx->scriptStackQuota); + jp->pool.init(name, 256, 1, &cx->scriptStackQuota); jp->indent = indent; jp->pretty = !!pretty; jp->grouped = !!grouped; @@ -793,7 +793,7 @@ js_NewPrinter(JSContext *cx, const char *name, JSFunction *fun, void js_DestroyPrinter(JSPrinter *jp) { - JS_FinishArenaPool(&jp->pool); + jp->pool.finish(); jp->sprinter.context->free(jp); } @@ -809,7 +809,7 @@ js_GetPrinterOutput(JSPrinter *jp) str = JS_NewStringCopyZ(cx, jp->sprinter.base); if (!str) return NULL; - JS_FreeArenaPool(&jp->pool); + jp->pool.free(); INIT_SPRINTER(cx, &jp->sprinter, &jp->pool, 0); return str; } @@ -1779,7 +1779,7 @@ InitSprintStack(JSContext *cx, SprintStack *ss, JSPrinter *jp, uintN depth) /* Allocate the parallel (to avoid padding) offset and opcode stacks. */ offsetsz = depth * sizeof(ptrdiff_t); opcodesz = depth * sizeof(jsbytecode); - JS_ARENA_ALLOCATE(space, &cx->tempPool, offsetsz + opcodesz); + cx->tempPool.allocate(space, offsetsz + opcodesz); if (!space) { js_ReportOutOfScriptQuota(cx); return JS_FALSE; @@ -4069,7 +4069,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) * Therefore after InitSprintStack succeeds, we must * release to mark before returning. */ - mark = JS_ARENA_MARK(&cx->tempPool); + mark = cx->tempPool.getMark(); if (!fun->hasLocalNames()) { innerLocalNames = NULL; } else { @@ -4079,7 +4079,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) } inner = fun->u.i.script; if (!InitSprintStack(cx, &ss2, jp, StackDepth(inner))) { - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); return NULL; } ss2.inGenExp = JS_TRUE; @@ -4103,7 +4103,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) jp->fun = outerfun; jp->localNames = outerLocalNames; if (!ok) { - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); return NULL; } @@ -4169,7 +4169,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop) * from cx's tempPool. */ rval = JS_strdup(cx, PopStr(&ss2, op)); - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); if (!rval) return NULL; todo = SprintCString(&ss->sprinter, rval); @@ -4846,7 +4846,7 @@ DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len, /* Initialize a sprinter for use with the offset stack. */ cx = jp->sprinter.context; - mark = JS_ARENA_MARK(&cx->tempPool); + mark = cx->tempPool.getMark(); ok = InitSprintStack(cx, &ss, jp, depth); if (!ok) goto out; @@ -4900,7 +4900,7 @@ DecompileCode(JSPrinter *jp, JSScript *script, jsbytecode *pc, uintN len, out: /* Free all temporary stuff allocated under this call. */ - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); return ok; } @@ -5017,7 +5017,7 @@ js_DecompileFunction(JSPrinter *jp) #if JS_HAS_DESTRUCTURING ss.printer = NULL; jp->script = script; - mark = JS_ARENA_MARK(&jp->sprinter.context->tempPool); + mark = jp->sprinter.context->tempPool.getMark(); #endif for (i = 0; i < fun->nargs; i++) { @@ -5068,7 +5068,7 @@ js_DecompileFunction(JSPrinter *jp) #if JS_HAS_DESTRUCTURING jp->script = NULL; - JS_ARENA_RELEASE(&jp->sprinter.context->tempPool, mark); + jp->sprinter.context->tempPool.release(mark); #endif if (!ok) return JS_FALSE; diff --git a/js/src/jsops.cpp b/js/src/jsops.cpp index fdf2346663ec..ab59b79cd3ad 100644 --- a/js/src/jsops.cpp +++ b/js/src/jsops.cpp @@ -2574,7 +2574,7 @@ BEGIN_CASE(JSOP_CALLUPVAR_DBG) /* Scope for tempPool mark and local names allocation in it. */ { - void *mark = JS_ARENA_MARK(&cx->tempPool); + void *mark = cx->tempPool.getMark(); jsuword *names = js_GetLocalNameArray(cx, fun, &cx->tempPool); if (!names) goto error; @@ -2584,7 +2584,7 @@ BEGIN_CASE(JSOP_CALLUPVAR_DBG) id = ATOM_TO_JSID(atom); ok = js_FindProperty(cx, id, &obj, &obj2, &prop); - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); if (!ok) goto error; } diff --git a/js/src/jsparse.cpp b/js/src/jsparse.cpp index e75984a61afe..45c8a4eb522d 100644 --- a/js/src/jsparse.cpp +++ b/js/src/jsparse.cpp @@ -165,9 +165,9 @@ Parser::init(const jschar *base, size_t length, { JSContext *cx = context; - tempPoolMark = JS_ARENA_MARK(&cx->tempPool); + tempPoolMark = cx->tempPool.getMark(); if (!tokenStream.init(base, length, fp, filename, lineno)) { - JS_ARENA_RELEASE(&cx->tempPool, tempPoolMark); + cx->tempPool.release(tempPoolMark); return false; } return true; @@ -180,7 +180,7 @@ Parser::~Parser() if (principals) JSPRINCIPALS_DROP(cx, principals); tokenStream.close(); - JS_ARENA_RELEASE(&cx->tempPool, tempPoolMark); + cx->tempPool.release(tempPoolMark); } void @@ -204,7 +204,7 @@ Parser::newObjectBox(JSObject *obj) * parsing and code generation for the whole script or top-level function. */ JSObjectBox *objbox; - JS_ARENA_ALLOCATE_TYPE(objbox, JSObjectBox, &context->tempPool); + context->tempPool.allocateType(objbox); if (!objbox) { js_ReportOutOfScriptQuota(context); return NULL; @@ -229,7 +229,7 @@ Parser::newFunctionBox(JSObject *obj, JSParseNode *fn, JSTreeContext *tc) * parsing and code generation for the whole script or top-level function. */ JSFunctionBox *funbox; - JS_ARENA_ALLOCATE_TYPE(funbox, JSFunctionBox, &context->tempPool); + context->tempPool.allocateType(funbox); if (!funbox) { js_ReportOutOfScriptQuota(context); return NULL; @@ -453,7 +453,7 @@ NewOrRecycledNode(JSTreeContext *tc) if (!pn) { JSContext *cx = tc->parser->context; - JS_ARENA_ALLOCATE_TYPE(pn, JSParseNode, &cx->tempPool); + cx->tempPool.allocateType(pn); if (!pn) js_ReportOutOfScriptQuota(cx); } else { @@ -739,10 +739,8 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *calle if (!compiler.init(chars, length, file, filename, lineno)) return NULL; - JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode), - &cx->scriptStackQuota); - JS_InitArenaPool(¬ePool, "note", 1024, sizeof(jssrcnote), - &cx->scriptStackQuota); + codePool.init("code", 1024, sizeof(jsbytecode), &cx->scriptStackQuota); + notePool.init("note", 1024, sizeof(jssrcnote), &cx->scriptStackQuota); Parser &parser = compiler.parser; TokenStream &tokenStream = parser.tokenStream; @@ -936,8 +934,8 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *calle printf("Code-gen growth: %d (%u bytecodes, %u srcnotes)\n", (char *)sbrk(0) - (char *)before, CG_OFFSET(&cg), cg.noteCount); #endif -#ifdef JS_ARENAMETER - JS_DumpArenaStats(stdout); +#ifdef DEBUG + JS_DumpArenaStats(); #endif script = js_NewScriptFromCG(cx, &cg); if (script && funbox && script != script->emptyScript()) @@ -954,8 +952,8 @@ Compiler::compileScript(JSContext *cx, JSObject *scopeChain, JSStackFrame *calle #endif out: - JS_FinishArenaPool(&codePool); - JS_FinishArenaPool(¬ePool); + codePool.finish(); + notePool.finish(); return script; too_many_slots: @@ -1513,10 +1511,8 @@ Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin /* No early return from after here until the js_FinishArenaPool calls. */ JSArenaPool codePool, notePool; - JS_InitArenaPool(&codePool, "code", 1024, sizeof(jsbytecode), - &cx->scriptStackQuota); - JS_InitArenaPool(¬ePool, "note", 1024, sizeof(jssrcnote), - &cx->scriptStackQuota); + codePool.init("code", 1024, sizeof(jsbytecode), &cx->scriptStackQuota); + notePool.init("note", 1024, sizeof(jssrcnote), &cx->scriptStackQuota); Parser &parser = compiler.parser; TokenStream &tokenStream = parser.tokenStream; @@ -1588,8 +1584,8 @@ Compiler::compileFunctionBody(JSContext *cx, JSFunction *fun, JSPrincipals *prin } /* Restore saved state and release code generation arenas. */ - JS_FinishArenaPool(&codePool); - JS_FinishArenaPool(¬ePool); + codePool.finish(); + notePool.finish(); return pn != NULL; } diff --git a/js/src/jspropertytree.cpp b/js/src/jspropertytree.cpp index 6d332fde368f..8a1e251cceba 100644 --- a/js/src/jspropertytree.cpp +++ b/js/src/jspropertytree.cpp @@ -132,8 +132,7 @@ PropertyTree::init() hash.ops = NULL; return false; } - JS_InitArenaPool(&arenaPool, "properties", - 256 * sizeof(JSScopeProperty), sizeof(void *), NULL); + arenaPool.init("properties", 256 * sizeof(JSScopeProperty), sizeof(void *), NULL); emptyShapeChanges = 0; return true; } @@ -145,7 +144,7 @@ PropertyTree::finish() JS_DHashTableFinish(&hash); hash.ops = NULL; } - JS_FinishArenaPool(&arenaPool); + arenaPool.finish(); } /* @@ -163,8 +162,7 @@ PropertyTree::newScopeProperty(JSContext *cx, bool gcLocked) if (sprop) { sprop->removeFree(); } else { - JS_ARENA_ALLOCATE_CAST(sprop, JSScopeProperty *, &arenaPool, - sizeof(JSScopeProperty)); + arenaPool.allocateCast(sprop, sizeof *sprop); if (!sprop) { JS_UNLOCK_GC(cx->runtime); JS_ReportOutOfMemory(cx); @@ -852,12 +850,13 @@ js::SweepScopeProperties(JSContext *cx) * nodes already GC'ed from the root ply, but we will avoid re-orphaning * their kids, because the kids member will already be null. */ - JSArena **ap = &JS_PROPERTY_TREE(cx).arenaPool.first.next; - while (JSArena *a = *ap) { - JSScopeProperty *limit = (JSScopeProperty *) a->avail; + JSArenaPool &arenaPool = JS_PROPERTY_TREE(cx).arenaPool; + JSArena * const first = arenaPool.getFirst(); + for (JSArena *a = arenaPool.getSecond(); a;) { + JSScopeProperty *limit = (JSScopeProperty *) a->getAvail(); uintN liveCount = 0; - for (JSScopeProperty *sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) { + for (JSScopeProperty *sprop = (JSScopeProperty *) a->getBase(); sprop < limit; sprop++) { /* If the id is null, sprop is already on the freelist. */ if (JSVAL_IS_NULL(sprop->id)) continue; @@ -912,15 +911,17 @@ js::SweepScopeProperties(JSContext *cx) /* If a contains no live properties, return it to the malloc heap. */ if (liveCount == 0) { - for (JSScopeProperty *sprop = (JSScopeProperty *) a->base; sprop < limit; sprop++) + for (JSScopeProperty *sprop = (JSScopeProperty *) a->getBase(); sprop < limit; sprop++) sprop->removeFree(); - JS_ARENA_DESTROY(&JS_PROPERTY_TREE(cx).arenaPool, a, ap); + a = arenaPool.destroy(a); + first->munge(a); } else { #ifdef DEBUG - livePropCapacity += limit - (JSScopeProperty *) a->base; + livePropCapacity += limit - (JSScopeProperty *) a->getBase(); totalLiveCount += liveCount; #endif - ap = &a->next; + first->munge(a->getNext()); + a = a->getNext(); } } diff --git a/js/src/jsregexp.cpp b/js/src/jsregexp.cpp index 6942060696ec..34d518381596 100644 --- a/js/src/jsregexp.cpp +++ b/js/src/jsregexp.cpp @@ -430,7 +430,7 @@ NewRENode(CompilerState *state, REOp op) RENode *ren; cx = state->context; - JS_ARENA_ALLOCATE_CAST(ren, RENode *, &cx->tempPool, sizeof *ren); + cx->tempPool.allocateCast(ren, sizeof *ren); if (!ren) { js_ReportOutOfScriptQuota(cx); return NULL; @@ -3330,13 +3330,13 @@ CompileRegExpToNative(JSContext* cx, JSRegExp* re, Fragment* fragment) RegExpNativeCompiler rc(cx, re, &state, fragment); JS_ASSERT(!fragment->code()); - mark = JS_ARENA_MARK(&cx->tempPool); + mark = cx->tempPool.getMark(); if (!CompileRegExpToAST(cx, NULL, re->source, re->flags, state)) { goto out; } rv = rc.compile(); out: - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); return rv; } @@ -3378,7 +3378,7 @@ js_NewRegExp(JSContext *cx, TokenStream *ts, uintN i; re = NULL; - mark = JS_ARENA_MARK(&cx->tempPool); + mark = cx->tempPool.getMark(); /* * Parsing the string as flat is now expressed internally using @@ -3438,7 +3438,7 @@ js_NewRegExp(JSContext *cx, TokenStream *ts, re->source = str; out: - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); return re; } @@ -3518,8 +3518,7 @@ PushBackTrackState(REGlobalData *gData, REOp op, ptrdiff_t offset = (char *)result - (char *)gData->backTrackStack; btincr = JS_ROUNDUP(btincr, btsize); - JS_ARENA_GROW_CAST(gData->backTrackStack, REBackTrackData *, - &gData->cx->regexpPool, btsize, btincr); + gData->cx->regexpPool.growCast(gData->backTrackStack, btsize, btincr); if (!gData->backTrackStack) { js_ReportOutOfScriptQuota(gData->cx); gData->ok = JS_FALSE; @@ -3977,8 +3976,7 @@ ReallocStateStack(REGlobalData *gData) size_t limit = gData->stateStackLimit; size_t sz = sizeof(REProgState) * limit; - JS_ARENA_GROW_CAST(gData->stateStack, REProgState *, - &gData->cx->regexpPool, sz, sz); + gData->cx->regexpPool.growCast(gData->stateStack, sz, sz); if (!gData->stateStack) { js_ReportOutOfScriptQuota(gData->cx); gData->ok = JS_FALSE; @@ -4838,9 +4836,8 @@ InitMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re, size_t length) uintN i; gData->backTrackStackSize = INITIAL_BACKTRACK; - JS_ARENA_ALLOCATE_CAST(gData->backTrackStack, REBackTrackData *, - &cx->regexpPool, - INITIAL_BACKTRACK); + JSArenaPool ®expPool = cx->regexpPool; + regexpPool.allocateCast(gData->backTrackStack, INITIAL_BACKTRACK); if (!gData->backTrackStack) goto bad; @@ -4855,9 +4852,8 @@ InitMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re, size_t length) } gData->stateStackLimit = INITIAL_STATESTACK; - JS_ARENA_ALLOCATE_CAST(gData->stateStack, REProgState *, - &cx->regexpPool, - sizeof(REProgState) * INITIAL_STATESTACK); + regexpPool.allocateCast(gData->stateStack, + sizeof(REProgState) * INITIAL_STATESTACK); if (!gData->stateStack) goto bad; @@ -4866,10 +4862,8 @@ InitMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re, size_t length) gData->regexp = re; gData->ok = JS_TRUE; - JS_ARENA_ALLOCATE_CAST(result, REMatchState *, - &cx->regexpPool, - offsetof(REMatchState, parens) - + re->parenCount * sizeof(RECapture)); + regexpPool.allocateCast(result, offsetof(REMatchState, parens) + + re->parenCount * sizeof(RECapture)); if (!result) goto bad; @@ -4922,17 +4916,16 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, gData.start = start; gData.skipped = 0; - if (!cx->regexpPool.first.next) { + if (!cx->regexpPool.getSecond()) { /* * The first arena in the regexpPool must have a timestamp at its base. */ - JS_ARENA_ALLOCATE_CAST(timestamp, int64 *, - &cx->regexpPool, sizeof *timestamp); + cx->regexpPool.allocateCast(timestamp, sizeof *timestamp); if (!timestamp) return JS_FALSE; *timestamp = JS_Now(); } - mark = JS_ARENA_MARK(&cx->regexpPool); + mark = cx->regexpPool.getMark(); x = InitMatch(cx, &gData, re, length); @@ -5076,7 +5069,7 @@ js_ExecuteRegExp(JSContext *cx, JSRegExp *re, JSString *str, size_t *indexp, res->rightContext.length = gData.cpend - ep; out: - JS_ARENA_RELEASE(&cx->regexpPool, mark); + cx->regexpPool.release(mark); return ok; } @@ -5216,9 +5209,8 @@ js_InitRegExpStatics(JSContext *cx) * + (sizeof(REProgState) * INITIAL_STATESTACK) * + (offsetof(REMatchState, parens) + avgParanSize * sizeof(RECapture)) */ - JS_InitArenaPool(&cx->regexpPool, "regexp", - 12 * 1024 - 40, /* FIXME: bug 421435 */ - sizeof(void *), &cx->scriptStackQuota); + cx->regexpPool.init("regexp", 12 * 1024 - 40, /* FIXME: bug 421435 */ + sizeof(void *), &cx->scriptStackQuota); JS_ClearRegExpStatics(cx); } @@ -5254,7 +5246,7 @@ void js_FreeRegExpStatics(JSContext *cx) { JS_ClearRegExpStatics(cx); - JS_FinishArenaPool(&cx->regexpPool); + cx->regexpPool.finish(); } #define DEFINE_STATIC_GETTER(name, code) \ diff --git a/js/src/jsscan.cpp b/js/src/jsscan.cpp index 229fd610ad0f..4257b3acf99f 100644 --- a/js/src/jsscan.cpp +++ b/js/src/jsscan.cpp @@ -194,7 +194,7 @@ TokenStream::init(const jschar *base, size_t length, FILE *fp, const char *fn, u size_t nb = fp ? 2 * LINE_LIMIT * sizeof(jschar) : LINE_LIMIT * sizeof(jschar); - JS_ARENA_ALLOCATE_CAST(buf, jschar *, &cx->tempPool, nb); + cx->tempPool.allocateCast(buf, nb); if (!buf) { js_ReportOutOfScriptQuota(cx); return false; diff --git a/js/src/jstracer.cpp b/js/src/jstracer.cpp index 40fce65a42fe..aa17f29d3c3b 100644 --- a/js/src/jstracer.cpp +++ b/js/src/jstracer.cpp @@ -3384,7 +3384,7 @@ TraceRecorder::import(LIns* base, ptrdiff_t offset, jsval* p, TraceType t, jsuword* localNames = NULL; const char* funName = NULL; if (*prefix == 'a' || *prefix == 'v') { - mark = JS_ARENA_MARK(&cx->tempPool); + mark = cx->tempPool.getMark(); if (fp->fun->hasLocalNames()) localNames = js_GetLocalNameArray(cx, fp->fun, &cx->tempPool); funName = fp->fun->atom ? js_AtomToPrintableString(cx, fp->fun->atom) : ""; @@ -3404,7 +3404,7 @@ TraceRecorder::import(LIns* base, ptrdiff_t offset, jsval* p, TraceType t, } if (mark) - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); addName(ins, name); static const char* typestr[] = { diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index 5f53efbdc7ed..f53662c5da3d 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -1762,7 +1762,7 @@ DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive) if (fun->u.i.nupvars) { fputs("\nupvars: {\n", stdout); - void *mark = JS_ARENA_MARK(&cx->tempPool); + void *mark = cx->tempPool.getMark(); jsuword *localNames = js_GetLocalNameArray(cx, fun, &cx->tempPool); if (!localNames) return false; @@ -1778,7 +1778,7 @@ DisassembleValue(JSContext *cx, jsval v, bool lines, bool recursive) js_AtomToPrintableString(cx, atom), cookie.level(), cookie.slot()); } - JS_ARENA_RELEASE(&cx->tempPool, mark); + cx->tempPool.release(mark); putchar('}'); } }