lua

A copy of the Lua development repository
Log | Files | Refs | README

lmem.c (6245B)


      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 
     26 /*
     27 ** About the realloc function:
     28 ** void *frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
     29 ** ('osize' is the old size, 'nsize' is the new size)
     30 **
     31 ** - frealloc(ud, p, x, 0) frees the block 'p' and returns NULL.
     32 ** Particularly, frealloc(ud, NULL, 0, 0) does nothing,
     33 ** which is equivalent to free(NULL) in ISO C.
     34 **
     35 ** - frealloc(ud, NULL, x, s) creates a new block of size 's'
     36 ** (no matter 'x'). Returns NULL if it cannot create the new block.
     37 **
     38 ** - otherwise, frealloc(ud, b, x, y) reallocates the block 'b' from
     39 ** size 'x' to size 'y'. Returns NULL if it cannot reallocate the
     40 ** block to the new size.
     41 */
     42 
     43 
     44 /*
     45 ** Macro to call the allocation function.
     46 */
     47 #define callfrealloc(g,block,os,ns)    ((*g->frealloc)(g->ud, block, os, ns))
     48 
     49 
     50 /*
     51 ** When an allocation fails, it will try again after an emergency
     52 ** collection, except when it cannot run a collection.  The GC should
     53 ** not be called while the state is not fully built, as the collector
     54 ** is not yet fully initialized. Also, it should not be called when
     55 ** 'gcstopem' is true, because then the interpreter is in the middle of
     56 ** a collection step.
     57 */
     58 #define cantryagain(g)	(completestate(g) && !g->gcstopem)
     59 
     60 
     61 
     62 
     63 #if defined(EMERGENCYGCTESTS)
     64 /*
     65 ** First allocation will fail except when freeing a block (frees never
     66 ** fail) and when it cannot try again; this fail will trigger 'tryagain'
     67 ** and a full GC cycle at every allocation.
     68 */
     69 static void *firsttry (global_State *g, void *block, size_t os, size_t ns) {
     70   if (ns > 0 && cantryagain(g))
     71     return NULL;  /* fail */
     72   else  /* normal allocation */
     73     return callfrealloc(g, block, os, ns);
     74 }
     75 #else
     76 #define firsttry(g,block,os,ns)    callfrealloc(g, block, os, ns)
     77 #endif
     78 
     79 
     80 
     81 
     82 
     83 /*
     84 ** {==================================================================
     85 ** Functions to allocate/deallocate arrays for the Parser
     86 ** ===================================================================
     87 */
     88 
     89 /*
     90 ** Minimum size for arrays during parsing, to avoid overhead of
     91 ** reallocating to size 1, then 2, and then 4. All these arrays
     92 ** will be reallocated to exact sizes or erased when parsing ends.
     93 */
     94 #define MINSIZEARRAY	4
     95 
     96 
     97 void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize,
     98                      unsigned size_elems, int limit, const char *what) {
     99   void *newblock;
    100   int size = *psize;
    101   if (nelems + 1 <= size)  /* does one extra element still fit? */
    102     return block;  /* nothing to be done */
    103   if (size >= limit / 2) {  /* cannot double it? */
    104     if (l_unlikely(size >= limit))  /* cannot grow even a little? */
    105       luaG_runerror(L, "too many %s (limit is %d)", what, limit);
    106     size = limit;  /* still have at least one free place */
    107   }
    108   else {
    109     size *= 2;
    110     if (size < MINSIZEARRAY)
    111       size = MINSIZEARRAY;  /* minimum size */
    112   }
    113   lua_assert(nelems + 1 <= size && size <= limit);
    114   /* 'limit' ensures that multiplication will not overflow */
    115   newblock = luaM_saferealloc_(L, block, cast_sizet(*psize) * size_elems,
    116                                          cast_sizet(size) * size_elems);
    117   *psize = size;  /* update only when everything else is OK */
    118   return newblock;
    119 }
    120 
    121 
    122 /*
    123 ** In prototypes, the size of the array is also its number of
    124 ** elements (to save memory). So, if it cannot shrink an array
    125 ** to its number of elements, the only option is to raise an
    126 ** error.
    127 */
    128 void *luaM_shrinkvector_ (lua_State *L, void *block, int *size,
    129                           int final_n, unsigned size_elem) {
    130   void *newblock;
    131   size_t oldsize = cast_sizet(*size) * size_elem;
    132   size_t newsize = cast_sizet(final_n) * size_elem;
    133   lua_assert(newsize <= oldsize);
    134   newblock = luaM_saferealloc_(L, block, oldsize, newsize);
    135   *size = final_n;
    136   return newblock;
    137 }
    138 
    139 /* }================================================================== */
    140 
    141 
    142 l_noret luaM_toobig (lua_State *L) {
    143   luaG_runerror(L, "memory allocation error: block too big");
    144 }
    145 
    146 
    147 /*
    148 ** Free memory
    149 */
    150 void luaM_free_ (lua_State *L, void *block, size_t osize) {
    151   global_State *g = G(L);
    152   lua_assert((osize == 0) == (block == NULL));
    153   callfrealloc(g, block, osize, 0);
    154   g->GCdebt += cast(l_mem, osize);
    155 }
    156 
    157 
    158 /*
    159 ** In case of allocation fail, this function will do an emergency
    160 ** collection to free some memory and then try the allocation again.
    161 */
    162 static void *tryagain (lua_State *L, void *block,
    163                        size_t osize, size_t nsize) {
    164   global_State *g = G(L);
    165   if (cantryagain(g)) {
    166     luaC_fullgc(L, 1);  /* try to free some memory... */
    167     return callfrealloc(g, block, osize, nsize);  /* try again */
    168   }
    169   else return NULL;  /* cannot run an emergency collection */
    170 }
    171 
    172 
    173 /*
    174 ** Generic allocation routine.
    175 */
    176 void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
    177   void *newblock;
    178   global_State *g = G(L);
    179   lua_assert((osize == 0) == (block == NULL));
    180   newblock = firsttry(g, block, osize, nsize);
    181   if (l_unlikely(newblock == NULL && nsize > 0)) {
    182     newblock = tryagain(L, block, osize, nsize);
    183     if (newblock == NULL)  /* still no memory? */
    184       return NULL;  /* do not update 'GCdebt' */
    185   }
    186   lua_assert((nsize == 0) == (newblock == NULL));
    187   g->GCdebt -= cast(l_mem, nsize) - cast(l_mem, osize);
    188   return newblock;
    189 }
    190 
    191 
    192 void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize,
    193                                                     size_t nsize) {
    194   void *newblock = luaM_realloc_(L, block, osize, nsize);
    195   if (l_unlikely(newblock == NULL && nsize > 0))  /* allocation failed? */
    196     luaM_error(L);
    197   return newblock;
    198 }
    199 
    200 
    201 void *luaM_malloc_ (lua_State *L, size_t size, int tag) {
    202   if (size == 0)
    203     return NULL;  /* that's all */
    204   else {
    205     global_State *g = G(L);
    206     void *newblock = firsttry(g, NULL, cast_sizet(tag), size);
    207     if (l_unlikely(newblock == NULL)) {
    208       newblock = tryagain(L, NULL, cast_sizet(tag), size);
    209       if (newblock == NULL)
    210         luaM_error(L);
    211     }
    212     g->GCdebt -= cast(l_mem, size);
    213     return newblock;
    214   }
    215 }