Jelajahi Sumber

parser fully reentrant(!)

Roberto Ierusalimschy 22 tahun lalu
induk
melakukan
8332d5c8a5
10 mengubah file dengan 120 tambahan dan 65 penghapusan
  1. 2 4
      lapi.c
  2. 7 5
      lcode.c
  3. 8 14
      ldo.c
  4. 2 2
      ldo.h
  5. 18 9
      lgc.c
  6. 14 4
      llex.c
  7. 2 1
      llex.h
  8. 22 15
      lobject.h
  9. 36 10
      lparser.c
  10. 9 1
      lundump.c

+ 2 - 4
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;
 }

+ 7 - 5
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++;
   }
 }

+ 8 - 14
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;
 }
 

+ 2 - 2
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);

+ 18 - 9
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; i<f->sizek; i++) {  /* mark literal strings */
     if (ttisstring(f->k+i))
       stringmark(tsvalue(f->k+i));
   }
-  for (i=0; i<f->sizeupvalues; i++)  /* mark upvalue names */
-    stringmark(f->upvalues[i]);
-  for (i=0; i<f->sizep; i++)  /* mark nested protos */
-    markvalue(st, f->p[i]);
-  for (i=0; i<f->sizelocvars; i++)  /* mark local-variable names */
-    stringmark(f->locvars[i].varname);
-  lua_assert(luaG_checkcode(f));
+  for (i=0; i<f->sizeupvalues; i++) {  /* mark upvalue names */
+    if (f->upvalues[i])
+      stringmark(f->upvalues[i]);
+  }
+  for (i=0; i<f->sizep; i++) {  /* mark nested protos */
+    if (f->p[i])
+      markvalue(st, f->p[i]);
+  }
+  for (i=0; i<f->sizelocvars; i++) {  /* mark local-variable names */
+    if (f->locvars[i].varname)
+      stringmark(f->locvars[i].varname);
+  }
 }
 
 

+ 14 - 4
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;

+ 2 - 1
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);

+ 22 - 15
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 */

+ 36 - 10
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; i<f->nups; 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; i<func->f->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;
         }

+ 9 - 1
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; i<n; i++) f->locvars[i].varname=NULL;
  for (i=0; i<n; i++)
  {
   f->locvars[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; i<n; i++) f->upvalues[i]=NULL;
  for (i=0; i<n; i++) f->upvalues[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; i<n; i++) setnilvalue(&f->k[i]);
  for (i=0; i<n; i++)
  {
   TObject* o=&f->k[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; i<n; i++) f->p[i]=NULL;
  for (i=0; i<n; i++) f->p[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;
 }