nsprpub/lib/ds/plarena.h

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 #ifndef plarena_h___
     7 #define plarena_h___
     8 /*
     9  * Lifetime-based fast allocation, inspired by much prior art, including
    10  * "Fast Allocation and Deallocation of Memory Based on Object Lifetimes"
    11  * David R. Hanson, Software -- Practice and Experience, Vol. 20(1).
    12  *
    13  * Also supports LIFO allocation (PL_ARENA_MARK/PL_ARENA_RELEASE).
    14  */
    15 #include "prtypes.h"
    16 #include "plarenas.h"
    18 PR_BEGIN_EXTERN_C
    20 typedef struct PLArena          PLArena;
    22 struct PLArena {
    23     PLArena     *next;          /* next arena for this lifetime */
    24     PRUword     base;           /* aligned base address, follows this header */
    25     PRUword     limit;          /* one beyond last byte in arena */
    26     PRUword     avail;          /* points to next available byte */
    27 };
    29 #ifdef PL_ARENAMETER
    30 typedef struct PLArenaStats PLArenaStats;
    32 struct PLArenaStats {
    33     PLArenaStats  *next;        /* next in arenaStats list */
    34     char          *name;        /* name for debugging */
    35     PRUint32      narenas;      /* number of arenas in pool */
    36     PRUint32      nallocs;      /* number of PL_ARENA_ALLOCATE() calls */
    37     PRUint32      nreclaims;    /* number of reclaims from freeArenas */
    38     PRUint32      nmallocs;     /* number of malloc() calls */
    39     PRUint32      ndeallocs;    /* number of lifetime deallocations */
    40     PRUint32      ngrows;       /* number of PL_ARENA_GROW() calls */
    41     PRUint32      ninplace;     /* number of in-place growths */
    42     PRUint32      nreleases;    /* number of PL_ARENA_RELEASE() calls */
    43     PRUint32      nfastrels;    /* number of "fast path" releases */
    44     PRUint32      nbytes;       /* total bytes allocated */
    45     PRUint32      maxalloc;     /* maximum allocation size in bytes */
    46     PRFloat64     variance;     /* size variance accumulator */
    47 };
    48 #endif
    50 struct PLArenaPool {
    51     PLArena     first;          /* first arena in pool list */
    52     PLArena     *current;       /* arena from which to allocate space */
    53     PRUint32    arenasize;      /* net exact size of a new arena */
    54     PRUword     mask;           /* alignment mask (power-of-2 - 1) */
    55 #ifdef PL_ARENAMETER
    56     PLArenaStats stats;
    57 #endif
    58 };
    60 /*
    61  * WARNING: The PL_MAKE_MEM_ macros are for internal use by NSPR. Do NOT use
    62  * them in your code.
    63  *
    64  * NOTE: Valgrind support to be added.
    65  *
    66  * The PL_MAKE_MEM_ macros are modeled after the MOZ_MAKE_MEM_ macros in
    67  * Mozilla's mfbt/MemoryChecking.h. Only AddressSanitizer is supported now.
    68  *
    69  * Provides a common interface to the ASan (AddressSanitizer) and Valgrind
    70  * functions used to mark memory in certain ways. In detail, the following
    71  * three macros are provided:
    72  *
    73  *   PL_MAKE_MEM_NOACCESS  - Mark memory as unsafe to access (e.g. freed)
    74  *   PL_MAKE_MEM_UNDEFINED - Mark memory as accessible, with content undefined
    75  *   PL_MAKE_MEM_DEFINED - Mark memory as accessible, with content defined
    76  *
    77  * With Valgrind in use, these directly map to the three respective Valgrind
    78  * macros. With ASan in use, the NOACCESS macro maps to poisoning the memory,
    79  * while the UNDEFINED/DEFINED macros unpoison memory.
    80  *
    81  * With no memory checker available, all macros expand to the empty statement.
    82  */
    84 /* WARNING: PL_SANITIZE_ADDRESS is for internal use by this header. Do NOT
    85  * define or test this macro in your code.
    86  */
    87 #if defined(__has_feature)
    88 #if __has_feature(address_sanitizer)
    89 #define PL_SANITIZE_ADDRESS 1
    90 #endif
    91 #elif defined(__SANITIZE_ADDRESS__)
    92 #define PL_SANITIZE_ADDRESS 1
    93 #endif
    95 #if defined(PL_SANITIZE_ADDRESS)
    97 /* These definitions are usually provided through the
    98  * sanitizer/asan_interface.h header installed by ASan.
    99  * See https://code.google.com/p/address-sanitizer/wiki/ManualPoisoning
   100  */
   102 void __asan_poison_memory_region(void const volatile *addr, size_t size);
   103 void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
   105 #define PL_MAKE_MEM_NOACCESS(addr, size) \
   106     __asan_poison_memory_region((addr), (size))
   108 #define PL_MAKE_MEM_UNDEFINED(addr, size) \
   109     __asan_unpoison_memory_region((addr), (size))
   111 #define PL_MAKE_MEM_DEFINED(addr, size) \
   112     __asan_unpoison_memory_region((addr), (size))
   114 #else
   116 #define PL_MAKE_MEM_NOACCESS(addr, size)
   117 #define PL_MAKE_MEM_UNDEFINED(addr, size)
   118 #define PL_MAKE_MEM_DEFINED(addr, size)
   120 #endif
   122 /*
   123  * If the including .c file uses only one power-of-2 alignment, it may define
   124  * PL_ARENA_CONST_ALIGN_MASK to the alignment mask and save a few instructions
   125  * per ALLOCATE and GROW.
   126  */
   127 #ifdef PL_ARENA_CONST_ALIGN_MASK
   128 #define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + PL_ARENA_CONST_ALIGN_MASK) \
   129                                 & ~PL_ARENA_CONST_ALIGN_MASK)
   131 #define PL_INIT_ARENA_POOL(pool, name, size) \
   132         PL_InitArenaPool(pool, name, size, PL_ARENA_CONST_ALIGN_MASK + 1)
   133 #else
   134 #define PL_ARENA_ALIGN(pool, n) (((PRUword)(n) + (pool)->mask) & ~(pool)->mask)
   135 #endif
   137 #define PL_ARENA_ALLOCATE(p, pool, nb) \
   138     PR_BEGIN_MACRO \
   139         PLArena *_a = (pool)->current; \
   140         PRUint32 _nb = PL_ARENA_ALIGN(pool, nb); \
   141         PRUword _p = _a->avail; \
   142         PRUword _q = _p + _nb; \
   143         if (_q > _a->limit) { \
   144             _p = (PRUword)PL_ArenaAllocate(pool, _nb); \
   145         } else { \
   146             _a->avail = _q; \
   147         } \
   148         p = (void *)_p; \
   149         PL_MAKE_MEM_UNDEFINED(p, nb); \
   150         PL_ArenaCountAllocation(pool, nb); \
   151     PR_END_MACRO
   153 #define PL_ARENA_GROW(p, pool, size, incr) \
   154     PR_BEGIN_MACRO \
   155         PLArena *_a = (pool)->current; \
   156         PRUint32 _incr = PL_ARENA_ALIGN(pool, incr); \
   157         PRUword _p = _a->avail; \
   158         PRUword _q = _p + _incr; \
   159         if (_p == (PRUword)(p) + PL_ARENA_ALIGN(pool, size) && \
   160             _q <= _a->limit) { \
   161             PL_MAKE_MEM_UNDEFINED((unsigned char *)(p) + size, incr); \
   162             _a->avail = _q; \
   163             PL_ArenaCountInplaceGrowth(pool, size, incr); \
   164         } else { \
   165             p = PL_ArenaGrow(pool, p, size, incr); \
   166         } \
   167         PL_ArenaCountGrowth(pool, size, incr); \
   168     PR_END_MACRO
   170 #define PL_ARENA_MARK(pool) ((void *) (pool)->current->avail)
   171 #define PR_UPTRDIFF(p,q) ((PRUword)(p) - (PRUword)(q))
   173 #define PL_CLEAR_UNUSED_PATTERN(a, pattern) \
   174     PR_BEGIN_MACRO \
   175         PR_ASSERT((a)->avail <= (a)->limit); \
   176         PL_MAKE_MEM_UNDEFINED((void*)(a)->avail, (a)->limit - (a)->avail); \
   177         memset((void*)(a)->avail, (pattern), (a)->limit - (a)->avail); \
   178     PR_END_MACRO
   179 #ifdef DEBUG
   180 #define PL_FREE_PATTERN 0xDA
   181 #define PL_CLEAR_UNUSED(a) PL_CLEAR_UNUSED_PATTERN((a), PL_FREE_PATTERN)
   182 #define PL_CLEAR_ARENA(a) \
   183     PR_BEGIN_MACRO \
   184         PL_MAKE_MEM_UNDEFINED((void*)(a), (a)->limit - (PRUword)(a)); \
   185         memset((void*)(a), PL_FREE_PATTERN, (a)->limit - (PRUword)(a)); \
   186     PR_END_MACRO
   187 #else
   188 #define PL_CLEAR_UNUSED(a)
   189 #define PL_CLEAR_ARENA(a)
   190 #endif
   192 #define PL_ARENA_RELEASE(pool, mark) \
   193     PR_BEGIN_MACRO \
   194         char *_m = (char *)(mark); \
   195         PLArena *_a = (pool)->current; \
   196         if (PR_UPTRDIFF(_m, _a->base) <= PR_UPTRDIFF(_a->avail, _a->base)) { \
   197             _a->avail = (PRUword)PL_ARENA_ALIGN(pool, _m); \
   198             PL_CLEAR_UNUSED(_a); \
   199             PL_MAKE_MEM_NOACCESS((void*)_a->avail, _a->limit - _a->avail); \
   200             PL_ArenaCountRetract(pool, _m); \
   201         } else { \
   202             PL_ArenaRelease(pool, _m); \
   203         } \
   204         PL_ArenaCountRelease(pool, _m); \
   205     PR_END_MACRO
   207 #ifdef PL_ARENAMETER
   208 #define PL_COUNT_ARENA(pool,op) ((pool)->stats.narenas op)
   209 #else
   210 #define PL_COUNT_ARENA(pool,op)
   211 #endif
   213 #define PL_ARENA_DESTROY(pool, a, pnext) \
   214     PR_BEGIN_MACRO \
   215         PL_COUNT_ARENA(pool,--); \
   216         if ((pool)->current == (a)) (pool)->current = &(pool)->first; \
   217         *(pnext) = (a)->next; \
   218         PL_CLEAR_ARENA(a); \
   219         free(a); \
   220         (a) = 0; \
   221     PR_END_MACRO
   223 #ifdef PL_ARENAMETER
   225 #include <stdio.h>
   227 PR_EXTERN(void) PL_ArenaCountAllocation(PLArenaPool *pool, PRUint32 nb);
   229 PR_EXTERN(void) PL_ArenaCountInplaceGrowth(
   230     PLArenaPool *pool, PRUint32 size, PRUint32 incr);
   232 PR_EXTERN(void) PL_ArenaCountGrowth(
   233     PLArenaPool *pool, PRUint32 size, PRUint32 incr);
   235 PR_EXTERN(void) PL_ArenaCountRelease(PLArenaPool *pool, char *mark);
   237 PR_EXTERN(void) PL_ArenaCountRetract(PLArenaPool *pool, char *mark);
   239 PR_EXTERN(void) PL_DumpArenaStats(FILE *fp);
   241 #else  /* !PL_ARENAMETER */
   243 #define PL_ArenaCountAllocation(ap, nb)                 /* nothing */
   244 #define PL_ArenaCountInplaceGrowth(ap, size, incr)      /* nothing */
   245 #define PL_ArenaCountGrowth(ap, size, incr)             /* nothing */
   246 #define PL_ArenaCountRelease(ap, mark)                  /* nothing */
   247 #define PL_ArenaCountRetract(ap, mark)                  /* nothing */
   249 #endif /* !PL_ARENAMETER */
   251 PR_END_EXTERN_C
   253 #endif /* plarena_h___ */

mercurial