aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMike Pall <mike>2012-10-21 13:51:12 +0200
committerMike Pall <mike>2012-10-21 13:51:12 +0200
commitf6536c6696deca9fb7b9744573406c83f0f893a4 (patch)
tree5e807c50097ece684b199b0767b3b260fea5fea7 /src
parent614e78d1f66a126a69e1ec15481185e20e342fb7 (diff)
downloadluajit-f6536c6696deca9fb7b9744573406c83f0f893a4.tar.gz
luajit-f6536c6696deca9fb7b9744573406c83f0f893a4.tar.bz2
luajit-f6536c6696deca9fb7b9744573406c83f0f893a4.zip
Fix detection of immutable upvalues.
Diffstat (limited to 'src')
-rw-r--r--src/lj_lex.h4
-rw-r--r--src/lj_parse.c123
2 files changed, 67 insertions, 60 deletions
diff --git a/src/lj_lex.h b/src/lj_lex.h
index 7a4fd74b..d16461a2 100644
--- a/src/lj_lex.h
+++ b/src/lj_lex.h
@@ -41,9 +41,11 @@ typedef struct BCInsLine {
41 41
42/* Info for local variables. Only used during bytecode generation. */ 42/* Info for local variables. Only used during bytecode generation. */
43typedef struct VarInfo { 43typedef struct VarInfo {
44 GCRef name; /* Local variable name. */ 44 GCRef name; /* Local variable name or goto/label name. */
45 BCPos startpc; /* First point where the local variable is active. */ 45 BCPos startpc; /* First point where the local variable is active. */
46 BCPos endpc; /* First point where the local variable is dead. */ 46 BCPos endpc; /* First point where the local variable is dead. */
47 uint8_t slot; /* Variable slot. */
48 uint8_t info; /* Variable/goto/label info. */
47} VarInfo; 49} VarInfo;
48 50
49/* Lua lexer state. */ 51/* Lua lexer state. */
diff --git a/src/lj_parse.c b/src/lj_parse.c
index a3a96535..29def7b4 100644
--- a/src/lj_parse.c
+++ b/src/lj_parse.c
@@ -110,19 +110,12 @@ typedef struct FuncScope {
110 110
111/* Index into variable stack. */ 111/* Index into variable stack. */
112typedef uint16_t VarIndex; 112typedef uint16_t VarIndex;
113#define LJ_MAX_VSTACK 65536 113#define LJ_MAX_VSTACK (65536 - LJ_MAX_UPVAL)
114 114
115/* Flags stored in upper bits of endpc. */ 115/* Variable/goto/label info. */
116#define VSTACK_MASK 0x1fffffff /* Mask for actual endpc. */ 116#define VSTACK_VAR_RW 0x01 /* R/W variable. */
117#define VSTACK_VAR_RW 0x80000000 /* R/W variable. */ 117#define VSTACK_GOTO 0x02 /* Pending goto. */
118#define VSTACK_GOTO 0x40000000 /* Pending goto. */ 118#define VSTACK_LABEL 0x04 /* Label. */
119#define VSTACK_LABEL 0x20000000 /* Label. */
120
121/* Upvalue map. */
122typedef struct UVMap {
123 VarIndex vidx; /* Varinfo index. */
124 uint16_t slot; /* Slot or parent upvalue index. */
125} UVMap;
126 119
127/* Per-function state. */ 120/* Per-function state. */
128typedef struct FuncState { 121typedef struct FuncState {
@@ -146,7 +139,8 @@ typedef struct FuncState {
146 uint8_t framesize; /* Fixed frame size. */ 139 uint8_t framesize; /* Fixed frame size. */
147 uint8_t nuv; /* Number of upvalues */ 140 uint8_t nuv; /* Number of upvalues */
148 VarIndex varmap[LJ_MAX_LOCVAR]; /* Map from register to variable idx. */ 141 VarIndex varmap[LJ_MAX_LOCVAR]; /* Map from register to variable idx. */
149 UVMap uvloc[LJ_MAX_UPVAL]; /* Map from upvalue to variable idx and slot. */ 142 VarIndex uvmap[LJ_MAX_UPVAL]; /* Map from upvalue to variable idx. */
143 VarIndex uvtmp[LJ_MAX_UPVAL]; /* Temporary upvalue map. */
150} FuncState; 144} FuncState;
151 145
152/* Binary and unary operators. ORDER OPR */ 146/* Binary and unary operators. ORDER OPR */
@@ -621,12 +615,12 @@ static void bcemit_store(FuncState *fs, ExpDesc *var, ExpDesc *e)
621{ 615{
622 BCIns ins; 616 BCIns ins;
623 if (var->k == VLOCAL) { 617 if (var->k == VLOCAL) {
624 fs->ls->vstack[var->u.s.aux].endpc |= VSTACK_VAR_RW; 618 fs->ls->vstack[var->u.s.aux].info |= VSTACK_VAR_RW;
625 expr_free(fs, e); 619 expr_free(fs, e);
626 expr_toreg(fs, e, var->u.s.info); 620 expr_toreg(fs, e, var->u.s.info);
627 return; 621 return;
628 } else if (var->k == VUPVAL) { 622 } else if (var->k == VUPVAL) {
629 fs->ls->vstack[var->u.s.aux].endpc |= VSTACK_VAR_RW; 623 fs->ls->vstack[var->u.s.aux].info |= VSTACK_VAR_RW;
630 expr_toval(fs, e); 624 expr_toval(fs, e);
631 if (e->k <= VKTRUE) 625 if (e->k <= VKTRUE)
632 ins = BCINS_AD(BC_USETP, var->u.s.info, const_pri(e)); 626 ins = BCINS_AD(BC_USETP, var->u.s.info, const_pri(e));
@@ -1059,12 +1053,14 @@ static void var_new(LexState *ls, BCReg n, GCstr *name)
1059static void var_add(LexState *ls, BCReg nvars) 1053static void var_add(LexState *ls, BCReg nvars)
1060{ 1054{
1061 FuncState *fs = ls->fs; 1055 FuncState *fs = ls->fs;
1062 fs->nactvar = (uint8_t)(fs->nactvar + nvars); 1056 BCReg nactvar = fs->nactvar;
1063 for (; nvars; nvars--) { 1057 while (nvars--) {
1064 VarInfo *v = &var_get(ls, fs, fs->nactvar - nvars); 1058 VarInfo *v = &var_get(ls, fs, nactvar);
1065 v->startpc = fs->pc; 1059 v->startpc = fs->pc;
1066 v->endpc = 0; 1060 v->slot = nactvar++;
1061 v->info = 0;
1067 } 1062 }
1063 fs->nactvar = nactvar;
1068} 1064}
1069 1065
1070/* Remove local variables. */ 1066/* Remove local variables. */
@@ -1072,7 +1068,7 @@ static void var_remove(LexState *ls, BCReg tolevel)
1072{ 1068{
1073 FuncState *fs = ls->fs; 1069 FuncState *fs = ls->fs;
1074 while (fs->nactvar > tolevel) 1070 while (fs->nactvar > tolevel)
1075 var_get(ls, fs, --fs->nactvar).endpc |= fs->pc; 1071 var_get(ls, fs, --fs->nactvar).endpc = fs->pc;
1076} 1072}
1077 1073
1078/* Lookup local variable name. */ 1074/* Lookup local variable name. */
@@ -1091,14 +1087,13 @@ static MSize var_lookup_uv(FuncState *fs, MSize vidx, ExpDesc *e)
1091{ 1087{
1092 MSize i, n = fs->nuv; 1088 MSize i, n = fs->nuv;
1093 for (i = 0; i < n; i++) 1089 for (i = 0; i < n; i++)
1094 if (fs->uvloc[i].vidx == vidx) 1090 if (fs->uvmap[i] == vidx)
1095 return i; /* Already exists. */ 1091 return i; /* Already exists. */
1096 /* Otherwise create a new one. */ 1092 /* Otherwise create a new one. */
1097 checklimit(fs, fs->nuv, LJ_MAX_UPVAL, "upvalues"); 1093 checklimit(fs, fs->nuv, LJ_MAX_UPVAL, "upvalues");
1098 lua_assert(e->k == VLOCAL || e->k == VUPVAL); 1094 lua_assert(e->k == VLOCAL || e->k == VUPVAL);
1099 fs->uvloc[n].vidx = (uint16_t)vidx; 1095 fs->uvmap[n] = (uint16_t)vidx;
1100 fs->uvloc[n].slot = (uint16_t)(e->u.s.info | 1096 fs->uvtmp[n] = (uint16_t)(e->k == VLOCAL ? vidx : LJ_MAX_VSTACK+e->u.s.info);
1101 (e->k == VLOCAL ? PROTO_UV_LOCAL : 0));
1102 fs->nuv = n+1; 1097 fs->nuv = n+1;
1103 return n; 1098 return n;
1104} 1099}
@@ -1138,7 +1133,7 @@ static MSize var_lookup_(FuncState *fs, GCstr *name, ExpDesc *e, int first)
1138/* -- Goto an label handling ---------------------------------------------- */ 1133/* -- Goto an label handling ---------------------------------------------- */
1139 1134
1140/* Add a new goto or label. */ 1135/* Add a new goto or label. */
1141static MSize gola_new(LexState *ls, GCstr *name, uint32_t type, BCPos pc) 1136static MSize gola_new(LexState *ls, GCstr *name, uint8_t info, BCPos pc)
1142{ 1137{
1143 FuncState *fs = ls->fs; 1138 FuncState *fs = ls->fs;
1144 MSize vtop = ls->vtop; 1139 MSize vtop = ls->vtop;
@@ -1151,15 +1146,15 @@ static MSize gola_new(LexState *ls, GCstr *name, uint32_t type, BCPos pc)
1151 /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */ 1146 /* NOBARRIER: name is anchored in fs->kt and ls->vstack is not a GCobj. */
1152 setgcref(ls->vstack[vtop].name, obj2gco(name)); 1147 setgcref(ls->vstack[vtop].name, obj2gco(name));
1153 ls->vstack[vtop].startpc = pc; 1148 ls->vstack[vtop].startpc = pc;
1154 ls->vstack[vtop].endpc = fs->nactvar | type; 1149 ls->vstack[vtop].slot = (uint8_t)fs->nactvar;
1150 ls->vstack[vtop].info = info;
1155 ls->vtop = vtop+1; 1151 ls->vtop = vtop+1;
1156 return vtop; 1152 return vtop;
1157} 1153}
1158 1154
1159#define gola_nactvar(v) ((uint8_t)((v)->endpc)) 1155#define gola_isgoto(v) ((v)->info & VSTACK_GOTO)
1160#define gola_isgoto(v) ((v)->endpc & VSTACK_GOTO) 1156#define gola_islabel(v) ((v)->info & VSTACK_LABEL)
1161#define gola_islabel(v) ((v)->endpc & VSTACK_LABEL) 1157#define gola_isgotolabel(v) ((v)->info & (VSTACK_GOTO|VSTACK_LABEL))
1162#define gola_isgotolabel(v) ((v)->endpc & (VSTACK_GOTO|VSTACK_LABEL))
1163 1158
1164/* Patch goto to jump to label. */ 1159/* Patch goto to jump to label. */
1165static void gola_patch(LexState *ls, VarInfo *vg, VarInfo *vl) 1160static void gola_patch(LexState *ls, VarInfo *vg, VarInfo *vl)
@@ -1167,7 +1162,7 @@ static void gola_patch(LexState *ls, VarInfo *vg, VarInfo *vl)
1167 FuncState *fs = ls->fs; 1162 FuncState *fs = ls->fs;
1168 BCPos pc = vg->startpc; 1163 BCPos pc = vg->startpc;
1169 setgcrefnull(vg->name); /* Invalidate pending goto. */ 1164 setgcrefnull(vg->name); /* Invalidate pending goto. */
1170 setbc_a(&fs->bcbase[pc].ins, gola_nactvar(vl)); 1165 setbc_a(&fs->bcbase[pc].ins, vl->slot);
1171 jmp_patch(fs, pc, vl->startpc); 1166 jmp_patch(fs, pc, vl->startpc);
1172} 1167}
1173 1168
@@ -1179,7 +1174,7 @@ static void gola_close(LexState *ls, VarInfo *vg)
1179 BCIns *ip = &fs->bcbase[pc].ins; 1174 BCIns *ip = &fs->bcbase[pc].ins;
1180 lua_assert(gola_isgoto(vg)); 1175 lua_assert(gola_isgoto(vg));
1181 lua_assert(bc_op(*ip) == BC_JMP || bc_op(*ip) == BC_UCLO); 1176 lua_assert(bc_op(*ip) == BC_JMP || bc_op(*ip) == BC_UCLO);
1182 setbc_a(ip, gola_nactvar(vg)); 1177 setbc_a(ip, vg->slot);
1183 if (bc_op(*ip) == BC_JMP) { 1178 if (bc_op(*ip) == BC_JMP) {
1184 BCPos next = jmp_next(fs, pc); 1179 BCPos next = jmp_next(fs, pc);
1185 if (next != NO_JMP) jmp_patch(fs, next, pc); /* Jump to UCLO. */ 1180 if (next != NO_JMP) jmp_patch(fs, next, pc); /* Jump to UCLO. */
@@ -1195,8 +1190,8 @@ static void gola_resolve(LexState *ls, FuncScope *bl, MSize idx)
1195 VarInfo *vl = ls->vstack + idx; 1190 VarInfo *vl = ls->vstack + idx;
1196 for (; vg < vl; vg++) 1191 for (; vg < vl; vg++)
1197 if (gcrefeq(vg->name, vl->name) && gola_isgoto(vg)) { 1192 if (gcrefeq(vg->name, vl->name) && gola_isgoto(vg)) {
1198 if (gola_nactvar(vg) < gola_nactvar(vl)) { 1193 if (vg->slot < vl->slot) {
1199 GCstr *name = strref(var_get(ls, ls->fs, gola_nactvar(vg)).name); 1194 GCstr *name = strref(var_get(ls, ls->fs, vg->slot).name);
1200 lua_assert((uintptr_t)name >= VARNAME__MAX); 1195 lua_assert((uintptr_t)name >= VARNAME__MAX);
1201 ls->linenumber = ls->fs->bcbase[vg->startpc].line; 1196 ls->linenumber = ls->fs->bcbase[vg->startpc].line;
1202 lua_assert(strref(vg->name) != NAME_BREAK); 1197 lua_assert(strref(vg->name) != NAME_BREAK);
@@ -1220,14 +1215,14 @@ static void gola_fixup(LexState *ls, FuncScope *bl)
1220 setgcrefnull(v->name); /* Invalidate label that goes out of scope. */ 1215 setgcrefnull(v->name); /* Invalidate label that goes out of scope. */
1221 for (vg = v+1; vg < ve; vg++) /* Resolve pending backward gotos. */ 1216 for (vg = v+1; vg < ve; vg++) /* Resolve pending backward gotos. */
1222 if (strref(vg->name) == name && gola_isgoto(vg)) { 1217 if (strref(vg->name) == name && gola_isgoto(vg)) {
1223 if ((bl->flags&FSCOPE_UPVAL) && gola_nactvar(vg) > gola_nactvar(v)) 1218 if ((bl->flags&FSCOPE_UPVAL) && vg->slot > v->slot)
1224 gola_close(ls, vg); 1219 gola_close(ls, vg);
1225 gola_patch(ls, vg, v); 1220 gola_patch(ls, vg, v);
1226 } 1221 }
1227 } else if (gola_isgoto(v)) { 1222 } else if (gola_isgoto(v)) {
1228 if (bl->prev) { /* Propagate goto or break to outer scope. */ 1223 if (bl->prev) { /* Propagate goto or break to outer scope. */
1229 bl->prev->flags |= name == NAME_BREAK ? FSCOPE_BREAK : FSCOPE_GOLA; 1224 bl->prev->flags |= name == NAME_BREAK ? FSCOPE_BREAK : FSCOPE_GOLA;
1230 v->endpc = bl->nactvar | VSTACK_GOTO; 1225 v->slot = bl->nactvar;
1231 if ((bl->flags & FSCOPE_UPVAL)) 1226 if ((bl->flags & FSCOPE_UPVAL))
1232 gola_close(ls, v); 1227 gola_close(ls, v);
1233 } else { /* No outer scope: undefined goto label or no loop. */ 1228 } else { /* No outer scope: undefined goto label or no loop. */
@@ -1314,6 +1309,23 @@ static void fs_fixup_bc(FuncState *fs, GCproto *pt, BCIns *bc, MSize n)
1314 bc[i] = base[i].ins; 1309 bc[i] = base[i].ins;
1315} 1310}
1316 1311
1312/* Fixup upvalues for child prototype, step #2. */
1313static void fs_fixup_uv2(FuncState *fs, GCproto *pt)
1314{
1315 VarInfo *vstack = fs->ls->vstack;
1316 uint16_t *uv = proto_uv(pt);
1317 MSize i, n = pt->sizeuv;
1318 for (i = 0; i < n; i++) {
1319 VarIndex vidx = uv[i];
1320 if (vidx >= LJ_MAX_VSTACK)
1321 uv[i] = vidx - LJ_MAX_VSTACK;
1322 else if ((vstack[vidx].info & VSTACK_VAR_RW))
1323 uv[i] = vstack[vidx].slot | PROTO_UV_LOCAL;
1324 else
1325 uv[i] = vstack[vidx].slot | PROTO_UV_LOCAL | PROTO_UV_IMMUTABLE;
1326 }
1327}
1328
1317/* Fixup constants for prototype. */ 1329/* Fixup constants for prototype. */
1318static void fs_fixup_k(FuncState *fs, GCproto *pt, void *kptr) 1330static void fs_fixup_k(FuncState *fs, GCproto *pt, void *kptr)
1319{ 1331{
@@ -1360,28 +1372,19 @@ static void fs_fixup_k(FuncState *fs, GCproto *pt, void *kptr)
1360 GCobj *o = gcV(&n->key); 1372 GCobj *o = gcV(&n->key);
1361 setgcref(((GCRef *)kptr)[~kidx], o); 1373 setgcref(((GCRef *)kptr)[~kidx], o);
1362 lj_gc_objbarrier(fs->L, pt, o); 1374 lj_gc_objbarrier(fs->L, pt, o);
1375 if (tvisproto(&n->key))
1376 fs_fixup_uv2(fs, gco2pt(o));
1363 } 1377 }
1364 } 1378 }
1365 } 1379 }
1366} 1380}
1367 1381
1368/* Fixup upvalues for prototype. */ 1382/* Fixup upvalues for prototype, step #1. */
1369static void fs_fixup_uv(FuncState *fs, GCproto *pt, uint16_t *uv) 1383static void fs_fixup_uv1(FuncState *fs, GCproto *pt, uint16_t *uv)
1370{ 1384{
1371 VarInfo *vstack;
1372 UVMap *uvloc;
1373 MSize i, n = fs->nuv;
1374 setmref(pt->uv, uv); 1385 setmref(pt->uv, uv);
1375 pt->sizeuv = n; 1386 pt->sizeuv = fs->nuv;
1376 vstack = fs->ls->vstack; 1387 memcpy(uv, fs->uvtmp, fs->nuv*sizeof(VarIndex));
1377 uvloc = fs->uvloc;
1378 for (i = 0; i < n; i++) {
1379 uint16_t slot = uvloc[i].slot;
1380 uint16_t vidx = uvloc[i].vidx;
1381 if ((slot & PROTO_UV_LOCAL) && !(vstack[vidx].endpc & VSTACK_VAR_RW))
1382 slot |= PROTO_UV_IMMUTABLE;
1383 uv[i] = slot;
1384 }
1385} 1388}
1386 1389
1387#ifndef LUAJIT_DISABLE_DEBUGINFO 1390#ifndef LUAJIT_DISABLE_DEBUGINFO
@@ -1462,13 +1465,13 @@ static void fs_buf_uleb128(LexState *ls, uint32_t v)
1462/* Prepare variable info for prototype. */ 1465/* Prepare variable info for prototype. */
1463static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) 1466static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar)
1464{ 1467{
1465 VarInfo *vs = fs->ls->vstack, *ve; 1468 VarInfo *vs =ls->vstack, *ve;
1466 MSize i, n; 1469 MSize i, n;
1467 BCPos lastpc; 1470 BCPos lastpc;
1468 lj_str_resetbuf(&ls->sb); /* Copy to temp. string buffer. */ 1471 lj_str_resetbuf(&ls->sb); /* Copy to temp. string buffer. */
1469 /* Store upvalue names. */ 1472 /* Store upvalue names. */
1470 for (i = 0, n = fs->nuv; i < n; i++) { 1473 for (i = 0, n = fs->nuv; i < n; i++) {
1471 GCstr *s = strref(vs[fs->uvloc[i].vidx].name); 1474 GCstr *s = strref(vs[fs->uvmap[i]].name);
1472 MSize len = s->len+1; 1475 MSize len = s->len+1;
1473 fs_buf_need(ls, len); 1476 fs_buf_need(ls, len);
1474 fs_buf_str(ls, strdata(s), len); 1477 fs_buf_str(ls, strdata(s), len);
@@ -1490,7 +1493,7 @@ static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar)
1490 } 1493 }
1491 startpc = vs->startpc; 1494 startpc = vs->startpc;
1492 fs_buf_uleb128(ls, startpc-lastpc); 1495 fs_buf_uleb128(ls, startpc-lastpc);
1493 fs_buf_uleb128(ls, (vs->endpc & VSTACK_MASK)-startpc); 1496 fs_buf_uleb128(ls, vs->endpc-startpc);
1494 lastpc = startpc; 1497 lastpc = startpc;
1495 } 1498 }
1496 } 1499 }
@@ -1600,7 +1603,7 @@ static GCproto *fs_finish(LexState *ls, BCLine line)
1600 *(uint32_t *)((char *)pt + ofsk - sizeof(GCRef)*(fs->nkgc+1)) = 0; 1603 *(uint32_t *)((char *)pt + ofsk - sizeof(GCRef)*(fs->nkgc+1)) = 0;
1601 fs_fixup_bc(fs, pt, (BCIns *)((char *)pt + sizeof(GCproto)), fs->pc); 1604 fs_fixup_bc(fs, pt, (BCIns *)((char *)pt + sizeof(GCproto)), fs->pc);
1602 fs_fixup_k(fs, pt, (void *)((char *)pt + ofsk)); 1605 fs_fixup_k(fs, pt, (void *)((char *)pt + ofsk));
1603 fs_fixup_uv(fs, pt, (uint16_t *)((char *)pt + ofsuv)); 1606 fs_fixup_uv1(fs, pt, (uint16_t *)((char *)pt + ofsuv));
1604 fs_fixup_line(fs, pt, (void *)((char *)pt + ofsli), numline); 1607 fs_fixup_line(fs, pt, (void *)((char *)pt + ofsli), numline);
1605 fs_fixup_var(ls, pt, (uint8_t *)((char *)pt + ofsdbg), ofsvar); 1608 fs_fixup_var(ls, pt, (uint8_t *)((char *)pt + ofsdbg), ofsvar);
1606 1609
@@ -2265,7 +2268,9 @@ static void parse_local(LexState *ls)
2265 bcreg_reserve(fs, 1); 2268 bcreg_reserve(fs, 1);
2266 var_add(ls, 1); 2269 var_add(ls, 1);
2267 parse_body(ls, &b, 0, ls->linenumber); 2270 parse_body(ls, &b, 0, ls->linenumber);
2268 bcemit_store(fs, &v, &b); 2271 /* bcemit_store(fs, &v, &b) without setting VSTACK_VAR_RW. */
2272 expr_free(fs, &b);
2273 expr_toreg(fs, &b, v.u.s.info);
2269 /* The upvalue is in scope, but the local is only valid after the store. */ 2274 /* The upvalue is in scope, but the local is only valid after the store. */
2270 var_get(ls, fs, fs->nactvar - 1).startpc = fs->pc; 2275 var_get(ls, fs, fs->nactvar - 1).startpc = fs->pc;
2271 } else { /* Local variable declaration. */ 2276 } else { /* Local variable declaration. */
@@ -2371,7 +2376,7 @@ static void parse_goto(LexState *ls)
2371 GCstr *name = lex_str(ls); 2376 GCstr *name = lex_str(ls);
2372 VarInfo *vl = gola_findlabel(ls, name); 2377 VarInfo *vl = gola_findlabel(ls, name);
2373 if (vl) /* Treat backwards goto within same scope like a loop. */ 2378 if (vl) /* Treat backwards goto within same scope like a loop. */
2374 bcemit_AJ(fs, BC_LOOP, gola_nactvar(vl), -1); /* No BC range check. */ 2379 bcemit_AJ(fs, BC_LOOP, vl->slot, -1); /* No BC range check. */
2375 fs->bl->flags |= FSCOPE_GOLA; 2380 fs->bl->flags |= FSCOPE_GOLA;
2376 gola_new(ls, name, VSTACK_GOTO, bcemit_jmp(fs)); 2381 gola_new(ls, name, VSTACK_GOTO, bcemit_jmp(fs));
2377} 2382}
@@ -2404,7 +2409,7 @@ static void parse_label(LexState *ls)
2404 } 2409 }
2405 /* Trailing label is considered to be outside of scope. */ 2410 /* Trailing label is considered to be outside of scope. */
2406 if (endofblock(ls->token) && ls->token != TK_until) 2411 if (endofblock(ls->token) && ls->token != TK_until)
2407 ls->vstack[idx].endpc = fs->bl->nactvar | VSTACK_LABEL; 2412 ls->vstack[idx].slot = fs->bl->nactvar;
2408 gola_resolve(ls, fs->bl, idx); 2413 gola_resolve(ls, fs->bl, idx);
2409} 2414}
2410 2415
@@ -2519,7 +2524,7 @@ static int predict_next(LexState *ls, FuncState *fs, BCPos pc)
2519 name = gco2str(gcref(var_get(ls, fs, bc_d(ins)).name)); 2524 name = gco2str(gcref(var_get(ls, fs, bc_d(ins)).name));
2520 break; 2525 break;
2521 case BC_UGET: 2526 case BC_UGET:
2522 name = gco2str(gcref(ls->vstack[fs->uvloc[bc_d(ins)].vidx].name)); 2527 name = gco2str(gcref(ls->vstack[fs->uvmap[bc_d(ins)]].name));
2523 break; 2528 break;
2524 case BC_GGET: 2529 case BC_GGET:
2525 /* There's no inverse index (yet), so lookup the strings. */ 2530 /* There's no inverse index (yet), so lookup the strings. */