diff --git a/lapi.c b/lapi.c index 966f72ec..33eed2eb 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 1.242 2003/08/25 19:51:54 roberto Exp roberto $ +** $Id: lapi.c,v 1.243 2003/08/25 20:00:50 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -715,12 +715,10 @@ LUA_API int lua_load (lua_State *L, lua_Chunkreader reader, void *data, const char *chunkname) { ZIO z; int status; - int c; lua_lock(L); if (!chunkname) chunkname = "?"; luaZ_init(L, &z, reader, data); - c = luaZ_lookahead(&z); - status = luaD_protectedparser(L, &z, (c == LUA_SIGNATURE[0]), chunkname); + status = luaD_protectedparser(L, &z, chunkname); lua_unlock(L); return status; } diff --git a/lcode.c b/lcode.c index bb15a1cd..1f63a0d0 100644 --- a/lcode.c +++ b/lcode.c @@ -1,5 +1,5 @@ /* -** $Id: lcode.c,v 1.117 2003/04/03 13:35:34 roberto Exp roberto $ +** $Id: lcode.c,v 1.119 2003/08/27 20:58:52 roberto Exp $ ** Code generator for Lua ** See Copyright Notice in lua.h */ @@ -207,17 +207,19 @@ static void freeexp (FuncState *fs, expdesc *e) { static int addk (FuncState *fs, TObject *k, TObject *v) { - const TObject *idx = luaH_get(fs->h, k); + TObject *idx = luaH_set(fs->L, fs->h, k); + Proto *f = fs->f; + int oldsize = f->sizek; if (ttisnumber(idx)) { lua_assert(luaO_rawequalObj(&fs->f->k[cast(int, nvalue(idx))], v)); return cast(int, nvalue(idx)); } else { /* constant not found; create a new entry */ - Proto *f = fs->f; + setnvalue(idx, cast(lua_Number, fs->nk)); luaM_growvector(fs->L, f->k, fs->nk, f->sizek, TObject, MAXARG_Bx, "constant table overflow"); - setobj2n(&f->k[fs->nk], v); - setnvalue(luaH_set(fs->L, fs->h, k), cast(lua_Number, fs->nk)); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(&f->k[fs->nk], v); /* write barrier */ return fs->nk++; } } diff --git a/ldo.c b/ldo.c index 2b5dfdbf..bf244c91 100644 --- a/ldo.c +++ b/ldo.c @@ -1,5 +1,5 @@ /* -** $Id: ldo.c,v 1.222 2003/08/25 19:51:54 roberto Exp roberto $ +** $Id: ldo.c,v 1.223 2003/08/26 12:04:13 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -429,18 +429,17 @@ int luaD_pcall (lua_State *L, Pfunc func, void *u, struct SParser { /* data to `f_parser' */ ZIO *z; Mbuffer buff; /* buffer to be used by the scanner */ - int bin; const char *name; }; static void f_parser (lua_State *L, void *ud) { - struct SParser *p; Proto *tf; Closure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = luaZ_lookahead(p->z); luaC_checkGC(L); - p = cast(struct SParser *, ud); - tf = p->bin ? luaU_undump(L, p->z, &p->buff, p->name) : - luaY_parser(L, p->z, &p->buff, p->name); + tf = (c == LUA_SIGNATURE[0]) ? luaU_undump(L, p->z, &p->buff, p->name) : + luaY_parser(L, p->z, &p->buff, p->name); cl = luaF_newLclosure(L, 0, gt(L)); cl->l.p = tf; setclvalue(L->top, cl); @@ -448,18 +447,13 @@ static void f_parser (lua_State *L, void *ud) { } -int luaD_protectedparser (lua_State *L, ZIO *z, int bin, const char *name) { +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name) { struct SParser p; int status; - ptrdiff_t oldtopr = savestack(L, L->top); /* save current top */ - p.z = z; p.bin = bin; p.name = name; + p.z = z; p.name = name; luaZ_initbuffer(L, &p.buff); - status = luaD_rawrunprotected(L, f_parser, &p); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); luaZ_freebuffer(L, &p.buff); - if (status != 0) { /* error? */ - StkId oldtop = restorestack(L, oldtopr); - seterrorobj(L, status, oldtop); - } return status; } diff --git a/ldo.h b/ldo.h index af13516f..f3d528be 100644 --- a/ldo.h +++ b/ldo.h @@ -1,5 +1,5 @@ /* -** $Id: ldo.h,v 1.56 2002/12/04 17:29:32 roberto Exp roberto $ +** $Id: ldo.h,v 1.57 2003/08/25 19:51:54 roberto Exp roberto $ ** Stack and Call structure of Lua ** See Copyright Notice in lua.h */ @@ -42,7 +42,7 @@ typedef void (*Pfunc) (lua_State *L, void *ud); void luaD_resetprotection (lua_State *L); -int luaD_protectedparser (lua_State *L, ZIO *z, int bin, const char *name); +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name); void luaD_callhook (lua_State *L, int event, int line); StkId luaD_precall (lua_State *L, StkId func); void luaD_call (lua_State *L, StkId func, int nResults); diff --git a/lgc.c b/lgc.c index d5169fdc..1ec12f1d 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 1.175 2003/07/16 20:49:02 roberto Exp roberto $ +** $Id: lgc.c,v 1.176 2003/07/29 19:25:37 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -176,20 +176,29 @@ static void traversetable (GCState *st, Table *h) { } +/* +** All marks are conditional because a GC may happen while the +** prototype is still being created +*/ static void traverseproto (GCState *st, Proto *f) { int i; - stringmark(f->source); + if (f->source) stringmark(f->source); for (i=0; isizek; i++) { /* mark literal strings */ if (ttisstring(f->k+i)) stringmark(tsvalue(f->k+i)); } - for (i=0; isizeupvalues; i++) /* mark upvalue names */ - stringmark(f->upvalues[i]); - for (i=0; isizep; i++) /* mark nested protos */ - markvalue(st, f->p[i]); - for (i=0; isizelocvars; i++) /* mark local-variable names */ - stringmark(f->locvars[i].varname); - lua_assert(luaG_checkcode(f)); + for (i=0; isizeupvalues; i++) { /* mark upvalue names */ + if (f->upvalues[i]) + stringmark(f->upvalues[i]); + } + for (i=0; isizep; i++) { /* mark nested protos */ + if (f->p[i]) + markvalue(st, f->p[i]); + } + for (i=0; isizelocvars; i++) { /* mark local-variable names */ + if (f->locvars[i].varname) + stringmark(f->locvars[i].varname); + } } diff --git a/llex.c b/llex.c index 217194b6..e7b20a46 100644 --- a/llex.c +++ b/llex.c @@ -1,5 +1,5 @@ /* -** $Id: llex.c,v 1.120 2003/05/15 12:20:24 roberto Exp roberto $ +** $Id: llex.c,v 1.121 2003/08/21 14:16:43 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -111,6 +111,16 @@ static void luaX_lexerror (LexState *ls, const char *s, int token) { } +TString *luaX_newstring (LexState *LS, const char *str, size_t l) { + lua_State *L = LS->L; + TString *ts = luaS_newlstr(L, str, l); + TObject *o = luaH_setstr(L, LS->fs->h, ts); /* entry for `str' */ + if (ttisnil(o)) + setbvalue(o, 1); /* make sure `str' will not be collected */ + return ts; +} + + static void inclinenumber (LexState *LS) { int old = LS->current; lua_assert(nextIsNewline(LS)); @@ -253,7 +263,7 @@ static void read_long_string (LexState *LS, SemInfo *seminfo) { save_and_next(LS, l); /* skip the second `]' */ save(LS, '\0', l); if (seminfo) - seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 2, l - 5); + seminfo->ts = luaX_newstring(LS, luaZ_buffer(LS->buff) + 2, l - 5); } @@ -311,7 +321,7 @@ static void read_string (LexState *LS, int del, SemInfo *seminfo) { } save_and_next(LS, l); /* skip delimiter */ save(LS, '\0', l); - seminfo->ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff) + 1, l - 3); + seminfo->ts = luaX_newstring(LS, luaZ_buffer(LS->buff) + 1, l - 3); } @@ -401,7 +411,7 @@ int luaX_lex (LexState *LS, SemInfo *seminfo) { else if (isalpha(LS->current) || LS->current == '_') { /* identifier or reserved word */ size_t l = readname(LS); - TString *ts = luaS_newlstr(LS->L, luaZ_buffer(LS->buff), l); + TString *ts = luaX_newstring(LS, luaZ_buffer(LS->buff), l); if (ts->tsv.reserved > 0) /* reserved word? */ return ts->tsv.reserved - 1 + FIRST_RESERVED; seminfo->ts = ts; diff --git a/llex.h b/llex.h index 00c73c77..a97def0a 100644 --- a/llex.h +++ b/llex.h @@ -1,5 +1,5 @@ /* -** $Id: llex.h,v 1.46 2002/11/22 16:35:20 roberto Exp roberto $ +** $Id: llex.h,v 1.47 2003/02/28 17:19:47 roberto Exp roberto $ ** Lexical Analyzer ** See Copyright Notice in lua.h */ @@ -65,6 +65,7 @@ typedef struct LexState { void luaX_init (lua_State *L); void luaX_setinput (lua_State *L, LexState *LS, ZIO *z, TString *source); +TString *luaX_newstring (LexState *LS, const char *str, size_t l); int luaX_lex (LexState *LS, SemInfo *seminfo); void luaX_checklimit (LexState *ls, int val, int limit, const char *msg); void luaX_syntaxerror (LexState *ls, const char *s); diff --git a/lobject.h b/lobject.h index 7488e2fe..86bc3601 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 1.159 2003/03/18 12:50:04 roberto Exp roberto $ +** $Id: lobject.h,v 1.160 2003/04/28 19:26:16 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -92,44 +92,49 @@ typedef struct lua_TObject { #define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) /* Macros to set values */ +#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) + #define setnvalue(obj,x) \ - { TObject *i_o=(obj); i_o->tt=LUA_TNUMBER; i_o->value.n=(x); } + { TObject *i_o=(obj); i_o->value.n=(x); i_o->tt=LUA_TNUMBER; } #define chgnvalue(obj,x) \ check_exp(ttype(obj)==LUA_TNUMBER, (obj)->value.n=(x)) #define setpvalue(obj,x) \ - { TObject *i_o=(obj); i_o->tt=LUA_TLIGHTUSERDATA; i_o->value.p=(x); } + { TObject *i_o=(obj); i_o->value.p=(x); i_o->tt=LUA_TLIGHTUSERDATA; } #define setbvalue(obj,x) \ - { TObject *i_o=(obj); i_o->tt=LUA_TBOOLEAN; i_o->value.b=(x); } + { TObject *i_o=(obj); i_o->value.b=(x); i_o->tt=LUA_TBOOLEAN; } #define setsvalue(obj,x) \ - { TObject *i_o=(obj); i_o->tt=LUA_TSTRING; \ - i_o->value.gc=cast(GCObject *, (x)); \ + { TObject *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TSTRING; \ lua_assert(i_o->value.gc->gch.tt == LUA_TSTRING); } #define setuvalue(obj,x) \ - { TObject *i_o=(obj); i_o->tt=LUA_TUSERDATA; \ - i_o->value.gc=cast(GCObject *, (x)); \ + { TObject *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TUSERDATA; \ lua_assert(i_o->value.gc->gch.tt == LUA_TUSERDATA); } #define setthvalue(obj,x) \ - { TObject *i_o=(obj); i_o->tt=LUA_TTHREAD; \ - i_o->value.gc=cast(GCObject *, (x)); \ + { TObject *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTHREAD; \ lua_assert(i_o->value.gc->gch.tt == LUA_TTHREAD); } #define setclvalue(obj,x) \ - { TObject *i_o=(obj); i_o->tt=LUA_TFUNCTION; \ - i_o->value.gc=cast(GCObject *, (x)); \ + { TObject *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TFUNCTION; \ lua_assert(i_o->value.gc->gch.tt == LUA_TFUNCTION); } #define sethvalue(obj,x) \ - { TObject *i_o=(obj); i_o->tt=LUA_TTABLE; \ - i_o->value.gc=cast(GCObject *, (x)); \ + { TObject *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TTABLE; \ lua_assert(i_o->value.gc->gch.tt == LUA_TTABLE); } -#define setnilvalue(obj) ((obj)->tt=LUA_TNIL) +#define setptvalue(obj,x) \ + { TObject *i_o=(obj); \ + i_o->value.gc=cast(GCObject *, (x)); i_o->tt=LUA_TPROTO; \ + lua_assert(i_o->value.gc->gch.tt == LUA_TPROTO); } @@ -155,6 +160,8 @@ typedef struct lua_TObject { /* to stack (not from same stack) */ #define setobj2s setobj #define setsvalue2s setsvalue +#define sethvalue2s sethvalue +#define setptvalue2s setptvalue /* from table to same table */ #define setobjt2t setobj /* to table */ diff --git a/lparser.c b/lparser.c index 1eb56401..633a5693 100644 --- a/lparser.c +++ b/lparser.c @@ -1,5 +1,5 @@ /* -** $Id: lparser.c,v 1.215 2003/07/29 18:51:00 roberto Exp roberto $ +** $Id: lparser.c,v 1.216 2003/08/25 19:51:54 roberto Exp roberto $ ** Lua Parser ** See Copyright Notice in lua.h */ @@ -13,6 +13,7 @@ #include "lcode.h" #include "ldebug.h" +#include "ldo.h" #include "lfunc.h" #include "llex.h" #include "lmem.h" @@ -71,6 +72,14 @@ static void lookahead (LexState *ls) { } +static void anchor_token (LexState *ls) { + if (ls->t.token == TK_NAME || ls->t.token == TK_STRING) { + TString *ts = ls->t.seminfo.ts; + luaX_newstring(ls, getstr(ts), ts->tsv.len); + } +} + + static void error_expected (LexState *ls, int token) { luaX_syntaxerror(ls, luaO_pushfstring(ls->L, "`%s' expected", luaX_token2str(ls, token))); @@ -138,9 +147,11 @@ static void checkname(LexState *ls, expdesc *e) { static int luaI_registerlocalvar (LexState *ls, TString *varname) { FuncState *fs = ls->fs; Proto *f = fs->f; + int oldsize = f->sizelocvars; luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, LocVar, USHRT_MAX, "too many local variables"); - f->locvars[fs->nlocvars].varname = varname; + while (oldsize < f->sizelocvars) f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; /* write barrier */ return fs->nlocvars++; } @@ -170,24 +181,27 @@ static void removevars (LexState *ls, int tolevel) { static void new_localvarstr (LexState *ls, const char *name, int n) { - new_localvar(ls, luaS_new(ls->L, name), n); + TString *ts = luaX_newstring(ls, name, strlen(name)); + new_localvar(ls, ts, n); } static int indexupvalue (FuncState *fs, TString *name, expdesc *v) { int i; Proto *f = fs->f; + int oldsize = f->sizeupvalues; for (i=0; inups; i++) { if (fs->upvalues[i].k == v->k && fs->upvalues[i].info == v->info) { - lua_assert(fs->f->upvalues[i] == name); + lua_assert(f->upvalues[i] == name); return i; } } /* new one */ luaX_checklimit(fs->ls, f->nups + 1, MAXUPVALUES, "upvalues"); - luaM_growvector(fs->L, fs->f->upvalues, f->nups, fs->f->sizeupvalues, + luaM_growvector(fs->L, f->upvalues, f->nups, f->sizeupvalues, TString *, MAX_INT, ""); - fs->f->upvalues[f->nups] = name; + while (oldsize < f->sizeupvalues) f->upvalues[oldsize++] = NULL; + f->upvalues[f->nups] = name; /* write barrier */ lua_assert(v->k == VLOCAL || v->k == VUPVAL); fs->upvalues[f->nups].k = cast(lu_byte, v->k); fs->upvalues[f->nups].info = cast(lu_byte, v->info); @@ -290,10 +304,12 @@ static void leaveblock (FuncState *fs) { static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { FuncState *fs = ls->fs; Proto *f = fs->f; + int oldsize = f->sizep; int i; luaM_growvector(ls->L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "constant table overflow"); - f->p[fs->np++] = func->f; + while (oldsize < f->sizep) f->p[oldsize++] = NULL; + f->p[fs->np++] = func->f; /* write barrier */ init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np-1)); for (i=0; if->nups; i++) { OpCode o = (func->upvalues[i].k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; @@ -303,24 +319,30 @@ static void pushclosure (LexState *ls, FuncState *func, expdesc *v) { static void open_func (LexState *ls, FuncState *fs) { + lua_State *L = ls->L; Proto *f = luaF_newproto(ls->L); fs->f = f; fs->prev = ls->fs; /* linked list of funcstates */ fs->ls = ls; - fs->L = ls->L; + fs->L = L; ls->fs = fs; fs->pc = 0; fs->lasttarget = 0; fs->jpc = NO_JUMP; fs->freereg = 0; fs->nk = 0; - fs->h = luaH_new(ls->L, 0, 0); fs->np = 0; fs->nlocvars = 0; fs->nactvar = 0; fs->bl = NULL; f->source = ls->source; f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->h = luaH_new(L, 0, 0); + /* anchor table of constants and prototype (to avoid being collected) */ + sethvalue2s(L->top, fs->h); + incr_top(L); + setptvalue2s(L->top, f); + incr_top(L); } @@ -345,6 +367,9 @@ static void close_func (LexState *ls) { lua_assert(luaG_checkcode(f)); lua_assert(fs->bl == NULL); ls->fs = fs->prev; + L->top -= 2; /* remove table and prototype from the stack */ + /* last token read was anchored in defunct function; must reanchor it */ + if (fs) anchor_token(ls); } @@ -362,6 +387,7 @@ Proto *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, const char *name) { lua_assert(funcstate.prev == NULL); lua_assert(funcstate.f->nups == 0); lua_assert(lexstate.nestlevel == 0); + lua_assert(lexstate.fs == NULL); return funcstate.f; } @@ -530,7 +556,7 @@ static void parlist (LexState *ls) { case TK_DOTS: { /* param -> `...' */ next(ls); /* use `arg' as default name */ - new_localvar(ls, luaS_new(ls->L, "arg"), nparams++); + new_localvarstr(ls, "arg", nparams++); f->is_vararg = 1; break; } diff --git a/lundump.c b/lundump.c index 30f6f904..0777dc0f 100644 --- a/lundump.c +++ b/lundump.c @@ -1,5 +1,5 @@ /* -** $Id: lundump.c,v 1.62 2003/08/15 13:48:53 roberto Exp roberto $ +** $Id: lundump.c,v 1.63 2003/08/25 19:51:54 roberto Exp roberto $ ** load pre-compiled Lua chunks ** See Copyright Notice in lua.h */ @@ -9,6 +9,7 @@ #include "lua.h" #include "ldebug.h" +#include "ldo.h" #include "lfunc.h" #include "lmem.h" #include "lopcodes.h" @@ -122,6 +123,7 @@ static void LoadLocals (LoadState* S, Proto* f) n=LoadInt(S); f->locvars=luaM_newvector(S->L,n,LocVar); f->sizelocvars=n; + for (i=0; ilocvars[i].varname=NULL; for (i=0; ilocvars[i].varname=LoadString(S); @@ -147,6 +149,7 @@ static void LoadUpvalues (LoadState* S, Proto* f) S->name,n,f->nups); f->upvalues=luaM_newvector(S->L,n,TString*); f->sizeupvalues=n; + for (i=0; iupvalues[i]=NULL; for (i=0; iupvalues[i]=LoadString(S); } @@ -158,6 +161,7 @@ static void LoadConstants (LoadState* S, Proto* f) n=LoadInt(S); f->k=luaM_newvector(S->L,n,TObject); f->sizek=n; + for (i=0; ik[i]); for (i=0; ik[i]; @@ -181,12 +185,15 @@ static void LoadConstants (LoadState* S, Proto* f) n=LoadInt(S); f->p=luaM_newvector(S->L,n,Proto*); f->sizep=n; + for (i=0; ip[i]=NULL; for (i=0; ip[i]=LoadFunction(S,f->source); } static Proto* LoadFunction (LoadState* S, TString* p) { Proto* f=luaF_newproto(S->L); + setptvalue2s(S->L->top, f); + incr_top(S->L); f->source=LoadString(S); if (f->source==NULL) f->source=p; f->lineDefined=LoadInt(S); f->nups=LoadByte(S); @@ -201,6 +208,7 @@ static Proto* LoadFunction (LoadState* S, TString* p) #ifndef TRUST_BINARIES if (!luaG_checkcode(f)) luaG_runerror(S->L,"bad code in %s",S->name); #endif + S->L->top--; return f; }