mirror of https://github.com/rusefi/lua.git
more freedom in handling memory-allocation errors (not all allocations
automatically raise an error), which allows fixing a bug when resizing a table.
This commit is contained in:
parent
40f823ec90
commit
e663a24ab0
14
lapi.c
14
lapi.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lapi.c,v 2.277 2017/11/23 19:29:04 roberto Exp roberto $
|
** $Id: lapi.c,v 2.278 2017/12/06 18:08:03 roberto Exp roberto $
|
||||||
** Lua API
|
** Lua API
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -99,16 +99,6 @@ static StkId index2stack (lua_State *L, int idx) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
** to be called by 'lua_checkstack' in protected mode, to grow stack
|
|
||||||
** capturing memory errors
|
|
||||||
*/
|
|
||||||
static void growstack (lua_State *L, void *ud) {
|
|
||||||
int size = *(int *)ud;
|
|
||||||
luaD_growstack(L, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
LUA_API int lua_checkstack (lua_State *L, int n) {
|
LUA_API int lua_checkstack (lua_State *L, int n) {
|
||||||
int res;
|
int res;
|
||||||
CallInfo *ci = L->ci;
|
CallInfo *ci = L->ci;
|
||||||
|
@ -121,7 +111,7 @@ LUA_API int lua_checkstack (lua_State *L, int n) {
|
||||||
if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */
|
if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */
|
||||||
res = 0; /* no */
|
res = 0; /* no */
|
||||||
else /* try to grow stack */
|
else /* try to grow stack */
|
||||||
res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK);
|
res = luaD_growstack(L, n, 0);
|
||||||
}
|
}
|
||||||
if (res && ci->top < L->top + n)
|
if (res && ci->top < L->top + n)
|
||||||
ci->top = L->top + n; /* adjust frame top */
|
ci->top = L->top + n; /* adjust frame top */
|
||||||
|
|
42
ldo.c
42
ldo.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ldo.c,v 2.176 2017/11/29 13:02:17 roberto Exp roberto $
|
** $Id: ldo.c,v 2.177 2017/12/01 15:44:51 roberto Exp roberto $
|
||||||
** Stack and Call structure of Lua
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -156,17 +156,17 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
|
||||||
** Stack reallocation
|
** Stack reallocation
|
||||||
** ===================================================================
|
** ===================================================================
|
||||||
*/
|
*/
|
||||||
static void correctstack (lua_State *L, StkId oldstack) {
|
static void correctstack (lua_State *L, StkId oldstack, StkId newstack) {
|
||||||
CallInfo *ci;
|
CallInfo *ci;
|
||||||
UpVal *up;
|
UpVal *up;
|
||||||
if (L->stack == oldstack)
|
if (oldstack == newstack)
|
||||||
return; /* stack address did not change */
|
return; /* stack address did not change */
|
||||||
L->top = (L->top - oldstack) + L->stack;
|
L->top = (L->top - oldstack) + newstack;
|
||||||
for (up = L->openupval; up != NULL; up = up->u.open.next)
|
for (up = L->openupval; up != NULL; up = up->u.open.next)
|
||||||
up->v = s2v((uplevel(up) - oldstack) + L->stack);
|
up->v = s2v((uplevel(up) - oldstack) + newstack);
|
||||||
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
for (ci = L->ci; ci != NULL; ci = ci->previous) {
|
||||||
ci->top = (ci->top - oldstack) + L->stack;
|
ci->top = (ci->top - oldstack) + newstack;
|
||||||
ci->func = (ci->func - oldstack) + L->stack;
|
ci->func = (ci->func - oldstack) + newstack;
|
||||||
if (isLua(ci))
|
if (isLua(ci))
|
||||||
ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */
|
ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */
|
||||||
}
|
}
|
||||||
|
@ -177,36 +177,40 @@ static void correctstack (lua_State *L, StkId oldstack) {
|
||||||
#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
|
#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200)
|
||||||
|
|
||||||
|
|
||||||
void luaD_reallocstack (lua_State *L, int newsize) {
|
int luaD_reallocstack (lua_State *L, int newsize, int safe) {
|
||||||
StkId oldstack = L->stack;
|
|
||||||
int lim = L->stacksize;
|
int lim = L->stacksize;
|
||||||
|
StkId newstack = luaM_reallocvector(L, L->stack, lim, newsize, StackValue);
|
||||||
lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
|
lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE);
|
||||||
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
|
lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK);
|
||||||
luaM_reallocvector(L, L->stack, L->stacksize, newsize, StackValue);
|
if (newstack == NULL) { /* reallocation failed? */
|
||||||
|
if (safe) luaM_error(L);
|
||||||
|
else return 0; /* no-safe mode: signal the error */
|
||||||
|
}
|
||||||
for (; lim < newsize; lim++)
|
for (; lim < newsize; lim++)
|
||||||
setnilvalue(s2v(L->stack + lim)); /* erase new segment */
|
setnilvalue(s2v(newstack + lim)); /* erase new segment */
|
||||||
|
correctstack(L, L->stack, newstack);
|
||||||
|
L->stack = newstack;
|
||||||
L->stacksize = newsize;
|
L->stacksize = newsize;
|
||||||
L->stack_last = L->stack + newsize - EXTRA_STACK;
|
L->stack_last = L->stack + newsize - EXTRA_STACK;
|
||||||
correctstack(L, oldstack);
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void luaD_growstack (lua_State *L, int n) {
|
int luaD_growstack (lua_State *L, int n, int safe) {
|
||||||
int size = L->stacksize;
|
int size = L->stacksize;
|
||||||
|
int newsize = 2 * size;
|
||||||
if (size > LUAI_MAXSTACK) /* error after extra size? */
|
if (size > LUAI_MAXSTACK) /* error after extra size? */
|
||||||
luaD_throw(L, LUA_ERRERR);
|
luaD_throw(L, LUA_ERRERR);
|
||||||
else {
|
else {
|
||||||
int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK;
|
int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK;
|
||||||
int newsize = 2 * size;
|
|
||||||
if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
|
if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK;
|
||||||
if (newsize < needed) newsize = needed;
|
if (newsize < needed) newsize = needed;
|
||||||
if (newsize > LUAI_MAXSTACK) { /* stack overflow? */
|
if (newsize > LUAI_MAXSTACK) { /* stack overflow? */
|
||||||
luaD_reallocstack(L, ERRORSTACKSIZE);
|
luaD_reallocstack(L, ERRORSTACKSIZE, 1);
|
||||||
luaG_runerror(L, "stack overflow");
|
luaG_runerror(L, "stack overflow");
|
||||||
}
|
}
|
||||||
else
|
} /* else */
|
||||||
luaD_reallocstack(L, newsize);
|
return luaD_reallocstack(L, newsize, safe);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -234,7 +238,7 @@ void luaD_shrinkstack (lua_State *L) {
|
||||||
good size is smaller than current size, shrink its stack */
|
good size is smaller than current size, shrink its stack */
|
||||||
if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) &&
|
if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) &&
|
||||||
goodsize < L->stacksize)
|
goodsize < L->stacksize)
|
||||||
luaD_reallocstack(L, goodsize);
|
luaD_reallocstack(L, goodsize, 0); /* ok if that fails */
|
||||||
else /* don't change stack */
|
else /* don't change stack */
|
||||||
condmovestack(L,{},{}); /* (change only for debugging) */
|
condmovestack(L,{},{}); /* (change only for debugging) */
|
||||||
}
|
}
|
||||||
|
|
9
ldo.h
9
ldo.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ldo.h,v 2.35 2017/11/23 16:35:54 roberto Exp roberto $
|
** $Id: ldo.h,v 2.36 2017/11/23 18:29:41 roberto Exp roberto $
|
||||||
** Stack and Call structure of Lua
|
** Stack and Call structure of Lua
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -22,7 +22,8 @@
|
||||||
*/
|
*/
|
||||||
#define luaD_checkstackaux(L,n,pre,pos) \
|
#define luaD_checkstackaux(L,n,pre,pos) \
|
||||||
if (L->stack_last - L->top <= (n)) \
|
if (L->stack_last - L->top <= (n)) \
|
||||||
{ pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); }
|
{ pre; luaD_growstack(L, n, 1); pos; } \
|
||||||
|
else { condmovestack(L,pre,pos); }
|
||||||
|
|
||||||
/* In general, 'pre'/'pos' are empty (nothing to save) */
|
/* In general, 'pre'/'pos' are empty (nothing to save) */
|
||||||
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)
|
#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0)
|
||||||
|
@ -55,8 +56,8 @@ LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u,
|
||||||
ptrdiff_t oldtop, ptrdiff_t ef);
|
ptrdiff_t oldtop, ptrdiff_t ef);
|
||||||
LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
|
LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult,
|
||||||
int nres);
|
int nres);
|
||||||
LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize);
|
LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int safe);
|
||||||
LUAI_FUNC void luaD_growstack (lua_State *L, int n);
|
LUAI_FUNC int luaD_growstack (lua_State *L, int n, int safe);
|
||||||
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
LUAI_FUNC void luaD_shrinkstack (lua_State *L);
|
||||||
LUAI_FUNC void luaD_inctop (lua_State *L);
|
LUAI_FUNC void luaD_inctop (lua_State *L);
|
||||||
|
|
||||||
|
|
11
lgc.c
11
lgc.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lgc.c,v 2.240 2017/11/30 15:37:16 roberto Exp roberto $
|
** $Id: lgc.c,v 2.241 2017/12/01 17:38:49 roberto Exp roberto $
|
||||||
** Garbage Collector
|
** Garbage Collector
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -816,18 +816,13 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** If possible, shrink string table (protected from memory errors).
|
** If possible, shrink string table.
|
||||||
*/
|
*/
|
||||||
static void shrinkstrtable (lua_State *L, void *ud) {
|
|
||||||
luaS_resize(L, *cast(int*, ud) / 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void checkSizes (lua_State *L, global_State *g) {
|
static void checkSizes (lua_State *L, global_State *g) {
|
||||||
if (!g->gcemergency) {
|
if (!g->gcemergency) {
|
||||||
l_mem olddebt = g->GCdebt;
|
l_mem olddebt = g->GCdebt;
|
||||||
if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
|
if (g->strt.nuse < g->strt.size / 4) /* string table too big? */
|
||||||
luaD_rawrunprotected(L, &shrinkstrtable, &g->strt.size);
|
luaS_resize(L, g->strt.size / 2);
|
||||||
g->GCestimate += g->GCdebt - olddebt; /* correct estimate */
|
g->GCestimate += g->GCdebt - olddebt; /* correct estimate */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
28
lmem.c
28
lmem.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lmem.c,v 1.92 2017/12/06 18:36:31 roberto Exp roberto $
|
** $Id: lmem.c,v 1.93 2017/12/07 18:59:52 roberto Exp roberto $
|
||||||
** Interface to Memory Manager
|
** Interface to Memory Manager
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -69,9 +69,12 @@ void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize,
|
||||||
if (size < MINSIZEARRAY)
|
if (size < MINSIZEARRAY)
|
||||||
size = MINSIZEARRAY; /* minimum size */
|
size = MINSIZEARRAY; /* minimum size */
|
||||||
}
|
}
|
||||||
|
lua_assert(nelems + 1 <= size && size <= limit);
|
||||||
/* 'limit' ensures that multiplication will not overflow */
|
/* 'limit' ensures that multiplication will not overflow */
|
||||||
newblock = luaM_realloc(L, block, cast(size_t, *psize) * size_elems,
|
newblock = luaM_realloc_(L, block, cast(size_t, *psize) * size_elems,
|
||||||
cast(size_t, size) * size_elems);
|
cast(size_t, size) * size_elems);
|
||||||
|
if (newblock == NULL)
|
||||||
|
luaM_error(L);
|
||||||
*psize = size; /* update only when everything else is OK */
|
*psize = size; /* update only when everything else is OK */
|
||||||
return newblock;
|
return newblock;
|
||||||
}
|
}
|
||||||
|
@ -115,20 +118,20 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) {
|
||||||
/*
|
/*
|
||||||
** generic allocation routine.
|
** generic allocation routine.
|
||||||
*/
|
*/
|
||||||
void *luaM_realloc (lua_State *L, void *block, size_t osize, size_t nsize) {
|
void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) {
|
||||||
void *newblock;
|
void *newblock;
|
||||||
global_State *g = G(L);
|
global_State *g = G(L);
|
||||||
lua_assert((osize == 0) == (block == NULL));
|
lua_assert((osize == 0) == (block == NULL));
|
||||||
hardtest(L, osize, nsize);
|
hardtest(L, osize, nsize);
|
||||||
newblock = (*g->frealloc)(g->ud, block, osize, nsize);
|
newblock = (*g->frealloc)(g->ud, block, osize, nsize);
|
||||||
if (newblock == NULL && nsize > 0) {
|
if (newblock == NULL && nsize > 0) {
|
||||||
lua_assert(nsize > osize); /* cannot fail when shrinking a block */
|
/* Is state fully built? Not shrinking a block? */
|
||||||
if (g->version) { /* is state fully built? */
|
if (g->version && nsize > osize) {
|
||||||
luaC_fullgc(L, 1); /* try to free some memory... */
|
luaC_fullgc(L, 1); /* try to free some memory... */
|
||||||
newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
|
newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */
|
||||||
}
|
}
|
||||||
if (newblock == NULL)
|
if (newblock == NULL)
|
||||||
luaD_throw(L, LUA_ERRMEM);
|
return NULL;
|
||||||
}
|
}
|
||||||
lua_assert((nsize == 0) == (newblock == NULL));
|
lua_assert((nsize == 0) == (newblock == NULL));
|
||||||
g->GCdebt = (g->GCdebt + nsize) - osize;
|
g->GCdebt = (g->GCdebt + nsize) - osize;
|
||||||
|
@ -136,7 +139,16 @@ void *luaM_realloc (lua_State *L, void *block, size_t osize, size_t nsize) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void *luaM_malloc (lua_State *L, size_t size, int tag) {
|
void *luaM_saferealloc_ (lua_State *L, void *block, size_t osize,
|
||||||
|
size_t nsize) {
|
||||||
|
void *newblock = luaM_realloc_(L, block, osize, nsize);
|
||||||
|
if (newblock == NULL && nsize > 0) /* allocation failed? */
|
||||||
|
luaM_error(L);
|
||||||
|
return newblock;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void *luaM_malloc_ (lua_State *L, size_t size, int tag) {
|
||||||
hardtest(L, 0, size);
|
hardtest(L, 0, size);
|
||||||
if (size == 0)
|
if (size == 0)
|
||||||
return NULL; /* that's all */
|
return NULL; /* that's all */
|
||||||
|
@ -149,7 +161,7 @@ void *luaM_malloc (lua_State *L, size_t size, int tag) {
|
||||||
newblock = (*g->frealloc)(g->ud, NULL, tag, size); /* try again */
|
newblock = (*g->frealloc)(g->ud, NULL, tag, size); /* try again */
|
||||||
}
|
}
|
||||||
if (newblock == NULL)
|
if (newblock == NULL)
|
||||||
luaD_throw(L, LUA_ERRMEM);
|
luaM_error(L);
|
||||||
}
|
}
|
||||||
g->GCdebt += size;
|
g->GCdebt += size;
|
||||||
return newblock;
|
return newblock;
|
||||||
|
|
21
lmem.h
21
lmem.h
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lmem.h,v 1.44 2017/12/06 18:36:31 roberto Exp roberto $
|
** $Id: lmem.h,v 1.45 2017/12/07 18:59:52 roberto Exp roberto $
|
||||||
** Interface to Memory Manager
|
** Interface to Memory Manager
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -14,6 +14,9 @@
|
||||||
#include "lua.h"
|
#include "lua.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define luaM_error(L) luaD_throw(L, LUA_ERRMEM)
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** This macro tests whether it is safe to multiply 'n' by the size of
|
** This macro tests whether it is safe to multiply 'n' by the size of
|
||||||
** type 't' without overflows. Because 'e' is always constant, it avoids
|
** type 't' without overflows. Because 'e' is always constant, it avoids
|
||||||
|
@ -45,25 +48,25 @@
|
||||||
** Arrays of chars do not need any test
|
** Arrays of chars do not need any test
|
||||||
*/
|
*/
|
||||||
#define luaM_reallocvchar(L,b,on,n) \
|
#define luaM_reallocvchar(L,b,on,n) \
|
||||||
cast(char *, luaM_realloc(L, (b), (on)*sizeof(char), (n)*sizeof(char)))
|
cast(char *, luaM_saferealloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char)))
|
||||||
|
|
||||||
#define luaM_freemem(L, b, s) luaM_free_(L, (b), (s))
|
#define luaM_freemem(L, b, s) luaM_free_(L, (b), (s))
|
||||||
#define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b)))
|
#define luaM_free(L, b) luaM_free_(L, (b), sizeof(*(b)))
|
||||||
#define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b)))
|
#define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b)))
|
||||||
|
|
||||||
#define luaM_new(L,t) cast(t*, luaM_malloc(L, sizeof(t), 0))
|
#define luaM_new(L,t) cast(t*, luaM_malloc_(L, sizeof(t), 0))
|
||||||
#define luaM_newvector(L,n,t) cast(t*, luaM_malloc(L, (n)*sizeof(t), 0))
|
#define luaM_newvector(L,n,t) cast(t*, luaM_malloc_(L, (n)*sizeof(t), 0))
|
||||||
#define luaM_newvectorchecked(L,n,t) \
|
#define luaM_newvectorchecked(L,n,t) \
|
||||||
(luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t))
|
(luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t))
|
||||||
|
|
||||||
#define luaM_newobject(L,tag,s) luaM_malloc(L, (s), tag)
|
#define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag)
|
||||||
|
|
||||||
#define luaM_growvector(L,v,nelems,size,t,limit,e) \
|
#define luaM_growvector(L,v,nelems,size,t,limit,e) \
|
||||||
((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \
|
((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \
|
||||||
luaM_limitN(limit,t),e)))
|
luaM_limitN(limit,t),e)))
|
||||||
|
|
||||||
#define luaM_reallocvector(L, v,oldn,n,t) \
|
#define luaM_reallocvector(L, v,oldn,n,t) \
|
||||||
((v)=cast(t *, luaM_realloc(L, v, cast(size_t, oldn) * sizeof(t), \
|
(cast(t *, luaM_realloc_(L, v, cast(size_t, oldn) * sizeof(t), \
|
||||||
cast(size_t, n) * sizeof(t))))
|
cast(size_t, n) * sizeof(t))))
|
||||||
|
|
||||||
#define luaM_shrinkvector(L,v,size,fs,t) \
|
#define luaM_shrinkvector(L,v,size,fs,t) \
|
||||||
|
@ -72,7 +75,9 @@
|
||||||
LUAI_FUNC l_noret luaM_toobig (lua_State *L);
|
LUAI_FUNC l_noret luaM_toobig (lua_State *L);
|
||||||
|
|
||||||
/* not to be called directly */
|
/* not to be called directly */
|
||||||
LUAI_FUNC void *luaM_realloc (lua_State *L, void *block, size_t oldsize,
|
LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize,
|
||||||
|
size_t size);
|
||||||
|
LUAI_FUNC void *luaM_saferealloc_ (lua_State *L, void *block, size_t oldsize,
|
||||||
size_t size);
|
size_t size);
|
||||||
LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize);
|
LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize);
|
||||||
LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems,
|
LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems,
|
||||||
|
@ -80,7 +85,7 @@ LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems,
|
||||||
const char *what);
|
const char *what);
|
||||||
LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem,
|
LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem,
|
||||||
int final_n, int size_elem);
|
int final_n, int size_elem);
|
||||||
LUAI_FUNC void *luaM_malloc (lua_State *L, size_t size, int tag);
|
LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: lstring.c,v 2.58 2017/12/01 16:40:29 roberto Exp roberto $
|
** $Id: lstring.c,v 2.59 2017/12/07 18:59:52 roberto Exp roberto $
|
||||||
** String table (keeps all strings handled by Lua)
|
** String table (keeps all strings handled by Lua)
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -70,12 +70,15 @@ unsigned int luaS_hashlongstr (TString *ts) {
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Resizes the string table.
|
** Resize the string table. If allocation fails, keep the current size.
|
||||||
|
** (This can degrade performance, but any size should work correctly.)
|
||||||
*/
|
*/
|
||||||
void luaS_resize (lua_State *L, int newsize) {
|
void luaS_resize (lua_State *L, int newsize) {
|
||||||
int i;
|
int i;
|
||||||
TString **newhash = luaM_newvector(L, newsize, TString *);
|
TString **newhash = luaM_newvector(L, newsize, TString *);
|
||||||
stringtable *tb = &G(L)->strt;
|
stringtable *tb = &G(L)->strt;
|
||||||
|
if (newhash == NULL) /* allocation failed? */
|
||||||
|
return; /* leave hash as it is */
|
||||||
for (i = 0; i < newsize; i++) /* initialize new hash array */
|
for (i = 0; i < newsize; i++) /* initialize new hash array */
|
||||||
newhash[i] = NULL;
|
newhash[i] = NULL;
|
||||||
for (i = 0; i < tb->size; i++) { /* rehash all elements into new array */
|
for (i = 0; i < tb->size; i++) { /* rehash all elements into new array */
|
||||||
|
|
101
ltable.c
101
ltable.c
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
** $Id: ltable.c,v 2.127 2017/11/23 19:29:04 roberto Exp roberto $
|
** $Id: ltable.c,v 2.128 2017/12/07 18:59:52 roberto Exp roberto $
|
||||||
** Lua tables (hash)
|
** Lua tables (hash)
|
||||||
** See Copyright Notice in lua.h
|
** See Copyright Notice in lua.h
|
||||||
*/
|
*/
|
||||||
|
@ -357,15 +357,6 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void setarrayvector (lua_State *L, Table *t, unsigned int size) {
|
|
||||||
unsigned int i;
|
|
||||||
luaM_reallocvector(L, t->array, t->sizearray, size, TValue);
|
|
||||||
for (i=t->sizearray; i<size; i++)
|
|
||||||
setnilvalue(&t->array[i]);
|
|
||||||
t->sizearray = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
** Creates an array for the hash part of a table with the given
|
** Creates an array for the hash part of a table with the given
|
||||||
** size, or reuses the dummy node if size is zero.
|
** size, or reuses the dummy node if size is zero.
|
||||||
|
@ -398,39 +389,79 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void luaH_resize (lua_State *L, Table *t, unsigned int nasize,
|
/*
|
||||||
unsigned int nhsize) {
|
** (Re)insert all elements from list 'nodes' into table 't'.
|
||||||
unsigned int i;
|
*/
|
||||||
|
static void reinsert(lua_State *L, Node *nodes, int nsize, Table *t) {
|
||||||
int j;
|
int j;
|
||||||
unsigned int oldasize = t->sizearray;
|
for (j = nsize - 1; j >= 0; j--) {
|
||||||
int oldhsize = allocsizenode(t);
|
Node *old = nodes + j;
|
||||||
Node *nold = t->node; /* save old hash ... */
|
|
||||||
if (nasize > oldasize) /* array part must grow? */
|
|
||||||
setarrayvector(L, t, nasize);
|
|
||||||
/* create new hash part with appropriate size */
|
|
||||||
setnodevector(L, t, nhsize);
|
|
||||||
if (nasize < oldasize) { /* array part must shrink? */
|
|
||||||
t->sizearray = nasize;
|
|
||||||
/* re-insert elements from vanishing slice */
|
|
||||||
for (i=nasize; i<oldasize; i++) {
|
|
||||||
if (!ttisnil(&t->array[i]))
|
|
||||||
luaH_setint(L, t, i + 1, &t->array[i]);
|
|
||||||
}
|
|
||||||
/* shrink array */
|
|
||||||
luaM_reallocvector(L, t->array, oldasize, nasize, TValue);
|
|
||||||
}
|
|
||||||
/* re-insert elements from hash part */
|
|
||||||
for (j = oldhsize - 1; j >= 0; j--) {
|
|
||||||
Node *old = nold + j;
|
|
||||||
if (!ttisnil(gval(old))) {
|
if (!ttisnil(gval(old))) {
|
||||||
/* doesn't need barrier/invalidate cache, as entry was
|
/* doesn't need barrier/invalidate cache, as entry was
|
||||||
already present in the table */
|
already present in the table */
|
||||||
TValue k; getnodekey(L, &k, old);
|
TValue k;
|
||||||
|
getnodekey(L, &k, old);
|
||||||
setobjt2t(L, luaH_set(L, t, &k), gval(old));
|
setobjt2t(L, luaH_set(L, t, &k), gval(old));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
** Resize table 't' for the new given sizes. Both allocations
|
||||||
|
** (for the hash part and for the array part) can fail, which
|
||||||
|
** creates some subtleties. If the first allocation, for the hash
|
||||||
|
** part, fails, an error is raised and that is it. Otherwise,
|
||||||
|
** copy the elements in the shrinking part of the array (if it
|
||||||
|
** is shrinking) into the new hash. Then it reallocates the array part.
|
||||||
|
** If that fails, it frees the new hash part and restores the old hash
|
||||||
|
** part (to restore the original state of the table), and then raises
|
||||||
|
** the allocation error. Otherwise, initialize the new part of the
|
||||||
|
** array (if any) with nils and reinsert the elements in the old
|
||||||
|
** hash back into the new parts of the table.
|
||||||
|
*/
|
||||||
|
void luaH_resize (lua_State *L, Table *t, unsigned int newasize,
|
||||||
|
unsigned int nhsize) {
|
||||||
|
unsigned int i;
|
||||||
|
Node *oldnode = t->node; /* save old hash ... */
|
||||||
|
Node *oldlastfree = t->lastfree;
|
||||||
|
int oldlsizenode = t->lsizenode;
|
||||||
|
int oldhsize = allocsizenode(t);
|
||||||
|
unsigned int oldasize = t->sizearray;
|
||||||
|
TValue *newarray;
|
||||||
|
/* create new hash part with appropriate size */
|
||||||
|
setnodevector(L, t, nhsize);
|
||||||
|
if (newasize < oldasize) { /* will array shrink? */
|
||||||
|
/* re-insert into the hash the elements from vanishing slice */
|
||||||
|
t->sizearray = newasize; /* pretend array has new size */
|
||||||
|
for (i = newasize; i < oldasize; i++) {
|
||||||
|
if (!ttisnil(&t->array[i]))
|
||||||
|
luaH_setint(L, t, i + 1, &t->array[i]);
|
||||||
|
}
|
||||||
|
t->sizearray = oldasize; /* restore current size */
|
||||||
|
}
|
||||||
|
/* allocate new array */
|
||||||
|
newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue);
|
||||||
|
if (newarray == NULL && newasize > 0) { /* allocation failed? */
|
||||||
|
if (nhsize > 0) /* not the dummy node? */
|
||||||
|
luaM_freearray(L, t->node, allocsizenode(t)); /* release new hash part */
|
||||||
|
t->node = oldnode; /* restore original hash part */
|
||||||
|
t->lastfree = oldlastfree;
|
||||||
|
t->lsizenode = oldlsizenode;
|
||||||
|
lua_assert(!isdummy(t) == (t->node != dummynode));
|
||||||
|
luaM_error(L); /* error with array unchanged */
|
||||||
|
}
|
||||||
|
/* allocation ok; initialize new part of the array */
|
||||||
|
t->array = newarray;
|
||||||
|
t->sizearray = newasize;
|
||||||
|
for (i = oldasize; i < newasize; i++)
|
||||||
|
setnilvalue(&t->array[i]);
|
||||||
|
/* re-insert elements from old hash part into new parts */
|
||||||
|
reinsert(L, oldnode, oldhsize, t);
|
||||||
|
/* free old hash */
|
||||||
if (oldhsize > 0) /* not the dummy node? */
|
if (oldhsize > 0) /* not the dummy node? */
|
||||||
luaM_freearray(L, nold, cast(size_t, oldhsize)); /* free old hash */
|
luaM_freearray(L, oldnode, cast(size_t, oldhsize));
|
||||||
|
lua_assert(!isdummy(t) == (t->node != dummynode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue