aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-05-05 14:16:11 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2017-05-05 14:16:11 -0300
commite8757a73e64c351bdafb75ee45be60e7ab4b3426 (patch)
tree10d50312c76f63cc37d886bb168d81084b5baa80
parent4ce8d2047c0613992ab092cf3ed78ebceffa61e3 (diff)
downloadlua-e8757a73e64c351bdafb75ee45be60e7ab4b3426.tar.gz
lua-e8757a73e64c351bdafb75ee45be60e7ab4b3426.tar.bz2
lua-e8757a73e64c351bdafb75ee45be60e7ab4b3426.zip
'luaV_execute' keeps local copy of program counter and hook mask,
to avoid excessive access to globals.
-rw-r--r--lvm.c91
1 files changed, 62 insertions, 29 deletions
diff --git a/lvm.c b/lvm.c
index 28833458..cab599d0 100644
--- a/lvm.c
+++ b/lvm.c
@@ -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);