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