116a5fed65808adf648004b34f98718301d718fa2darylm/*
216a5fed65808adf648004b34f98718301d718fa2darylm** $Id: lmem.c,v 1.84.1.1 2013/04/12 18:48:47 roberto Exp $
316a5fed65808adf648004b34f98718301d718fa2darylm** Interface to Memory Manager
416a5fed65808adf648004b34f98718301d718fa2darylm** See Copyright Notice in lua.h
516a5fed65808adf648004b34f98718301d718fa2darylm*/
616a5fed65808adf648004b34f98718301d718fa2darylm
716a5fed65808adf648004b34f98718301d718fa2darylm
816a5fed65808adf648004b34f98718301d718fa2darylm#include <stddef.h>
916a5fed65808adf648004b34f98718301d718fa2darylm
1016a5fed65808adf648004b34f98718301d718fa2darylm#define lmem_c
1116a5fed65808adf648004b34f98718301d718fa2darylm#define LUA_CORE
1216a5fed65808adf648004b34f98718301d718fa2darylm
1316a5fed65808adf648004b34f98718301d718fa2darylm#include "lua.h"
1416a5fed65808adf648004b34f98718301d718fa2darylm
1516a5fed65808adf648004b34f98718301d718fa2darylm#include "ldebug.h"
1616a5fed65808adf648004b34f98718301d718fa2darylm#include "ldo.h"
1716a5fed65808adf648004b34f98718301d718fa2darylm#include "lgc.h"
1816a5fed65808adf648004b34f98718301d718fa2darylm#include "lmem.h"
1916a5fed65808adf648004b34f98718301d718fa2darylm#include "lobject.h"
2016a5fed65808adf648004b34f98718301d718fa2darylm#include "lstate.h"
2116a5fed65808adf648004b34f98718301d718fa2darylm
2216a5fed65808adf648004b34f98718301d718fa2darylm
2316a5fed65808adf648004b34f98718301d718fa2darylm
2416a5fed65808adf648004b34f98718301d718fa2darylm/*
2516a5fed65808adf648004b34f98718301d718fa2darylm** About the realloc function:
2616a5fed65808adf648004b34f98718301d718fa2darylm** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize);
2716a5fed65808adf648004b34f98718301d718fa2darylm** (`osize' is the old size, `nsize' is the new size)
2816a5fed65808adf648004b34f98718301d718fa2darylm**
2916a5fed65808adf648004b34f98718301d718fa2darylm** * frealloc(ud, NULL, x, s) creates a new block of size `s' (no
3016a5fed65808adf648004b34f98718301d718fa2darylm** matter 'x').
3116a5fed65808adf648004b34f98718301d718fa2darylm**
3216a5fed65808adf648004b34f98718301d718fa2darylm** * frealloc(ud, p, x, 0) frees the block `p'
3316a5fed65808adf648004b34f98718301d718fa2darylm** (in this specific case, frealloc must return NULL);
3416a5fed65808adf648004b34f98718301d718fa2darylm** particularly, frealloc(ud, NULL, 0, 0) does nothing
3516a5fed65808adf648004b34f98718301d718fa2darylm** (which is equivalent to free(NULL) in ANSI C)
3616a5fed65808adf648004b34f98718301d718fa2darylm**
3716a5fed65808adf648004b34f98718301d718fa2darylm** frealloc returns NULL if it cannot create or reallocate the area
3816a5fed65808adf648004b34f98718301d718fa2darylm** (any reallocation to an equal or smaller size cannot fail!)
3916a5fed65808adf648004b34f98718301d718fa2darylm*/
4016a5fed65808adf648004b34f98718301d718fa2darylm
4116a5fed65808adf648004b34f98718301d718fa2darylm
4216a5fed65808adf648004b34f98718301d718fa2darylm
4316a5fed65808adf648004b34f98718301d718fa2darylm#define MINSIZEARRAY	4
4416a5fed65808adf648004b34f98718301d718fa2darylm
4516a5fed65808adf648004b34f98718301d718fa2darylm
4616a5fed65808adf648004b34f98718301d718fa2darylmvoid *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems,
4716a5fed65808adf648004b34f98718301d718fa2darylm                     int limit, const char *what) {
4816a5fed65808adf648004b34f98718301d718fa2darylm  void *newblock;
4916a5fed65808adf648004b34f98718301d718fa2darylm  int newsize;
5016a5fed65808adf648004b34f98718301d718fa2darylm  if (*size >= limit/2) {  /* cannot double it? */
5116a5fed65808adf648004b34f98718301d718fa2darylm    if (*size >= limit)  /* cannot grow even a little? */
5216a5fed65808adf648004b34f98718301d718fa2darylm      luaG_runerror(L, "too many %s (limit is %d)", what, limit);
5316a5fed65808adf648004b34f98718301d718fa2darylm    newsize = limit;  /* still have at least one free place */
5416a5fed65808adf648004b34f98718301d718fa2darylm  }
5516a5fed65808adf648004b34f98718301d718fa2darylm  else {
5616a5fed65808adf648004b34f98718301d718fa2darylm    newsize = (*size)*2;
5716a5fed65808adf648004b34f98718301d718fa2darylm    if (newsize < MINSIZEARRAY)
5816a5fed65808adf648004b34f98718301d718fa2darylm      newsize = MINSIZEARRAY;  /* minimum size */
5916a5fed65808adf648004b34f98718301d718fa2darylm  }
6016a5fed65808adf648004b34f98718301d718fa2darylm  newblock = luaM_reallocv(L, block, *size, newsize, size_elems);
6116a5fed65808adf648004b34f98718301d718fa2darylm  *size = newsize;  /* update only when everything else is OK */
6216a5fed65808adf648004b34f98718301d718fa2darylm  return newblock;
6316a5fed65808adf648004b34f98718301d718fa2darylm}
6416a5fed65808adf648004b34f98718301d718fa2darylm
6516a5fed65808adf648004b34f98718301d718fa2darylm
6616a5fed65808adf648004b34f98718301d718fa2darylml_noret luaM_toobig (lua_State *L) {
6716a5fed65808adf648004b34f98718301d718fa2darylm  luaG_runerror(L, "memory allocation error: block too big");
6816a5fed65808adf648004b34f98718301d718fa2darylm}
6916a5fed65808adf648004b34f98718301d718fa2darylm
7016a5fed65808adf648004b34f98718301d718fa2darylm
7116a5fed65808adf648004b34f98718301d718fa2darylm
7216a5fed65808adf648004b34f98718301d718fa2darylm/*
7316a5fed65808adf648004b34f98718301d718fa2darylm** generic allocation routine.
7416a5fed65808adf648004b34f98718301d718fa2darylm*/
7516a5fed65808adf648004b34f98718301d718fa2darylmvoid *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
7616a5fed65808adf648004b34f98718301d718fa2darylm  void *newblock;
7716a5fed65808adf648004b34f98718301d718fa2darylm  global_State *g = G(L);
7816a5fed65808adf648004b34f98718301d718fa2darylm  size_t realosize = (block) ? osize : 0;
7916a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert((realosize == 0) == (block == NULL));
8016a5fed65808adf648004b34f98718301d718fa2darylm#if defined(HARDMEMTESTS)
8116a5fed65808adf648004b34f98718301d718fa2darylm  if (nsize > realosize && g->gcrunning)
8216a5fed65808adf648004b34f98718301d718fa2darylm    luaC_fullgc(L, 1);  /* force a GC whenever possible */
8316a5fed65808adf648004b34f98718301d718fa2darylm#endif
8416a5fed65808adf648004b34f98718301d718fa2darylm  newblock = (*g->frealloc)(g->ud, block, osize, nsize);
8516a5fed65808adf648004b34f98718301d718fa2darylm  if (newblock == NULL && nsize > 0) {
8616a5fed65808adf648004b34f98718301d718fa2darylm    api_check(L, nsize > realosize,
8716a5fed65808adf648004b34f98718301d718fa2darylm                 "realloc cannot fail when shrinking a block");
8816a5fed65808adf648004b34f98718301d718fa2darylm    if (g->gcrunning) {
8916a5fed65808adf648004b34f98718301d718fa2darylm      luaC_fullgc(L, 1);  /* try to free some memory... */
9016a5fed65808adf648004b34f98718301d718fa2darylm      newblock = (*g->frealloc)(g->ud, block, osize, nsize);  /* try again */
9116a5fed65808adf648004b34f98718301d718fa2darylm    }
9216a5fed65808adf648004b34f98718301d718fa2darylm    if (newblock == NULL)
9316a5fed65808adf648004b34f98718301d718fa2darylm      luaD_throw(L, LUA_ERRMEM);
9416a5fed65808adf648004b34f98718301d718fa2darylm  }
9516a5fed65808adf648004b34f98718301d718fa2darylm  lua_assert((nsize == 0) == (newblock == NULL));
9616a5fed65808adf648004b34f98718301d718fa2darylm  g->GCdebt = (g->GCdebt + nsize) - realosize;
9716a5fed65808adf648004b34f98718301d718fa2darylm  return newblock;
9816a5fed65808adf648004b34f98718301d718fa2darylm}
9916a5fed65808adf648004b34f98718301d718fa2darylm
100