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

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