aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2012-09-16 18:46:04 +0200
committerMike Pall <mike>2012-09-16 18:46:04 +0200
commitead325b0c9deafb23f499f9739acca3bb36c3e46 (patch)
treeba120a3bb3c5fb2d8b4cf30ab5341d619cba52f3
parentaed20093781541c19b5c7d6149eda71a7141bc1c (diff)
downloadluajit-ead325b0c9deafb23f499f9739acca3bb36c3e46.tar.gz
luajit-ead325b0c9deafb23f499f9739acca3bb36c3e46.tar.bz2
luajit-ead325b0c9deafb23f499f9739acca3bb36c3e46.zip
From Lua 5.2: Add goto and ::label:: statements.
-rw-r--r--src/lj_errmsg.h5
-rw-r--r--src/lj_lex.c5
-rw-r--r--src/lj_lex.h5
-rw-r--r--src/lj_parse.c517
-rw-r--r--src/lj_record.c2
5 files changed, 362 insertions, 172 deletions
diff --git a/src/lj_errmsg.h b/src/lj_errmsg.h
index dd3eefa8..c07d4387 100644
--- a/src/lj_errmsg.h
+++ b/src/lj_errmsg.h
@@ -134,8 +134,11 @@ ERRDEF(XFUNARG, "function arguments expected")
134ERRDEF(XSYMBOL, "unexpected symbol") 134ERRDEF(XSYMBOL, "unexpected symbol")
135ERRDEF(XDOTS, "cannot use " LUA_QL("...") " outside a vararg function") 135ERRDEF(XDOTS, "cannot use " LUA_QL("...") " outside a vararg function")
136ERRDEF(XSYNTAX, "syntax error") 136ERRDEF(XSYNTAX, "syntax error")
137ERRDEF(XBREAK, "no loop to break")
138ERRDEF(XFOR, LUA_QL("=") " or " LUA_QL("in") " expected") 137ERRDEF(XFOR, LUA_QL("=") " or " LUA_QL("in") " expected")
138ERRDEF(XBREAK, "no loop to break")
139ERRDEF(XLUNDEF, "undefined label " LUA_QS)
140ERRDEF(XLDUP, "duplicate label " LUA_QS)
141ERRDEF(XGSCOPE, "<goto %s> jumps into the scope of local " LUA_QS)
139 142
140/* Bytecode reader errors. */ 143/* Bytecode reader errors. */
141ERRDEF(BCFMT, "cannot load incompatible bytecode") 144ERRDEF(BCFMT, "cannot load incompatible bytecode")
diff --git a/src/lj_lex.c b/src/lj_lex.c
index c85ea314..e464f420 100644
--- a/src/lj_lex.c
+++ b/src/lj_lex.c
@@ -272,9 +272,9 @@ static int llex(LexState *ls, TValue *tv)
272 save_and_next(ls); 272 save_and_next(ls);
273 } while (lj_char_isident(ls->current)); 273 } while (lj_char_isident(ls->current));
274 s = lj_parse_keepstr(ls, ls->sb.buf, ls->sb.n); 274 s = lj_parse_keepstr(ls, ls->sb.buf, ls->sb.n);
275 setstrV(ls->L, tv, s);
275 if (s->reserved > 0) /* Reserved word? */ 276 if (s->reserved > 0) /* Reserved word? */
276 return TK_OFS + s->reserved; 277 return TK_OFS + s->reserved;
277 setstrV(ls->L, tv, s);
278 return TK_name; 278 return TK_name;
279 } 279 }
280 switch (ls->current) { 280 switch (ls->current) {
@@ -330,6 +330,9 @@ static int llex(LexState *ls, TValue *tv)
330 case '~': 330 case '~':
331 next(ls); 331 next(ls);
332 if (ls->current != '=') return '~'; else { next(ls); return TK_ne; } 332 if (ls->current != '=') return '~'; else { next(ls); return TK_ne; }
333 case ':':
334 next(ls);
335 if (ls->current != ':') return ':'; else { next(ls); return TK_label; }
333 case '"': 336 case '"':
334 case '\'': 337 case '\'':
335 read_string(ls, ls->current, tv); 338 read_string(ls, ls->current, tv);
diff --git a/src/lj_lex.h b/src/lj_lex.h
index 1ddf4b59..16f35aa5 100644
--- a/src/lj_lex.h
+++ b/src/lj_lex.h
@@ -15,10 +15,11 @@
15/* Lua lexer tokens. */ 15/* Lua lexer tokens. */
16#define TKDEF(_, __) \ 16#define TKDEF(_, __) \
17 _(and) _(break) _(do) _(else) _(elseif) _(end) _(false) \ 17 _(and) _(break) _(do) _(else) _(elseif) _(end) _(false) \
18 _(for) _(function) _(if) _(in) _(local) _(nil) _(not) _(or) \ 18 _(for) _(function) _(goto) _(if) _(in) _(local) _(nil) _(not) _(or) \
19 _(repeat) _(return) _(then) _(true) _(until) _(while) \ 19 _(repeat) _(return) _(then) _(true) _(until) _(while) \
20 __(concat, ..) __(dots, ...) __(eq, ==) __(ge, >=) __(le, <=) __(ne, ~=) \ 20 __(concat, ..) __(dots, ...) __(eq, ==) __(ge, >=) __(le, <=) __(ne, ~=) \
21 __(number, <number>) __(name, <name>) __(string, <string>) __(eof, <eof>) 21 __(label, ::) __(number, <number>) __(name, <name>) __(string, <string>) \
22 __(eof, <eof>)
22 23
23enum { 24enum {
24 TK_OFS = 256, 25 TK_OFS = 256,
diff --git a/src/lj_parse.c b/src/lj_parse.c
index 6c2f0d31..322a542d 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -95,17 +95,28 @@ static int expr_numiszero(ExpDesc *e)
95/* Per-function linked list of scope blocks. */ 95/* Per-function linked list of scope blocks. */
96typedef struct FuncScope { 96typedef struct FuncScope {
97 struct FuncScope *prev; /* Link to outer scope. */ 97 struct FuncScope *prev; /* Link to outer scope. */
98 BCPos breaklist; /* Jump list for loop breaks. */ 98 MSize vstart; /* Start of block-local variables. */
99 uint8_t nactvar; /* Number of active vars outside the scope. */ 99 uint8_t nactvar; /* Number of active vars outside the scope. */
100 uint8_t upval; /* Some variable in the scope is an upvalue. */ 100 uint8_t flags; /* Scope flags. */
101 uint8_t isbreakable; /* Scope is a loop and allows a break. */
102} FuncScope; 101} FuncScope;
103 102
103#define FSCOPE_LOOP 0x01 /* Scope is a (breakable) loop. */
104#define FSCOPE_BREAK 0x02 /* Break used in scope. */
105#define FSCOPE_GOLA 0x04 /* Goto or label used in scope. */
106#define FSCOPE_UPVAL 0x08 /* Upvalue in scope. */
107#define FSCOPE_NOCLOSE 0x10 /* Do not close upvalues. */
108
109#define NAME_BREAK ((GCstr *)(uintptr_t)1)
110
104/* Index into variable stack. */ 111/* Index into variable stack. */
105typedef uint16_t VarIndex; 112typedef uint16_t VarIndex;
106#define LJ_MAX_VSTACK 65536 113#define LJ_MAX_VSTACK 65536
107 114
108#define VSTACK_VAR_RW 0x80000000 /* In endpc: R/W variable. */ 115/* Flags stored in upper bits of endpc. */
116#define VSTACK_MASK 0x1fffffff /* Mask for actual endpc. */
117#define VSTACK_VAR_RW 0x80000000 /* R/W variable. */
118#define VSTACK_GOTO 0x40000000 /* Pending goto. */
119#define VSTACK_LABEL 0x20000000 /* Label. */
109 120
110/* Upvalue map. */ 121/* Upvalue map. */
111typedef struct UVMap { 122typedef struct UVMap {
@@ -680,8 +691,7 @@ static BCPos bcemit_jmp(FuncState *fs)
680 BCPos j = fs->pc - 1; 691 BCPos j = fs->pc - 1;
681 BCIns *ip = &fs->bcbase[j].ins; 692 BCIns *ip = &fs->bcbase[j].ins;
682 fs->jpc = NO_JMP; 693 fs->jpc = NO_JMP;
683 if ((int32_t)j >= (int32_t)fs->lasttarget && 694 if ((int32_t)j >= (int32_t)fs->lasttarget && bc_op(*ip) == BC_UCLO)
684 bc_op(*ip) == BC_UCLO)
685 setbc_j(ip, NO_JMP); 695 setbc_j(ip, NO_JMP);
686 else 696 else
687 j = bcemit_AJ(fs, BC_JMP, fs->freereg, NO_JMP); 697 j = bcemit_AJ(fs, BC_JMP, fs->freereg, NO_JMP);
@@ -1009,7 +1019,7 @@ static void lex_match(LexState *ls, LexToken what, LexToken who, BCLine line)
1009static GCstr *lex_str(LexState *ls) 1019static GCstr *lex_str(LexState *ls)
1010{ 1020{
1011 GCstr *s; 1021 GCstr *s;
1012 if (ls->token != TK_name) 1022 if (ls->token != TK_name && (LJ_52 || ls->token != TK_goto))
1013 err_token(ls, TK_name); 1023 err_token(ls, TK_name);
1014 s = strV(&ls->tokenval); 1024 s = strV(&ls->tokenval);
1015 lj_lex_next(ls); 1025 lj_lex_next(ls);
@@ -1094,7 +1104,7 @@ static MSize var_lookup_uv(FuncState *fs, MSize vidx, ExpDesc *e)
1094} 1104}
1095 1105
1096/* Forward declaration. */ 1106/* Forward declaration. */
1097static void scope_uvmark(FuncState *fs, BCReg level); 1107static void fscope_uvmark(FuncState *fs, BCReg level);
1098 1108
1099/* Recursively lookup variables in enclosing functions. */ 1109/* Recursively lookup variables in enclosing functions. */
1100static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first) 1110static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first)
@@ -1104,7 +1114,7 @@ static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first)
1104 if ((int32_t)reg >= 0) { /* Local in this function? */ 1114 if ((int32_t)reg >= 0) { /* Local in this function? */
1105 expr_init(e, VLOCAL, reg); 1115 expr_init(e, VLOCAL, reg);
1106 if (!first) 1116 if (!first)
1107 scope_uvmark(fs, reg); /* Scope now has an upvalue. */ 1117 fscope_uvmark(fs, reg); /* Scope now has an upvalue. */
1108 return (MSize)(e->u.s.aux = (uint32_t)fs->varmap[reg]); 1118 return (MSize)(e->u.s.aux = (uint32_t)fs->varmap[reg]);
1109 } else { 1119 } else {
1110 MSize vidx = var_lookup_(fs->prev, name, e, 0); /* Var in outer func? */ 1120 MSize vidx = var_lookup_(fs->prev, name, e, 0); /* Var in outer func? */
@@ -1125,6 +1135,170 @@ static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first)
1125#define var_lookup(ls, e) \ 1135#define var_lookup(ls, e) \
1126 var_lookup_((ls)->fs, lex_str(ls), (e), 1) 1136 var_lookup_((ls)->fs, lex_str(ls), (e), 1)
1127 1137
1138/* -- Goto an label handling ---------------------------------------------- */
1139
1140/* Add a new goto or label. */
1141static MSize gola_new(LexState *ls, GCstr *name, uint32_t type, BCPos pc)
1142{
1143 FuncState *fs = ls->fs;
1144 MSize vtop = ls->vtop;
1145 if (LJ_UNLIKELY(vtop >= ls->sizevstack)) {
1146 if (ls->sizevstack >= LJ_MAX_VSTACK)
1147 lj_lex_error(ls, 0, LJ_ERR_XLIMC, LJ_MAX_VSTACK);
1148 lj_mem_growvec(ls->L, ls->vstack, ls->sizevstack, LJ_MAX_VSTACK, VarInfo);
1149 }
1150 lua_assert(name == NAME_BREAK || lj_tab_getstr(fs->kt, name) != NULL);
1151 /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */
1152 setgcref(ls->vstack[vtop].name, obj2gco(name));
1153 ls->vstack[vtop].startpc = pc;
1154 ls->vstack[vtop].endpc = fs->nactvar | type;
1155 ls->vtop = vtop+1;
1156 return vtop;
1157}
1158
1159#define gola_nactvar(v) ((uint8_t)((v)->endpc))
1160#define gola_isgoto(v) ((v)->endpc & VSTACK_GOTO)
1161#define gola_islabel(v) ((v)->endpc & VSTACK_LABEL)
1162#define gola_isgotolabel(v) ((v)->endpc & (VSTACK_GOTO|VSTACK_LABEL))
1163
1164/* Patch goto to jump to label. */
1165static void gola_patch(LexState *ls, VarInfo *vg, VarInfo *vl)
1166{
1167 FuncState *fs = ls->fs;
1168 BCPos pc = vg->startpc;
1169 setgcrefnull(vg->name); /* Invalidate pending goto. */
1170 setbc_a(&fs->bcbase[pc].ins, gola_nactvar(vl));
1171 jmp_patch(fs, pc, vl->startpc);
1172}
1173
1174/* Patch goto to close upvalues. */
1175static void gola_close(LexState *ls, VarInfo *vg)
1176{
1177 FuncState *fs = ls->fs;
1178 BCPos pc = vg->startpc;
1179 BCIns *ip = &fs->bcbase[pc].ins;
1180 lua_assert(gola_isgoto(vg));
1181 lua_assert(bc_op(*ip) == BC_JMP || bc_op(*ip) == BC_UCLO);
1182 setbc_a(ip, gola_nactvar(vg));
1183 if (bc_op(*ip) == BC_JMP) {
1184 BCPos next = jmp_next(fs, pc);
1185 if (next != NO_JMP) jmp_patch(fs, next, pc); /* Jump to UCLO. */
1186 setbc_op(ip, BC_UCLO); /* Turn into UCLO. */
1187 setbc_j(ip, NO_JMP);
1188 }
1189}
1190
1191/* Resolve pending forward gotos for label. */
1192static void gola_resolve(LexState *ls, MSize idx)
1193{
1194 VarInfo *vg = ls->vstack + ls->fs->bl->vstart;
1195 VarInfo *vl = ls->vstack + idx;
1196 for (; vg < vl; vg++)
1197 if (gcrefeq(vg->name, vl->name) && gola_isgoto(vg)) {
1198 if (gola_nactvar(vg) < gola_nactvar(vl)) {
1199 GCstr *name = strref(var_get(ls, ls->fs, gola_nactvar(vg)).name);
1200 lua_assert((uintptr_t)name >= VARNAME__MAX);
1201 ls->linenumber = ls->fs->bcbase[vg->startpc].line;
1202 lj_lex_error(ls, 0, LJ_ERR_XGSCOPE,
1203 strdata(strref(vg->name)), strdata(name));
1204 }
1205 gola_patch(ls, vg, vl);
1206 }
1207}
1208
1209/* Fixup remaining gotos and labels for scope. */
1210static void gola_fixup(LexState *ls, FuncScope *bl)
1211{
1212 VarInfo *v = ls->vstack + bl->vstart;
1213 VarInfo *ve = ls->vstack + ls->vtop;
1214 for (; v < ve; v++) {
1215 GCstr *name = strref(v->name);
1216 if (name != NULL) { /* Only consider remaining valid gotos/labels. */
1217 if (gola_islabel(v)) {
1218 VarInfo *vg;
1219 setgcrefnull(v->name); /* Invalidate label that goes out of scope. */
1220 for (vg = v+1; vg < ve; vg++) /* Resolve pending backward gotos. */
1221 if (strref(vg->name) == name && gola_isgoto(vg)) {
1222 if ((bl->flags&FSCOPE_UPVAL) && gola_nactvar(vg) > gola_nactvar(v))
1223 gola_close(ls, vg);
1224 gola_patch(ls, vg, v);
1225 }
1226 } else if (gola_isgoto(v)) {
1227 if (bl->prev) { /* Propagate goto or break to outer scope. */
1228 bl->prev->flags |= name == NAME_BREAK ? FSCOPE_BREAK : FSCOPE_GOLA;
1229 v->endpc = bl->nactvar | VSTACK_GOTO;
1230 if ((bl->flags & FSCOPE_UPVAL))
1231 gola_close(ls, v);
1232 } else { /* No outer scope: undefined goto label or no loop. */
1233 ls->linenumber = ls->fs->bcbase[v->startpc].line;
1234 if (name == NAME_BREAK)
1235 lj_lex_error(ls, 0, LJ_ERR_XBREAK);
1236 else
1237 lj_lex_error(ls, 0, LJ_ERR_XLUNDEF, strdata(name));
1238 }
1239 }
1240 }
1241 }
1242}
1243
1244/* Find existing label. */
1245static VarInfo *gola_findlabel(LexState *ls, GCstr *name)
1246{
1247 VarInfo *v = ls->vstack + ls->fs->bl->vstart;
1248 VarInfo *ve = ls->vstack + ls->vtop;
1249 for (; v < ve; v++)
1250 if (strref(v->name) == name && gola_islabel(v))
1251 return v;
1252 return NULL;
1253}
1254
1255/* -- Scope handling ------------------------------------------------------ */
1256
1257/* Begin a scope. */
1258static void fscope_begin(FuncState *fs, FuncScope *bl, int flags)
1259{
1260 bl->nactvar = (uint8_t)fs->nactvar;
1261 bl->flags = flags;
1262 bl->vstart = fs->ls->vtop;
1263 bl->prev = fs->bl;
1264 fs->bl = bl;
1265 lua_assert(fs->freereg == fs->nactvar);
1266}
1267
1268/* End a scope. */
1269static void fscope_end(FuncState *fs)
1270{
1271 FuncScope *bl = fs->bl;
1272 LexState *ls = fs->ls;
1273 fs->bl = bl->prev;
1274 var_remove(ls, bl->nactvar);
1275 fs->freereg = fs->nactvar;
1276 lua_assert(bl->nactvar == fs->nactvar);
1277 if ((bl->flags & (FSCOPE_UPVAL|FSCOPE_NOCLOSE)) == FSCOPE_UPVAL)
1278 bcemit_AJ(fs, BC_UCLO, bl->nactvar, 0);
1279 if ((bl->flags & FSCOPE_BREAK)) {
1280 if ((bl->flags & FSCOPE_LOOP)) {
1281 MSize idx = gola_new(ls, NAME_BREAK, VSTACK_LABEL, fs->pc);
1282 ls->vtop = idx; /* Drop break label immediately. */
1283 gola_resolve(ls, idx);
1284 return;
1285 } /* else: need the fixup step to propagate the breaks. */
1286 } else if (!(bl->flags & FSCOPE_GOLA)) {
1287 return;
1288 }
1289 gola_fixup(ls, bl);
1290}
1291
1292/* Mark scope as having an upvalue. */
1293static void fscope_uvmark(FuncState *fs, BCReg level)
1294{
1295 FuncScope *bl;
1296 for (bl = fs->bl; bl && bl->nactvar > level; bl = bl->prev)
1297 ;
1298 if (bl)
1299 bl->flags |= FSCOPE_UPVAL;
1300}
1301
1128/* -- Function state management ------------------------------------------- */ 1302/* -- Function state management ------------------------------------------- */
1129 1303
1130/* Fixup bytecode for prototype. */ 1304/* Fixup bytecode for prototype. */
@@ -1287,36 +1461,37 @@ static void fs_buf_uleb128(LexState *ls, uint32_t v)
1287/* Prepare variable info for prototype. */ 1461/* Prepare variable info for prototype. */
1288static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) 1462static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar)
1289{ 1463{
1290 VarInfo *vstack = fs->ls->vstack; 1464 VarInfo *vs = fs->ls->vstack, *ve;
1291 MSize i, n; 1465 MSize i, n;
1292 BCPos lastpc; 1466 BCPos lastpc;
1293 lj_str_resetbuf(&ls->sb); /* Copy to temp. string buffer. */ 1467 lj_str_resetbuf(&ls->sb); /* Copy to temp. string buffer. */
1294 /* Store upvalue names. */ 1468 /* Store upvalue names. */
1295 for (i = 0, n = fs->nuv; i < n; i++) { 1469 for (i = 0, n = fs->nuv; i < n; i++) {
1296 GCstr *s = strref(vstack[fs->uvloc[i].vidx].name); 1470 GCstr *s = strref(vs[fs->uvloc[i].vidx].name);
1297 MSize len = s->len+1; 1471 MSize len = s->len+1;
1298 fs_buf_need(ls, len); 1472 fs_buf_need(ls, len);
1299 fs_buf_str(ls, strdata(s), len); 1473 fs_buf_str(ls, strdata(s), len);
1300 } 1474 }
1301 *ofsvar = ls->sb.n; 1475 *ofsvar = ls->sb.n;
1302 vstack += fs->vbase;
1303 lastpc = 0; 1476 lastpc = 0;
1304 /* Store local variable names and compressed ranges. */ 1477 /* Store local variable names and compressed ranges. */
1305 for (i = 0, n = ls->vtop - fs->vbase; i < n; i++) { 1478 for (ve = vs + ls->vtop, vs += fs->vbase; vs < ve; vs++) {
1306 GCstr *s = strref(vstack[i].name); 1479 if (!gola_isgotolabel(vs)) {
1307 BCPos startpc = vstack[i].startpc; 1480 GCstr *s = strref(vs->name);
1308 BCPos endpc = vstack[i].endpc & ~VSTACK_VAR_RW; 1481 BCPos startpc;
1309 if ((uintptr_t)s < VARNAME__MAX) { 1482 if ((uintptr_t)s < VARNAME__MAX) {
1310 fs_buf_need(ls, 1 + 2*5); 1483 fs_buf_need(ls, 1 + 2*5);
1311 ls->sb.buf[ls->sb.n++] = (uint8_t)(uintptr_t)s; 1484 ls->sb.buf[ls->sb.n++] = (uint8_t)(uintptr_t)s;
1312 } else { 1485 } else {
1313 MSize len = s->len+1; 1486 MSize len = s->len+1;
1314 fs_buf_need(ls, len + 2*5); 1487 fs_buf_need(ls, len + 2*5);
1315 fs_buf_str(ls, strdata(s), len); 1488 fs_buf_str(ls, strdata(s), len);
1489 }
1490 startpc = vs->startpc;
1491 fs_buf_uleb128(ls, startpc-lastpc);
1492 fs_buf_uleb128(ls, (vs->endpc & VSTACK_MASK)-startpc);
1493 lastpc = startpc;
1316 } 1494 }
1317 fs_buf_uleb128(ls, startpc-lastpc);
1318 fs_buf_uleb128(ls, endpc-startpc);
1319 lastpc = startpc;
1320 } 1495 }
1321 fs_buf_need(ls, 1); 1496 fs_buf_need(ls, 1);
1322 ls->sb.buf[ls->sb.n++] = '\0'; /* Terminator for varinfo. */ 1497 ls->sb.buf[ls->sb.n++] = '\0'; /* Terminator for varinfo. */
@@ -1359,14 +1534,17 @@ static void fs_fixup_ret(FuncState *fs)
1359{ 1534{
1360 BCPos lastpc = fs->pc; 1535 BCPos lastpc = fs->pc;
1361 if (lastpc <= fs->lasttarget || !bcopisret(bc_op(fs->bcbase[lastpc-1].ins))) { 1536 if (lastpc <= fs->lasttarget || !bcopisret(bc_op(fs->bcbase[lastpc-1].ins))) {
1362 if (fs->flags & PROTO_CHILD) 1537 if ((fs->bl->flags & FSCOPE_UPVAL))
1363 bcemit_AJ(fs, BC_UCLO, 0, 0); 1538 bcemit_AJ(fs, BC_UCLO, 0, 0);
1364 bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */ 1539 bcemit_AD(fs, BC_RET0, 0, 1); /* Need final return. */
1365 } 1540 }
1541 fs->bl->flags |= FSCOPE_NOCLOSE; /* Handled above. */
1542 fscope_end(fs);
1543 lua_assert(fs->bl == NULL);
1366 /* May need to fixup returns encoded before first function was created. */ 1544 /* May need to fixup returns encoded before first function was created. */
1367 if (fs->flags & PROTO_FIXUP_RETURN) { 1545 if (fs->flags & PROTO_FIXUP_RETURN) {
1368 BCPos pc; 1546 BCPos pc;
1369 for (pc = 0; pc < lastpc; pc++) { 1547 for (pc = 1; pc < lastpc; pc++) {
1370 BCIns ins = fs->bcbase[pc].ins; 1548 BCIns ins = fs->bcbase[pc].ins;
1371 BCPos offset; 1549 BCPos offset;
1372 switch (bc_op(ins)) { 1550 switch (bc_op(ins)) {
@@ -1397,9 +1575,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1397 GCproto *pt; 1575 GCproto *pt;
1398 1576
1399 /* Apply final fixups. */ 1577 /* Apply final fixups. */
1400 lua_assert(fs->bl == NULL);
1401 fs_fixup_ret(fs); 1578 fs_fixup_ret(fs);
1402 var_remove(ls, 0);
1403 1579
1404 /* Calculate total size of prototype including all colocated arrays. */ 1580 /* Calculate total size of prototype including all colocated arrays. */
1405 sizept = sizeof(GCproto) + fs->pc*sizeof(BCIns) + fs->nkgc*sizeof(GCRef); 1581 sizept = sizeof(GCproto) + fs->pc*sizeof(BCIns) + fs->nkgc*sizeof(GCRef);
@@ -1564,7 +1740,8 @@ static void expr_table(LexState *ls, ExpDesc *e)
1564 if (!expr_isk(&key)) expr_index(fs, e, &key); 1740 if (!expr_isk(&key)) expr_index(fs, e, &key);
1565 if (expr_isnumk(&key) && expr_numiszero(&key)) needarr = 1; else nhash++; 1741 if (expr_isnumk(&key) && expr_numiszero(&key)) needarr = 1; else nhash++;
1566 lex_check(ls, '='); 1742 lex_check(ls, '=');
1567 } else if (ls->token == TK_name && lj_lex_lookahead(ls) == '=') { 1743 } else if ((ls->token == TK_name || (!LJ_52 && ls->token == TK_goto)) &&
1744 lj_lex_lookahead(ls) == '=') {
1568 expr_str(ls, &key); 1745 expr_str(ls, &key);
1569 lex_check(ls, '='); 1746 lex_check(ls, '=');
1570 nhash++; 1747 nhash++;
@@ -1657,7 +1834,7 @@ static BCReg parse_params(LexState *ls, int needself)
1657 var_new_lit(ls, nparams++, "self"); 1834 var_new_lit(ls, nparams++, "self");
1658 if (ls->token != ')') { 1835 if (ls->token != ')') {
1659 do { 1836 do {
1660 if (ls->token == TK_name) { 1837 if (ls->token == TK_name || (!LJ_52 && ls->token == TK_goto)) {
1661 var_new(ls, nparams++, lex_str(ls)); 1838 var_new(ls, nparams++, lex_str(ls));
1662 } else if (ls->token == TK_dots) { 1839 } else if (ls->token == TK_dots) {
1663 lj_lex_next(ls); 1840 lj_lex_next(ls);
@@ -1682,9 +1859,11 @@ static void parse_chunk(LexState *ls);
1682static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line) 1859static void parse_body(LexState *ls, ExpDesc *e, int needself, BCLine line)
1683{ 1860{
1684 FuncState fs, *pfs = ls->fs; 1861 FuncState fs, *pfs = ls->fs;
1862 FuncScope bl;
1685 GCproto *pt; 1863 GCproto *pt;
1686 ptrdiff_t oldbase = pfs->bcbase - ls->bcstack; 1864 ptrdiff_t oldbase = pfs->bcbase - ls->bcstack;
1687 fs_init(ls, &fs); 1865 fs_init(ls, &fs);
1866 fscope_begin(&fs, &bl, 0);
1688 fs.linedefined = line; 1867 fs.linedefined = line;
1689 fs.numparams = (uint8_t)parse_params(ls, needself); 1868 fs.numparams = (uint8_t)parse_params(ls, needself);
1690 fs.bcbase = pfs->bcbase + pfs->pc; 1869 fs.bcbase = pfs->bcbase + pfs->pc;
@@ -1778,7 +1957,7 @@ static void expr_primary(LexState *ls, ExpDesc *v)
1778 expr(ls, v); 1957 expr(ls, v);
1779 lex_match(ls, ')', '(', line); 1958 lex_match(ls, ')', '(', line);
1780 expr_discharge(ls->fs, v); 1959 expr_discharge(ls->fs, v);
1781 } else if (ls->token == TK_name) { 1960 } else if (ls->token == TK_name || (!LJ_52 && ls->token == TK_goto)) {
1782 var_lookup(ls, v); 1961 var_lookup(ls, v);
1783 } else { 1962 } else {
1784 err_syntax(ls, LJ_ERR_XSYMBOL); 1963 err_syntax(ls, LJ_ERR_XSYMBOL);
@@ -1964,125 +2143,6 @@ static BCPos expr_cond(LexState *ls)
1964 return v.f; 2143 return v.f;
1965} 2144}
1966 2145
1967/* -- Scope handling ------------------------------------------------------ */
1968
1969/* Begin a scope. */
1970static void scope_begin(FuncState *fs, FuncScope *bl, int isbreakable)
1971{
1972 bl->breaklist = NO_JMP;
1973 bl->isbreakable = (uint8_t)isbreakable;
1974 bl->nactvar = (uint8_t)fs->nactvar;
1975 bl->upval = 0;
1976 bl->prev = fs->bl;
1977 fs->bl = bl;
1978 lua_assert(fs->freereg == fs->nactvar);
1979}
1980
1981/* End a scope. */
1982static void scope_end(FuncState *fs)
1983{
1984 FuncScope *bl = fs->bl;
1985 fs->bl = bl->prev;
1986 var_remove(fs->ls, bl->nactvar);
1987 fs->freereg = fs->nactvar;
1988 lua_assert(bl->nactvar == fs->nactvar);
1989 /* A scope is either breakable or has upvalues. */
1990 lua_assert(!bl->isbreakable || !bl->upval);
1991 if (bl->upval)
1992 bcemit_AJ(fs, BC_UCLO, bl->nactvar, 0);
1993 else /* Avoid in upval case, it clears lasttarget and kills UCLO+JMP join. */
1994 jmp_tohere(fs, bl->breaklist);
1995}
1996
1997/* Mark scope as having an upvalue. */
1998static void scope_uvmark(FuncState *fs, BCReg level)
1999{
2000 FuncScope *bl;
2001 for (bl = fs->bl; bl && bl->nactvar > level; bl = bl->prev)
2002 ;
2003 if (bl)
2004 bl->upval = 1;
2005}
2006
2007/* Parse 'break' statement. */
2008static void parse_break(LexState *ls)
2009{
2010 FuncState *fs = ls->fs;
2011 FuncScope *bl;
2012 BCReg savefr;
2013 int upval = 0;
2014 for (bl = fs->bl; bl && !bl->isbreakable; bl = bl->prev)
2015 upval |= bl->upval; /* Collect upvalues in intervening scopes. */
2016 if (!bl) /* Error if no breakable scope found. */
2017 err_syntax(ls, LJ_ERR_XBREAK);
2018 savefr = fs->freereg;
2019 fs->freereg = bl->nactvar; /* Shrink slots to help data-flow analysis. */
2020 if (upval)
2021 bcemit_AJ(fs, BC_UCLO, bl->nactvar, 0); /* Close upvalues. */
2022 jmp_append(fs, &bl->breaklist, bcemit_jmp(fs));
2023 fs->freereg = savefr;
2024}
2025
2026/* Check for end of block. */
2027static int endofblock(LexToken token)
2028{
2029 switch (token) {
2030 case TK_else: case TK_elseif: case TK_end: case TK_until: case TK_eof:
2031 return 1;
2032 default:
2033 return 0;
2034 }
2035}
2036
2037/* Parse 'return' statement. */
2038static void parse_return(LexState *ls)
2039{
2040 BCIns ins;
2041 FuncState *fs = ls->fs;
2042 lj_lex_next(ls); /* Skip 'return'. */
2043 fs->flags |= PROTO_HAS_RETURN;
2044 if (endofblock(ls->token) || ls->token == ';') { /* Bare return. */
2045 ins = BCINS_AD(BC_RET0, 0, 1);
2046 } else { /* Return with one or more values. */
2047 ExpDesc e; /* Receives the _last_ expression in the list. */
2048 BCReg nret = expr_list(ls, &e);
2049 if (nret == 1) { /* Return one result. */
2050 if (e.k == VCALL) { /* Check for tail call. */
2051 BCIns *ip = bcptr(fs, &e);
2052 /* It doesn't pay off to add BC_VARGT just for 'return ...'. */
2053 if (bc_op(*ip) == BC_VARG) goto notailcall;
2054 fs->pc--;
2055 ins = BCINS_AD(bc_op(*ip)-BC_CALL+BC_CALLT, bc_a(*ip), bc_c(*ip));
2056 } else { /* Can return the result from any register. */
2057 ins = BCINS_AD(BC_RET1, expr_toanyreg(fs, &e), 2);
2058 }
2059 } else {
2060 if (e.k == VCALL) { /* Append all results from a call. */
2061 notailcall:
2062 setbc_b(bcptr(fs, &e), 0);
2063 ins = BCINS_AD(BC_RETM, fs->nactvar, e.u.s.aux - fs->nactvar);
2064 } else {
2065 expr_tonextreg(fs, &e); /* Force contiguous registers. */
2066 ins = BCINS_AD(BC_RET, fs->nactvar, nret+1);
2067 }
2068 }
2069 }
2070 if (fs->flags & PROTO_CHILD)
2071 bcemit_AJ(fs, BC_UCLO, 0, 0); /* May need to close upvalues first. */
2072 bcemit_INS(fs, ins);
2073}
2074
2075/* Parse a block. */
2076static void parse_block(LexState *ls)
2077{
2078 FuncState *fs = ls->fs;
2079 FuncScope bl;
2080 scope_begin(fs, &bl, 0);
2081 parse_chunk(ls);
2082 lua_assert(bl.breaklist == NO_JMP);
2083 scope_end(fs);
2084}
2085
2086/* -- Assignments --------------------------------------------------------- */ 2146/* -- Assignments --------------------------------------------------------- */
2087 2147
2088/* List of LHS variables. */ 2148/* List of LHS variables. */
@@ -2243,7 +2303,119 @@ static void parse_func(LexState *ls, BCLine line)
2243 fs->bcbase[fs->pc - 1].line = line; /* Set line for the store. */ 2303 fs->bcbase[fs->pc - 1].line = line; /* Set line for the store. */
2244} 2304}
2245 2305
2246/* -- Loop and conditional statements ------------------------------------- */ 2306/* -- Control transfer statements ----------------------------------------- */
2307
2308/* Check for end of block. */
2309static int endofblock(LexToken token)
2310{
2311 switch (token) {
2312 case TK_else: case TK_elseif: case TK_end: case TK_until: case TK_eof:
2313 return 1;
2314 default:
2315 return 0;
2316 }
2317}
2318
2319/* Parse 'return' statement. */
2320static void parse_return(LexState *ls)
2321{
2322 BCIns ins;
2323 FuncState *fs = ls->fs;
2324 lj_lex_next(ls); /* Skip 'return'. */
2325 fs->flags |= PROTO_HAS_RETURN;
2326 if (endofblock(ls->token) || ls->token == ';') { /* Bare return. */
2327 ins = BCINS_AD(BC_RET0, 0, 1);
2328 } else { /* Return with one or more values. */
2329 ExpDesc e; /* Receives the _last_ expression in the list. */
2330 BCReg nret = expr_list(ls, &e);
2331 if (nret == 1) { /* Return one result. */
2332 if (e.k == VCALL) { /* Check for tail call. */
2333 BCIns *ip = bcptr(fs, &e);
2334 /* It doesn't pay off to add BC_VARGT just for 'return ...'. */
2335 if (bc_op(*ip) == BC_VARG) goto notailcall;
2336 fs->pc--;
2337 ins = BCINS_AD(bc_op(*ip)-BC_CALL+BC_CALLT, bc_a(*ip), bc_c(*ip));
2338 } else { /* Can return the result from any register. */
2339 ins = BCINS_AD(BC_RET1, expr_toanyreg(fs, &e), 2);
2340 }
2341 } else {
2342 if (e.k == VCALL) { /* Append all results from a call. */
2343 notailcall:
2344 setbc_b(bcptr(fs, &e), 0);
2345 ins = BCINS_AD(BC_RETM, fs->nactvar, e.u.s.aux - fs->nactvar);
2346 } else {
2347 expr_tonextreg(fs, &e); /* Force contiguous registers. */
2348 ins = BCINS_AD(BC_RET, fs->nactvar, nret+1);
2349 }
2350 }
2351 }
2352 if (fs->flags & PROTO_CHILD)
2353 bcemit_AJ(fs, BC_UCLO, 0, 0); /* May need to close upvalues first. */
2354 bcemit_INS(fs, ins);
2355}
2356
2357/* Parse 'break' statement. */
2358static void parse_break(LexState *ls)
2359{
2360 ls->fs->bl->flags |= FSCOPE_BREAK;
2361 gola_new(ls, NAME_BREAK, VSTACK_GOTO, bcemit_jmp(ls->fs));
2362}
2363
2364/* Parse 'goto' statement. */
2365static void parse_goto(LexState *ls)
2366{
2367 FuncState *fs = ls->fs;
2368 GCstr *name = lex_str(ls);
2369 VarInfo *vl = gola_findlabel(ls, name);
2370 if (vl) /* Treat backwards goto within same scope like a loop. */
2371 bcemit_AJ(fs, BC_LOOP, gola_nactvar(vl), -1); /* No BC range check. */
2372 fs->bl->flags |= FSCOPE_GOLA;
2373 gola_new(ls, name, VSTACK_GOTO, bcemit_jmp(fs));
2374}
2375
2376/* Parse label. */
2377static void parse_label(LexState *ls)
2378{
2379 FuncState *fs = ls->fs;
2380 GCstr *name;
2381 MSize idx;
2382 fs->lasttarget = fs->pc;
2383 fs->bl->flags |= FSCOPE_GOLA;
2384 lj_lex_next(ls); /* Skip '::'. */
2385 name = lex_str(ls);
2386 if (gola_findlabel(ls, name))
2387 lj_lex_error(ls, 0, LJ_ERR_XLDUP, strdata(name));
2388 idx = gola_new(ls, name, VSTACK_LABEL, fs->pc);
2389 lex_check(ls, TK_label);
2390 /* Recursively parse trailing statements: labels and ';' (Lua 5.2 only). */
2391 for (;;) {
2392 if (ls->token == TK_label) {
2393 synlevel_begin(ls);
2394 parse_label(ls);
2395 synlevel_end(ls);
2396 } else if (LJ_52 && ls->token == ';') {
2397 lj_lex_next(ls);
2398 } else {
2399 break;
2400 }
2401 }
2402 /* Trailing label is considered to be outside of scope. */
2403 if (endofblock(ls->token) && ls->token != TK_until)
2404 ls->vstack[idx].endpc = fs->bl->nactvar | VSTACK_LABEL;
2405 gola_resolve(ls, idx);
2406}
2407
2408/* -- Blocks, loops and conditional statements ---------------------------- */
2409
2410/* Parse a block. */
2411static void parse_block(LexState *ls)
2412{
2413 FuncState *fs = ls->fs;
2414 FuncScope bl;
2415 fscope_begin(fs, &bl, 0);
2416 parse_chunk(ls);
2417 fscope_end(fs);
2418}
2247 2419
2248/* Parse 'while' statement. */ 2420/* Parse 'while' statement. */
2249static void parse_while(LexState *ls, BCLine line) 2421static void parse_while(LexState *ls, BCLine line)
@@ -2254,13 +2426,13 @@ static void parse_while(LexState *ls, BCLine line)
2254 lj_lex_next(ls); /* Skip 'while'. */ 2426 lj_lex_next(ls); /* Skip 'while'. */
2255 start = fs->lasttarget = fs->pc; 2427 start = fs->lasttarget = fs->pc;
2256 condexit = expr_cond(ls); 2428 condexit = expr_cond(ls);
2257 scope_begin(fs, &bl, 1); 2429 fscope_begin(fs, &bl, FSCOPE_LOOP);
2258 lex_check(ls, TK_do); 2430 lex_check(ls, TK_do);
2259 loop = bcemit_AD(fs, BC_LOOP, fs->nactvar, 0); 2431 loop = bcemit_AD(fs, BC_LOOP, fs->nactvar, 0);
2260 parse_block(ls); 2432 parse_block(ls);
2261 jmp_patch(fs, bcemit_jmp(fs), start); 2433 jmp_patch(fs, bcemit_jmp(fs), start);
2262 lex_match(ls, TK_end, TK_while, line); 2434 lex_match(ls, TK_end, TK_while, line);
2263 scope_end(fs); 2435 fscope_end(fs);
2264 jmp_tohere(fs, condexit); 2436 jmp_tohere(fs, condexit);
2265 jmp_patchins(fs, loop, fs->pc); 2437 jmp_patchins(fs, loop, fs->pc);
2266} 2438}
@@ -2272,24 +2444,24 @@ static void parse_repeat(LexState *ls, BCLine line)
2272 BCPos loop = fs->lasttarget = fs->pc; 2444 BCPos loop = fs->lasttarget = fs->pc;
2273 BCPos condexit; 2445 BCPos condexit;
2274 FuncScope bl1, bl2; 2446 FuncScope bl1, bl2;
2275 scope_begin(fs, &bl1, 1); /* Breakable loop scope. */ 2447 fscope_begin(fs, &bl1, FSCOPE_LOOP); /* Breakable loop scope. */
2276 scope_begin(fs, &bl2, 0); /* Inner scope. */ 2448 fscope_begin(fs, &bl2, 0); /* Inner scope. */
2277 lj_lex_next(ls); /* Skip 'repeat'. */ 2449 lj_lex_next(ls); /* Skip 'repeat'. */
2278 bcemit_AD(fs, BC_LOOP, fs->nactvar, 0); 2450 bcemit_AD(fs, BC_LOOP, fs->nactvar, 0);
2279 parse_chunk(ls); 2451 parse_chunk(ls);
2280 lex_match(ls, TK_until, TK_repeat, line); 2452 lex_match(ls, TK_until, TK_repeat, line);
2281 condexit = expr_cond(ls); /* Parse condition (still inside inner scope). */ 2453 condexit = expr_cond(ls); /* Parse condition (still inside inner scope). */
2282 if (!bl2.upval) { /* No upvalues? Just end inner scope. */ 2454 if (!(bl2.flags & FSCOPE_UPVAL)) { /* No upvalues? Just end inner scope. */
2283 scope_end(fs); 2455 fscope_end(fs);
2284 } else { /* Otherwise generate: cond: UCLO+JMP out, !cond: UCLO+JMP loop. */ 2456 } else { /* Otherwise generate: cond: UCLO+JMP out, !cond: UCLO+JMP loop. */
2285 parse_break(ls); /* Break from loop and close upvalues. */ 2457 parse_break(ls); /* Break from loop and close upvalues. */
2286 jmp_tohere(fs, condexit); 2458 jmp_tohere(fs, condexit);
2287 scope_end(fs); /* End inner scope and close upvalues. */ 2459 fscope_end(fs); /* End inner scope and close upvalues. */
2288 condexit = bcemit_jmp(fs); 2460 condexit = bcemit_jmp(fs);
2289 } 2461 }
2290 jmp_patch(fs, condexit, loop); /* Jump backwards if !cond. */ 2462 jmp_patch(fs, condexit, loop); /* Jump backwards if !cond. */
2291 jmp_patchins(fs, loop, fs->pc); 2463 jmp_patchins(fs, loop, fs->pc);
2292 scope_end(fs); /* End loop scope. */ 2464 fscope_end(fs); /* End loop scope. */
2293} 2465}
2294 2466
2295/* Parse numeric 'for'. */ 2467/* Parse numeric 'for'. */
@@ -2318,11 +2490,11 @@ static void parse_for_num(LexState *ls, GCstr *varname, BCLine line)
2318 var_add(ls, 3); /* Hidden control variables. */ 2490 var_add(ls, 3); /* Hidden control variables. */
2319 lex_check(ls, TK_do); 2491 lex_check(ls, TK_do);
2320 loop = bcemit_AJ(fs, BC_FORI, base, NO_JMP); 2492 loop = bcemit_AJ(fs, BC_FORI, base, NO_JMP);
2321 scope_begin(fs, &bl, 0); /* Scope for visible variables. */ 2493 fscope_begin(fs, &bl, 0); /* Scope for visible variables. */
2322 var_add(ls, 1); 2494 var_add(ls, 1);
2323 bcreg_reserve(fs, 1); 2495 bcreg_reserve(fs, 1);
2324 parse_block(ls); 2496 parse_block(ls);
2325 scope_end(fs); 2497 fscope_end(fs);
2326 /* Perform loop inversion. Loop control instructions are at the end. */ 2498 /* Perform loop inversion. Loop control instructions are at the end. */
2327 loopend = bcemit_AJ(fs, BC_FORL, base, NO_JMP); 2499 loopend = bcemit_AJ(fs, BC_FORL, base, NO_JMP);
2328 fs->bcbase[loopend].line = line; /* Fix line for control ins. */ 2500 fs->bcbase[loopend].line = line; /* Fix line for control ins. */
@@ -2389,11 +2561,11 @@ static void parse_for_iter(LexState *ls, GCstr *indexname)
2389 var_add(ls, 3); /* Hidden control variables. */ 2561 var_add(ls, 3); /* Hidden control variables. */
2390 lex_check(ls, TK_do); 2562 lex_check(ls, TK_do);
2391 loop = bcemit_AJ(fs, isnext ? BC_ISNEXT : BC_JMP, base, NO_JMP); 2563 loop = bcemit_AJ(fs, isnext ? BC_ISNEXT : BC_JMP, base, NO_JMP);
2392 scope_begin(fs, &bl, 0); /* Scope for visible variables. */ 2564 fscope_begin(fs, &bl, 0); /* Scope for visible variables. */
2393 var_add(ls, nvars-3); 2565 var_add(ls, nvars-3);
2394 bcreg_reserve(fs, nvars-3); 2566 bcreg_reserve(fs, nvars-3);
2395 parse_block(ls); 2567 parse_block(ls);
2396 scope_end(fs); 2568 fscope_end(fs);
2397 /* Perform loop inversion. Loop control instructions are at the end. */ 2569 /* Perform loop inversion. Loop control instructions are at the end. */
2398 jmp_patchins(fs, loop, fs->pc); 2570 jmp_patchins(fs, loop, fs->pc);
2399 bcemit_ABC(fs, isnext ? BC_ITERN : BC_ITERC, base, nvars-3+1, 2+1); 2571 bcemit_ABC(fs, isnext ? BC_ITERN : BC_ITERC, base, nvars-3+1, 2+1);
@@ -2409,7 +2581,7 @@ static void parse_for(LexState *ls, BCLine line)
2409 FuncState *fs = ls->fs; 2581 FuncState *fs = ls->fs;
2410 GCstr *varname; 2582 GCstr *varname;
2411 FuncScope bl; 2583 FuncScope bl;
2412 scope_begin(fs, &bl, 1); /* Breakable loop scope. */ 2584 fscope_begin(fs, &bl, FSCOPE_LOOP);
2413 lj_lex_next(ls); /* Skip 'for'. */ 2585 lj_lex_next(ls); /* Skip 'for'. */
2414 varname = lex_str(ls); /* Get first variable name. */ 2586 varname = lex_str(ls); /* Get first variable name. */
2415 if (ls->token == '=') 2587 if (ls->token == '=')
@@ -2419,7 +2591,7 @@ static void parse_for(LexState *ls, BCLine line)
2419 else 2591 else
2420 err_syntax(ls, LJ_ERR_XFOR); 2592 err_syntax(ls, LJ_ERR_XFOR);
2421 lex_match(ls, TK_end, TK_for, line); 2593 lex_match(ls, TK_end, TK_for, line);
2422 scope_end(fs); /* Resolve break list. */ 2594 fscope_end(fs); /* Resolve break list. */
2423} 2595}
2424 2596
2425/* Parse condition and 'then' block. */ 2597/* Parse condition and 'then' block. */
@@ -2500,6 +2672,15 @@ static int parse_stmt(LexState *ls)
2500 lj_lex_next(ls); 2672 lj_lex_next(ls);
2501 break; 2673 break;
2502#endif 2674#endif
2675 case TK_label:
2676 parse_label(ls);
2677 break;
2678 case TK_goto:
2679 if (LJ_52 || lj_lex_lookahead(ls) == TK_name) {
2680 lj_lex_next(ls);
2681 parse_goto(ls);
2682 break;
2683 } /* else: fallthrough */
2503 default: 2684 default:
2504 parse_call_assign(ls); 2685 parse_call_assign(ls);
2505 break; 2686 break;
@@ -2526,6 +2707,7 @@ static void parse_chunk(LexState *ls)
2526GCproto *lj_parse(LexState *ls) 2707GCproto *lj_parse(LexState *ls)
2527{ 2708{
2528 FuncState fs; 2709 FuncState fs;
2710 FuncScope bl;
2529 GCproto *pt; 2711 GCproto *pt;
2530 lua_State *L = ls->L; 2712 lua_State *L = ls->L;
2531#ifdef LUAJIT_DISABLE_DEBUGINFO 2713#ifdef LUAJIT_DISABLE_DEBUGINFO
@@ -2542,6 +2724,7 @@ GCproto *lj_parse(LexState *ls)
2542 fs.bcbase = NULL; 2724 fs.bcbase = NULL;
2543 fs.bclim = 0; 2725 fs.bclim = 0;
2544 fs.flags |= PROTO_VARARG; /* Main chunk is always a vararg func. */ 2726 fs.flags |= PROTO_VARARG; /* Main chunk is always a vararg func. */
2727 fscope_begin(&fs, &bl, 0);
2545 bcemit_AD(&fs, BC_FUNCV, 0, 0); /* Placeholder. */ 2728 bcemit_AD(&fs, BC_FUNCV, 0, 0); /* Placeholder. */
2546 lj_lex_next(ls); /* Read-ahead first token. */ 2729 lj_lex_next(ls); /* Read-ahead first token. */
2547 parse_chunk(ls); 2730 parse_chunk(ls);
diff --git a/src/lj_record.c b/src/lj_record.c
index 8718f8bb..7620ae4c 100644
--- a/src/lj_record.c
+++ b/src/lj_record.c
@@ -550,7 +550,7 @@ static void rec_loop_interp(jit_State *J, const BCIns *pc, LoopEvent ev)
550 ** an inner loop even in a root trace. But it's better to be a bit 550 ** an inner loop even in a root trace. But it's better to be a bit
551 ** more conservative here and only do it for very short loops. 551 ** more conservative here and only do it for very short loops.
552 */ 552 */
553 if (!innerloopleft(J, pc)) 553 if (bc_j(*pc) != -1 && !innerloopleft(J, pc))
554 lj_trace_err(J, LJ_TRERR_LINNER); /* Root trace hit an inner loop. */ 554 lj_trace_err(J, LJ_TRERR_LINNER); /* Root trace hit an inner loop. */
555 if ((ev != LOOPEV_ENTERLO && 555 if ((ev != LOOPEV_ENTERLO &&
556 J->loopref && J->cur.nins - J->loopref > 24) || --J->loopunroll < 0) 556 J->loopref && J->cur.nins - J->loopref > 24) || --J->loopunroll < 0)