diff options
author | Mike Pall <mike> | 2012-10-21 13:51:12 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2012-10-21 13:51:12 +0200 |
commit | f6536c6696deca9fb7b9744573406c83f0f893a4 (patch) | |
tree | 5e807c50097ece684b199b0767b3b260fea5fea7 /src | |
parent | 614e78d1f66a126a69e1ec15481185e20e342fb7 (diff) | |
download | luajit-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.h | 4 | ||||
-rw-r--r-- | src/lj_parse.c | 123 |
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. */ |
43 | typedef struct VarInfo { | 43 | typedef 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. */ |
112 | typedef uint16_t VarIndex; | 112 | typedef 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. */ | ||
122 | typedef 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. */ |
128 | typedef struct FuncState { | 121 | typedef 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) | |||
1059 | static void var_add(LexState *ls, BCReg nvars) | 1053 | static 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. */ |
1141 | static MSize gola_new(LexState *ls, GCstr *name, uint32_t type, BCPos pc) | 1136 | static 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. */ |
1165 | static void gola_patch(LexState *ls, VarInfo *vg, VarInfo *vl) | 1160 | static 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. */ | ||
1313 | static 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. */ |
1318 | static void fs_fixup_k(FuncState *fs, GCproto *pt, void *kptr) | 1330 | static 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. */ |
1369 | static void fs_fixup_uv(FuncState *fs, GCproto *pt, uint16_t *uv) | 1383 | static 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. */ |
1463 | static size_t fs_prep_var(LexState *ls, FuncState *fs, size_t *ofsvar) | 1466 | static 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. */ |