зеркало из https://github.com/mozilla/gecko-dev.git
Bug 559408: Arena macros to methods. (r=galish)
This commit is contained in:
Родитель
21a98fb81f
Коммит
a850080a2f
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 <jk@blackdown.de>, 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,55 +195,53 @@ 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);
|
||||
|
@ -264,102 +251,22 @@ JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr)
|
|||
memmove((void *) a->base, (char *) a + boff, size);
|
||||
|
||||
/* Store ap in the oversized-load arena header. */
|
||||
SET_HEADER(pool, a, ap);
|
||||
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);
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
JS_PUBLIC_API(void)
|
||||
JS_DumpArenaStats(FILE *fp)
|
||||
{
|
||||
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, "\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", stats->maxalloc);
|
||||
fprintf(fp, " maximum allocation size: %u\n", unsigned(maxalloc));
|
||||
}
|
||||
#endif /* DEBUG */
|
||||
|
||||
/* Backwards compatibility. */
|
||||
|
||||
JS_FRIEND_API(void *)
|
||||
JS_ARENA_MARK(const JSArenaPool *pool)
|
||||
{
|
||||
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 */
|
||||
|
|
438
js/src/jsarena.h
438
js/src/jsarena.h
|
@ -47,25 +47,67 @@
|
|||
* Also supports LIFO allocation (JS_ARENA_MARK/JS_ARENA_RELEASE).
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#ifdef DEBUG
|
||||
#include <stdio.h>
|
||||
#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
|
||||
};
|
||||
|
||||
#define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + (pool)->mask) & ~(pool)->mask)
|
||||
|
||||
#define JS_ARENA_ALLOCATE(p, pool, nb) \
|
||||
JS_ARENA_ALLOCATE_CAST(p, void *, pool, nb)
|
||||
|
||||
#define JS_ARENA_ALLOCATE_TYPE(p, type, pool) \
|
||||
JS_ARENA_ALLOCATE_COMMON(p, type *, pool, sizeof(type), 0)
|
||||
|
||||
#define JS_ARENA_ALLOCATE_CAST(p, type, pool, nb) \
|
||||
JS_ARENA_ALLOCATE_COMMON(p, type, pool, nb, _nb > _a->limit)
|
||||
|
||||
/*
|
||||
* 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 <jk@blackdown.de>, 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_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
|
||||
|
||||
public:
|
||||
/*
|
||||
* 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);
|
||||
void init(const char *name, size_t size, size_t align, size_t *quotap);
|
||||
|
||||
/*
|
||||
* Free the arenas in pool and finish using it altogether.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_FinishArenaPool(JSArenaPool *pool);
|
||||
void finish();
|
||||
|
||||
/*
|
||||
* Deprecated do-nothing function.
|
||||
* 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.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaFinish(void);
|
||||
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 <typename T>
|
||||
void allocateCast(T &p, size_t nb) {
|
||||
p = (T) allocate(nb, true);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void allocateType(T *&p) {
|
||||
p = (T *) allocate(sizeof(T), false);
|
||||
}
|
||||
|
||||
void allocate(void *&p, size_t nb) { allocateCast<void *>(p, nb); }
|
||||
|
||||
void *grow(jsuword p, size_t size, size_t incr);
|
||||
|
||||
template <typename T>
|
||||
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;
|
||||
|
||||
/*
|
||||
* Deprecated do-nothing function.
|
||||
* The mask to align |base|.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaShutDown(void);
|
||||
jsuword headerBaseMask() const;
|
||||
|
||||
jsuword headerSize() const;
|
||||
|
||||
/*
|
||||
* Friend functions used by the JS_ARENA_*() macros.
|
||||
* 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|.
|
||||
*/
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_ArenaAllocate(JSArenaPool *pool, size_t nb);
|
||||
JSArena ***ptrToHeader(void *p) const {
|
||||
JS_ASSERT((jsuword(p) & headerBaseMask()) == 0);
|
||||
return (JSArena ***)(p) - 1;
|
||||
}
|
||||
JSArena ***ptrToHeader(jsuword p) const { return ptrToHeader((void *) p); }
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr);
|
||||
/*
|
||||
* |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; }
|
||||
|
||||
extern JS_PUBLIC_API(void *)
|
||||
JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr);
|
||||
void *allocateInternal(size_t nb);
|
||||
void *reallocInternal(void *p, size_t size, size_t incr);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaRelease(JSArenaPool *pool, char *mark);
|
||||
void releaseInternal(void *mark) {
|
||||
for (JSArena *a = &first; a; a = a->next) {
|
||||
JS_ASSERT(a->base <= a->avail && a->avail <= a->limit);
|
||||
|
||||
#ifdef JS_ARENAMETER
|
||||
if (a->markMatch(mark)) {
|
||||
a->avail = align(mark);
|
||||
JS_ASSERT(a->avail <= a->limit);
|
||||
freeArenaList(a);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
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);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb);
|
||||
void *newp = allocate(size + incr, true);
|
||||
if (newp)
|
||||
memcpy(newp, p, size);
|
||||
return newp;
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr);
|
||||
/*
|
||||
* 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;
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr);
|
||||
#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
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaCountRelease(JSArenaPool *pool, char *mark);
|
||||
do {
|
||||
*ap = a->next;
|
||||
if (quotap)
|
||||
*quotap += a->limit - (jsuword) a;
|
||||
a->clear();
|
||||
decArenaCount();
|
||||
js_free(a);
|
||||
} while ((a = *ap) != NULL);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_ArenaCountRetract(JSArenaPool *pool, char *mark);
|
||||
current = head;
|
||||
}
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DumpArenaStats(FILE *fp);
|
||||
/* 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
|
||||
};
|
||||
|
||||
#else /* !JS_ARENAMETER */
|
||||
/* Backwards compatibility. */
|
||||
|
||||
#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 */
|
||||
JS_BEGIN_EXTERN_C
|
||||
|
||||
JS_FRIEND_API(void *)
|
||||
JS_ARENA_MARK(const JSArenaPool *pool);
|
||||
|
||||
JS_FRIEND_API(void)
|
||||
JS_ARENA_RELEASE(JSArenaPool *pool, void *mark);
|
||||
|
||||
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
|
||||
|
||||
#endif /* !JS_ARENAMETER */
|
||||
|
||||
JS_END_EXTERN_C
|
||||
|
||||
|
|
|
@ -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 <cdleary@mozilla.com>
|
||||
*
|
||||
* 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
|
|
@ -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<JSAtomListElement>(ale);
|
||||
if (!ale) {
|
||||
js_ReportOutOfScriptQuota(parser->context);
|
||||
return NULL;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<jsbytecode *>(base, incr);
|
||||
} else {
|
||||
size = BYTECODE_SIZE(limit - base);
|
||||
incr -= size;
|
||||
JS_ARENA_GROW_CAST(base, jsbytecode *, cg->codePool, size, incr);
|
||||
cg->codePool->growCast<jsbytecode *>(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<JSJumpTarget *>(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<jsbytecode *>(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<JSCodeGenerator>(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<jssrcnote *>(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<jssrcnote *>(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<jssrcnote *>(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<JSTryNode>(tryNode);
|
||||
if (!tryNode) {
|
||||
js_ReportOutOfScriptQuota(cx);
|
||||
return JS_FALSE;
|
||||
|
|
|
@ -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<uint32 *>(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<jschar *>(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<jsuword *>(names, (size_t) n * sizeof *names);
|
||||
if (!names) {
|
||||
js_ReportOutOfScriptQuota(cx);
|
||||
return NULL;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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<char *>(base, nb);
|
||||
} else {
|
||||
JS_ARENA_GROW_CAST(base, char *, sp->pool, sp->size, nb);
|
||||
sp->pool->growCast<char *>(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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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<JSObjectBox>(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<JSFunctionBox>(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<JSParseNode>(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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<JSScopeProperty *>(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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<RENode *>(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<REBackTrackData *>(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<REProgState *>(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<REBackTrackData *>(gData->backTrackStack, INITIAL_BACKTRACK);
|
||||
if (!gData->backTrackStack)
|
||||
goto bad;
|
||||
|
||||
|
@ -4855,8 +4852,7 @@ InitMatch(JSContext *cx, REGlobalData *gData, JSRegExp *re, size_t length)
|
|||
}
|
||||
|
||||
gData->stateStackLimit = INITIAL_STATESTACK;
|
||||
JS_ARENA_ALLOCATE_CAST(gData->stateStack, REProgState *,
|
||||
&cx->regexpPool,
|
||||
regexpPool.allocateCast<REProgState *>(gData->stateStack,
|
||||
sizeof(REProgState) * INITIAL_STATESTACK);
|
||||
if (!gData->stateStack)
|
||||
goto bad;
|
||||
|
@ -4866,9 +4862,7 @@ 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)
|
||||
regexpPool.allocateCast<REMatchState *>(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<int64 *>(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,8 +5209,7 @@ 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 */
|
||||
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) \
|
||||
|
|
|
@ -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<jschar *>(buf, nb);
|
||||
if (!buf) {
|
||||
js_ReportOutOfScriptQuota(cx);
|
||||
return false;
|
||||
|
|
|
@ -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) : "<anonymous>";
|
||||
|
@ -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[] = {
|
||||
|
|
|
@ -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('}');
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче