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