LCOV - code coverage report
Current view: directory - xpcom/typelib/xpt/src - xpt_arena.c (source / functions) Found Hit Coverage
Test: app.info Lines: 76 52 68.4 %
Date: 2012-06-02 Functions: 9 5 55.6 %

       1                 : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 : /* ***** BEGIN LICENSE BLOCK *****
       3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       4                 :  *
       5                 :  * The contents of this file are subject to the Mozilla Public License Version
       6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       7                 :  * the License. You may obtain a copy of the License at
       8                 :  * http://www.mozilla.org/MPL/
       9                 :  *
      10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      12                 :  * for the specific language governing rights and limitations under the
      13                 :  * License.
      14                 :  *
      15                 :  * The Original Code is mozilla.org code.
      16                 :  *
      17                 :  * The Initial Developer of the Original Code is
      18                 :  * Netscape Communications Corporation.
      19                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      20                 :  * the Initial Developer. All Rights Reserved.
      21                 :  *
      22                 :  * Contributor(s):
      23                 :  *
      24                 :  * Alternatively, the contents of this file may be used under the terms of
      25                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      26                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      27                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      28                 :  * of those above. If you wish to allow use of your version of this file only
      29                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      30                 :  * use your version of this file under the terms of the MPL, indicate your
      31                 :  * decision by deleting the provisions above and replace them with the notice
      32                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      33                 :  * the provisions above, a recipient may use your version of this file under
      34                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      35                 :  *
      36                 :  * ***** END LICENSE BLOCK ***** */
      37                 : 
      38                 : /* Quick arena hack for xpt. */
      39                 : 
      40                 : /* XXX This exists because we don't want to drag in NSPR. It *seemed*
      41                 : *  to make more sense to write a quick and dirty arena than to clone
      42                 : *  plarena (like js/src did). This is not optimal, but it works. 
      43                 : *  Half of the code here is instrumentation.
      44                 : */
      45                 : 
      46                 : #include "xpt_arena.h"
      47                 : #include <string.h>
      48                 : #include <stdio.h>
      49                 : #include <stdlib.h>
      50                 : 
      51                 : /*************************/
      52                 : /* logging stats support */
      53                 : 
      54                 : #if 0 && defined(DEBUG_jband)
      55                 : #define XPT_ARENA_LOGGING 1
      56                 : #endif
      57                 : 
      58                 : #ifdef XPT_ARENA_LOGGING
      59                 : 
      60                 : #define LOG_MALLOC(_a, _req, _used)                             \
      61                 :     do{                                                         \
      62                 :     XPT_ASSERT((_a));                                           \
      63                 :     ++(_a)->LOG_MallocCallCount;                                \
      64                 :     (_a)->LOG_MallocTotalBytesRequested += (_req);              \
      65                 :     (_a)->LOG_MallocTotalBytesUsed += (_used);                  \
      66                 :     } while(0)
      67                 : 
      68                 : #define LOG_REAL_MALLOC(_a, _size)                              \
      69                 :     do{                                                         \
      70                 :     XPT_ASSERT((_a));                                           \
      71                 :     ++(_a)->LOG_RealMallocCallCount;                            \
      72                 :     (_a)->LOG_RealMallocTotalBytesRequested += (_size);         \
      73                 :     } while(0)
      74                 : 
      75                 : #define LOG_FREE(_a)                                            \
      76                 :     do{                                                         \
      77                 :     XPT_ASSERT((_a));                                           \
      78                 :     ++(_a)->LOG_FreeCallCount;                                  \
      79                 :     } while(0)
      80                 : 
      81                 : #define LOG_DONE_LOADING(_a)                                    \
      82                 :     do{                                                         \
      83                 :     XPT_ASSERT((_a));                                           \
      84                 :     (_a)->LOG_LoadingFreeCallCount = (_a)->LOG_FreeCallCount;   \
      85                 :     } while(0)
      86                 : 
      87                 : #define PRINT_STATS(_a)       xpt_DebugPrintArenaStats((_a))
      88                 : static void xpt_DebugPrintArenaStats(XPTArena *arena);
      89                 : 
      90                 : #else /* !XPT_ARENA_LOGGING */
      91                 : 
      92                 : #define LOG_MALLOC(_a, _req, _used)   ((void)0)
      93                 : #define LOG_REAL_MALLOC(_a, _size)    ((void)0)
      94                 : #define LOG_FREE(_a)                  ((void)0)
      95                 : 
      96                 : #define LOG_DONE_LOADING(_a)          ((void)0)        
      97                 : #define PRINT_STATS(_a)               ((void)0)
      98                 : 
      99                 : #endif /* XPT_ARENA_LOGGING */
     100                 : 
     101                 : /****************************************************/
     102                 : 
     103                 : /* Block header for each block in the arena */
     104                 : typedef struct BLK_HDR BLK_HDR;
     105                 : struct BLK_HDR
     106                 : {
     107                 :     BLK_HDR *next;
     108                 :     size_t   size;
     109                 : };
     110                 : 
     111                 : #define XPT_MIN_BLOCK_SIZE 32
     112                 : 
     113                 : /* XXX this is lame. Should clone the code to do this bitwise */
     114                 : #define ALIGN_RND(s,a) ((a)==1?(s):((((s)+(a)-1)/(a))*(a)))
     115                 : 
     116                 : struct XPTArena
     117                 : {
     118                 :     BLK_HDR *first;
     119                 :     PRUint8 *next;
     120                 :     size_t   space;
     121                 :     size_t   alignment;
     122                 :     size_t   block_size;
     123                 :     char    *name;
     124                 : 
     125                 : #ifdef XPT_ARENA_LOGGING
     126                 :     PRUint32 LOG_MallocCallCount;
     127                 :     PRUint32 LOG_MallocTotalBytesRequested;
     128                 :     PRUint32 LOG_MallocTotalBytesUsed;
     129                 :     PRUint32 LOG_FreeCallCount;
     130                 :     PRUint32 LOG_LoadingFreeCallCount;
     131                 :     PRUint32 LOG_RealMallocCallCount;
     132                 :     PRUint32 LOG_RealMallocTotalBytesRequested;
     133                 : #endif /* XPT_ARENA_LOGGING */
     134                 : };
     135                 : 
     136                 : XPT_PUBLIC_API(XPTArena *)
     137          219916 : XPT_NewArena(PRUint32 block_size, size_t alignment, const char* name)
     138                 : {
     139          219916 :     XPTArena *arena = calloc(1, sizeof(XPTArena));
     140          219916 :     if (arena) {
     141          219916 :         XPT_ASSERT(alignment);
     142          219916 :         if (alignment > sizeof(double))
     143               0 :             alignment = sizeof(double);
     144          219916 :         arena->alignment = alignment;
     145                 : 
     146          219916 :         if (block_size < XPT_MIN_BLOCK_SIZE)
     147               0 :             block_size = XPT_MIN_BLOCK_SIZE;
     148          219916 :         arena->block_size = ALIGN_RND(block_size, alignment);
     149                 : 
     150                 :         /* must have room for at least one item! */
     151          219916 :         XPT_ASSERT(arena->block_size >= 
     152                 :                    ALIGN_RND(sizeof(BLK_HDR), alignment) +
     153                 :                    ALIGN_RND(1, alignment));
     154                 : 
     155          219916 :         if (name) {
     156          219916 :             arena->name = XPT_STRDUP(arena, name);           
     157                 : #ifdef XPT_ARENA_LOGGING
     158                 :             /* fudge the stats since we are using space in the arena */
     159                 :             arena->LOG_MallocCallCount = 0;
     160                 :             arena->LOG_MallocTotalBytesRequested = 0;
     161                 :             arena->LOG_MallocTotalBytesUsed = 0;
     162                 : #endif /* XPT_ARENA_LOGGING */
     163                 :         }
     164                 :     }
     165          219916 :     return arena;        
     166                 : }
     167                 : 
     168                 : XPT_PUBLIC_API(void)
     169          219906 : XPT_DestroyArena(XPTArena *arena)
     170                 : {
     171                 :     BLK_HDR* cur;
     172                 :     BLK_HDR* next;
     173                 :         
     174          219906 :     cur = arena->first;
     175         2285994 :     while (cur) {
     176         1846182 :         next = cur->next;
     177         1846182 :         free(cur);
     178         1846182 :         cur = next;
     179                 :     }
     180          219906 :     free(arena);
     181          219906 : }
     182                 : 
     183                 : XPT_PUBLIC_API(void)
     184               0 : XPT_DumpStats(XPTArena *arena)
     185                 : {
     186                 :     PRINT_STATS(arena);
     187               0 : }        
     188                 : 
     189                 : 
     190                 : /* 
     191                 : * Our alignment rule is that we always round up the size of each allocation 
     192                 : * so that the 'arena->next' pointer one will point to properly aligned space.
     193                 : */
     194                 : 
     195                 : XPT_PUBLIC_API(void *)
     196        65692906 : XPT_ArenaMalloc(XPTArena *arena, size_t size)
     197                 : {
     198                 :     PRUint8 *cur;
     199                 :     size_t bytes;
     200                 : 
     201        65692906 :     if (!size)
     202               0 :         return NULL;
     203                 : 
     204        65692906 :     if (!arena) {
     205               0 :         XPT_ASSERT(0);
     206               0 :         return NULL;
     207                 :     }
     208                 : 
     209        65692906 :     bytes = ALIGN_RND(size, arena->alignment);
     210                 :     
     211                 :     LOG_MALLOC(arena, size, bytes);
     212                 : 
     213        65692906 :     if (bytes > arena->space) {
     214                 :         BLK_HDR* new_block;
     215         1855882 :         size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), arena->alignment);
     216         1855882 :         size_t new_space = arena->block_size;
     217                 :          
     218         4665216 :         while (bytes > new_space - block_header_size)
     219          953452 :             new_space += arena->block_size;
     220                 : 
     221         1855882 :         new_block = (BLK_HDR*) calloc(new_space/arena->alignment, 
     222                 :                                       arena->alignment);
     223         1855882 :         if (!new_block) {
     224               0 :             arena->next = NULL;
     225               0 :             arena->space = 0;
     226               0 :             return NULL;
     227                 :         }
     228                 : 
     229                 :         LOG_REAL_MALLOC(arena, new_space);
     230                 : 
     231                 :         /* link block into the list of blocks for use when we destroy */
     232         1855882 :         new_block->next = arena->first;
     233         1855882 :         arena->first = new_block;
     234                 : 
     235                 :         /* save other block header info */
     236         1855882 :         new_block->size = new_space;
     237                 : 
     238                 :         /* set info for current block */
     239         1855882 :         arena->next  = ((PRUint8*)new_block) + block_header_size;
     240         1855882 :         arena->space = new_space - block_header_size;
     241                 : 
     242                 : #ifdef DEBUG
     243                 :         /* mark block for corruption check */
     244         1855882 :         memset(arena->next, 0xcd, arena->space);
     245                 : #endif
     246                 :     } 
     247                 :     
     248                 : #ifdef DEBUG
     249                 :     {
     250                 :         /* do corruption check */
     251                 :         size_t i;
     252      1979856074 :         for (i = 0; i < bytes; ++i) {
     253      1914163168 :             XPT_ASSERT(arena->next[i] == 0xcd);        
     254                 :         }
     255                 :         /* we guarantee that the block will be filled with zeros */
     256        65692906 :         memset(arena->next, 0, bytes);
     257                 :     }        
     258                 : #endif
     259                 : 
     260        65692906 :     cur = arena->next;
     261        65692906 :     arena->next  += bytes;
     262        65692906 :     arena->space -= bytes;
     263                 :     
     264        65692906 :     return cur;    
     265                 : }
     266                 : 
     267                 : 
     268                 : XPT_PUBLIC_API(char *)
     269          219916 : XPT_ArenaStrDup(XPTArena *arena, const char * s)
     270                 : {
     271                 :     size_t len;
     272                 :     char* cur;
     273                 : 
     274          219916 :     if (!s)
     275               0 :         return NULL;
     276                 : 
     277          219916 :     len = strlen(s)+1;
     278          219916 :     cur = XPT_ArenaMalloc(arena, len);
     279          219916 :     memcpy(cur, s, len);
     280          219916 :     return cur;
     281                 : }
     282                 : 
     283                 : XPT_PUBLIC_API(void)
     284               0 : XPT_NotifyDoneLoading(XPTArena *arena)
     285                 : {
     286                 : #ifdef XPT_ARENA_LOGGING
     287                 :     if (arena) {
     288                 :         LOG_DONE_LOADING(arena);        
     289                 :     }
     290                 : #endif
     291               0 : }
     292                 : 
     293                 : XPT_PUBLIC_API(void)
     294         5402703 : XPT_ArenaFree(XPTArena *arena, void *block)
     295                 : {
     296                 :     LOG_FREE(arena);
     297         5402703 : }
     298                 : 
     299                 : #ifdef XPT_ARENA_LOGGING
     300                 : static void xpt_DebugPrintArenaStats(XPTArena *arena)
     301                 : {
     302                 :     printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n");
     303                 :     printf("Start xpt arena stats for \"%s\"\n", 
     304                 :             arena->name ? arena->name : "unnamed arena");
     305                 :     printf("\n");
     306                 :     printf("%d times arena malloc called\n", (int) arena->LOG_MallocCallCount);       
     307                 :     printf("%d total bytes requested from arena malloc\n", (int) arena->LOG_MallocTotalBytesRequested);       
     308                 :     printf("%d average bytes requested per call to arena malloc\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0);
     309                 :     printf("%d average bytes used per call (accounts for alignment overhead)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0);
     310                 :     printf("%d average bytes used per call (accounts for all overhead and waste)\n", (int)arena->LOG_MallocCallCount ? (arena->LOG_RealMallocTotalBytesRequested/arena->LOG_MallocCallCount) : 0);
     311                 :     printf("\n");
     312                 :     printf("%d during loading times arena free called\n", (int) arena->LOG_LoadingFreeCallCount);       
     313                 :     printf("%d during loading approx total bytes not freed\n", (int) arena->LOG_LoadingFreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0));       
     314                 :     printf("\n");
     315                 :     printf("%d total times arena free called\n", (int) arena->LOG_FreeCallCount);       
     316                 :     printf("%d approx total bytes not freed until arena destruction\n", (int) arena->LOG_FreeCallCount * (int) (arena->LOG_MallocCallCount ? (arena->LOG_MallocTotalBytesUsed/arena->LOG_MallocCallCount) : 0 ));       
     317                 :     printf("\n");
     318                 :     printf("%d times arena called system malloc\n", (int) arena->LOG_RealMallocCallCount);       
     319                 :     printf("%d total bytes arena requested from system\n", (int) arena->LOG_RealMallocTotalBytesRequested);       
     320                 :     printf("%d byte block size specified at arena creation time\n", (int) arena->block_size);       
     321                 :     printf("%d byte block alignment specified at arena creation time\n", (int) arena->alignment);       
     322                 :     printf("\n");
     323                 :     printf("End xpt arena stats\n");
     324                 :     printf("()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()()\n");
     325                 : }        
     326                 : #endif
     327                 : 
     328                 : /***************************************************************************/
     329                 : 
     330                 : #ifdef DEBUG
     331                 : XPT_PUBLIC_API(void)
     332               0 : XPT_AssertFailed(const char *s, const char *file, PRUint32 lineno)
     333                 : {
     334               0 :     fprintf(stderr, "Assertion failed: %s, file %s, line %d\n",
     335                 :             s, file, lineno);
     336               0 :     abort();
     337                 : }        
     338                 : #endif
     339                 : 
     340                 : XPT_PUBLIC_API(size_t)
     341               0 : XPT_SizeOfArena(XPTArena *arena, xptMallocSizeOfFun mallocSizeOf)
     342                 : {
     343               0 :     size_t n = mallocSizeOf(arena);
     344                 : 
     345                 :     /*
     346                 :      * We don't measure arena->name separately because it's allocated out of
     347                 :      * the arena itself.
     348                 :      */
     349                 : 
     350                 :     BLK_HDR* cur;
     351                 :     BLK_HDR* next;
     352                 :         
     353               0 :     cur = arena->first;
     354               0 :     while (cur) {
     355               0 :         next = cur->next;
     356               0 :         n += mallocSizeOf(cur);
     357               0 :         cur = next;
     358                 :     }
     359                 : 
     360               0 :     return n;
     361                 : }

Generated by: LCOV version 1.7