From 4f88418170d298b065a7f71d86b1127153919ae9 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Fri, 17 Apr 2009 11:28:06 -0300 Subject: [PATCH] 'CallInfo' stack implemented as double-linked list instead of an array --- lapi.c | 6 ++--- ldebug.c | 24 ++++++++++---------- ldo.c | 69 +++++++++++++++++--------------------------------------- ldo.h | 5 +--- lgc.c | 39 ++++++++++++++++---------------- lstate.c | 61 +++++++++++++++++++++++++++++++++++++------------ lstate.h | 13 +++++++---- ltests.c | 18 ++++++--------- lua.h | 4 ++-- lvm.c | 14 ++++++------ 10 files changed, 127 insertions(+), 126 deletions(-) diff --git a/lapi.c b/lapi.c index ea2b7c88..0e3ef071 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.73 2009/03/30 18:39:20 roberto Exp roberto $ +** $Id: lapi.c,v 2.74 2009/04/08 18:04:33 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -72,7 +72,7 @@ static TValue *index2adr (lua_State *L, int idx) { static Table *getcurrenv (lua_State *L) { - if (L->ci == L->base_ci) /* no enclosing function? */ + if (L->ci->previous == NULL) /* no enclosing function? */ return hvalue(gt(L)); /* use global table as environment */ else { Closure *func = curr_func(L); @@ -185,7 +185,7 @@ LUA_API void lua_replace (lua_State *L, int idx) { StkId o; lua_lock(L); /* explicit test for incompatible code */ - if (idx == LUA_ENVIRONINDEX && L->ci == L->base_ci) + if (idx == LUA_ENVIRONINDEX && L->ci->previous == NULL) luaG_runerror(L, "no calling environment"); api_checknelems(L, 1); o = index2adr(L, idx); diff --git a/ldebug.c b/ldebug.c index 8492a97b..bcb7eaf3 100644 --- a/ldebug.c +++ b/ldebug.c @@ -1,5 +1,5 @@ /* -** $Id: ldebug.c,v 2.44 2009/03/10 17:14:37 roberto Exp roberto $ +** $Id: ldebug.c,v 2.45 2009/03/26 12:56:38 roberto Exp roberto $ ** Debug Interface ** See Copyright Notice in lua.h */ @@ -86,18 +86,18 @@ LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { int status; CallInfo *ci; lua_lock(L); - for (ci = L->ci; level > 0 && ci > L->base_ci; ci--) { + for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) { level--; if (isLua(ci)) /* Lua function? */ level -= ci->u.l.tailcalls; /* skip lost tail calls */ } - if (level == 0 && ci > L->base_ci) { /* level found? */ + if (level == 0 && ci != &L->base_ci) { /* level found? */ status = 1; - ar->i_ci = cast_int(ci - L->base_ci); + ar->i_ci = ci; } else if (level < 0) { /* level is of a lost tail call? */ status = 1; - ar->i_ci = 0; + ar->i_ci = NULL; } else status = 0; /* no such level */ lua_unlock(L); @@ -116,7 +116,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n) { if (fp && (name = luaF_getlocalname(fp, n, currentpc(L, ci))) != NULL) return name; /* is a local variable in a Lua function */ else { - StkId limit = (ci == L->ci) ? L->top : (ci+1)->func; + StkId limit = (ci == L->ci) ? L->top : ci->next->func; if (limit - ci->base >= n && n > 0) /* is 'n' inside 'ci' stack? */ return "(*temporary)"; else @@ -126,7 +126,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n) { LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { - CallInfo *ci = L->base_ci + ar->i_ci; + CallInfo *ci = ar->i_ci; const char *name = findlocal(L, ci, n); lua_lock(L); if (name) { @@ -139,7 +139,7 @@ LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { - CallInfo *ci = L->base_ci + ar->i_ci; + CallInfo *ci = ar->i_ci; const char *name = findlocal(L, ci, n); lua_lock(L); if (name) @@ -246,8 +246,8 @@ LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { f = clvalue(func); L->top--; /* pop function */ } - else if (ar->i_ci != 0) { /* no tail call? */ - ci = L->base_ci + ar->i_ci; + else if (ar->i_ci != NULL) { /* no tail call? */ + ci = ar->i_ci; lua_assert(ttisfunction(ci->func)); f = clvalue(ci->func); } @@ -525,9 +525,9 @@ static const char *getobjname (lua_State *L, CallInfo *ci, int stackpos, static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { TMS tm = 0; Instruction i; - if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci - 1)) + if ((isLua(ci) && ci->u.l.tailcalls > 0) || !isLua(ci->previous)) return NULL; /* calling function is not Lua (or is unknown) */ - ci--; /* calling function */ + ci = ci->previous; /* calling function */ i = ci_func(ci)->l.p->code[currentpc(L, ci)]; switch (GET_OPCODE(i)) { case OP_CALL: diff --git a/ldo.c b/ldo.c index 28560e0a..1a051222 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 2.58 2009/04/08 18:04:33 roberto Exp roberto $ +** $Id: ldo.c,v 2.59 2009/04/15 16:53:39 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -70,12 +70,8 @@ void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { static void restore_stack_limit (lua_State *L) { - lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK - 1); - if (L->size_ci > LUAI_MAXCALLS) { /* there was an overflow? */ - int inuse = cast_int(L->ci - L->base_ci); - if (inuse + 1 < LUAI_MAXCALLS) /* can `undo' overflow? */ - luaD_reallocCI(L, LUAI_MAXCALLS); - } + if (L->nci >= LUAI_MAXCALLS) /* stack overflow? */ + luaE_freeCI(L); /* erase all extras CIs */ } @@ -124,7 +120,7 @@ static void correctstack (lua_State *L, TValue *oldstack) { L->top = (L->top - oldstack) + L->stack; for (up = L->openupval; up != NULL; up = up->gch.next) gco2uv(up)->v = (gco2uv(up)->v - oldstack) + L->stack; - for (ci = L->base_ci; ci <= L->ci; ci++) { + for (ci = L->ci; ci != NULL; ci = ci->previous) { ci->top = (ci->top - oldstack) + L->stack; ci->base = (ci->base - oldstack) + L->stack; ci->func = (ci->func - oldstack) + L->stack; @@ -144,15 +140,6 @@ void luaD_reallocstack (lua_State *L, int newsize) { } -void luaD_reallocCI (lua_State *L, int newsize) { - CallInfo *oldci = L->base_ci; - luaM_reallocvector(L, L->base_ci, L->size_ci, newsize, CallInfo); - L->size_ci = newsize; - L->ci = (L->ci - oldci) + L->base_ci; - L->end_ci = L->base_ci + L->size_ci - 1; -} - - void luaD_growstack (lua_State *L, int n) { if (n <= L->stacksize) /* double size is enough? */ luaD_reallocstack(L, 2*L->stacksize); @@ -161,18 +148,6 @@ void luaD_growstack (lua_State *L, int n) { } -static CallInfo *growCI (lua_State *L) { - if (L->size_ci > LUAI_MAXCALLS) /* overflow while handling overflow? */ - luaD_throw(L, LUA_ERRERR); - else { - luaD_reallocCI(L, 2*L->size_ci); - if (L->size_ci > LUAI_MAXCALLS) - luaG_runerror(L, "stack overflow"); - } - return ++L->ci; -} - - void luaD_callhook (lua_State *L, int event, int line) { lua_Hook hook = L->hook; if (hook && L->allowhook) { @@ -182,9 +157,9 @@ void luaD_callhook (lua_State *L, int event, int line) { ar.event = event; ar.currentline = line; if (event == LUA_HOOKTAILRET) - ar.i_ci = 0; /* tail call; no debug information about it */ + ar.i_ci = NULL; /* tail call; no debug information about it */ else - ar.i_ci = cast_int(L->ci - L->base_ci); + ar.i_ci = L->ci; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ L->ci->top = L->top + LUA_MINSTACK; lua_assert(L->ci->top <= L->stack_last); @@ -235,9 +210,7 @@ static StkId tryfuncTM (lua_State *L, StkId func) { -#define inc_ci(L) \ - ((L->ci == L->end_ci) ? growCI(L) : \ - (condhardstacktests(luaD_reallocCI(L, L->size_ci)), ++L->ci)) +#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) /* @@ -265,7 +238,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { base = adjust_varargs(L, p, nargs); func = restorestack(L, funcr); /* previous call may change the stack */ } - ci = inc_ci(L); /* now `enter' new function */ + ci = next_ci(L); /* now 'enter' new function */ ci->func = func; L->base = ci->base = base; ci->top = L->base + p->maxstacksize; @@ -287,7 +260,7 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { CallInfo *ci; int n; luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ - ci = inc_ci(L); /* now `enter' new function */ + ci = next_ci(L); /* now 'enter' new function */ ci->func = restorestack(L, funcr); L->base = ci->base = ci->func + 1; ci->top = L->top + LUA_MINSTACK; @@ -318,17 +291,17 @@ static StkId callrethooks (lua_State *L, StkId firstResult) { int luaD_poscall (lua_State *L, StkId firstResult) { StkId res; int wanted, i; - CallInfo *ci; + CallInfo *ci = L->ci; if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { if (L->hookmask & LUA_MASKRET) firstResult = callrethooks(L, firstResult); - L->oldpc = (L->ci - 1)->savedpc; /* set 'oldpc' for returning function */ + L->oldpc = L->ci->previous->savedpc; /* 'oldpc' for returning function */ } - ci = L->ci--; res = ci->func; /* res == final position of 1st result */ - wanted = (ci - 1)->nresults; - L->base = (ci - 1)->base; /* restore base */ - L->savedpc = (ci - 1)->savedpc; /* restore savedpc */ + L->ci = ci = L->ci->previous; /* back to caller */ + wanted = ci->nresults; + L->base = ci->base; /* restore base */ + L->savedpc = ci->savedpc; /* restore savedpc */ /* move results to correct place */ for (i = wanted; i != 0 && firstResult < L->top; i--) setobjs2s(L, res++, firstResult++); @@ -387,7 +360,7 @@ static void finishCcall (lua_State *L) { static void unroll (lua_State *L, void *ud) { UNUSED(ud); for (;;) { - if (L->ci == L->base_ci) /* stack is empty? */ + if (L->ci == &L->base_ci) /* stack is empty? */ return; /* coroutine finished normally */ if (!isLua(L->ci)) /* C function? */ finishCcall(L); @@ -403,7 +376,7 @@ static void resume (lua_State *L, void *ud) { StkId firstArg = cast(StkId, ud); CallInfo *ci = L->ci; if (L->status == LUA_OK) { /* start coroutine? */ - lua_assert(ci == L->base_ci && firstArg > L->base); + lua_assert(ci == &L->base_ci && firstArg > L->base); if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ luaV_execute(L); /* call it */ } @@ -437,7 +410,7 @@ static int resume_error (lua_State *L, const char *msg) { */ static CallInfo *findpcall (lua_State *L) { CallInfo *ci; - for (ci = L->ci; ci > L->base_ci; ci--) { /* search for first pcall */ + for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ if (ci->callstatus & CIST_YPCALL) return ci; } @@ -471,7 +444,7 @@ LUA_API int lua_resume (lua_State *L, int nargs) { if (L->status != LUA_YIELD) { if (L->status != LUA_OK) return resume_error(L, "cannot resume dead coroutine"); - else if (L->ci != L->base_ci) + else if (L->ci != &L->base_ci) return resume_error(L, "cannot resume non-suspended coroutine"); } luai_userstateresume(L, nargs); @@ -515,7 +488,7 @@ LUA_API int lua_yield (lua_State *L, int nresults) { int luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t old_top, ptrdiff_t ef) { int status; - ptrdiff_t old_ci = saveci(L, L->ci); + CallInfo *old_ci = L->ci; lu_byte old_allowhooks = L->allowhook; unsigned short old_nny = L->nny; ptrdiff_t old_errfunc = L->errfunc; @@ -525,7 +498,7 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, StkId oldtop = restorestack(L, old_top); luaF_close(L, oldtop); /* close possible pending closures */ luaD_seterrorobj(L, status, oldtop); - L->ci = restoreci(L, old_ci); + L->ci = old_ci; L->base = L->ci->base; L->savedpc = L->ci->savedpc; L->allowhook = old_allowhooks; diff --git a/ldo.h b/ldo.h index c600bfe4..57695b0a 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 2.10 2008/08/13 17:02:42 roberto Exp roberto $ +** $Id: ldo.h,v 2.11 2009/03/10 17:14:37 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -24,9 +24,6 @@ #define savestack(L,p) ((char *)(p) - (char *)L->stack) #define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) -#define saveci(L,p) ((char *)(p) - (char *)L->base_ci) -#define restoreci(L,n) ((CallInfo *)((char *)L->base_ci + (n))) - /* type of protected functions, to be ran by `runprotected' */ typedef void (*Pfunc) (lua_State *L, void *ud); diff --git a/lgc.c b/lgc.c index 482375d0..c15c4a09 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.48 2009/02/17 19:47:58 roberto Exp roberto $ +** $Id: lgc.c,v 2.49 2009/03/10 17:14:37 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -379,38 +379,34 @@ static void traverseclosure (global_State *g, Closure *cl) { } -static void checkstacksizes (lua_State *L, StkId max) { - /* should not change the stack when handling overflow or - during an emergency gc cycle */ - if (L->size_ci > LUAI_MAXCALLS || G(L)->gckind == KGC_EMERGENCY) - return; /* do not touch the stacks */ +static void checkstacksize (lua_State *L, StkId max) { + /* should not change the stack during an emergency gc cycle */ + if (G(L)->gckind == KGC_EMERGENCY) + return; /* do not touch the stack */ else { - int ci_used = cast_int(L->ci - L->base_ci) + 1; /* number of `ci' in use */ int s_used = cast_int(max - L->stack) + 1; /* part of stack in use */ - if (2*ci_used < L->size_ci) - luaD_reallocCI(L, 2*ci_used); if (2*s_used < (L->stacksize - EXTRA_STACK)) luaD_reallocstack(L, 2*s_used); } } -static void traversestack (global_State *g, lua_State *l) { +static void traversestack (global_State *g, lua_State *L) { StkId o, lim; CallInfo *ci; - if (l->stack == NULL || l->base_ci == NULL) + if (L->stack == NULL) return; /* stack not completely built yet */ - markvalue(g, gt(l)); - lim = l->top; - for (ci = l->base_ci; ci <= l->ci; ci++) { - lua_assert(ci->top <= l->stack_last); + markvalue(g, gt(L)); + lim = L->top; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + lua_assert(ci->top <= L->stack_last); if (lim < ci->top) lim = ci->top; } - for (o = l->stack; o < l->top; o++) + for (o = L->stack; o < L->top; o++) markvalue(g, o); for (; o <= lim; o++) setnilvalue(o); - checkstacksizes(l, lim); + checkstacksize(L, lim); } @@ -445,7 +441,7 @@ static l_mem propagatemark (global_State *g) { black2gray(o); traversestack(g, th); return sizeof(lua_State) + sizeof(TValue) * th->stacksize + - sizeof(CallInfo) * th->size_ci; + sizeof(CallInfo) * th->nci; } case LUA_TPROTO: { Proto *p = gco2p(o); @@ -554,8 +550,11 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { global_State *g = G(L); int deadmask = otherwhite(g); while ((curr = *p) != NULL && count-- > 0) { - if (ttisthread(gch(curr))) /* sweep open upvalues of each thread */ - sweepwholelist(L, &gco2th(curr)->openupval); + if (ttisthread(gch(curr))) { + lua_State *L1 = gco2th(curr); + sweepwholelist(L, &L1->openupval); /* sweep open upvalues */ + luaE_freeCI(L1); /* free extra CallInfo slots */ + } if ((gch(curr)->marked ^ WHITEBITS) & deadmask) { /* not dead? */ lua_assert(!isdead(g, curr) || testbit(gch(curr)->marked, FIXEDBIT)); makewhite(g, curr); /* make it white (for next cycle) */ diff --git a/lstate.c b/lstate.c index df62f3e3..f9aa89c5 100644 --- a/lstate.c +++ b/lstate.c @@ -1,5 +1,5 @@ /* -** $Id: lstate.c,v 2.49 2009/02/18 17:20:56 roberto Exp roberto $ +** $Id: lstate.c,v 2.50 2009/03/10 17:14:37 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -40,12 +40,41 @@ typedef struct LG { +/* +** maximum number of nested calls made by error-handling function +*/ +#define LUAI_EXTRACALLS 10 + + +CallInfo *luaE_extendCI (lua_State *L) { + CallInfo *ci = luaM_new(L, CallInfo); + lua_assert(L->ci->next == NULL); + L->ci->next = ci; + ci->previous = L->ci; + ci->next = NULL; + if (++L->nci >= LUAI_MAXCALLS) { + if (L->nci == LUAI_MAXCALLS) /* overflow? */ + luaG_runerror(L, "stack overflow"); + if (L->nci >= LUAI_MAXCALLS + LUAI_EXTRACALLS) /* again? */ + luaD_throw(L, LUA_ERRERR); /* error while handling overflow */ + } + return ci; +} + + +void luaE_freeCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next = ci->next; + ci->next = NULL; + while ((ci = next) != NULL) { + next = ci->next; + luaM_free(L, ci); + L->nci--; + } +} + + static void stack_init (lua_State *L1, lua_State *L) { - /* initialize CallInfo array */ - L1->base_ci = luaM_newvector(L, BASIC_CI_SIZE, CallInfo); - L1->ci = L1->base_ci; - L1->size_ci = BASIC_CI_SIZE; - L1->end_ci = L1->base_ci + L1->size_ci - 1; /* initialize stack array */ L1->stack = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, TValue); L1->stacksize = BASIC_STACK_SIZE + EXTRA_STACK; @@ -53,16 +82,18 @@ static void stack_init (lua_State *L1, lua_State *L) { L1->stack_last = L1->stack+(L1->stacksize - EXTRA_STACK)-1; /* initialize first ci */ L1->ci->func = L1->top; - setnilvalue(L1->top++); /* `function' entry for this `ci' */ + setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ L1->base = L1->ci->base = L1->top; L1->ci->top = L1->top + LUA_MINSTACK; L1->ci->callstatus = 0; } -static void freestack (lua_State *L, lua_State *L1) { - luaM_freearray(L, L1->base_ci, L1->size_ci, CallInfo); - luaM_freearray(L, L1->stack, L1->stacksize, TValue); +static void freestack (lua_State *L) { + L->ci = &L->base_ci; /* reset 'ci' list */ + luaE_freeCI(L); + lua_assert(L->nci == 0); + luaM_freearray(L, L->stack, L->stacksize, TValue); } @@ -94,10 +125,11 @@ static void preinit_state (lua_State *L, global_State *g) { L->allowhook = 1; resethookcount(L); L->openupval = NULL; - L->size_ci = 0; L->nny = 1; L->status = LUA_OK; - L->base_ci = L->ci = NULL; + L->base_ci.next = L->base_ci.previous = NULL; + L->ci = &L->base_ci; + L->nci = 0; L->savedpc = NULL; L->errfunc = 0; setnilvalue(gt(L)); @@ -110,7 +142,7 @@ static void close_state (lua_State *L) { luaC_freeall(L); /* collect all objects */ luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *); luaZ_freebuffer(L, &g->buff); - freestack(L, L); + freestack(L); lua_assert(g->totalbytes == sizeof(LG)); (*g->frealloc)(g->ud, fromstate(L), state_size(LG), 0); } @@ -142,7 +174,7 @@ void luaE_freethread (lua_State *L, lua_State *L1) { luaF_close(L1, L1->stack); /* close all upvalues for this thread */ lua_assert(L1->openupval == NULL); luai_userstatefree(L1); - freestack(L, L1); + freestack(L1); luaM_freemem(L, fromstate(L1), state_size(lua_State)); } @@ -211,3 +243,4 @@ LUA_API void lua_close (lua_State *L) { close_state(L); } + diff --git a/lstate.h b/lstate.h index c9155a94..0e34a54c 100644 --- a/lstate.h +++ b/lstate.h @@ -1,5 +1,5 @@ /* -** $Id: lstate.h,v 2.40 2009/03/23 14:26:12 roberto Exp roberto $ +** $Id: lstate.h,v 2.41 2009/04/08 18:04:33 roberto Exp roberto $ ** Global State ** See Copyright Notice in lua.h */ @@ -80,8 +80,9 @@ typedef struct CallInfo { StkId base; /* base for this function */ StkId func; /* function index in the stack */ StkId top; /* top for this function */ + struct CallInfo *previous, *next; /* dynamic call link */ const Instruction *savedpc; - short nresults; /* expected number of results from this function */ + short nresults; /* expected number of results from a call */ lu_byte callstatus; union { struct { /* only for Lua functions */ @@ -163,14 +164,12 @@ struct lua_State { StkId base; /* base of current function */ global_State *l_G; CallInfo *ci; /* call info for current function */ + int nci; /* number of total CallInfo structures linked */ const Instruction *savedpc; /* `savedpc' of current function */ const Instruction *oldpc; /* last pc traced */ StkId stack_last; /* last free slot in the stack */ StkId stack; /* stack base */ - CallInfo *end_ci; /* points after end of ci array*/ - CallInfo *base_ci; /* array of CallInfo's */ int stacksize; - int size_ci; /* size of array `base_ci' */ unsigned short nny; /* number of non-yieldable calls in stack */ lu_byte hookmask; lu_byte allowhook; @@ -183,6 +182,7 @@ struct lua_State { GCObject *gclist; struct lua_longjmp *errorJmp; /* current error recover point */ ptrdiff_t errfunc; /* current error handling function (stack index) */ + CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ }; @@ -223,6 +223,9 @@ union GCObject { LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); +LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); +LUAI_FUNC void luaE_freeCI (lua_State *L); + #endif diff --git a/ltests.c b/ltests.c index e0de86f3..9a55f6da 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.59 2009/03/03 18:52:36 roberto Exp roberto $ +** $Id: ltests.c,v 2.60 2009/04/14 19:10:17 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -296,13 +296,10 @@ static void checkstack (global_State *g, lua_State *L1) { lua_assert(!isblack(uvo)); /* open upvalues cannot be black */ } checkliveness(g, gt(L1)); - if (L1->base_ci) { - for (ci = L1->base_ci; ci <= L1->ci; ci++) { - lua_assert(ci->top <= L1->stack_last); - lua_assert(lua_checkpc(L1, ci)); - } + for (ci = L1->ci; ci != NULL; ci = ci->previous) { + lua_assert(ci->top <= L1->stack_last); + lua_assert(lua_checkpc(L1, ci)); } - else lua_assert(L1->size_ci == 0); if (L1->stack) { for (o = L1->stack; o < L1->top; o++) checkliveness(g, o); @@ -356,10 +353,10 @@ printf(">>> %d %s %02x\n", g->gcstate, luaT_typenames[gch(o)->tt], gch(o)->mar int lua_checkpc (lua_State *L, pCallInfo ci) { - if (ci == L->base_ci || !isLua(ci)) return 1; + if (!isLua(ci)) return 1; else { Proto *p = ci_func(ci)->l.p; - if (ci < L->ci) + if (ci != L->ci) return p->code <= ci->savedpc && ci->savedpc <= p->code + p->sizecode; else return p->code <= L->savedpc && L->savedpc <= p->code + p->sizecode; @@ -575,8 +572,7 @@ static int stacklevel (lua_State *L) { unsigned long a = 0; lua_pushinteger(L, (L->top - L->stack)); lua_pushinteger(L, (L->stack_last - L->stack)); - lua_pushinteger(L, (L->ci - L->base_ci)); - lua_pushinteger(L, (L->end_ci - L->base_ci)); + lua_pushinteger(L, L->nci); lua_pushinteger(L, (unsigned long)&a); return 5; } diff --git a/lua.h b/lua.h index a55e62b6..fb725765 100644 --- a/lua.h +++ b/lua.h @@ -1,5 +1,5 @@ /* -** $Id: lua.h,v 1.234 2009/03/23 14:26:12 roberto Exp roberto $ +** $Id: lua.h,v 1.235 2009/04/08 18:04:33 roberto Exp roberto $ ** Lua - An Extensible Extension Language ** Lua.org, PUC-Rio, Brazil (http://www.lua.org) ** See Copyright Notice at the end of this file @@ -367,7 +367,7 @@ struct lua_Debug { int lastlinedefined; /* (S) */ char short_src[LUA_IDSIZE]; /* (S) */ /* private part */ - int i_ci; /* active function */ + struct CallInfo *i_ci; /* active function */ }; /* }====================================================================== */ diff --git a/lvm.c b/lvm.c index 494b40cd..0c70491d 100644 --- a/lvm.c +++ b/lvm.c @@ -1,5 +1,5 @@ /* -** $Id: lvm.c,v 2.83 2009/03/04 13:32:29 roberto Exp roberto $ +** $Id: lvm.c,v 2.84 2009/03/10 17:14:37 roberto Exp roberto $ ** Lua virtual machine ** See Copyright Notice in lua.h */ @@ -663,19 +663,19 @@ void luaV_execute (lua_State *L) { } else { /* tail call: put new frame in place of previous one */ - CallInfo *ci = L->ci - 1; /* previous frame */ - int aux; + StkId pfunc = L->ci->func; /* called function index */ + CallInfo *ci = L->ci->previous; /* caller frame */ StkId func = ci->func; - StkId pfunc = (ci+1)->func; /* previous function index */ + int aux; if (cl->p->sizep > 0) luaF_close(L, ci->base); - L->base = ci->base = ci->func + ((ci+1)->base - pfunc); + L->base = ci->base = ci->func + (L->ci->base - pfunc); for (aux = 0; pfunc+aux < L->top; aux++) /* move frame down */ setobjs2s(L, func+aux, pfunc+aux); ci->top = L->top = func+aux; /* correct top */ lua_assert(L->top == L->base + clvalue(func)->l.p->maxstacksize); ci->savedpc = L->savedpc; ci->u.l.tailcalls++; /* one more call lost */ - L->ci--; /* remove new frame */ + L->ci = ci; /* remove new frame */ goto reentry; } } @@ -684,7 +684,7 @@ void luaV_execute (lua_State *L) { if (b != 0) L->top = ra+b-1; if (cl->p->sizep > 0) luaF_close(L, base); b = luaD_poscall(L, ra); - if (!((L->ci + 1)->callstatus & CIST_REENTRY)) + if (!(L->ci->next->callstatus & CIST_REENTRY)) return; /* external invocation: return */ else { /* invocation via reentry: continue execution */ if (b) L->top = L->ci->top;