2001-09-20 02:39:41 +04:00
|
|
|
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/* ----- BEGIN LICENSE BLOCK -----
|
|
|
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
1998-10-14 14:22:38 +04:00
|
|
|
*
|
2001-09-20 02:39:41 +04:00
|
|
|
* The contents of this file are subject to the Mozilla Public
|
1999-09-29 03:12:09 +04:00
|
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
|
|
* except in compliance with the License. You may obtain a copy of
|
2001-09-20 02:39:41 +04:00
|
|
|
* the License at http://www.mozilla.org/MPL/
|
1998-10-14 14:22:38 +04:00
|
|
|
*
|
1999-09-29 03:12:09 +04:00
|
|
|
* Software distributed under the License is distributed on an "AS
|
2001-09-20 02:39:41 +04:00
|
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
1999-09-29 03:12:09 +04:00
|
|
|
* implied. See the License for the specific language governing
|
|
|
|
* rights and limitations under the License.
|
1998-10-14 14:22:38 +04:00
|
|
|
*
|
2001-09-20 02:39:41 +04:00
|
|
|
* The Original Code is .
|
1999-09-29 03:12:09 +04:00
|
|
|
*
|
2001-09-20 02:39:41 +04:00
|
|
|
* The Initial Developer of the Original Code is Netscape Communications Corporation.
|
|
|
|
* Portions created by Netscape Communications Corporation are
|
1999-09-29 03:12:09 +04:00
|
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
|
|
* Rights Reserved.
|
|
|
|
*
|
2001-03-16 11:06:08 +03:00
|
|
|
* Contributor(s):
|
1999-09-29 03:12:09 +04:00
|
|
|
*
|
2001-09-20 02:39:41 +04:00
|
|
|
* 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 LGPL or the GPL. 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 ----- */
|
1998-10-14 14:22:38 +04:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Lifetime-based fast allocation, inspired by much prior art, including
|
|
|
|
* "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
|
|
|
|
* David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
|
|
|
|
*/
|
|
|
|
#include "jsstddef.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include "jstypes.h"
|
|
|
|
#include "jsbit.h"
|
|
|
|
#include "jsarena.h" /* Added by JSIFY */
|
|
|
|
#include "jsutil.h" /* Added by JSIFY */
|
2000-07-13 09:08:35 +04:00
|
|
|
#include "jslock.h"
|
|
|
|
|
|
|
|
static JSArena *arena_freelist;
|
1998-10-14 14:22:38 +04:00
|
|
|
|
|
|
|
#ifdef JS_THREADSAFE
|
2000-07-13 09:08:35 +04:00
|
|
|
static JSLock *arena_freelist_lock;
|
1998-10-14 14:22:38 +04:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef JS_ARENAMETER
|
|
|
|
static JSArenaStats *arena_stats_list;
|
|
|
|
|
|
|
|
#define COUNT(pool,what) (pool)->stats.what++
|
|
|
|
#else
|
|
|
|
#define COUNT(pool,what) /* nothing */
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define JS_ARENA_DEFAULT_ALIGN sizeof(double)
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_InitArenaPool(JSArenaPool *pool, const char *name, JSUint32 size, JSUint32 align)
|
|
|
|
{
|
2000-07-13 09:08:35 +04:00
|
|
|
#ifdef JS_THREADSAFE
|
|
|
|
/* Must come through here once in primordial thread to init safely! */
|
|
|
|
if (!arena_freelist_lock) {
|
|
|
|
arena_freelist_lock = JS_NEW_LOCK();
|
|
|
|
JS_ASSERT(arena_freelist_lock);
|
|
|
|
}
|
|
|
|
#endif
|
1998-10-14 14:22:38 +04:00
|
|
|
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 =
|
2001-01-27 11:00:45 +03:00
|
|
|
JS_ARENA_ALIGN(pool, &pool->first + 1);
|
1998-10-14 14:22:38 +04:00
|
|
|
pool->current = &pool->first;
|
|
|
|
pool->arenasize = size;
|
|
|
|
#ifdef JS_ARENAMETER
|
|
|
|
memset(&pool->stats, 0, sizeof pool->stats);
|
|
|
|
pool->stats.name = strdup(name);
|
|
|
|
pool->stats.next = arena_stats_list;
|
|
|
|
arena_stats_list = &pool->stats;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void *)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_ArenaAllocate(JSArenaPool *pool, JSUint32 nb)
|
|
|
|
{
|
|
|
|
JSArena **ap, *a, *b;
|
|
|
|
JSUint32 sz;
|
|
|
|
void *p;
|
|
|
|
|
|
|
|
JS_ASSERT((nb & pool->mask) == 0);
|
|
|
|
for (a = pool->current; a->avail + nb > a->limit; pool->current = a) {
|
2000-07-13 09:08:35 +04:00
|
|
|
if (!a->next) {
|
|
|
|
ap = &arena_freelist;
|
|
|
|
JS_ACQUIRE_LOCK(arena_freelist_lock);
|
|
|
|
while ((b = *ap) != NULL) { /* reclaim a free arena */
|
2000-07-14 09:35:08 +04:00
|
|
|
/*
|
|
|
|
* Insist on exact arenasize match if nb is not greater than
|
Fixes to make JS GC truly exact:
- All jsvals for which JSVAL_IS_GCTHING evaluates to true must contain tagged
pointers into the GC heap -- therefore jsapi.c's JS_DefineConstDoubles cannot
"cheat" by tagging addresses of static jsdoubles to avoid js_NewNumberValue.
- Finalization is now interleaved with the Sweep phase, to avoid allocating
memory for finalization records while sweeping. Instead, the JSRuntime holds a
preallocated JSGCThing vector (gcFinalVec) that the Sweep phase fills and
flushes via gc_finalize_phase, repeatedly.
This means that finalizers cannot allocate a new GC thing, an incompatible but
plausible change. js_AllocGCThing asserts and then checks whether it is called
while rt->gcLevel is non-zero, and fails the allocation attempt if so. But this
fixes bug 38942, where the old sweep-then-finalize with a sweep => malloc
dependency could lead to memory exhaustion.
- Instead of scanning whole stackPool arenas, which led to UMRs (bug 27924) and
sometimes to gross over-scanning that depended on the GC bounds-checking all
thing pointers against its heap, we scan exactly those stack slots in use:
- arguments reachable from fp->argv;
- variables reachable from fp->vars;
- operands now reachable from fp->spbase, bounded above by the lesser of
fp->sp or fp->spbase + fp->script->depth for an interpreted frame; if the
latter, fp->sp has advanced logically above the operand budget, in order to
call a native method, and all unused slots from fp->sp up to depth slots
above fp->spbase must be set to JSVAL_VOID;
- stack segments pushed when calling native methods, prefixed by JSStackHeader
structs and linked from cx->stackSegments through each header.
The stack segment headers help the GC avoid scanning unused portions of the
stack: the generating pc slots running depth slots below fp->spbase, and slots
at the end of an arena that aren't sufficient to satisfy a contiguous allocation
for more args, vars, or operands.
- Exact GC means the stack pointer must remain above live operands until the
interpreter is done with them, so jsinterp.c got heavily whacked. Instead of
POPs of various kinds followed by a PUSH for binary operators (e.g.), we use
FETCH and STORE macros that index by -1 and -2 from sp, and minimize adjustments
to sp. When sp is homed to fp->sp, this allows js_DecompileValueGenerator to
find the value reliably, and if possible its generating pc.
- Finally, the O(n**2) growth rate of gc_find_flags has been fixed, using the
scheme sketched in bug 49816 and documented in a new major comment in jsgc.c.
Briefly, by allocating flags and things from one arena, we can align things on
1024-byte "thing page" boundaries, and use JSGCPageInfo headers in each page to
find a given thing's flags in O(1) time.
/be
2000-09-14 10:14:45 +04:00
|
|
|
* arenasize. Otherwise take any arena big enough, but not by
|
|
|
|
* more than nb + arenasize.
|
2000-07-14 09:35:08 +04:00
|
|
|
*/
|
2000-07-15 23:12:49 +04:00
|
|
|
sz = (JSUint32)(b->limit - b->base);
|
2000-07-14 09:35:08 +04:00
|
|
|
if ((nb > pool->arenasize)
|
2000-07-15 23:12:49 +04:00
|
|
|
? sz >= nb && sz <= nb + pool->arenasize
|
|
|
|
: sz == pool->arenasize) {
|
2000-07-13 09:08:35 +04:00
|
|
|
*ap = b->next;
|
|
|
|
JS_RELEASE_LOCK(arena_freelist_lock);
|
|
|
|
b->next = NULL;
|
|
|
|
a = a->next = b;
|
|
|
|
COUNT(pool, nreclaims);
|
|
|
|
goto claim;
|
|
|
|
}
|
|
|
|
ap = &b->next;
|
|
|
|
}
|
|
|
|
JS_RELEASE_LOCK(arena_freelist_lock);
|
|
|
|
sz = JS_MAX(pool->arenasize, nb); /* allocate a new arena */
|
|
|
|
sz += sizeof *a + pool->mask; /* header and alignment slop */
|
|
|
|
b = (JSArena *) malloc(sz);
|
|
|
|
if (!b)
|
|
|
|
return 0;
|
|
|
|
a = a->next = b;
|
|
|
|
a->next = NULL;
|
|
|
|
a->limit = (jsuword)a + sz;
|
|
|
|
JS_COUNT_ARENA(pool,++);
|
|
|
|
COUNT(pool, nmallocs);
|
|
|
|
claim:
|
2001-01-27 11:00:45 +03:00
|
|
|
a->base = a->avail = JS_ARENA_ALIGN(pool, a + 1);
|
2000-07-13 09:08:35 +04:00
|
|
|
continue;
|
1998-10-14 14:22:38 +04:00
|
|
|
}
|
2000-07-13 09:08:35 +04:00
|
|
|
a = a->next; /* move to next arena */
|
1998-10-14 14:22:38 +04:00
|
|
|
}
|
|
|
|
p = (void *)a->avail;
|
|
|
|
a->avail += nb;
|
|
|
|
return p;
|
|
|
|
}
|
|
|
|
|
2001-01-27 11:00:45 +03:00
|
|
|
JS_PUBLIC_API(void *)
|
|
|
|
JS_ArenaRealloc(JSArenaPool *pool, void *p, JSUint32 size, JSUint32 incr)
|
|
|
|
{
|
|
|
|
JSArena **ap, *a;
|
2001-03-16 11:06:08 +03:00
|
|
|
jsuword boff, aoff, newsize;
|
2001-01-27 11:00:45 +03:00
|
|
|
|
|
|
|
ap = &pool->first.next;
|
|
|
|
while ((a = *ap) != pool->current)
|
|
|
|
ap = &a->next;
|
|
|
|
JS_ASSERT(a->base == (jsuword)p);
|
2001-03-16 11:06:08 +03:00
|
|
|
boff = JS_UPTRDIFF(a->base, a);
|
|
|
|
aoff = newsize = size + incr;
|
|
|
|
JS_ASSERT(newsize > pool->arenasize);
|
|
|
|
newsize += sizeof *a + pool->mask; /* header and alignment slop */
|
|
|
|
a = (JSArena *) realloc(a, newsize);
|
2001-01-27 11:00:45 +03:00
|
|
|
if (!a)
|
|
|
|
return NULL;
|
|
|
|
*ap = a;
|
|
|
|
pool->current = a;
|
|
|
|
#ifdef JS_ARENAMETER
|
|
|
|
pool->stats.nreallocs++;
|
|
|
|
#endif
|
|
|
|
a->base = JS_ARENA_ALIGN(pool, a + 1);
|
2001-03-16 11:06:08 +03:00
|
|
|
a->limit = (jsuword)a + newsize;
|
2001-01-27 11:00:45 +03:00
|
|
|
a->avail = JS_ARENA_ALIGN(pool, a->base + aoff);
|
2001-03-16 11:06:08 +03:00
|
|
|
|
|
|
|
/* Check whether realloc aligned differently, and copy if necessary. */
|
|
|
|
if (boff != JS_UPTRDIFF(a->base, a))
|
|
|
|
memmove((void *)a->base, (char *)a + boff, size);
|
2001-01-27 11:00:45 +03:00
|
|
|
return (void *)a->base;
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void *)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_ArenaGrow(JSArenaPool *pool, void *p, JSUint32 size, JSUint32 incr)
|
|
|
|
{
|
|
|
|
void *newp;
|
|
|
|
|
|
|
|
JS_ARENA_ALLOCATE(newp, pool, size + incr);
|
2000-04-21 13:25:43 +04:00
|
|
|
if (newp)
|
|
|
|
memcpy(newp, p, size);
|
1998-10-14 14:22:38 +04:00
|
|
|
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, JSBool reallyFree)
|
|
|
|
{
|
|
|
|
JSArena **ap, *a;
|
|
|
|
|
|
|
|
ap = &head->next;
|
|
|
|
a = *ap;
|
|
|
|
if (!a)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#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
|
|
|
|
|
|
|
|
if (reallyFree) {
|
|
|
|
do {
|
|
|
|
*ap = a->next;
|
|
|
|
JS_CLEAR_ARENA(a);
|
|
|
|
JS_COUNT_ARENA(pool,--);
|
|
|
|
free(a);
|
|
|
|
} while ((a = *ap) != NULL);
|
|
|
|
} else {
|
|
|
|
/* Insert the whole arena chain at the front of the freelist. */
|
|
|
|
do {
|
|
|
|
ap = &(*ap)->next;
|
|
|
|
} while (*ap);
|
2000-07-13 09:08:35 +04:00
|
|
|
JS_ACQUIRE_LOCK(arena_freelist_lock);
|
1998-10-14 14:22:38 +04:00
|
|
|
*ap = arena_freelist;
|
|
|
|
arena_freelist = a;
|
2000-07-13 09:08:35 +04:00
|
|
|
JS_RELEASE_LOCK(arena_freelist_lock);
|
1998-10-14 14:22:38 +04:00
|
|
|
head->next = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
pool->current = head;
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_ArenaRelease(JSArenaPool *pool, char *mark)
|
|
|
|
{
|
|
|
|
JSArena *a;
|
|
|
|
|
2000-07-13 09:08:35 +04:00
|
|
|
for (a = &pool->first; a; a = a->next) {
|
|
|
|
if (JS_UPTRDIFF(mark, a->base) <= JS_UPTRDIFF(a->avail, a->base)) {
|
2001-01-27 11:00:45 +03:00
|
|
|
a->avail = JS_ARENA_ALIGN(pool, mark);
|
1998-10-14 14:22:38 +04:00
|
|
|
FreeArenaList(pool, a, JS_TRUE);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_FreeArenaPool(JSArenaPool *pool)
|
|
|
|
{
|
|
|
|
FreeArenaList(pool, &pool->first, JS_FALSE);
|
|
|
|
COUNT(pool, ndeallocs);
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_FinishArenaPool(JSArenaPool *pool)
|
|
|
|
{
|
|
|
|
FreeArenaList(pool, &pool->first, JS_TRUE);
|
|
|
|
#ifdef JS_ARENAMETER
|
|
|
|
{
|
|
|
|
JSArenaStats *stats, **statsp;
|
|
|
|
|
|
|
|
if (pool->stats.name)
|
|
|
|
free(pool->stats.name);
|
|
|
|
for (statsp = &arena_stats_list; (stats = *statsp) != 0;
|
|
|
|
statsp = &stats->next) {
|
|
|
|
if (stats == &pool->stats) {
|
|
|
|
*statsp = stats->next;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_CompactArenaPool(JSArenaPool *pool)
|
|
|
|
{
|
|
|
|
#if 0 /* XP_MAC */
|
|
|
|
JSArena *a = pool->first.next;
|
|
|
|
|
|
|
|
while (a) {
|
|
|
|
reallocSmaller(a, a->avail - (jsuword)a);
|
|
|
|
a->limit = a->avail;
|
|
|
|
a = a->next;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_ArenaFinish()
|
|
|
|
{
|
|
|
|
JSArena *a, *next;
|
|
|
|
|
2000-07-13 09:08:35 +04:00
|
|
|
JS_ACQUIRE_LOCK(arena_freelist_lock);
|
|
|
|
a = arena_freelist;
|
|
|
|
arena_freelist = NULL;
|
|
|
|
JS_RELEASE_LOCK(arena_freelist_lock);
|
|
|
|
for (; a; a = next) {
|
1998-10-14 14:22:38 +04:00
|
|
|
next = a->next;
|
|
|
|
free(a);
|
|
|
|
}
|
2000-07-13 09:08:35 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
JS_PUBLIC_API(void)
|
|
|
|
JS_ArenaShutDown(void)
|
|
|
|
{
|
|
|
|
#ifdef JS_THREADSAFE
|
|
|
|
/* Must come through here once in the process's last thread! */
|
|
|
|
if (arena_freelist_lock) {
|
|
|
|
JS_DESTROY_LOCK(arena_freelist_lock);
|
|
|
|
arena_freelist_lock = NULL;
|
|
|
|
}
|
1998-10-14 14:22:38 +04:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef JS_ARENAMETER
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_ArenaCountAllocation(JSArenaPool *pool, JSUint32 nb)
|
|
|
|
{
|
|
|
|
pool->stats.nallocs++;
|
|
|
|
pool->stats.nbytes += nb;
|
|
|
|
if (nb > pool->stats.maxalloc)
|
|
|
|
pool->stats.maxalloc = nb;
|
|
|
|
pool->stats.variance += nb * nb;
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_ArenaCountInplaceGrowth(JSArenaPool *pool, JSUint32 size, JSUint32 incr)
|
|
|
|
{
|
|
|
|
pool->stats.ninplace++;
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_ArenaCountGrowth(JSArenaPool *pool, JSUint32 size, JSUint32 incr)
|
|
|
|
{
|
|
|
|
pool->stats.ngrows++;
|
|
|
|
pool->stats.nbytes += incr;
|
|
|
|
pool->stats.variance -= size * size;
|
|
|
|
size += incr;
|
|
|
|
if (size > pool->stats.maxalloc)
|
|
|
|
pool->stats.maxalloc = size;
|
|
|
|
pool->stats.variance += size * size;
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_ArenaCountRelease(JSArenaPool *pool, char *mark)
|
|
|
|
{
|
|
|
|
pool->stats.nreleases++;
|
|
|
|
}
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_ArenaCountRetract(JSArenaPool *pool, char *mark)
|
|
|
|
{
|
|
|
|
pool->stats.nfastrels++;
|
|
|
|
}
|
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
|
1999-11-23 04:02:28 +03:00
|
|
|
JS_PUBLIC_API(void)
|
1998-10-14 14:22:38 +04:00
|
|
|
JS_DumpArenaStats(FILE *fp)
|
|
|
|
{
|
|
|
|
JSArenaStats *stats;
|
2001-01-27 11:00:45 +03:00
|
|
|
uint32 nallocs, nbytes;
|
|
|
|
double mean, variance, sigma;
|
1998-10-14 14:22:38 +04:00
|
|
|
|
|
|
|
for (stats = arena_stats_list; stats; stats = stats->next) {
|
2001-01-27 11:00:45 +03:00
|
|
|
nallocs = stats->nallocs;
|
|
|
|
if (nallocs != 0) {
|
|
|
|
nbytes = stats->nbytes;
|
|
|
|
mean = (double)nbytes / nallocs;
|
|
|
|
variance = stats->variance * nallocs - nbytes * nbytes;
|
|
|
|
if (variance < 0 || nallocs == 1)
|
|
|
|
variance = 0;
|
|
|
|
else
|
|
|
|
variance /= nallocs * (nallocs - 1);
|
|
|
|
sigma = sqrt(variance);
|
1998-10-14 14:22:38 +04:00
|
|
|
} else {
|
2001-01-27 11:00:45 +03:00
|
|
|
mean = variance = sigma = 0;
|
1998-10-14 14:22:38 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
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 free arena reclaims: %u\n", stats->nreclaims);
|
|
|
|
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);
|
2001-01-27 11:00:45 +03:00
|
|
|
fprintf(fp, " number of realloc'ing growths: %u\n", stats->nreallocs);
|
1998-10-14 14:22:38 +04:00
|
|
|
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);
|
2001-01-27 11:00:45 +03:00
|
|
|
fprintf(fp, " standard deviation: %g\n", sigma);
|
1998-10-14 14:22:38 +04:00
|
|
|
fprintf(fp, " maximum allocation size: %u\n", stats->maxalloc);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* JS_ARENAMETER */
|