diff options
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 91 |
1 files changed, 62 insertions, 29 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.275 2017/04/30 20:43:26 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.276 2017/05/04 13:32:01 roberto Exp roberto $ |
3 | ** Lua virtual machine | 3 | ** Lua virtual machine |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -742,17 +742,37 @@ void luaV_finishOp (lua_State *L) { | |||
742 | ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) | 742 | ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) |
743 | 743 | ||
744 | 744 | ||
745 | /* execute a jump instruction */ | 745 | |
746 | #define updatemask(L) (mask = L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) | ||
747 | |||
748 | |||
749 | /* | ||
750 | ** Execute a jump instruction. The 'updatemask' allows signals to stop | ||
751 | ** tight loops. (Without it, the local copy of 'mask' could never change.) | ||
752 | */ | ||
746 | #define dojump(ci,i,e) \ | 753 | #define dojump(ci,i,e) \ |
747 | { int a = GETARG_A(i); \ | 754 | { int a = GETARG_A(i); \ |
748 | if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \ | 755 | if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \ |
749 | ci->u.l.savedpc += GETARG_sBx(i) + e; } | 756 | pc += GETARG_sBx(i) + e; updatemask(L); } |
757 | |||
750 | 758 | ||
751 | /* for test instructions, execute the jump instruction that follows it */ | 759 | /* for test instructions, execute the jump instruction that follows it */ |
752 | #define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } | 760 | #define donextjump(ci) { i = *pc; dojump(ci, i, 1); } |
753 | 761 | ||
762 | /* | ||
763 | ** Whenever code can raise errors (including memory errors), the global | ||
764 | ** 'pc' must be correct to report occasional errors. | ||
765 | */ | ||
766 | #define savepc(L) (ci->u.l.savedpc = pc) | ||
767 | |||
768 | |||
769 | /* | ||
770 | ** Protect code that, in general, can raise errors, reallocate the | ||
771 | ** stack, and change the hooks. | ||
772 | */ | ||
773 | #define Protect(code) \ | ||
774 | { savepc(L); {code;}; base = ci->u.l.base; updatemask(L); } | ||
754 | 775 | ||
755 | #define Protect(x) { {x;}; base = ci->u.l.base; } | ||
756 | 776 | ||
757 | #define checkGC(L,c) \ | 777 | #define checkGC(L,c) \ |
758 | { luaC_condGC(L, L->top = (c), /* limit of live values */ \ | 778 | { luaC_condGC(L, L->top = (c), /* limit of live values */ \ |
@@ -762,12 +782,9 @@ void luaV_finishOp (lua_State *L) { | |||
762 | 782 | ||
763 | /* fetch an instruction and prepare its execution */ | 783 | /* fetch an instruction and prepare its execution */ |
764 | #define vmfetch() { \ | 784 | #define vmfetch() { \ |
765 | i = *(ci->u.l.savedpc++); \ | 785 | i = *(pc++); \ |
766 | if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) \ | 786 | if (mask) Protect(luaG_traceexec(L)); \ |
767 | Protect(luaG_traceexec(L)); \ | ||
768 | ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ | 787 | ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ |
769 | lua_assert(base == ci->u.l.base); \ | ||
770 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); \ | ||
771 | } | 788 | } |
772 | 789 | ||
773 | #define vmdispatch(o) switch(o) | 790 | #define vmdispatch(o) switch(o) |
@@ -795,18 +812,24 @@ void luaV_execute (lua_State *L) { | |||
795 | CallInfo *ci = L->ci; | 812 | CallInfo *ci = L->ci; |
796 | LClosure *cl; | 813 | LClosure *cl; |
797 | TValue *k; | 814 | TValue *k; |
798 | StkId base; | 815 | StkId base; /* local copy of 'ci->u.l.base' */ |
816 | int mask; /* local copy of 'L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)' */ | ||
817 | const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */ | ||
799 | ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ | 818 | ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ |
800 | newframe: /* reentry point when frame changes (call/return) */ | 819 | newframe: /* reentry point when frame changes (call/return) */ |
801 | lua_assert(ci == L->ci); | 820 | lua_assert(ci == L->ci); |
802 | cl = clLvalue(ci->func); /* local reference to function's closure */ | 821 | cl = clLvalue(ci->func); /* local reference to function's closure */ |
803 | k = cl->p->k; /* local reference to function's constant table */ | 822 | k = cl->p->k; /* local reference to function's constant table */ |
804 | base = ci->u.l.base; /* local copy of function's base */ | 823 | updatemask(L); |
824 | base = ci->u.l.base; | ||
825 | pc = ci->u.l.savedpc; | ||
805 | /* main loop of interpreter */ | 826 | /* main loop of interpreter */ |
806 | for (;;) { | 827 | for (;;) { |
807 | Instruction i; | 828 | Instruction i; |
808 | StkId ra; | 829 | StkId ra; |
809 | vmfetch(); | 830 | vmfetch(); |
831 | lua_assert(base == ci->u.l.base); | ||
832 | lua_assert(base <= L->top && L->top < L->stack + L->stacksize); | ||
810 | vmdispatch (GET_OPCODE(i)) { | 833 | vmdispatch (GET_OPCODE(i)) { |
811 | vmcase(OP_MOVE) { | 834 | vmcase(OP_MOVE) { |
812 | setobjs2s(L, ra, RB(i)); | 835 | setobjs2s(L, ra, RB(i)); |
@@ -824,14 +847,14 @@ void luaV_execute (lua_State *L) { | |||
824 | } | 847 | } |
825 | vmcase(OP_LOADKX) { | 848 | vmcase(OP_LOADKX) { |
826 | TValue *rb; | 849 | TValue *rb; |
827 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); | 850 | lua_assert(GET_OPCODE(*pc) == OP_EXTRAARG); |
828 | rb = k + GETARG_Ax(*ci->u.l.savedpc++); | 851 | rb = k + GETARG_Ax(*pc++); |
829 | setobj2s(L, ra, rb); | 852 | setobj2s(L, ra, rb); |
830 | vmbreak; | 853 | vmbreak; |
831 | } | 854 | } |
832 | vmcase(OP_LOADBOOL) { | 855 | vmcase(OP_LOADBOOL) { |
833 | setbvalue(ra, GETARG_B(i)); | 856 | setbvalue(ra, GETARG_B(i)); |
834 | if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ | 857 | if (GETARG_C(i)) pc++; /* skip next instruction (if C) */ |
835 | vmbreak; | 858 | vmbreak; |
836 | } | 859 | } |
837 | vmcase(OP_LOADNIL) { | 860 | vmcase(OP_LOADNIL) { |
@@ -933,7 +956,9 @@ void luaV_execute (lua_State *L) { | |||
933 | vmcase(OP_NEWTABLE) { | 956 | vmcase(OP_NEWTABLE) { |
934 | int b = GETARG_B(i); | 957 | int b = GETARG_B(i); |
935 | int c = GETARG_C(i); | 958 | int c = GETARG_C(i); |
936 | Table *t = luaH_new(L); | 959 | Table *t; |
960 | savepc(L); /* in case of allocation errors */ | ||
961 | t = luaH_new(L); | ||
937 | sethvalue(L, ra, t); | 962 | sethvalue(L, ra, t); |
938 | if (b != 0 || c != 0) | 963 | if (b != 0 || c != 0) |
939 | luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); | 964 | luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); |
@@ -1173,7 +1198,7 @@ void luaV_execute (lua_State *L) { | |||
1173 | TValue *rc = RKC(i); | 1198 | TValue *rc = RKC(i); |
1174 | Protect( | 1199 | Protect( |
1175 | if (luaV_equalobj(L, rb, rc) != GETARG_A(i)) | 1200 | if (luaV_equalobj(L, rb, rc) != GETARG_A(i)) |
1176 | ci->u.l.savedpc++; | 1201 | pc++; |
1177 | else | 1202 | else |
1178 | donextjump(ci); | 1203 | donextjump(ci); |
1179 | ) | 1204 | ) |
@@ -1182,7 +1207,7 @@ void luaV_execute (lua_State *L) { | |||
1182 | vmcase(OP_LT) { | 1207 | vmcase(OP_LT) { |
1183 | Protect( | 1208 | Protect( |
1184 | if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) | 1209 | if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) |
1185 | ci->u.l.savedpc++; | 1210 | pc++; |
1186 | else | 1211 | else |
1187 | donextjump(ci); | 1212 | donextjump(ci); |
1188 | ) | 1213 | ) |
@@ -1191,7 +1216,7 @@ void luaV_execute (lua_State *L) { | |||
1191 | vmcase(OP_LE) { | 1216 | vmcase(OP_LE) { |
1192 | Protect( | 1217 | Protect( |
1193 | if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) | 1218 | if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) |
1194 | ci->u.l.savedpc++; | 1219 | pc++; |
1195 | else | 1220 | else |
1196 | donextjump(ci); | 1221 | donextjump(ci); |
1197 | ) | 1222 | ) |
@@ -1199,7 +1224,7 @@ void luaV_execute (lua_State *L) { | |||
1199 | } | 1224 | } |
1200 | vmcase(OP_TEST) { | 1225 | vmcase(OP_TEST) { |
1201 | if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) | 1226 | if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) |
1202 | ci->u.l.savedpc++; | 1227 | pc++; |
1203 | else | 1228 | else |
1204 | donextjump(ci); | 1229 | donextjump(ci); |
1205 | vmbreak; | 1230 | vmbreak; |
@@ -1207,7 +1232,7 @@ void luaV_execute (lua_State *L) { | |||
1207 | vmcase(OP_TESTSET) { | 1232 | vmcase(OP_TESTSET) { |
1208 | TValue *rb = RB(i); | 1233 | TValue *rb = RB(i); |
1209 | if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) | 1234 | if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) |
1210 | ci->u.l.savedpc++; | 1235 | pc++; |
1211 | else { | 1236 | else { |
1212 | setobjs2s(L, ra, rb); | 1237 | setobjs2s(L, ra, rb); |
1213 | donextjump(ci); | 1238 | donextjump(ci); |
@@ -1218,6 +1243,7 @@ void luaV_execute (lua_State *L) { | |||
1218 | int b = GETARG_B(i); | 1243 | int b = GETARG_B(i); |
1219 | int nresults = GETARG_C(i) - 1; | 1244 | int nresults = GETARG_C(i) - 1; |
1220 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 1245 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
1246 | savepc(L); | ||
1221 | if (luaD_precall(L, ra, nresults)) { /* C function? */ | 1247 | if (luaD_precall(L, ra, nresults)) { /* C function? */ |
1222 | if (nresults >= 0) | 1248 | if (nresults >= 0) |
1223 | L->top = ci->top; /* adjust results */ | 1249 | L->top = ci->top; /* adjust results */ |
@@ -1233,6 +1259,7 @@ void luaV_execute (lua_State *L) { | |||
1233 | int b = GETARG_B(i); | 1259 | int b = GETARG_B(i); |
1234 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 1260 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
1235 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); | 1261 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); |
1262 | savepc(L); | ||
1236 | if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ | 1263 | if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ |
1237 | Protect((void)0); /* update 'base' */ | 1264 | Protect((void)0); /* update 'base' */ |
1238 | } | 1265 | } |
@@ -1263,6 +1290,7 @@ void luaV_execute (lua_State *L) { | |||
1263 | vmcase(OP_RETURN) { | 1290 | vmcase(OP_RETURN) { |
1264 | int b = GETARG_B(i); | 1291 | int b = GETARG_B(i); |
1265 | if (cl->p->sizep > 0) luaF_close(L, base); | 1292 | if (cl->p->sizep > 0) luaF_close(L, base); |
1293 | savepc(L); | ||
1266 | b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); | 1294 | b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); |
1267 | if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ | 1295 | if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ |
1268 | return; /* external invocation: return */ | 1296 | return; /* external invocation: return */ |
@@ -1280,7 +1308,7 @@ void luaV_execute (lua_State *L) { | |||
1280 | lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */ | 1308 | lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */ |
1281 | lua_Integer limit = ivalue(ra + 1); | 1309 | lua_Integer limit = ivalue(ra + 1); |
1282 | if ((0 < step) ? (idx <= limit) : (limit <= idx)) { | 1310 | if ((0 < step) ? (idx <= limit) : (limit <= idx)) { |
1283 | ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ | 1311 | pc += GETARG_sBx(i); /* jump back */ |
1284 | chgivalue(ra, idx); /* update internal index... */ | 1312 | chgivalue(ra, idx); /* update internal index... */ |
1285 | setivalue(ra + 3, idx); /* ...and external index */ | 1313 | setivalue(ra + 3, idx); /* ...and external index */ |
1286 | } | 1314 | } |
@@ -1291,11 +1319,12 @@ void luaV_execute (lua_State *L) { | |||
1291 | lua_Number limit = fltvalue(ra + 1); | 1319 | lua_Number limit = fltvalue(ra + 1); |
1292 | if (luai_numlt(0, step) ? luai_numle(idx, limit) | 1320 | if (luai_numlt(0, step) ? luai_numle(idx, limit) |
1293 | : luai_numle(limit, idx)) { | 1321 | : luai_numle(limit, idx)) { |
1294 | ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ | 1322 | pc += GETARG_sBx(i); /* jump back */ |
1295 | chgfltvalue(ra, idx); /* update internal index... */ | 1323 | chgfltvalue(ra, idx); /* update internal index... */ |
1296 | setfltvalue(ra + 3, idx); /* ...and external index */ | 1324 | setfltvalue(ra + 3, idx); /* ...and external index */ |
1297 | } | 1325 | } |
1298 | } | 1326 | } |
1327 | updatemask(L); | ||
1299 | vmbreak; | 1328 | vmbreak; |
1300 | } | 1329 | } |
1301 | vmcase(OP_FORPREP) { | 1330 | vmcase(OP_FORPREP) { |
@@ -1313,6 +1342,7 @@ void luaV_execute (lua_State *L) { | |||
1313 | } | 1342 | } |
1314 | else { /* try making all values floats */ | 1343 | else { /* try making all values floats */ |
1315 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; | 1344 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; |
1345 | savepc(L); /* in case of errors */ | ||
1316 | if (!tonumber(plimit, &nlimit)) | 1346 | if (!tonumber(plimit, &nlimit)) |
1317 | luaG_runerror(L, "'for' limit must be a number"); | 1347 | luaG_runerror(L, "'for' limit must be a number"); |
1318 | setfltvalue(plimit, nlimit); | 1348 | setfltvalue(plimit, nlimit); |
@@ -1323,7 +1353,7 @@ void luaV_execute (lua_State *L) { | |||
1323 | luaG_runerror(L, "'for' initial value must be a number"); | 1353 | luaG_runerror(L, "'for' initial value must be a number"); |
1324 | setfltvalue(init, luai_numsub(L, ninit, nstep)); | 1354 | setfltvalue(init, luai_numsub(L, ninit, nstep)); |
1325 | } | 1355 | } |
1326 | ci->u.l.savedpc += GETARG_sBx(i); | 1356 | pc += GETARG_sBx(i); |
1327 | vmbreak; | 1357 | vmbreak; |
1328 | } | 1358 | } |
1329 | vmcase(OP_TFORCALL) { | 1359 | vmcase(OP_TFORCALL) { |
@@ -1334,7 +1364,7 @@ void luaV_execute (lua_State *L) { | |||
1334 | L->top = cb + 3; /* func. + 2 args (state and index) */ | 1364 | L->top = cb + 3; /* func. + 2 args (state and index) */ |
1335 | Protect(luaD_call(L, cb, GETARG_C(i))); | 1365 | Protect(luaD_call(L, cb, GETARG_C(i))); |
1336 | L->top = ci->top; | 1366 | L->top = ci->top; |
1337 | i = *(ci->u.l.savedpc++); /* go to next instruction */ | 1367 | i = *(pc++); /* go to next instruction */ |
1338 | ra = RA(i); | 1368 | ra = RA(i); |
1339 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP); | 1369 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP); |
1340 | goto l_tforloop; | 1370 | goto l_tforloop; |
@@ -1343,7 +1373,7 @@ void luaV_execute (lua_State *L) { | |||
1343 | l_tforloop: | 1373 | l_tforloop: |
1344 | if (!ttisnil(ra + 1)) { /* continue loop? */ | 1374 | if (!ttisnil(ra + 1)) { /* continue loop? */ |
1345 | setobjs2s(L, ra, ra + 1); /* save control variable */ | 1375 | setobjs2s(L, ra, ra + 1); /* save control variable */ |
1346 | ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ | 1376 | pc += GETARG_sBx(i); /* jump back */ |
1347 | } | 1377 | } |
1348 | vmbreak; | 1378 | vmbreak; |
1349 | } | 1379 | } |
@@ -1354,11 +1384,12 @@ void luaV_execute (lua_State *L) { | |||
1354 | Table *h; | 1384 | Table *h; |
1355 | if (n == 0) n = cast_int(L->top - ra) - 1; | 1385 | if (n == 0) n = cast_int(L->top - ra) - 1; |
1356 | if (c == 0) { | 1386 | if (c == 0) { |
1357 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); | 1387 | lua_assert(GET_OPCODE(*pc) == OP_EXTRAARG); |
1358 | c = GETARG_Ax(*ci->u.l.savedpc++); | 1388 | c = GETARG_Ax(*pc++); |
1359 | } | 1389 | } |
1360 | h = hvalue(ra); | 1390 | h = hvalue(ra); |
1361 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; | 1391 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; |
1392 | savepc(L); /* in case of allocation errors */ | ||
1362 | if (last > h->sizearray) /* needs more space? */ | 1393 | if (last > h->sizearray) /* needs more space? */ |
1363 | luaH_resizearray(L, h, last); /* preallocate it at once */ | 1394 | luaH_resizearray(L, h, last); /* preallocate it at once */ |
1364 | for (; n > 0; n--) { | 1395 | for (; n > 0; n--) { |
@@ -1372,8 +1403,10 @@ void luaV_execute (lua_State *L) { | |||
1372 | vmcase(OP_CLOSURE) { | 1403 | vmcase(OP_CLOSURE) { |
1373 | Proto *p = cl->p->p[GETARG_Bx(i)]; | 1404 | Proto *p = cl->p->p[GETARG_Bx(i)]; |
1374 | LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ | 1405 | LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ |
1375 | if (ncl == NULL) /* no match? */ | 1406 | if (ncl == NULL) { /* no match? */ |
1407 | savepc(L); /* in case of allocation errors */ | ||
1376 | pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ | 1408 | pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ |
1409 | } | ||
1377 | else | 1410 | else |
1378 | setclLvalue(L, ra, ncl); /* push cashed closure */ | 1411 | setclLvalue(L, ra, ncl); /* push cashed closure */ |
1379 | checkGC(L, ra + 1); | 1412 | checkGC(L, ra + 1); |