diff options
Diffstat (limited to 'lvm.c')
-rw-r--r-- | lvm.c | 47 |
1 files changed, 25 insertions, 22 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.301 2017/11/01 18:20:48 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.302 2017/11/03 12:12:30 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 | */ |
@@ -654,13 +654,14 @@ static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, | |||
654 | } | 654 | } |
655 | 655 | ||
656 | 656 | ||
657 | #define basepc(base) ((base - 1)->stkci.u.l.savedpc) | ||
658 | |||
657 | /* | 659 | /* |
658 | ** finish execution of an opcode interrupted by an yield | 660 | ** finish execution of an opcode interrupted by an yield |
659 | */ | 661 | */ |
660 | void luaV_finishOp (lua_State *L) { | 662 | void luaV_finishOp (lua_State *L) { |
661 | CallInfo *ci = L->ci; | ||
662 | StkId base = L->func + 1; | 663 | StkId base = L->func + 1; |
663 | Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ | 664 | Instruction inst = *(basepc(base) - 1); /* interrupted instruction */ |
664 | OpCode op = GET_OPCODE(inst); | 665 | OpCode op = GET_OPCODE(inst); |
665 | switch (op) { /* finish its execution */ | 666 | switch (op) { /* finish its execution */ |
666 | case OP_ADDI: case OP_SUBI: | 667 | case OP_ADDI: case OP_SUBI: |
@@ -684,9 +685,9 @@ void luaV_finishOp (lua_State *L) { | |||
684 | callstatus(base - 1) ^= CIST_LEQ; /* clear mark */ | 685 | callstatus(base - 1) ^= CIST_LEQ; /* clear mark */ |
685 | res = !res; /* negate result */ | 686 | res = !res; /* negate result */ |
686 | } | 687 | } |
687 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); | 688 | lua_assert(GET_OPCODE(*basepc(base)) == OP_JMP); |
688 | if (res != GETARG_A(inst)) /* condition failed? */ | 689 | if (res != GETARG_A(inst)) /* condition failed? */ |
689 | ci->u.l.savedpc++; /* skip jump instruction */ | 690 | basepc(base)++; /* skip jump instruction */ |
690 | break; | 691 | break; |
691 | } | 692 | } |
692 | case OP_CONCAT: { | 693 | case OP_CONCAT: { |
@@ -704,7 +705,7 @@ void luaV_finishOp (lua_State *L) { | |||
704 | break; | 705 | break; |
705 | } | 706 | } |
706 | case OP_TFORCALL: { | 707 | case OP_TFORCALL: { |
707 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); | 708 | lua_assert(GET_OPCODE(*basepc(base)) == OP_TFORLOOP); |
708 | L->top = functop(base - 1); /* correct top */ | 709 | L->top = functop(base - 1); /* correct top */ |
709 | break; | 710 | break; |
710 | } | 711 | } |
@@ -763,20 +764,22 @@ void luaV_finishOp (lua_State *L) { | |||
763 | ** Whenever code can raise errors (including memory errors), the global | 764 | ** Whenever code can raise errors (including memory errors), the global |
764 | ** 'pc' must be correct to report occasional errors. | 765 | ** 'pc' must be correct to report occasional errors. |
765 | */ | 766 | */ |
766 | #define savepc(L) (ci->u.l.savedpc = pc) | 767 | #define savepc(base) (basepc(base) = pc) |
768 | |||
767 | 769 | ||
770 | /* update internal copies to its correct values */ | ||
771 | #define updatestate() (base = L->func + 1, updatemask(L)) | ||
768 | 772 | ||
769 | /* | 773 | /* |
770 | ** Protect code that, in general, can raise errors, reallocate the | 774 | ** Protect code that, in general, can raise errors, reallocate the |
771 | ** stack, and change the hooks. | 775 | ** stack, and change the hooks. |
772 | */ | 776 | */ |
773 | #define Protect(code) \ | 777 | #define Protect(code) { savepc(base); {code;}; updatestate(); } |
774 | { savepc(L); {code;}; base = L->func + 1; updatemask(L); } | ||
775 | 778 | ||
776 | 779 | ||
777 | #define checkGC(L,c) \ | 780 | #define checkGC(L,c) \ |
778 | { luaC_condGC(L, L->top = (c), /* limit of live values */ \ | 781 | { luaC_condGC(L, L->top = (c), /* limit of live values */ \ |
779 | {Protect((void)0); L->top = functop(base - 1);}); /* restore top */ \ | 782 | {updatestate(); L->top = functop(base - 1);}); /* restore top */ \ |
780 | luai_threadyield(L); } | 783 | luai_threadyield(L); } |
781 | 784 | ||
782 | 785 | ||
@@ -798,14 +801,14 @@ void luaV_execute (lua_State *L) { | |||
798 | TValue *k; | 801 | TValue *k; |
799 | StkId base = L->func + 1; /* local copy of 'L->func + 1' */ | 802 | StkId base = L->func + 1; /* local copy of 'L->func + 1' */ |
800 | int mask; /* local copy of 'L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)' */ | 803 | int mask; /* local copy of 'L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)' */ |
801 | const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */ | 804 | const Instruction *pc; /* local copy of 'basepc(base)' */ |
802 | callstatus(base - 1) |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ | 805 | callstatus(base - 1) |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ |
803 | newframe: /* reentry point when frame changes (call/return) */ | 806 | newframe: /* reentry point when frame changes (call/return) */ |
804 | lua_assert(ci == L->ci); | 807 | lua_assert(ci == L->ci); |
805 | cl = clLvalue(s2v(L->func)); /* local reference to function's closure */ | 808 | cl = clLvalue(s2v(L->func)); /* local reference to function's closure */ |
806 | k = cl->p->k; /* local reference to function's constant table */ | 809 | k = cl->p->k; /* local reference to function's constant table */ |
807 | updatemask(L); | 810 | updatemask(L); |
808 | pc = ci->u.l.savedpc; | 811 | pc = basepc(base); |
809 | /* main loop of interpreter */ | 812 | /* main loop of interpreter */ |
810 | for (;;) { | 813 | for (;;) { |
811 | Instruction i; | 814 | Instruction i; |
@@ -969,7 +972,7 @@ void luaV_execute (lua_State *L) { | |||
969 | int b = GETARG_B(i); | 972 | int b = GETARG_B(i); |
970 | int c = GETARG_C(i); | 973 | int c = GETARG_C(i); |
971 | Table *t; | 974 | Table *t; |
972 | savepc(L); /* in case of allocation errors */ | 975 | savepc(base); /* in case of allocation errors */ |
973 | t = luaH_new(L); | 976 | t = luaH_new(L); |
974 | sethvalue2s(L, ra, t); | 977 | sethvalue2s(L, ra, t); |
975 | if (b != 0 || c != 0) | 978 | if (b != 0 || c != 0) |
@@ -1368,9 +1371,9 @@ void luaV_execute (lua_State *L) { | |||
1368 | int b = GETARG_B(i); | 1371 | int b = GETARG_B(i); |
1369 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ | 1372 | if (b != 0) L->top = ra+b; /* else previous instruction set top */ |
1370 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); | 1373 | lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); |
1371 | savepc(L); | 1374 | savepc(base); |
1372 | if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ | 1375 | if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ |
1373 | Protect((void)0); /* update 'base' */ | 1376 | updatestate(); /* update 'base' */ |
1374 | } | 1377 | } |
1375 | else { | 1378 | else { |
1376 | /* tail call: put called frame (n) in place of caller one (o) */ | 1379 | /* tail call: put called frame (n) in place of caller one (o) */ |
@@ -1388,7 +1391,7 @@ void luaV_execute (lua_State *L) { | |||
1388 | setobjs2s(L, ofunc + aux, nfunc + aux); | 1391 | setobjs2s(L, ofunc + aux, nfunc + aux); |
1389 | ofunc->stkci.framesize = L->top - nfunc; | 1392 | ofunc->stkci.framesize = L->top - nfunc; |
1390 | L->top = functop(ofunc); /* correct top */ | 1393 | L->top = functop(ofunc); /* correct top */ |
1391 | oci->u.l.savedpc = nci->u.l.savedpc; | 1394 | ofunc->stkci.u.l.savedpc = nfunc->stkci.u.l.savedpc; |
1392 | callstatus(ofunc) |= CIST_TAIL; /* function was tail called */ | 1395 | callstatus(ofunc) |= CIST_TAIL; /* function was tail called */ |
1393 | ci = L->ci = oci; /* remove new frame */ | 1396 | ci = L->ci = oci; /* remove new frame */ |
1394 | base = ofunc + 1; | 1397 | base = ofunc + 1; |
@@ -1401,7 +1404,7 @@ void luaV_execute (lua_State *L) { | |||
1401 | vmcase(OP_RETURN) { | 1404 | vmcase(OP_RETURN) { |
1402 | int b = GETARG_B(i); | 1405 | int b = GETARG_B(i); |
1403 | if (cl->p->sizep > 0) luaF_close(L, base); | 1406 | if (cl->p->sizep > 0) luaF_close(L, base); |
1404 | savepc(L); | 1407 | savepc(base); |
1405 | b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); | 1408 | b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); |
1406 | if (callstatus(base - 1) & CIST_FRESH) /* local 'base' still from callee */ | 1409 | if (callstatus(base - 1) & CIST_FRESH) /* local 'base' still from callee */ |
1407 | return; /* external invocation: return */ | 1410 | return; /* external invocation: return */ |
@@ -1409,8 +1412,8 @@ void luaV_execute (lua_State *L) { | |||
1409 | ci = L->ci; | 1412 | ci = L->ci; |
1410 | base = L->func + 1; | 1413 | base = L->func + 1; |
1411 | if (b) L->top = functop(base - 1); | 1414 | if (b) L->top = functop(base - 1); |
1412 | lua_assert(isLua(L->func)); | 1415 | lua_assert(isLua(base - 1)); |
1413 | lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); | 1416 | lua_assert(GET_OPCODE(*(basepc(base) - 1)) == OP_CALL); |
1414 | goto newframe; /* restart luaV_execute over previous Lua function */ | 1417 | goto newframe; /* restart luaV_execute over previous Lua function */ |
1415 | } | 1418 | } |
1416 | } | 1419 | } |
@@ -1455,7 +1458,7 @@ void luaV_execute (lua_State *L) { | |||
1455 | } | 1458 | } |
1456 | else { /* try making all values floats */ | 1459 | else { /* try making all values floats */ |
1457 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; | 1460 | lua_Number ninit; lua_Number nlimit; lua_Number nstep; |
1458 | savepc(L); /* in case of errors */ | 1461 | savepc(base); /* in case of errors */ |
1459 | if (!tonumber(plimit, &nlimit)) | 1462 | if (!tonumber(plimit, &nlimit)) |
1460 | luaG_runerror(L, "'for' limit must be a number"); | 1463 | luaG_runerror(L, "'for' limit must be a number"); |
1461 | setfltvalue(plimit, nlimit); | 1464 | setfltvalue(plimit, nlimit); |
@@ -1501,7 +1504,7 @@ void luaV_execute (lua_State *L) { | |||
1501 | } | 1504 | } |
1502 | h = hvalue(s2v(ra)); | 1505 | h = hvalue(s2v(ra)); |
1503 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; | 1506 | last = ((c-1)*LFIELDS_PER_FLUSH) + n; |
1504 | savepc(L); /* in case of allocation errors */ | 1507 | savepc(base); /* in case of allocation errors */ |
1505 | if (last > h->sizearray) /* needs more space? */ | 1508 | if (last > h->sizearray) /* needs more space? */ |
1506 | luaH_resizearray(L, h, last); /* preallocate it at once */ | 1509 | luaH_resizearray(L, h, last); /* preallocate it at once */ |
1507 | for (; n > 0; n--) { | 1510 | for (; n > 0; n--) { |
@@ -1518,7 +1521,7 @@ void luaV_execute (lua_State *L) { | |||
1518 | Proto *p = cl->p->p[GETARG_Bx(i)]; | 1521 | Proto *p = cl->p->p[GETARG_Bx(i)]; |
1519 | LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ | 1522 | LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ |
1520 | if (ncl == NULL) { /* no match? */ | 1523 | if (ncl == NULL) { /* no match? */ |
1521 | savepc(L); /* in case of allocation errors */ | 1524 | savepc(base); /* in case of allocation errors */ |
1522 | pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ | 1525 | pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ |
1523 | } | 1526 | } |
1524 | else | 1527 | else |