LCOV - code coverage report
Current view: top level - xpcom/typelib/xpt - xpt_arena.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 35 74 47.3 %
Date: 2017-07-14 16:53:18 Functions: 2 7 28.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       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/. */
       5             : 
       6             : /* Quick arena hack for xpt. */
       7             : 
       8             : /* XXX This exists because we don't want to drag in NSPR. It *seemed*
       9             : *  to make more sense to write a quick and dirty arena than to clone
      10             : *  plarena (like js/src did). This is not optimal, but it works.
      11             : */
      12             : 
      13             : #include "xpt_arena.h"
      14             : #include "mozilla/MemoryReporting.h"
      15             : #include <string.h>
      16             : #include <stdio.h>
      17             : #include <stdlib.h>
      18             : 
      19             : /****************************************************/
      20             : 
      21             : /* Block header for each block in the arena */
      22             : struct BLK_HDR
      23             : {
      24             :     BLK_HDR *next;
      25             : };
      26             : 
      27             : #define XPT_MIN_BLOCK_SIZE 32
      28             : 
      29             : /* XXX this is lame. Should clone the code to do this bitwise */
      30             : #define ALIGN_RND(s,a) ((a)==1?(s):((((s)+(a)-1)/(a))*(a)))
      31             : 
      32             : struct XPTSubArena
      33             : {
      34             :     BLK_HDR *first;
      35             :     uint8_t *next;
      36             :     size_t   space;
      37             :     size_t   block_size;
      38             : };
      39             : 
      40             : struct XPTArena
      41             : {
      42             :     // We have one sub-arena with 8-byte alignment for most allocations, and
      43             :     // one with 1-byte alignment for C string allocations. The latter sub-arena
      44             :     // avoids significant amounts of unnecessary padding between C strings.
      45             :     XPTSubArena subarena8;
      46             :     XPTSubArena subarena1;
      47             : };
      48             : 
      49             : XPT_PUBLIC_API(XPTArena *)
      50           3 : XPT_NewArena(size_t block_size8, size_t block_size1)
      51             : {
      52           3 :     XPTArena *arena = static_cast<XPTArena*>(calloc(1, sizeof(XPTArena)));
      53           3 :     if (arena) {
      54           3 :         if (block_size8 < XPT_MIN_BLOCK_SIZE)
      55           0 :             block_size8 = XPT_MIN_BLOCK_SIZE;
      56           3 :         arena->subarena8.block_size = ALIGN_RND(block_size8, 8);
      57             : 
      58           3 :         if (block_size1 < XPT_MIN_BLOCK_SIZE)
      59           0 :             block_size1 = XPT_MIN_BLOCK_SIZE;
      60           3 :         arena->subarena1.block_size = block_size1;
      61             :     }
      62           3 :     return arena;
      63             : }
      64             : 
      65             : static void
      66           0 : DestroySubArena(XPTSubArena *subarena)
      67             : {
      68           0 :     BLK_HDR* cur = subarena->first;
      69           0 :     while (cur) {
      70           0 :         BLK_HDR* next = cur->next;
      71           0 :         free(cur);
      72           0 :         cur = next;
      73             :     }
      74           0 : }
      75             : 
      76             : XPT_PUBLIC_API(void)
      77           0 : XPT_DestroyArena(XPTArena *arena)
      78             : {
      79           0 :     DestroySubArena(&arena->subarena8);
      80           0 :     DestroySubArena(&arena->subarena1);
      81           0 :     free(arena);
      82           0 : }
      83             : 
      84             : /*
      85             : * Our alignment rule is that we always round up the size of each allocation
      86             : * so that the 'arena->next' pointer one will point to properly aligned space.
      87             : */
      88             : 
      89             : XPT_PUBLIC_API(void *)
      90       80598 : XPT_ArenaCalloc(XPTArena *arena, size_t size, size_t alignment)
      91             : {
      92       80598 :     if (!size)
      93           0 :         return NULL;
      94             : 
      95       80598 :     if (!arena) {
      96           0 :         XPT_ASSERT(0);
      97           0 :         return NULL;
      98             :     }
      99             : 
     100             :     XPTSubArena *subarena;
     101       80598 :     if (alignment == 8) {
     102       40887 :         subarena = &arena->subarena8;
     103       39711 :     } else if (alignment == 1) {
     104       39711 :         subarena = &arena->subarena1;
     105             :     } else {
     106           0 :         XPT_ASSERT(0);
     107           0 :         return NULL;
     108             :     }
     109             : 
     110       80598 :     size_t bytes = ALIGN_RND(size, alignment);
     111             : 
     112       80598 :     if (bytes > subarena->space) {
     113             :         BLK_HDR* new_block;
     114         195 :         size_t block_header_size = ALIGN_RND(sizeof(BLK_HDR), alignment);
     115         195 :         size_t new_space = subarena->block_size;
     116             : 
     117         195 :         while (bytes > new_space - block_header_size)
     118           0 :             new_space += subarena->block_size;
     119             : 
     120             :         new_block =
     121         195 :             static_cast<BLK_HDR*>(calloc(new_space / alignment, alignment));
     122         195 :         if (!new_block) {
     123           0 :             subarena->next = NULL;
     124           0 :             subarena->space = 0;
     125           0 :             return NULL;
     126             :         }
     127             : 
     128             :         /* link block into the list of blocks for use when we destroy */
     129         195 :         new_block->next = subarena->first;
     130         195 :         subarena->first = new_block;
     131             : 
     132             :         /* set info for current block */
     133         195 :         subarena->next =
     134         195 :             reinterpret_cast<uint8_t*>(new_block) + block_header_size;
     135         195 :         subarena->space = new_space - block_header_size;
     136             : 
     137             : #ifdef DEBUG
     138             :         /* mark block for corruption check */
     139         195 :         memset(subarena->next, 0xcd, subarena->space);
     140             : #endif
     141             :     }
     142             : 
     143             : #ifdef DEBUG
     144             :     {
     145             :         /* do corruption check */
     146             :         size_t i;
     147     2540739 :         for (i = 0; i < bytes; ++i) {
     148     2460141 :             XPT_ASSERT(subarena->next[i] == 0xcd);
     149             :         }
     150             :         /* we guarantee that the block will be filled with zeros */
     151       80598 :         memset(subarena->next, 0, bytes);
     152             :     }
     153             : #endif
     154             : 
     155       80598 :     uint8_t* p = subarena->next;
     156       80598 :     subarena->next  += bytes;
     157       80598 :     subarena->space -= bytes;
     158             : 
     159       80598 :     return p;
     160             : }
     161             : 
     162             : /***************************************************************************/
     163             : 
     164             : #ifdef DEBUG
     165             : XPT_PUBLIC_API(void)
     166           0 : XPT_AssertFailed(const char *s, const char *file, uint32_t lineno)
     167             : {
     168             :     fprintf(stderr, "Assertion failed: %s, file %s, line %d\n",
     169           0 :             s, file, lineno);
     170           0 :     abort();
     171             : }
     172             : #endif
     173             : 
     174             : static size_t
     175           0 : SizeOfSubArenaExcludingThis(XPTSubArena *subarena, MozMallocSizeOf mallocSizeOf)
     176             : {
     177           0 :     size_t n = 0;
     178             : 
     179           0 :     BLK_HDR* cur = subarena->first;
     180           0 :     while (cur) {
     181           0 :         BLK_HDR* next = cur->next;
     182           0 :         n += mallocSizeOf(cur);
     183           0 :         cur = next;
     184             :     }
     185             : 
     186           0 :     return n;
     187             : }
     188             : 
     189             : XPT_PUBLIC_API(size_t)
     190           0 : XPT_SizeOfArenaIncludingThis(XPTArena *arena, MozMallocSizeOf mallocSizeOf)
     191             : {
     192           0 :     size_t n = mallocSizeOf(arena);
     193           0 :     n += SizeOfSubArenaExcludingThis(&arena->subarena8, mallocSizeOf);
     194           0 :     n += SizeOfSubArenaExcludingThis(&arena->subarena1, mallocSizeOf);
     195           0 :     return n;
     196             : }

Generated by: LCOV version 1.13