aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2010-02-08 05:26:52 +0100
committerMike Pall <mike>2010-02-08 05:26:52 +0100
commit60b5af44222fff87a7184365a7f49654032d4cbf (patch)
tree9c108bc330f16ef8914c3bea84b5170000788932 /src
parent1307f49137f328b0880c736644755428d84be0ba (diff)
downloadluajit-60b5af44222fff87a7184365a7f49654032d4cbf.tar.gz
luajit-60b5af44222fff87a7184365a7f49654032d4cbf.tar.bz2
luajit-60b5af44222fff87a7184365a7f49654032d4cbf.zip
Redesign of prototype generation, part 1: varinfo and uvname.
Use a growable, per-chunk variable stack. Collect varinfo/uvname for prototype at the end.
Diffstat (limited to 'src')
-rw-r--r--src/lj_api.c6
-rw-r--r--src/lj_errmsg.h1
-rw-r--r--src/lj_gc.c6
-rw-r--r--src/lj_lex.c14
-rw-r--r--src/lj_lex.h6
-rw-r--r--src/lj_parse.c172
6 files changed, 109 insertions, 96 deletions
diff --git a/src/lj_api.c b/src/lj_api.c
index 8216c395..48bd605d 100644
--- a/src/lj_api.c
+++ b/src/lj_api.c
@@ -1102,7 +1102,7 @@ static TValue *cpparser(lua_State *L, lua_CFunction dummy, void *ud)
1102 GCfunc *fn; 1102 GCfunc *fn;
1103 UNUSED(dummy); 1103 UNUSED(dummy);
1104 cframe_errfunc(L->cframe) = -1; /* Inherit error function. */ 1104 cframe_errfunc(L->cframe) = -1; /* Inherit error function. */
1105 lj_lex_start(L, ls); 1105 lj_lex_setup(L, ls);
1106 fn = lj_func_newL(L, lj_parse(ls), tabref(L->env)); 1106 fn = lj_func_newL(L, lj_parse(ls), tabref(L->env));
1107 /* Parser may realloc stack. Don't combine above/below into one statement. */ 1107 /* Parser may realloc stack. Don't combine above/below into one statement. */
1108 setfuncV(L, L->top++, fn); 1108 setfuncV(L, L->top++, fn);
@@ -1114,14 +1114,12 @@ LUA_API int lua_load(lua_State *L, lua_Reader reader, void *data,
1114{ 1114{
1115 LexState ls; 1115 LexState ls;
1116 int status; 1116 int status;
1117 global_State *g;
1118 ls.rfunc = reader; 1117 ls.rfunc = reader;
1119 ls.rdata = data; 1118 ls.rdata = data;
1120 ls.chunkarg = chunkname ? chunkname : "?"; 1119 ls.chunkarg = chunkname ? chunkname : "?";
1121 lj_str_initbuf(L, &ls.sb); 1120 lj_str_initbuf(L, &ls.sb);
1122 status = lj_vm_cpcall(L, NULL, &ls, cpparser); 1121 status = lj_vm_cpcall(L, NULL, &ls, cpparser);
1123 g = G(L); 1122 lj_lex_cleanup(L, &ls);
1124 lj_str_freebuf(g, &ls.sb);
1125 lj_gc_check(L); 1123 lj_gc_check(L);
1126 return status; 1124 return status;
1127} 1125}
diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h
index 826366a6..0a2d9dd7 100644
--- a/src/lj_errmsg.h
+++ b/src/lj_errmsg.h
@@ -118,6 +118,7 @@ ERRDEF(XBCLOAD, "cannot load Lua bytecode")
118ERRDEF(XTOKEN, LUA_QS " expected") 118ERRDEF(XTOKEN, LUA_QS " expected")
119ERRDEF(XJUMP, "control structure too long") 119ERRDEF(XJUMP, "control structure too long")
120ERRDEF(XSLOTS, "function or expression too complex") 120ERRDEF(XSLOTS, "function or expression too complex")
121ERRDEF(XLIMC, "chunk has more than %d local variables")
121ERRDEF(XLIMM, "main function has more than %d %s") 122ERRDEF(XLIMM, "main function has more than %d %s")
122ERRDEF(XLIMF, "function at line %d has more than %d %s") 123ERRDEF(XLIMF, "function at line %d has more than %d %s")
123ERRDEF(XMATCH, LUA_QS " expected (to close " LUA_QS " at line %d)") 124ERRDEF(XMATCH, LUA_QS " expected (to close " LUA_QS " at line %d)")
diff --git a/src/lj_gc.c b/src/lj_gc.c
index c1ade95a..5750d0ef 100644
--- a/src/lj_gc.c
+++ b/src/lj_gc.c
@@ -256,11 +256,9 @@ static void gc_traverse_proto(global_State *g, GCproto *pt)
256 for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */ 256 for (i = -(ptrdiff_t)pt->sizekgc; i < 0; i++) /* Mark collectable consts. */
257 gc_markobj(g, proto_kgc(pt, i)); 257 gc_markobj(g, proto_kgc(pt, i));
258 for (i = 0; i < (ptrdiff_t)pt->sizeuvname; i++) /* Mark upvalue names. */ 258 for (i = 0; i < (ptrdiff_t)pt->sizeuvname; i++) /* Mark upvalue names. */
259 if (proto_uvname(pt, i)) 259 gc_mark_str(gco2str(proto_uvname(pt, i)));
260 gc_mark_str(gco2str(proto_uvname(pt, i)));
261 for (i = 0; i < (ptrdiff_t)pt->sizevarinfo; i++) /* Mark names of locals. */ 260 for (i = 0; i < (ptrdiff_t)pt->sizevarinfo; i++) /* Mark names of locals. */
262 if (gcref(proto_varinfo(pt)[i].name)) 261 gc_mark_str(gco2str(gcref(proto_varinfo(pt)[i].name)));
263 gc_mark_str(gco2str(gcref(proto_varinfo(pt)[i].name)));
264} 262}
265 263
266/* Traverse the frame structure of a stack. */ 264/* Traverse the frame structure of a stack. */
diff --git a/src/lj_lex.c b/src/lj_lex.c
index d1df138e..28aad901 100644
--- a/src/lj_lex.c
+++ b/src/lj_lex.c
@@ -301,12 +301,16 @@ static int llex(LexState *ls, TValue *tv)
301 301
302/* -- Lexer API ----------------------------------------------------------- */ 302/* -- Lexer API ----------------------------------------------------------- */
303 303
304void lj_lex_start(lua_State *L, LexState *ls) 304/* Setup lexer state. */
305void lj_lex_setup(lua_State *L, LexState *ls)
305{ 306{
306 ls->L = L; 307 ls->L = L;
307 ls->fs = NULL; 308 ls->fs = NULL;
308 ls->n = 0; 309 ls->n = 0;
309 ls->p = NULL; 310 ls->p = NULL;
311 ls->vstack = NULL;
312 ls->sizevstack = 0;
313 ls->vtop = 0;
310 ls->lookahead = TK_eof; /* No look-ahead token. */ 314 ls->lookahead = TK_eof; /* No look-ahead token. */
311 ls->linenumber = 1; 315 ls->linenumber = 1;
312 ls->lastline = 1; 316 ls->lastline = 1;
@@ -335,6 +339,14 @@ void lj_lex_start(lua_State *L, LexState *ls)
335 ls->chunkname = lj_str_newz(L, ls->chunkarg); 339 ls->chunkname = lj_str_newz(L, ls->chunkarg);
336} 340}
337 341
342/* Cleanup lexer state. */
343void lj_lex_cleanup(lua_State *L, LexState *ls)
344{
345 global_State *g = G(L);
346 lj_mem_freevec(g, ls->vstack, ls->sizevstack, VarInfo);
347 lj_str_freebuf(g, &ls->sb);
348}
349
338void lj_lex_next(LexState *ls) 350void lj_lex_next(LexState *ls)
339{ 351{
340 ls->lastline = ls->linenumber; 352 ls->lastline = ls->linenumber;
diff --git a/src/lj_lex.h b/src/lj_lex.h
index cc5d5a9f..ee183b40 100644
--- a/src/lj_lex.h
+++ b/src/lj_lex.h
@@ -50,10 +50,14 @@ typedef struct LexState {
50 BCLine lastline; /* Line of last token. */ 50 BCLine lastline; /* Line of last token. */
51 GCstr *chunkname; /* Current chunk name (interned string). */ 51 GCstr *chunkname; /* Current chunk name (interned string). */
52 const char *chunkarg; /* Chunk name argument. */ 52 const char *chunkarg; /* Chunk name argument. */
53 VarInfo *vstack; /* Stack for names and extents of local variables. */
54 MSize sizevstack; /* Size of variable stack. */
55 MSize vtop; /* Top of variable stack. */
53 uint32_t level; /* Syntactical nesting level. */ 56 uint32_t level; /* Syntactical nesting level. */
54} LexState; 57} LexState;
55 58
56LJ_FUNC void lj_lex_start(lua_State *L, LexState *ls); 59LJ_FUNC void lj_lex_setup(lua_State *L, LexState *ls);
60LJ_FUNC void lj_lex_cleanup(lua_State *L, LexState *ls);
57LJ_FUNC void lj_lex_next(LexState *ls); 61LJ_FUNC void lj_lex_next(LexState *ls);
58LJ_FUNC LexToken lj_lex_lookahead(LexState *ls); 62LJ_FUNC LexToken lj_lex_lookahead(LexState *ls);
59LJ_FUNC const char *lj_lex_token2str(LexState *ls, LexToken token); 63LJ_FUNC const char *lj_lex_token2str(LexState *ls, LexToken token);
diff --git a/src/lj_parse.c b/src/lj_parse.c
index 96136280..d949698f 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -88,11 +88,15 @@ typedef struct FuncScope {
88 uint8_t isbreakable; /* Scope is a loop and allows a break. */ 88 uint8_t isbreakable; /* Scope is a loop and allows a break. */
89} FuncScope; 89} FuncScope;
90 90
91/* Upvalue type and location. */ 91/* Index into variable stack. */
92typedef struct UVLoc { 92typedef uint16_t VarIndex;
93 uint8_t k; /* Upvalue type (ExpKind). */ 93#define LJ_MAX_VSTACK 65536
94 uint8_t info; /* Upvalue location (BCReg or uvidx). */ 94
95} UVLoc; 95/* Upvalue map. */
96typedef struct UVMap {
97 VarIndex vidx; /* Varinfo index. */
98 uint16_t slot; /* Slot or parent upvalue index. */
99} UVMap;
96 100
97/* Per-function state. */ 101/* Per-function state. */
98typedef struct FuncState { 102typedef struct FuncState {
@@ -108,13 +112,13 @@ typedef struct FuncState {
108 BCReg freereg; /* First free register. */ 112 BCReg freereg; /* First free register. */
109 BCReg nkn, nkgc; /* Number of lua_Number/GCobj constants */ 113 BCReg nkn, nkgc; /* Number of lua_Number/GCobj constants */
110 BCLine linedefined; /* First line of the function definition. */ 114 BCLine linedefined; /* First line of the function definition. */
111 MSize nvarinfo; /* Number of entries in varinfo. */ 115 MSize vbase; /* Base of variable stack for this function. */
112 uint8_t nactvar; /* Number of active local variables. */ 116 uint8_t nactvar; /* Number of active local variables. */
113 uint8_t flags; /* Prototype flags. */ 117 uint8_t flags; /* Prototype flags. */
114 uint8_t framesize; /* Fixed frame size. */ 118 uint8_t framesize; /* Fixed frame size. */
115 uint8_t nuv; /* Number of upvalues */ 119 uint8_t nuv; /* Number of upvalues */
116 uint16_t varmap[LJ_MAX_LOCVAR]; /* Map from register to varinfo index. */ 120 VarIndex varmap[LJ_MAX_LOCVAR]; /* Map from register to variable idx. */
117 UVLoc uvloc[LJ_MAX_UPVAL]; /* Upvalue type and location. */ 121 UVMap uvloc[LJ_MAX_UPVAL]; /* Map from upvalue to variable idx and slot. */
118} FuncState; 122} FuncState;
119 123
120/* Binary and unary operators. ORDER OPR */ 124/* Binary and unary operators. ORDER OPR */
@@ -924,28 +928,27 @@ static GCstr *lex_str(LexState *ls)
924 928
925/* -- Variable handling --------------------------------------------------- */ 929/* -- Variable handling --------------------------------------------------- */
926 930
927#define var_get(fs, i) (proto_varinfo((fs)->pt)[(fs)->varmap[(i)]]) 931#define var_get(ls, fs, i) ((ls)->vstack[(fs)->varmap[(i)]])
928 932
929/* Define a new local variable. */ 933/* Define a new local variable. */
930static void var_new(LexState *ls, BCReg n, GCstr *name) 934static void var_new(LexState *ls, BCReg n, GCstr *name)
931{ 935{
932 FuncState *fs = ls->fs; 936 FuncState *fs = ls->fs;
933 GCproto *pt = fs->pt; 937 MSize vtop = ls->vtop;
934 VarInfo *varinfo = proto_varinfo(pt);
935 checklimit(fs, fs->nactvar+n, LJ_MAX_LOCVAR, "local variables"); 938 checklimit(fs, fs->nactvar+n, LJ_MAX_LOCVAR, "local variables");
936 if (LJ_UNLIKELY(fs->nvarinfo >= pt->sizevarinfo)) { 939 if (LJ_UNLIKELY(vtop >= ls->sizevstack)) {
937 MSize oldsize = pt->sizevarinfo; 940 if (ls->sizevstack >= LJ_MAX_VSTACK)
938 checklimit(fs, fs->nvarinfo, 32767, "local variables"); 941 lj_lex_error(ls, 0, LJ_ERR_XLIMC, LJ_MAX_VSTACK);
939 lj_mem_growvec(fs->L, varinfo, pt->sizevarinfo, 32767, VarInfo); 942 lj_mem_growvec(ls->L, ls->vstack, ls->sizevstack, LJ_MAX_VSTACK, VarInfo);
940 setmref(pt->varinfo, varinfo);
941 while (oldsize < pt->sizevarinfo) setgcrefnull(varinfo[oldsize++].name);
942 } 943 }
943 setgcref(varinfo[fs->nvarinfo].name, obj2gco(name)); 944 lua_assert(lj_tab_getstr(fs->kt, name) != NULL);
944 lj_gc_objbarrier(ls->L, pt, name); 945 /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */
945 fs->varmap[fs->nactvar+n] = (uint16_t)(fs->nvarinfo++); 946 setgcref(ls->vstack[vtop].name, obj2gco(name));
947 fs->varmap[fs->nactvar+n] = (uint16_t)vtop;
948 ls->vtop = vtop+1;
946} 949}
947 950
948#define var_new_lit(ls, v, n) \ 951#define var_new_lit(ls, n, v) \
949 var_new(ls, (n), lj_parse_keepstr(ls, "" v, sizeof(v)-1)) 952 var_new(ls, (n), lj_parse_keepstr(ls, "" v, sizeof(v)-1))
950 953
951/* Add local variables. */ 954/* Add local variables. */
@@ -954,7 +957,7 @@ static void var_add(LexState *ls, BCReg nvars)
954 FuncState *fs = ls->fs; 957 FuncState *fs = ls->fs;
955 fs->nactvar = cast_byte(fs->nactvar + nvars); 958 fs->nactvar = cast_byte(fs->nactvar + nvars);
956 for (; nvars; nvars--) 959 for (; nvars; nvars--)
957 var_get(fs, fs->nactvar - nvars).startpc = fs->pc; 960 var_get(ls, fs, fs->nactvar - nvars).startpc = fs->pc;
958} 961}
959 962
960/* Remove local variables. */ 963/* Remove local variables. */
@@ -962,7 +965,7 @@ static void var_remove(LexState *ls, BCReg tolevel)
962{ 965{
963 FuncState *fs = ls->fs; 966 FuncState *fs = ls->fs;
964 while (fs->nactvar > tolevel) 967 while (fs->nactvar > tolevel)
965 var_get(fs, --fs->nactvar).endpc = fs->pc; 968 var_get(ls, fs, --fs->nactvar).endpc = fs->pc;
966} 969}
967 970
968/* Lookup local variable name. */ 971/* Lookup local variable name. */
@@ -970,46 +973,33 @@ static BCReg var_lookup_local(FuncState *fs, GCstr *n)
970{ 973{
971 int i; 974 int i;
972 for (i = fs->nactvar-1; i >= 0; i--) { 975 for (i = fs->nactvar-1; i >= 0; i--) {
973 if (n == gco2str(gcref(var_get(fs, i).name))) 976 if (n == gco2str(gcref(var_get(fs->ls, fs, i).name)))
974 return (BCReg)i; 977 return (BCReg)i;
975 } 978 }
976 return (BCReg)-1; /* Not found. */ 979 return (BCReg)-1; /* Not found. */
977} 980}
978 981
979/* Lookup upvalue name. */ 982/* Lookup or add upvalue index. */
980static uint32_t var_lookup_uv(FuncState *fs, GCstr *name, ExpDesc *v) 983static MSize var_lookup_uv(FuncState *fs, MSize vidx, ExpDesc *e)
981{ 984{
982 uint32_t i; 985 MSize i, n = fs->nuv;
983 GCproto *pt = fs->pt; 986 for (i = 0; i < n; i++)
984 GCRef *uvname; 987 if (fs->uvloc[i].vidx == vidx)
985 for (i = 0; i < fs->nuv; i++) { 988 return i; /* Already exists. */
986 if (fs->uvloc[i].info == v->u.s.info && fs->uvloc[i].k == v->k) { 989 /* Otherwise create a new one. */
987 lua_assert(gco2str(proto_uvname(pt, i)) == name); 990 checklimit(fs, fs->nuv, LJ_MAX_UPVAL, "upvalues");
988 return i; 991 lua_assert(e->k == VLOCAL || e->k == VUPVAL);
989 } 992 fs->uvloc[n].vidx = (uint16_t)vidx;
990 } 993 fs->uvloc[n].slot = (uint16_t)(e->u.s.info | (e->k == VLOCAL ? 0x8000 : 0));
991 /* Not found, create a new upvalue for this name. */ 994 fs->nuv = n+1;
992 uvname = mref(pt->uvname, GCRef); 995 return n;
993 if (LJ_UNLIKELY(fs->nuv >= pt->sizeuvname)) {
994 MSize oldsize = pt->sizeuvname;
995 checklimit(fs, fs->nuv, LJ_MAX_UPVAL, "upvalues");
996 lj_mem_growvec(fs->L, uvname, pt->sizeuvname, LJ_MAX_UPVAL, GCRef);
997 setmref(pt->uvname, uvname);
998 while (oldsize < pt->sizeuvname) setgcrefnull(uvname[oldsize++]);
999 }
1000 setgcref(uvname[fs->nuv], obj2gco(name));
1001 lj_gc_objbarrier(fs->L, pt, name);
1002 lua_assert(v->k == VLOCAL || v->k == VUPVAL);
1003 fs->uvloc[fs->nuv].k = cast_byte(v->k);
1004 fs->uvloc[fs->nuv].info = cast_byte(v->u.s.info);
1005 return fs->nuv++;
1006} 996}
1007 997
1008/* Forward declaration. */ 998/* Forward declaration. */
1009static void scope_uvmark(FuncState *fs, BCReg level); 999static void scope_uvmark(FuncState *fs, BCReg level);
1010 1000
1011/* Recursively lookup variables in enclosing functions. */ 1001/* Recursively lookup variables in enclosing functions. */
1012static int var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first) 1002static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first)
1013{ 1003{
1014 if (fs) { 1004 if (fs) {
1015 BCReg reg = var_lookup_local(fs, name); 1005 BCReg reg = var_lookup_local(fs, name);
@@ -1017,17 +1007,20 @@ static int var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first)
1017 expr_init(e, VLOCAL, reg); 1007 expr_init(e, VLOCAL, reg);
1018 if (!first) 1008 if (!first)
1019 scope_uvmark(fs, reg); /* Scope now has an upvalue. */ 1009 scope_uvmark(fs, reg); /* Scope now has an upvalue. */
1020 return 1; 1010 return (MSize)fs->varmap[reg];
1021 } else if (var_lookup_(fs->prev, name, e, 0)) { /* In outer function? */ 1011 } else {
1022 e->u.s.info = var_lookup_uv(fs, name, e); /* Make it an upvalue here. */ 1012 MSize vidx = var_lookup_(fs->prev, name, e, 0); /* Var in outer func? */
1023 e->k = VUPVAL; 1013 if ((int32_t)vidx >= 0) { /* Yes, make it an upvalue here. */
1024 return 1; 1014 e->u.s.info = (uint8_t)var_lookup_uv(fs, vidx, e);
1015 e->k = VUPVAL;
1016 return vidx;
1017 }
1025 } 1018 }
1026 } else { /* Not found in any function, must be a global. */ 1019 } else { /* Not found in any function, must be a global. */
1027 expr_init(e, VGLOBAL, 0); 1020 expr_init(e, VGLOBAL, 0);
1028 e->u.sval = name; 1021 e->u.sval = name;
1029 } 1022 }
1030 return 0; /* Global. */ 1023 return (MSize)-1; /* Global. */
1031} 1024}
1032 1025
1033/* Lookup variable name. */ 1026/* Lookup variable name. */
@@ -1080,15 +1073,12 @@ static void fs_fixup_k(FuncState *fs, GCproto *pt)
1080/* Fixup upvalues for prototype. */ 1073/* Fixup upvalues for prototype. */
1081static void fs_fixup_uv(FuncState *fs, GCproto *pt) 1074static void fs_fixup_uv(FuncState *fs, GCproto *pt)
1082{ 1075{
1083 uint32_t i; 1076 MSize i, n = fs->nuv;
1084 uint16_t *uv = lj_mem_newvec(fs->L, fs->nuv, uint16_t); 1077 uint16_t *uv = lj_mem_newvec(fs->L, n, uint16_t);
1085 setmref(pt->uv, uv); 1078 setmref(pt->uv, uv);
1086 pt->sizeuv = fs->nuv; 1079 pt->sizeuv = n;
1087 for (i = 0; i < pt->sizeuv; i++) { 1080 for (i = 0; i < n; i++)
1088 uint32_t v = fs->uvloc[i].info; 1081 uv[i] = fs->uvloc[i].slot;
1089 if (fs->uvloc[i].k == VLOCAL) v |= 0x8000;
1090 uv[i] = (uint16_t)v;
1091 }
1092} 1082}
1093 1083
1094/* Check if bytecode op returns. */ 1084/* Check if bytecode op returns. */
@@ -1143,9 +1133,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1143 FuncState *fs = ls->fs; 1133 FuncState *fs = ls->fs;
1144 GCproto *pt = fs->pt; 1134 GCproto *pt = fs->pt;
1145 BCIns *bc; 1135 BCIns *bc;
1146 GCRef *uvname;
1147 BCLine *lineinfo; 1136 BCLine *lineinfo;
1148 VarInfo *varinfo;
1149 1137
1150 /* Apply final fixups. */ 1138 /* Apply final fixups. */
1151 var_remove(ls, 0); 1139 var_remove(ls, 0);
@@ -1156,21 +1144,31 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1156 lj_mem_reallocvec(L, bc, pt->sizebc, fs->pc, BCIns); 1144 lj_mem_reallocvec(L, bc, pt->sizebc, fs->pc, BCIns);
1157 setmref(pt->bc, bc); 1145 setmref(pt->bc, bc);
1158 pt->sizebc = fs->pc; 1146 pt->sizebc = fs->pc;
1147
1159 fs_fixup_k(fs, pt); 1148 fs_fixup_k(fs, pt);
1160 fs_fixup_uv(fs, pt); 1149 fs_fixup_uv(fs, pt);
1150
1161 lineinfo = proto_lineinfo(pt); 1151 lineinfo = proto_lineinfo(pt);
1162 lj_mem_reallocvec(L, lineinfo, pt->sizelineinfo, fs->pc, BCLine); 1152 lj_mem_reallocvec(L, lineinfo, pt->sizelineinfo, fs->pc, BCLine);
1163 setmref(pt->lineinfo, lineinfo); 1153 setmref(pt->lineinfo, lineinfo);
1164 pt->sizelineinfo = fs->pc; 1154 pt->sizelineinfo = fs->pc;
1165 varinfo = proto_varinfo(pt); 1155
1166 lj_mem_reallocvec(L, varinfo, pt->sizevarinfo, fs->nvarinfo, VarInfo); 1156 {
1167 setmref(pt->varinfo, varinfo); 1157 MSize n = ls->vtop - fs->vbase;
1168 pt->sizevarinfo = fs->nvarinfo; 1158 VarInfo *vi = lj_mem_newvec(L, n, VarInfo);
1169 uvname = mref(pt->uvname, GCRef); 1159 memcpy(vi, &ls->vstack[fs->vbase], n*sizeof(VarInfo));
1170 lj_mem_reallocvec(L, uvname, pt->sizeuvname, fs->nuv, GCRef); 1160 setmref(pt->varinfo, vi);
1171 setmref(pt->uvname, uvname); 1161 pt->sizevarinfo = n;
1172 pt->sizeuvname = fs->nuv; 1162 }
1173 lua_assert(fs->bl == NULL); 1163
1164 {
1165 MSize i, n = fs->nuv;
1166 GCRef *uvname = lj_mem_newvec(L, n, GCRef);
1167 for (i = 0; i < n; i++)
1168 setgcref(uvname[i], gcref(ls->vstack[fs->uvloc[i].vidx].name));
1169 setmref(pt->uvname, uvname);
1170 pt->sizeuvname = n;
1171 }
1174 1172
1175 /* Initialize prototype fields. */ 1173 /* Initialize prototype fields. */
1176 pt->flags = fs->flags; 1174 pt->flags = fs->flags;
@@ -1182,7 +1180,9 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1182 setprotoV(L, L->top++, pt); 1180 setprotoV(L, L->top++, pt);
1183 ); 1181 );
1184 1182
1185 /* Remove FuncState from list. Pop const table and prototype. */ 1183 /* Remove VarInfo and FuncState. Pop const table and prototype. */
1184 lua_assert(fs->bl == NULL);
1185 ls->vtop = fs->vbase;
1186 ls->fs = fs->prev; 1186 ls->fs = fs->prev;
1187 L->top -= 2; 1187 L->top -= 2;
1188 lua_assert(ls->fs != NULL || ls->token == TK_eof); 1188 lua_assert(ls->fs != NULL || ls->token == TK_eof);
@@ -1202,6 +1202,7 @@ static void fs_init(LexState *ls, FuncState *fs, BCLine line)
1202 fs->pt = pt; 1202 fs->pt = pt;
1203 fs->prev = ls->fs; ls->fs = fs; /* Append to list. */ 1203 fs->prev = ls->fs; ls->fs = fs; /* Append to list. */
1204 fs->ls = ls; 1204 fs->ls = ls;
1205 fs->vbase = ls->vtop;
1205 fs->L = L; 1206 fs->L = L;
1206 fs->pc = 0; 1207 fs->pc = 0;
1207 fs->lasttarget = 0; 1208 fs->lasttarget = 0;
@@ -1209,7 +1210,6 @@ static void fs_init(LexState *ls, FuncState *fs, BCLine line)
1209 fs->freereg = 0; 1210 fs->freereg = 0;
1210 fs->nkgc = 0; 1211 fs->nkgc = 0;
1211 fs->nkn = 0; 1212 fs->nkn = 0;
1212 fs->nvarinfo = 0;
1213 fs->nactvar = 0; 1213 fs->nactvar = 0;
1214 fs->nuv = 0; 1214 fs->nuv = 0;
1215 fs->bl = NULL; 1215 fs->bl = NULL;
@@ -1382,7 +1382,7 @@ static void parse_params(LexState *ls, int needself)
1382 BCReg nparams = 0; 1382 BCReg nparams = 0;
1383 lex_check(ls, '('); 1383 lex_check(ls, '(');
1384 if (needself) { 1384 if (needself) {
1385 var_new_lit(ls, "self", 0); 1385 var_new_lit(ls, 0, "self");
1386 var_add(ls, 1); 1386 var_add(ls, 1);
1387 } 1387 }
1388 if (ls->token != ')') { 1388 if (ls->token != ')') {
@@ -1921,7 +1921,7 @@ static void parse_local(LexState *ls)
1921 parse_body(ls, &b, 0, ls->linenumber); 1921 parse_body(ls, &b, 0, ls->linenumber);
1922 bcemit_store(fs, &v, &b); 1922 bcemit_store(fs, &v, &b);
1923 /* The upvalue is in scope, but the local is only valid after the store. */ 1923 /* The upvalue is in scope, but the local is only valid after the store. */
1924 var_get(fs, fs->nactvar - 1).startpc = fs->pc; 1924 var_get(ls, fs, fs->nactvar - 1).startpc = fs->pc;
1925 } else { /* Local variable declaration. */ 1925 } else { /* Local variable declaration. */
1926 ExpDesc e; 1926 ExpDesc e;
1927 BCReg nexps, nvars = 0; 1927 BCReg nexps, nvars = 0;
@@ -2045,9 +2045,9 @@ static void parse_for_num(LexState *ls, GCstr *varname, BCLine line)
2045 FuncState *fs = ls->fs; 2045 FuncState *fs = ls->fs;
2046 BCReg base = fs->freereg; 2046 BCReg base = fs->freereg;
2047 /* Hidden control variables. */ 2047 /* Hidden control variables. */
2048 var_new_lit(ls, "(for index)", FORL_IDX); 2048 var_new_lit(ls, FORL_IDX, "(for index)");
2049 var_new_lit(ls, "(for limit)", FORL_STOP); 2049 var_new_lit(ls, FORL_STOP, "(for limit)");
2050 var_new_lit(ls, "(for step)", FORL_STEP); 2050 var_new_lit(ls, FORL_STEP, "(for step)");
2051 /* Visible copy of index variable. */ 2051 /* Visible copy of index variable. */
2052 var_new(ls, FORL_EXT, varname); 2052 var_new(ls, FORL_EXT, varname);
2053 lex_check(ls, '='); 2053 lex_check(ls, '=');
@@ -2072,9 +2072,9 @@ static void parse_for_iter(LexState *ls, GCstr *indexname)
2072 BCLine line; 2072 BCLine line;
2073 BCReg base = fs->freereg; 2073 BCReg base = fs->freereg;
2074 /* Hidden control variables. */ 2074 /* Hidden control variables. */
2075 var_new_lit(ls, "(for generator)", nvars++); 2075 var_new_lit(ls, nvars++, "(for generator)");
2076 var_new_lit(ls, "(for state)", nvars++); 2076 var_new_lit(ls, nvars++, "(for state)");
2077 var_new_lit(ls, "(for control)", nvars++); 2077 var_new_lit(ls, nvars++, "(for control)");
2078 /* Visible variables returned from iterator. */ 2078 /* Visible variables returned from iterator. */
2079 var_new(ls, nvars++, indexname); 2079 var_new(ls, nvars++, indexname);
2080 while (lex_opt(ls, ',')) 2080 while (lex_opt(ls, ','))