Home | History | Annotate | Download | only in src
      1 /*
      2 ** $Id: lmem.c,v 1.84 2012/05/23 15:41:53 roberto Exp $
      3 ** Interface to Memory Manager
      4 ** See Copyright Notice in lua.h
      5 */
      6 
      7 
      8 #include <stddef.h>
      9 
     10 #define lmem_c
     11 #define LUA_CORE
     12 
     13 #include "lua.h"
     14 
     15 #include "ldebug.h"
     16 #include "ldo.h"
     17 #include "lgc.h"
     18 #include "lmem.h"
     19 #include "lobject.h"
     20 #include "lstate.h"
     21 
     22 
     23 
     24 /*
     25 ** About the realloc function:
     26 ** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
     27 ** (`osize' is the old size, `nsize' is the new size)
     28 **
     29 ** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no
     30 ** matter 'x').
     31 **
     32 ** * frealloc(ud, p, x, 0) frees the block `p'
     33 ** (in this specific case, frealloc must return NULL);
     34 ** particularly, frealloc(ud, NULL, 0, 0) does nothing
     35 ** (which is equivalent to free(NULL) in ANSI C)
     36 **
     37 ** frealloc returns NULL if it cannot create or reallocate the area
     38 ** (any reallocation to an equal or smaller size cannot fail!)
     39 */
     40 
     41 
     42 
     43 #define MINSIZEARRAY	4
     44 
     45 
     46 void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
     47                      int limit, const char *what) {
     48   void *newblock;
     49   int newsize;
     50   if (*size >= limit/2) {  /* cannot double it? */
     51     if (*size >= limit)  /* cannot grow even a little? */
     52       luaG_runerror(L, "too many %s (limit is %d)", what, limit);
     53     newsize = limit;  /* still have at least one free place */
     54   }
     55   else {
     56     newsize = (*size)*2;
     57     if (newsize < MINSIZEARRAY)
     58       newsize = MINSIZEARRAY;  /* minimum size */
     59   }
     60   newblock = luaM_reallocv(L, block, *size, newsize, size_elems);
     61   *size = newsize;  /* update only when everything else is OK */
     62   return newblock;
     63 }
     64 
     65 
     66 l_noret luaM_toobig (lua_State *L) {
     67   luaG_runerror(L, "memory allocation error: block too big");
     68 }
     69 
     70 
     71 
     72 /*
     73 ** generic allocation routine.
     74 */
     75 void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
     76   void *newblock;
     77   global_State *g = G(L);
     78   size_t realosize = (block) ? osize : 0;
     79   lua_assert((realosize == 0) == (block == NULL));
     80 #if defined(HARDMEMTESTS)
     81   if (nsize > realosize && g->gcrunning)
     82     luaC_fullgc(L, 1);  /* force a GC whenever possible */
     83 #endif
     84   newblock = (*g->frealloc)(g->ud, block, osize, nsize);
     85   if (newblock == NULL && nsize > 0) {
     86     api_check(L, nsize > realosize,
     87                  "realloc cannot fail when shrinking a block");
     88     if (g->gcrunning) {
     89       luaC_fullgc(L, 1);  /* try to free some memory... */
     90       newblock = (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */
     91     }
     92     if (newblock == NULL)
     93       luaD_throw(L, LUA_ERRMEM);
     94   }
     95   lua_assert((nsize == 0) == (newblock == NULL));
     96   g->GCdebt = (g->GCdebt + nsize) - realosize;
     97   return newblock;
     98 }
     99 
    100