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 |
