LCOV - code coverage report
Current view: top level - external/lua/src - lmem.c (source / functions) Hit Total Coverage
Test: rapport Lines: 43 67 64.2 %
Date: 2021-12-10 16:22:55 Functions: 6 8 75.0 %
Branches: 13 28 46.4 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            : ** $Id: lmem.c $
       3                 :            : ** Interface to Memory Manager
       4                 :            : ** See Copyright Notice in lua.h
       5                 :            : */
       6                 :            : 
       7                 :            : #define lmem_c
       8                 :            : #define LUA_CORE
       9                 :            : 
      10                 :            : #include "lprefix.h"
      11                 :            : 
      12                 :            : 
      13                 :            : #include <stddef.h>
      14                 :            : 
      15                 :            : #include "lua.h"
      16                 :            : 
      17                 :            : #include "ldebug.h"
      18                 :            : #include "ldo.h"
      19                 :            : #include "lgc.h"
      20                 :            : #include "lmem.h"
      21                 :            : #include "lobject.h"
      22                 :            : #include "lstate.h"
      23                 :            : 
      24                 :            : 
      25                 :            : #if defined(EMERGENCYGCTESTS)
      26                 :            : /*
      27                 :            : ** First allocation will fail whenever not building initial state
      28                 :            : ** and not shrinking a block. (This fail will trigger 'tryagain' and
      29                 :            : ** a full GC cycle at every allocation.)
      30                 :            : */
      31                 :            : static void *firsttry (global_State *g, void *block, size_t os, size_t ns) {
      32                 :            :   if (ttisnil(&g->nilvalue) && ns > os)
      33                 :            :     return NULL;  /* fail */
      34                 :            :   else  /* normal allocation */
      35                 :            :     return (*g->frealloc)(g->ud, block, os, ns);
      36                 :            : }
      37                 :            : #else
      38                 :            : #define firsttry(g,block,os,ns)    ((*g->frealloc)(g->ud, block, os, ns))
      39                 :            : #endif
      40                 :            : 
      41                 :            : 
      42                 :            : 
      43                 :            : 
      44                 :            : 
      45                 :            : /*
      46                 :            : ** About the realloc function:
      47                 :            : ** void *frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
      48                 :            : ** ('osize' is the old size, 'nsize' is the new size)
      49                 :            : **
      50                 :            : ** - frealloc(ud, p, x, 0) frees the block 'p' and returns NULL.
      51                 :            : ** Particularly, frealloc(ud, NULL, 0, 0) does nothing,
      52                 :            : ** which is equivalent to free(NULL) in ISO C.
      53                 :            : **
      54                 :            : ** - frealloc(ud, NULL, x, s) creates a new block of size 's'
      55                 :            : ** (no matter 'x'). Returns NULL if it cannot create the new block.
      56                 :            : **
      57                 :            : ** - otherwise, frealloc(ud, b, x, y) reallocates the block 'b' from
      58                 :            : ** size 'x' to size 'y'. Returns NULL if it cannot reallocate the
      59                 :            : ** block to the new size.
      60                 :            : */
      61                 :            : 
      62                 :            : 
      63                 :            : 
      64                 :            : 
      65                 :            : /*
      66                 :            : ** {==================================================================
      67                 :            : ** Functions to allocate/deallocate arrays for the Parser
      68                 :            : ** ===================================================================
      69                 :            : */
      70                 :            : 
      71                 :            : /*
      72                 :            : ** Minimum size for arrays during parsing, to avoid overhead of
      73                 :            : ** reallocating to size 1, then 2, and then 4. All these arrays
      74                 :            : ** will be reallocated to exact sizes or erased when parsing ends.
      75                 :            : */
      76                 :            : #define MINSIZEARRAY    4
      77                 :            : 
      78                 :            : 
      79                 :      16968 : void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize,
      80                 :            :                      int size_elems, int limit, const char *what) {
      81                 :            :   void *newblock;
      82                 :      16968 :   int size = *psize;
      83         [ +  + ]:      16968 :   if (nelems + 1 <= size)  /* does one extra element still fit? */
      84                 :      12101 :     return block;  /* nothing to be done */
      85         [ -  + ]:       4867 :   if (size >= limit / 2) {  /* cannot double it? */
      86         [ #  # ]:          0 :     if (unlikely(size >= limit))  /* cannot grow even a little? */
      87                 :          0 :       luaG_runerror(L, "too many %s (limit is %d)", what, limit);
      88                 :          0 :     size = limit;  /* still have at least one free place */
      89                 :          0 :   }
      90                 :            :   else {
      91                 :       4867 :     size *= 2;
      92         [ +  + ]:       4867 :     if (size < MINSIZEARRAY)
      93                 :       2648 :       size = MINSIZEARRAY;  /* minimum size */
      94                 :            :   }
      95                 :            :   lua_assert(nelems + 1 <= size && size <= limit);
      96                 :            :   /* 'limit' ensures that multiplication will not overflow */
      97                 :       9734 :   newblock = luaM_saferealloc_(L, block, cast_sizet(*psize) * size_elems,
      98                 :       4867 :                                          cast_sizet(size) * size_elems);
      99                 :       4867 :   *psize = size;  /* update only when everything else is OK */
     100                 :       4867 :   return newblock;
     101                 :      16968 : }
     102                 :            : 
     103                 :            : 
     104                 :            : /*
     105                 :            : ** In prototypes, the size of the array is also its number of
     106                 :            : ** elements (to save memory). So, if it cannot shrink an array
     107                 :            : ** to its number of elements, the only option is to raise an
     108                 :            : ** error.
     109                 :            : */
     110                 :       4564 : void *luaM_shrinkvector_ (lua_State *L, void *block, int *size,
     111                 :            :                           int final_n, int size_elem) {
     112                 :            :   void *newblock;
     113                 :       4564 :   size_t oldsize = cast_sizet((*size) * size_elem);
     114                 :       4564 :   size_t newsize = cast_sizet(final_n * size_elem);
     115                 :            :   lua_assert(newsize <= oldsize);
     116                 :       4564 :   newblock = luaM_saferealloc_(L, block, oldsize, newsize);
     117                 :       4564 :   *size = final_n;
     118                 :       4564 :   return newblock;
     119                 :            : }
     120                 :            : 
     121                 :            : /* }================================================================== */
     122                 :            : 
     123                 :            : 
     124                 :          0 : l_noret luaM_toobig (lua_State *L) {
     125                 :          0 :   luaG_runerror(L, "memory allocation error: block too big");
     126                 :            : }
     127                 :            : 
     128                 :            : 
     129                 :            : /*
     130                 :            : ** Free memory
     131                 :            : */
     132                 :      32544 : void luaM_free_ (lua_State *L, void *block, size_t osize) {
     133                 :      32544 :   global_State *g = G(L);
     134                 :            :   lua_assert((osize == 0) == (block == NULL));
     135                 :      32544 :   (*g->frealloc)(g->ud, block, osize, 0);
     136                 :      32544 :   g->GCdebt -= osize;
     137                 :      32544 : }
     138                 :            : 
     139                 :            : 
     140                 :            : /*
     141                 :            : ** In case of allocation fail, this function will call the GC to try
     142                 :            : ** to free some memory and then try the allocation again.
     143                 :            : ** (It should not be called when shrinking a block, because then the
     144                 :            : ** interpreter may be in the middle of a collection step.)
     145                 :            : */
     146                 :          0 : static void *tryagain (lua_State *L, void *block,
     147                 :            :                        size_t osize, size_t nsize) {
     148                 :          0 :   global_State *g = G(L);
     149         [ #  # ]:          0 :   if (ttisnil(&g->nilvalue)) {  /* is state fully build? */
     150                 :          0 :     luaC_fullgc(L, 1);  /* try to free some memory... */
     151                 :          0 :     return (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */
     152                 :            :   }
     153                 :          0 :   else return NULL;  /* cannot free any memory without a full state */
     154                 :          0 : }
     155                 :            : 
     156                 :            : 
     157                 :            : /*
     158                 :            : ** Generic allocation routine.
     159                 :            : ** If allocation fails while shrinking a block, do not try again; the
     160                 :            : ** GC shrinks some blocks and it is not reentrant.
     161                 :            : */
     162                 :      41590 : void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
     163                 :            :   void *newblock;
     164                 :      41590 :   global_State *g = G(L);
     165                 :            :   lua_assert((osize == 0) == (block == NULL));
     166                 :      41590 :   newblock = firsttry(g, block, osize, nsize);
     167   [ +  +  +  - ]:      41590 :   if (unlikely(newblock == NULL && nsize > 0)) {
     168         [ #  # ]:          0 :     if (nsize > osize)  /* not shrinking a block? */
     169                 :          0 :       newblock = tryagain(L, block, osize, nsize);
     170         [ #  # ]:          0 :     if (newblock == NULL)  /* still no memory? */
     171                 :          0 :       return NULL;  /* do not update 'GCdebt' */
     172                 :          0 :   }
     173                 :            :   lua_assert((nsize == 0) == (newblock == NULL));
     174                 :      41590 :   g->GCdebt = (g->GCdebt + nsize) - osize;
     175                 :      41590 :   return newblock;
     176                 :      41590 : }
     177                 :            : 
     178                 :            : 
     179                 :      10759 : void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize,
     180                 :            :                                                     size_t nsize) {
     181                 :      10759 :   void *newblock = luaM_realloc_(L, block, osize, nsize);
     182   [ +  +  -  + ]:      10759 :   if (unlikely(newblock == NULL && nsize > 0))  /* allocation failed? */
     183                 :          0 :     luaM_error(L);
     184                 :      10759 :   return newblock;
     185                 :            : }
     186                 :            : 
     187                 :            : 
     188                 :     233211 : void *luaM_malloc_ (lua_State *L, size_t size, int tag) {
     189         [ +  - ]:     233211 :   if (size == 0)
     190                 :          0 :     return NULL;  /* that's all */
     191                 :            :   else {
     192                 :     233211 :     global_State *g = G(L);
     193                 :     233211 :     void *newblock = firsttry(g, NULL, tag, size);
     194         [ +  - ]:     233211 :     if (unlikely(newblock == NULL)) {
     195                 :          0 :       newblock = tryagain(L, NULL, tag, size);
     196         [ #  # ]:          0 :       if (newblock == NULL)
     197                 :          0 :         luaM_error(L);
     198                 :          0 :     }
     199                 :     233211 :     g->GCdebt += size;
     200                 :     233211 :     return newblock;
     201                 :            :   }
     202                 :     233211 : }

Generated by: LCOV version 1.15