Annotation of sbbs/javascript/include/mozilla/js/jsarena.h, revision 1.1.1.1

1.1       root        1: /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
                      2:  *
                      3:  * The contents of this file are subject to the Netscape Public
                      4:  * License Version 1.1 (the "License"); you may not use this file
                      5:  * except in compliance with the License. You may obtain a copy of
                      6:  * the License at http://www.mozilla.org/NPL/
                      7:  *
                      8:  * Software distributed under the License is distributed on an "AS
                      9:  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
                     10:  * implied. See the License for the specific language governing
                     11:  * rights and limitations under the License.
                     12:  *
                     13:  * The Original Code is Mozilla Communicator client code, released
                     14:  * March 31, 1998.
                     15:  *
                     16:  * The Initial Developer of the Original Code is Netscape
                     17:  * Communications Corporation.  Portions created by Netscape are
                     18:  * Copyright (C) 1998 Netscape Communications Corporation. All
                     19:  * Rights Reserved.
                     20:  *
                     21:  * Contributor(s): 
                     22:  *
                     23:  * Alternatively, the contents of this file may be used under the
                     24:  * terms of the GNU Public License (the "GPL"), in which case the
                     25:  * provisions of the GPL are applicable instead of those above.
                     26:  * If you wish to allow use of your version of this file only
                     27:  * under the terms of the GPL and not to allow others to use your
                     28:  * version of this file under the NPL, indicate your decision by
                     29:  * deleting the provisions above and replace them with the notice
                     30:  * and other provisions required by the GPL.  If you do not delete
                     31:  * the provisions above, a recipient may use your version of this
                     32:  * file under either the NPL or the GPL.
                     33:  */
                     34: 
                     35: #ifndef jsarena_h___
                     36: #define jsarena_h___
                     37: /*
                     38:  * Lifetime-based fast allocation, inspired by much prior art, including
                     39:  * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
                     40:  * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
                     41:  *
                     42:  * Also supports LIFO allocation (JS_ARENA_MARK/JS_ARENA_RELEASE).
                     43:  */
                     44: #include <stdlib.h>
                     45: #include "jstypes.h"
                     46: #include "jscompat.h"
                     47: 
                     48: JS_BEGIN_EXTERN_C
                     49: 
                     50: typedef struct JSArena JSArena;
                     51: typedef struct JSArenaPool JSArenaPool;
                     52: 
                     53: struct JSArena {
                     54:     JSArena     *next;          /* next arena for this lifetime */
                     55:     jsuword     base;           /* aligned base address, follows this header */
                     56:     jsuword     limit;          /* one beyond last byte in arena */
                     57:     jsuword     avail;          /* points to next available byte */
                     58: };
                     59: 
                     60: #ifdef JS_ARENAMETER
                     61: typedef struct JSArenaStats JSArenaStats;
                     62: 
                     63: struct JSArenaStats {
                     64:     JSArenaStats *next;         /* next in arenaStats list */
                     65:     char        *name;          /* name for debugging */
                     66:     uint32      narenas;        /* number of arenas in pool */
                     67:     uint32      nallocs;        /* number of JS_ARENA_ALLOCATE() calls */
                     68:     uint32      nreclaims;      /* number of reclaims from freeArenas */
                     69:     uint32      nmallocs;       /* number of malloc() calls */
                     70:     uint32      ndeallocs;      /* number of lifetime deallocations */
                     71:     uint32      ngrows;         /* number of JS_ARENA_GROW() calls */
                     72:     uint32      ninplace;       /* number of in-place growths */
                     73:     uint32      nreallocs;      /* number of arena grow extending reallocs */
                     74:     uint32      nreleases;      /* number of JS_ARENA_RELEASE() calls */
                     75:     uint32      nfastrels;      /* number of "fast path" releases */
                     76:     size_t      nbytes;         /* total bytes allocated */
                     77:     size_t      maxalloc;       /* maximum allocation size in bytes */
                     78:     double      variance;       /* size variance accumulator */
                     79: };
                     80: #endif
                     81: 
                     82: struct JSArenaPool {
                     83:     JSArena     first;          /* first arena in pool list */
                     84:     JSArena     *current;       /* arena from which to allocate space */
                     85:     size_t      arenasize;      /* net exact size of a new arena */
                     86:     jsuword     mask;           /* alignment mask (power-of-2 - 1) */
                     87: #ifdef JS_ARENAMETER
                     88:     JSArenaStats stats;
                     89: #endif
                     90: };
                     91: 
                     92: /*
                     93:  * If the including .c file uses only one power-of-2 alignment, it may define
                     94:  * JS_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
                     95:  * per ALLOCATE and GROW.
                     96:  */
                     97: #ifdef JS_ARENA_CONST_ALIGN_MASK
                     98: #define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + JS_ARENA_CONST_ALIGN_MASK)   \
                     99:                                 & ~(jsuword)JS_ARENA_CONST_ALIGN_MASK)
                    100: 
                    101: #define JS_INIT_ARENA_POOL(pool, name, size) \
                    102:        JS_InitArenaPool(pool, name, size, JS_ARENA_CONST_ALIGN_MASK + 1)
                    103: #else
                    104: #define JS_ARENA_ALIGN(pool, n) (((jsuword)(n) + (pool)->mask) & ~(pool)->mask)
                    105: #endif
                    106: 
                    107: #define JS_ARENA_ALLOCATE(p, pool, nb)                                        \
                    108:     JS_ARENA_ALLOCATE_CAST(p, void *, pool, nb)
                    109: 
                    110: #define JS_ARENA_ALLOCATE_TYPE(p, type, pool)                                 \
                    111:     JS_ARENA_ALLOCATE_CAST(p, type *, pool, sizeof(type))
                    112: 
                    113: #define JS_ARENA_ALLOCATE_CAST(p, type, pool, nb)                             \
                    114:     JS_BEGIN_MACRO                                                            \
                    115:        JSArena *_a = (pool)->current;                                        \
                    116:        size_t _nb = JS_ARENA_ALIGN(pool, nb);                                \
                    117:        jsuword _p = _a->avail;                                               \
                    118:        jsuword _q = _p + _nb;                                                \
                    119:        if (_q > _a->limit)                                                   \
                    120:            _p = (jsuword)JS_ArenaAllocate(pool, _nb);                        \
                    121:        else                                                                  \
                    122:            _a->avail = _q;                                                   \
                    123:        p = (type) _p;                                                        \
                    124:        JS_ArenaCountAllocation(pool, nb);                                    \
                    125:     JS_END_MACRO
                    126: 
                    127: #define JS_ARENA_GROW(p, pool, size, incr)                                    \
                    128:     JS_ARENA_GROW_CAST(p, void *, pool, size, incr)
                    129: 
                    130: #define JS_ARENA_GROW_CAST(p, type, pool, size, incr)                         \
                    131:     JS_BEGIN_MACRO                                                            \
                    132:         JSArena *_a = (pool)->current;                                        \
                    133:         if (_a->avail == (jsuword)(p) + JS_ARENA_ALIGN(pool, size)) {         \
                    134:             size_t _nb = (size) + (incr);                                     \
                    135:             jsuword _q = (jsuword)(p) + JS_ARENA_ALIGN(pool, _nb);            \
                    136:             if (_q <= _a->limit) {                                            \
                    137:                 _a->avail = _q;                                               \
                    138:                 JS_ArenaCountInplaceGrowth(pool, size, incr);                 \
                    139:             } else if ((jsuword)(p) == _a->base) {                            \
                    140:                 p = (type) JS_ArenaRealloc(pool, p, size, incr);              \
                    141:             } else {                                                          \
                    142:                 p = (type) JS_ArenaGrow(pool, p, size, incr);                 \
                    143:             }                                                                 \
                    144:         } else {                                                              \
                    145:             p = (type) JS_ArenaGrow(pool, p, size, incr);                     \
                    146:         }                                                                     \
                    147:         JS_ArenaCountGrowth(pool, size, incr);                                \
                    148:     JS_END_MACRO
                    149: 
                    150: #define JS_ARENA_MARK(pool)     ((void *) (pool)->current->avail)
                    151: #define JS_UPTRDIFF(p,q)        ((jsuword)(p) - (jsuword)(q))
                    152: 
                    153: #ifdef DEBUG
                    154: #define JS_FREE_PATTERN         0xDA
                    155: #define JS_CLEAR_UNUSED(a)      (JS_ASSERT((a)->avail <= (a)->limit),         \
                    156:                                  memset((void*)(a)->avail, JS_FREE_PATTERN,   \
                    157:                                         (a)->limit - (a)->avail))
                    158: #define JS_CLEAR_ARENA(a)       memset((void*)(a), JS_FREE_PATTERN,           \
                    159:                                        (a)->limit - (jsuword)(a))
                    160: #else
                    161: #define JS_CLEAR_UNUSED(a)      /* nothing */
                    162: #define JS_CLEAR_ARENA(a)       /* nothing */
                    163: #endif
                    164: 
                    165: #define JS_ARENA_RELEASE(pool, mark)                                          \
                    166:     JS_BEGIN_MACRO                                                            \
                    167:         char *_m = (char *)(mark);                                            \
                    168:         JSArena *_a = (pool)->current;                                        \
                    169:         if (_a != &(pool)->first &&                                           \
                    170:             JS_UPTRDIFF(_m, _a->base) <= JS_UPTRDIFF(_a->avail, _a->base)) {  \
                    171:             _a->avail = (jsuword)JS_ARENA_ALIGN(pool, _m);                    \
                    172:             JS_ASSERT(_a->avail <= _a->limit);                                \
                    173:             JS_CLEAR_UNUSED(_a);                                              \
                    174:             JS_ArenaCountRetract(pool, _m);                                   \
                    175:         } else {                                                              \
                    176:             JS_ArenaRelease(pool, _m);                                        \
                    177:         }                                                                     \
                    178:         JS_ArenaCountRelease(pool, _m);                                       \
                    179:     JS_END_MACRO
                    180: 
                    181: #ifdef JS_ARENAMETER
                    182: #define JS_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
                    183: #else
                    184: #define JS_COUNT_ARENA(pool,op)
                    185: #endif
                    186: 
                    187: #define JS_ARENA_DESTROY(pool, a, pnext)                                      \
                    188:     JS_BEGIN_MACRO                                                            \
                    189:         JS_COUNT_ARENA(pool,--);                                              \
                    190:         if ((pool)->current == (a)) (pool)->current = &(pool)->first;         \
                    191:         *(pnext) = (a)->next;                                                 \
                    192:         JS_CLEAR_ARENA(a);                                                    \
                    193:         free(a);                                                              \
                    194:         (a) = NULL;                                                           \
                    195:     JS_END_MACRO
                    196: 
                    197: /*
                    198:  * Initialize an arena pool with the given name for debugging and metering,
                    199:  * with a minimum size per arena of size bytes.
                    200:  */
                    201: extern JS_PUBLIC_API(void)
                    202: JS_InitArenaPool(JSArenaPool *pool, const char *name, size_t size,
                    203:                  size_t align);
                    204: 
                    205: /*
                    206:  * Free the arenas in pool.  The user may continue to allocate from pool
                    207:  * after calling this function.  There is no need to call JS_InitArenaPool()
                    208:  * again unless JS_FinishArenaPool(pool) has been called.
                    209:  */
                    210: extern JS_PUBLIC_API(void)
                    211: JS_FreeArenaPool(JSArenaPool *pool);
                    212: 
                    213: /*
                    214:  * Free the arenas in pool and finish using it altogether.
                    215:  */
                    216: extern JS_PUBLIC_API(void)
                    217: JS_FinishArenaPool(JSArenaPool *pool);
                    218: 
                    219: /*
                    220:  * Finish using arenas, freeing all memory associated with them except for
                    221:  * any locks needed for thread safety.
                    222:  */
                    223: extern JS_PUBLIC_API(void)
                    224: JS_ArenaFinish(void);
                    225: 
                    226: /*
                    227:  * Free any locks or other memory needed for thread safety, just before
                    228:  * shutting down.  At that point, we must be called by a single thread.
                    229:  *
                    230:  * After shutting down, the next thread to call JS_InitArenaPool must not
                    231:  * race with any other thread.  Once a pool has been initialized, threads
                    232:  * may safely call jsarena.c functions on thread-local pools.  The upshot
                    233:  * is that pools are per-thread, but the underlying global freelist is
                    234:  * thread-safe, provided that both the first pool initialization and the
                    235:  * shut-down call are single-threaded.
                    236:  */
                    237: extern JS_PUBLIC_API(void)
                    238: JS_ArenaShutDown(void);
                    239: 
                    240: /*
                    241:  * Friend functions used by the JS_ARENA_*() macros.
                    242:  */
                    243: extern JS_PUBLIC_API(void *)
                    244: JS_ArenaAllocate(JSArenaPool *pool, size_t nb);
                    245: 
                    246: extern JS_PUBLIC_API(void *)
                    247: JS_ArenaRealloc(JSArenaPool *pool, void *p, size_t size, size_t incr);
                    248: 
                    249: extern JS_PUBLIC_API(void *)
                    250: JS_ArenaGrow(JSArenaPool *pool, void *p, size_t size, size_t incr);
                    251: 
                    252: extern JS_PUBLIC_API(void)
                    253: JS_ArenaRelease(JSArenaPool *pool, char *mark);
                    254: 
                    255: /*
                    256:  * Function to be used directly when an allocation has likely grown to consume
                    257:  * an entire JSArena, in which case the arena is returned to the malloc heap.
                    258:  */
                    259: extern JS_PUBLIC_API(void)
                    260: JS_ArenaFreeAllocation(JSArenaPool *pool, void *p, size_t size);
                    261: 
                    262: #ifdef JS_ARENAMETER
                    263: 
                    264: #include <stdio.h>
                    265: 
                    266: extern JS_PUBLIC_API(void)
                    267: JS_ArenaCountAllocation(JSArenaPool *pool, size_t nb);
                    268: 
                    269: extern JS_PUBLIC_API(void)
                    270: JS_ArenaCountInplaceGrowth(JSArenaPool *pool, size_t size, size_t incr);
                    271: 
                    272: extern JS_PUBLIC_API(void)
                    273: JS_ArenaCountGrowth(JSArenaPool *pool, size_t size, size_t incr);
                    274: 
                    275: extern JS_PUBLIC_API(void)
                    276: JS_ArenaCountRelease(JSArenaPool *pool, char *mark);
                    277: 
                    278: extern JS_PUBLIC_API(void)
                    279: JS_ArenaCountRetract(JSArenaPool *pool, char *mark);
                    280: 
                    281: extern JS_PUBLIC_API(void)
                    282: JS_DumpArenaStats(FILE *fp);
                    283: 
                    284: #else  /* !JS_ARENAMETER */
                    285: 
                    286: #define JS_ArenaCountAllocation(ap, nb)                 /* nothing */
                    287: #define JS_ArenaCountInplaceGrowth(ap, size, incr)      /* nothing */
                    288: #define JS_ArenaCountGrowth(ap, size, incr)             /* nothing */
                    289: #define JS_ArenaCountRelease(ap, mark)                  /* nothing */
                    290: #define JS_ArenaCountRetract(ap, mark)                  /* nothing */
                    291: 
                    292: #endif /* !JS_ARENAMETER */
                    293: 
                    294: JS_END_EXTERN_C
                    295: 
                    296: #endif /* jsarena_h___ */

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.