diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-03 10:12:30 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2017-11-03 10:12:30 -0200 |
commit | 54eb35a8aa0f60265cf1b4764beabe1199d66f42 (patch) | |
tree | 83bc4049d312bdbe0b8e78ed1745839fcf9a5a03 | |
parent | ba36180fd7b68341ad57e0fbe7a55cdfb334908d (diff) | |
download | lua-54eb35a8aa0f60265cf1b4764beabe1199d66f42.tar.gz lua-54eb35a8aa0f60265cf1b4764beabe1199d66f42.tar.bz2 lua-54eb35a8aa0f60265cf1b4764beabe1199d66f42.zip |
more fields moved out of 'CallInfo'
-rw-r--r-- | lapi.c | 45 | ||||
-rw-r--r-- | lapi.h | 7 | ||||
-rw-r--r-- | ldebug.c | 29 | ||||
-rw-r--r-- | ldo.c | 80 | ||||
-rw-r--r-- | lgc.c | 6 | ||||
-rw-r--r-- | lobject.h | 13 | ||||
-rw-r--r-- | lstate.c | 6 | ||||
-rw-r--r-- | lstate.h | 22 | ||||
-rw-r--r-- | ltests.c | 11 | ||||
-rw-r--r-- | ltm.c | 6 | ||||
-rw-r--r-- | lvm.c | 54 |
11 files changed, 152 insertions, 127 deletions
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.c,v 2.272 2017/11/01 18:20:48 roberto Exp roberto $ | 2 | ** $Id: lapi.c,v 2.273 2017/11/02 11:28:56 roberto Exp roberto $ |
3 | ** Lua API | 3 | ** Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -10,6 +10,7 @@ | |||
10 | #include "lprefix.h" | 10 | #include "lprefix.h" |
11 | 11 | ||
12 | 12 | ||
13 | #include <limits.h> | ||
13 | #include <stdarg.h> | 14 | #include <stdarg.h> |
14 | #include <string.h> | 15 | #include <string.h> |
15 | 16 | ||
@@ -60,12 +61,12 @@ const char lua_ident[] = | |||
60 | static TValue *index2value (lua_State *L, int idx) { | 61 | static TValue *index2value (lua_State *L, int idx) { |
61 | if (idx > 0) { | 62 | if (idx > 0) { |
62 | StkId o = L->func + idx; | 63 | StkId o = L->func + idx; |
63 | api_check(L, idx <= L->ci->top - (L->func + 1), "unacceptable index"); | 64 | api_check(L, idx < L->func->stkci.framesize, "unacceptable index"); |
64 | if (o >= L->top) return NONVALIDVALUE; | 65 | if (o >= L->top) return NONVALIDVALUE; |
65 | else return s2v(o); | 66 | else return s2v(o); |
66 | } | 67 | } |
67 | else if (!ispseudo(idx)) { /* negative index */ | 68 | else if (!ispseudo(idx)) { /* negative index */ |
68 | api_check(L, idx != 0 && -idx <= L->top - (L->func + 1), "invalid index"); | 69 | api_check(L, idx != 0 && -idx < L->func->stkci.framesize, "invalid index"); |
69 | return s2v(L->top + idx); | 70 | return s2v(L->top + idx); |
70 | } | 71 | } |
71 | else if (idx == LUA_REGISTRYINDEX) | 72 | else if (idx == LUA_REGISTRYINDEX) |
@@ -109,10 +110,12 @@ static void growstack (lua_State *L, void *ud) { | |||
109 | 110 | ||
110 | LUA_API int lua_checkstack (lua_State *L, int n) { | 111 | LUA_API int lua_checkstack (lua_State *L, int n) { |
111 | int res; | 112 | int res; |
112 | CallInfo *ci = L->ci; | 113 | int frameuse = L->top - L->func; |
113 | lua_lock(L); | 114 | lua_lock(L); |
114 | api_check(L, n >= 0, "negative 'n'"); | 115 | api_check(L, n >= 0, "negative 'n'"); |
115 | if (L->stack_last - L->top > n) /* stack large enough? */ | 116 | if (n >= USHRT_MAX - frameuse) |
117 | res = 0; /* frame size overflow */ | ||
118 | else if (L->stack_last - L->top > n) /* stack large enough? */ | ||
116 | res = 1; /* yes; check is OK */ | 119 | res = 1; /* yes; check is OK */ |
117 | else { /* no; need to grow stack */ | 120 | else { /* no; need to grow stack */ |
118 | int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; | 121 | int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; |
@@ -121,8 +124,8 @@ LUA_API int lua_checkstack (lua_State *L, int n) { | |||
121 | else /* try to grow stack */ | 124 | else /* try to grow stack */ |
122 | res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); | 125 | res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); |
123 | } | 126 | } |
124 | if (res && ci->top < L->top + n) | 127 | if (res && L->func->stkci.framesize < frameuse + n) |
125 | ci->top = L->top + n; /* adjust frame top */ | 128 | L->func->stkci.framesize = frameuse + n; /* adjust frame size */ |
126 | lua_unlock(L); | 129 | lua_unlock(L); |
127 | return res; | 130 | return res; |
128 | } | 131 | } |
@@ -134,7 +137,7 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { | |||
134 | lua_lock(to); | 137 | lua_lock(to); |
135 | api_checknelems(from, n); | 138 | api_checknelems(from, n); |
136 | api_check(from, G(from) == G(to), "moving among independent states"); | 139 | api_check(from, G(from) == G(to), "moving among independent states"); |
137 | api_check(from, to->ci->top - to->top >= n, "stack overflow"); | 140 | api_check(from, functop(to->func) - to->top >= n, "stack overflow"); |
138 | from->top -= n; | 141 | from->top -= n; |
139 | for (i = 0; i < n; i++) { | 142 | for (i = 0; i < n; i++) { |
140 | setobjs2s(to, to->top, from->top + i); | 143 | setobjs2s(to, to->top, from->top + i); |
@@ -929,15 +932,16 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { | |||
929 | 932 | ||
930 | 933 | ||
931 | #define checkresults(L,na,nr) \ | 934 | #define checkresults(L,na,nr) \ |
932 | api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ | 935 | api_check(L, (nr) == LUA_MULTRET || \ |
933 | "results from function overflow current stack size") | 936 | (functop(L->func) - L->top >= (nr) - (na)), \ |
937 | "results from function overflow current frame size") | ||
934 | 938 | ||
935 | 939 | ||
936 | LUA_API void lua_callk (lua_State *L, int nargs, int nresults, | 940 | LUA_API void lua_callk (lua_State *L, int nargs, int nresults, |
937 | lua_KContext ctx, lua_KFunction k) { | 941 | lua_KContext ctx, lua_KFunction k) { |
938 | StkId func; | 942 | StkId func; |
939 | lua_lock(L); | 943 | lua_lock(L); |
940 | api_check(L, k == NULL || !isLua(L->ci), | 944 | api_check(L, k == NULL || !isLua(L->func), |
941 | "cannot use continuations inside hooks"); | 945 | "cannot use continuations inside hooks"); |
942 | api_checknelems(L, nargs+1); | 946 | api_checknelems(L, nargs+1); |
943 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); | 947 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); |
@@ -976,36 +980,37 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, | |||
976 | lua_KContext ctx, lua_KFunction k) { | 980 | lua_KContext ctx, lua_KFunction k) { |
977 | struct CallS c; | 981 | struct CallS c; |
978 | int status; | 982 | int status; |
979 | ptrdiff_t func; | 983 | ptrdiff_t efunc; |
980 | lua_lock(L); | 984 | lua_lock(L); |
981 | api_check(L, k == NULL || !isLua(L->ci), | 985 | api_check(L, k == NULL || !isLua(L->func), |
982 | "cannot use continuations inside hooks"); | 986 | "cannot use continuations inside hooks"); |
983 | api_checknelems(L, nargs+1); | 987 | api_checknelems(L, nargs+1); |
984 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); | 988 | api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); |
985 | checkresults(L, nargs, nresults); | 989 | checkresults(L, nargs, nresults); |
986 | if (errfunc == 0) | 990 | if (errfunc == 0) |
987 | func = 0; | 991 | efunc = 0; |
988 | else { | 992 | else { |
989 | StkId o = index2stack(L, errfunc); | 993 | StkId o = index2stack(L, errfunc); |
990 | func = savestack(L, o); | 994 | efunc = savestack(L, o); |
991 | } | 995 | } |
992 | c.func = L->top - (nargs+1); /* function to be called */ | 996 | c.func = L->top - (nargs+1); /* function to be called */ |
993 | if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ | 997 | if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ |
994 | c.nresults = nresults; /* do a 'conventional' protected call */ | 998 | c.nresults = nresults; /* do a 'conventional' protected call */ |
995 | status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); | 999 | status = luaD_pcall(L, f_call, &c, savestack(L, c.func), efunc); |
996 | } | 1000 | } |
997 | else { /* prepare continuation (call is already protected by 'resume') */ | 1001 | else { /* prepare continuation (call is already protected by 'resume') */ |
998 | CallInfo *ci = L->ci; | 1002 | CallInfo *ci = L->ci; |
1003 | StkId func = L->func; | ||
999 | ci->u.c.k = k; /* save continuation */ | 1004 | ci->u.c.k = k; /* save continuation */ |
1000 | ci->u.c.ctx = ctx; /* save context */ | 1005 | ci->u.c.ctx = ctx; /* save context */ |
1001 | /* save information for error recovery */ | 1006 | /* save information for error recovery */ |
1002 | ci->u2.funcidx = savestack(L, c.func); | 1007 | ci->u2.funcidx = savestack(L, c.func); |
1003 | ci->u.c.old_errfunc = L->errfunc; | 1008 | ci->u.c.old_errfunc = L->errfunc; |
1004 | L->errfunc = func; | 1009 | L->errfunc = efunc; |
1005 | setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ | 1010 | setoah(callstatus(func), L->allowhook); /* save value of 'allowhook' */ |
1006 | ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ | 1011 | callstatus(func) |= CIST_YPCALL; /* function can do error recovery */ |
1007 | luaD_call(L, c.func, nresults); /* do the call */ | 1012 | luaD_call(L, c.func, nresults); /* do the call */ |
1008 | ci->callstatus &= ~CIST_YPCALL; | 1013 | callstatus(func) &= ~CIST_YPCALL; |
1009 | L->errfunc = ci->u.c.old_errfunc; | 1014 | L->errfunc = ci->u.c.old_errfunc; |
1010 | status = LUA_OK; /* if it is here, there were no errors */ | 1015 | status = LUA_OK; /* if it is here, there were no errors */ |
1011 | } | 1016 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lapi.h,v 2.9 2015/03/06 19:49:50 roberto Exp roberto $ | 2 | ** $Id: lapi.h,v 2.10 2017/11/01 18:20:48 roberto Exp roberto $ |
3 | ** Auxiliary functions from Lua API | 3 | ** Auxiliary functions from Lua API |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -11,11 +11,12 @@ | |||
11 | #include "llimits.h" | 11 | #include "llimits.h" |
12 | #include "lstate.h" | 12 | #include "lstate.h" |
13 | 13 | ||
14 | #define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ | 14 | #define api_incr_top(L) {L->top++; api_check(L, L->top <= functop(L->func), \ |
15 | "stack overflow");} | 15 | "stack overflow");} |
16 | 16 | ||
17 | #define adjustresults(L,nres) \ | 17 | #define adjustresults(L,nres) \ |
18 | { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } | 18 | { if ((nres) == LUA_MULTRET && functop(L->func) < L->top) \ |
19 | setfunctop(L->func, L->top); } | ||
19 | 20 | ||
20 | #define api_checknelems(L,n) api_check(L, (n) < (L->top - L->func), \ | 21 | #define api_checknelems(L,n) api_check(L, (n) < (L->top - L->func), \ |
21 | "not enough elements in the stack") | 22 | "not enough elements in the stack") |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldebug.c,v 2.134 2017/11/01 18:20:48 roberto Exp roberto $ | 2 | ** $Id: ldebug.c,v 2.135 2017/11/02 11:28:56 roberto Exp roberto $ |
3 | ** Debug Interface | 3 | ** Debug Interface |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -43,7 +43,7 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | |||
43 | 43 | ||
44 | 44 | ||
45 | static int currentpc (CallInfo *ci) { | 45 | static int currentpc (CallInfo *ci) { |
46 | lua_assert(isLua(ci)); | 46 | lua_assert(isLua(ci->func)); |
47 | return pcRel(ci->u.l.savedpc, ci_func(ci)->p); | 47 | return pcRel(ci->u.l.savedpc, ci_func(ci)->p); |
48 | } | 48 | } |
49 | 49 | ||
@@ -120,7 +120,7 @@ LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { | |||
120 | mask = 0; | 120 | mask = 0; |
121 | func = NULL; | 121 | func = NULL; |
122 | } | 122 | } |
123 | if (isLua(L->ci)) | 123 | if (isLua(L->func)) |
124 | L->oldpc = L->ci->u.l.savedpc; | 124 | L->oldpc = L->ci->u.l.savedpc; |
125 | L->hook = func; | 125 | L->hook = func; |
126 | L->basehookcount = count; | 126 | L->basehookcount = count; |
@@ -172,7 +172,7 @@ static const char *findlocal (lua_State *L, CallInfo *ci, int n, | |||
172 | StkId *pos) { | 172 | StkId *pos) { |
173 | const char *name = NULL; | 173 | const char *name = NULL; |
174 | StkId base; | 174 | StkId base; |
175 | if (isLua(ci)) { | 175 | if (isLua(ci->func)) { |
176 | base = ci->func + 1; | 176 | base = ci->func + 1; |
177 | name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); | 177 | name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); |
178 | } | 178 | } |
@@ -277,12 +277,12 @@ static void collectvalidlines (lua_State *L, Closure *f) { | |||
277 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { | 277 | static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { |
278 | if (ci == NULL) /* no 'ci'? */ | 278 | if (ci == NULL) /* no 'ci'? */ |
279 | return NULL; /* no info */ | 279 | return NULL; /* no info */ |
280 | else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ | 280 | else if (callstatus(ci->func) & CIST_FIN) { /* is this a finalizer? */ |
281 | *name = "__gc"; | 281 | *name = "__gc"; |
282 | return "metamethod"; /* report it as such */ | 282 | return "metamethod"; /* report it as such */ |
283 | } | 283 | } |
284 | /* calling function is a known Lua function? */ | 284 | /* calling function is a known Lua function? */ |
285 | else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) | 285 | else if (!(callstatus(ci->func) & CIST_TAIL) && isLua(ci->previous->func)) |
286 | return funcnamefromcode(L, ci->previous, name); | 286 | return funcnamefromcode(L, ci->previous, name); |
287 | else return NULL; /* no way to find a name */ | 287 | else return NULL; /* no way to find a name */ |
288 | } | 288 | } |
@@ -298,7 +298,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
298 | break; | 298 | break; |
299 | } | 299 | } |
300 | case 'l': { | 300 | case 'l': { |
301 | ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; | 301 | ar->currentline = (ci && isLua(ci->func)) ? currentline(ci) : -1; |
302 | break; | 302 | break; |
303 | } | 303 | } |
304 | case 'u': { | 304 | case 'u': { |
@@ -314,7 +314,7 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, | |||
314 | break; | 314 | break; |
315 | } | 315 | } |
316 | case 't': { | 316 | case 't': { |
317 | ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; | 317 | ar->istailcall = (ci) ? callstatus(ci->func) & CIST_TAIL : 0; |
318 | break; | 318 | break; |
319 | } | 319 | } |
320 | case 'n': { | 320 | case 'n': { |
@@ -549,7 +549,7 @@ static const char *funcnamefromcode (lua_State *L, CallInfo *ci, | |||
549 | Proto *p = ci_func(ci)->p; /* calling function */ | 549 | Proto *p = ci_func(ci)->p; /* calling function */ |
550 | int pc = currentpc(ci); /* calling instruction index */ | 550 | int pc = currentpc(ci); /* calling instruction index */ |
551 | Instruction i = p->code[pc]; /* calling instruction */ | 551 | Instruction i = p->code[pc]; /* calling instruction */ |
552 | if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ | 552 | if (callstatus(ci->func) & CIST_HOOKED) { /* was it called inside a hook? */ |
553 | *name = "?"; | 553 | *name = "?"; |
554 | return "hook"; | 554 | return "hook"; |
555 | } | 555 | } |
@@ -635,7 +635,7 @@ static const char *varinfo (lua_State *L, const TValue *o) { | |||
635 | const char *name = NULL; /* to avoid warnings */ | 635 | const char *name = NULL; /* to avoid warnings */ |
636 | CallInfo *ci = L->ci; | 636 | CallInfo *ci = L->ci; |
637 | const char *kind = NULL; | 637 | const char *kind = NULL; |
638 | if (isLua(ci)) { | 638 | if (isLua(L->func)) { |
639 | kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ | 639 | kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ |
640 | if (!kind && isinstack(L, o)) /* no? try a register */ | 640 | if (!kind && isinstack(L, o)) /* no? try a register */ |
641 | kind = getobjname(ci_func(ci)->p, currentpc(ci), | 641 | kind = getobjname(ci_func(ci)->p, currentpc(ci), |
@@ -719,7 +719,7 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { | |||
719 | va_start(argp, fmt); | 719 | va_start(argp, fmt); |
720 | msg = luaO_pushvfstring(L, fmt, argp); /* format message */ | 720 | msg = luaO_pushvfstring(L, fmt, argp); /* format message */ |
721 | va_end(argp); | 721 | va_end(argp); |
722 | if (isLua(ci)) /* if Lua function, add source:line information */ | 722 | if (isLua(L->func)) /* if Lua function, add source:line information */ |
723 | luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); | 723 | luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); |
724 | luaG_errormsg(L); | 724 | luaG_errormsg(L); |
725 | } | 725 | } |
@@ -740,14 +740,15 @@ static int changedline (Proto *p, int oldpc, int newpc) { | |||
740 | 740 | ||
741 | void luaG_traceexec (lua_State *L) { | 741 | void luaG_traceexec (lua_State *L) { |
742 | CallInfo *ci = L->ci; | 742 | CallInfo *ci = L->ci; |
743 | StkId func = L->func; | ||
743 | lu_byte mask = L->hookmask; | 744 | lu_byte mask = L->hookmask; |
744 | int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); | 745 | int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); |
745 | if (counthook) | 746 | if (counthook) |
746 | resethookcount(L); /* reset count */ | 747 | resethookcount(L); /* reset count */ |
747 | else if (!(mask & LUA_MASKLINE)) | 748 | else if (!(mask & LUA_MASKLINE)) |
748 | return; /* no line hook and count != 0; nothing to be done */ | 749 | return; /* no line hook and count != 0; nothing to be done */ |
749 | if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ | 750 | if (callstatus(func) & CIST_HOOKYIELD) { /* called hook last time? */ |
750 | ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ | 751 | callstatus(func) &= ~CIST_HOOKYIELD; /* erase mark */ |
751 | return; /* do not call hook again (VM yielded, so it did not move) */ | 752 | return; /* do not call hook again (VM yielded, so it did not move) */ |
752 | } | 753 | } |
753 | if (counthook) | 754 | if (counthook) |
@@ -767,7 +768,7 @@ void luaG_traceexec (lua_State *L) { | |||
767 | if (counthook) | 768 | if (counthook) |
768 | L->hookcount = 1; /* undo decrement to zero */ | 769 | L->hookcount = 1; /* undo decrement to zero */ |
769 | ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ | 770 | ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ |
770 | ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ | 771 | callstatus(func) |= CIST_HOOKYIELD; /* mark that it yielded */ |
771 | luaD_throw(L, LUA_YIELD); | 772 | luaD_throw(L, LUA_YIELD); |
772 | } | 773 | } |
773 | } | 774 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ldo.c,v 2.164 2017/11/01 18:20:48 roberto Exp roberto $ | 2 | ** $Id: ldo.c,v 2.165 2017/11/02 11:28:56 roberto Exp roberto $ |
3 | ** Stack and Call structure of Lua | 3 | ** Stack and Call structure of Lua |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -123,8 +123,8 @@ l_noret luaD_throw (lua_State *L, int errcode) { | |||
123 | else { /* no handler at all; abort */ | 123 | else { /* no handler at all; abort */ |
124 | if (g->panic) { /* panic function? */ | 124 | if (g->panic) { /* panic function? */ |
125 | seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ | 125 | seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ |
126 | if (L->ci->top < L->top) | 126 | if (functop(L->func) < L->top) /* check invariant */ |
127 | L->ci->top = L->top; /* pushing msg. can break this invariant */ | 127 | setfunctop(L->func, L->top); |
128 | lua_unlock(L); | 128 | lua_unlock(L); |
129 | g->panic(L); /* call panic function (last chance to jump out) */ | 129 | g->panic(L); /* call panic function (last chance to jump out) */ |
130 | } | 130 | } |
@@ -164,7 +164,6 @@ static void correctstack (lua_State *L, StkId oldstack) { | |||
164 | for (up = L->openupval; up != NULL; up = up->u.open.next) | 164 | for (up = L->openupval; up != NULL; up = up->u.open.next) |
165 | up->v = s2v((uplevel(up) - oldstack) + L->stack); | 165 | up->v = s2v((uplevel(up) - oldstack) + L->stack); |
166 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 166 | for (ci = L->ci; ci != NULL; ci = ci->previous) { |
167 | ci->top = (ci->top - oldstack) + L->stack; | ||
168 | ci->func = (ci->func - oldstack) + L->stack; | 167 | ci->func = (ci->func - oldstack) + L->stack; |
169 | } | 168 | } |
170 | } | 169 | } |
@@ -208,10 +207,11 @@ void luaD_growstack (lua_State *L, int n) { | |||
208 | 207 | ||
209 | 208 | ||
210 | static int stackinuse (lua_State *L) { | 209 | static int stackinuse (lua_State *L) { |
211 | CallInfo *ci; | ||
212 | StkId lim = L->top; | 210 | StkId lim = L->top; |
213 | for (ci = L->ci; ci != NULL; ci = ci->previous) { | 211 | StkId func = L->func; |
214 | if (lim < ci->top) lim = ci->top; | 212 | for (; func->stkci.previous != 0; func -= func->stkci.previous) { |
213 | if (lim < functop(func)) | ||
214 | lim = functop(func); | ||
215 | } | 215 | } |
216 | lua_assert(lim <= L->stack_last); | 216 | lua_assert(lim <= L->stack_last); |
217 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ | 217 | return cast_int(lim - L->stack) + 1; /* part of stack in use */ |
@@ -255,34 +255,38 @@ void luaD_hook (lua_State *L, int event, int line) { | |||
255 | if (hook && L->allowhook) { /* make sure there is a hook */ | 255 | if (hook && L->allowhook) { /* make sure there is a hook */ |
256 | CallInfo *ci = L->ci; | 256 | CallInfo *ci = L->ci; |
257 | ptrdiff_t top = savestack(L, L->top); | 257 | ptrdiff_t top = savestack(L, L->top); |
258 | ptrdiff_t ci_top = savestack(L, ci->top); | 258 | int origframesize = L->func->stkci.framesize; |
259 | int tmpframesize; /* frame size to run hook */ | ||
259 | lua_Debug ar; | 260 | lua_Debug ar; |
260 | ar.event = event; | 261 | ar.event = event; |
261 | ar.currentline = line; | 262 | ar.currentline = line; |
262 | ar.i_ci = ci; | 263 | ar.i_ci = ci; |
263 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ | 264 | luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ |
264 | ci->top = L->top + LUA_MINSTACK; | 265 | tmpframesize = L->top - L->func + LUA_MINSTACK; |
265 | lua_assert(ci->top <= L->stack_last); | 266 | if (tmpframesize > origframesize) /* need to grow frame? */ |
267 | L->func->stkci.framesize = tmpframesize; | ||
268 | lua_assert(functop(L->func) <= L->stack_last); | ||
266 | L->allowhook = 0; /* cannot call hooks inside a hook */ | 269 | L->allowhook = 0; /* cannot call hooks inside a hook */ |
267 | ci->callstatus |= CIST_HOOKED; | 270 | callstatus(L->func) |= CIST_HOOKED; |
268 | lua_unlock(L); | 271 | lua_unlock(L); |
269 | (*hook)(L, &ar); | 272 | (*hook)(L, &ar); |
270 | lua_lock(L); | 273 | lua_lock(L); |
271 | lua_assert(!L->allowhook); | 274 | lua_assert(!L->allowhook); |
272 | L->allowhook = 1; | 275 | L->allowhook = 1; |
273 | ci->top = restorestack(L, ci_top); | 276 | L->func->stkci.framesize = origframesize; |
274 | L->top = restorestack(L, top); | 277 | L->top = restorestack(L, top); |
275 | ci->callstatus &= ~CIST_HOOKED; | 278 | callstatus(L->func) &= ~CIST_HOOKED; |
276 | } | 279 | } |
277 | } | 280 | } |
278 | 281 | ||
279 | 282 | ||
280 | static void callhook (lua_State *L, CallInfo *ci) { | 283 | static void callhook (lua_State *L, CallInfo *ci) { |
281 | int hook = LUA_HOOKCALL; | 284 | int hook = LUA_HOOKCALL; |
285 | StkId previous = L->func - L->func->stkci.previous; | ||
282 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ | 286 | ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ |
283 | if (isLua(ci->previous) && | 287 | if (isLua(previous) && |
284 | GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { | 288 | GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { |
285 | ci->callstatus |= CIST_TAIL; | 289 | callstatus(L->func) |= CIST_TAIL; |
286 | hook = LUA_HOOKTAILCALL; | 290 | hook = LUA_HOOKTAILCALL; |
287 | } | 291 | } |
288 | luaD_hook(L, hook, -1); | 292 | luaD_hook(L, hook, -1); |
@@ -358,8 +362,8 @@ static int moveresults (lua_State *L, StkId firstResult, StkId res, | |||
358 | ** wanted multiple (variable number of) results. | 362 | ** wanted multiple (variable number of) results. |
359 | */ | 363 | */ |
360 | int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { | 364 | int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { |
361 | StkId res; | 365 | StkId res = L->func; /* res == final position of 1st result */ |
362 | int wanted = ci->nresults; | 366 | int wanted = res->stkci.nresults; |
363 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { | 367 | if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { |
364 | if (L->hookmask & LUA_MASKRET) { | 368 | if (L->hookmask & LUA_MASKRET) { |
365 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ | 369 | ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ |
@@ -368,7 +372,6 @@ int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { | |||
368 | } | 372 | } |
369 | L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ | 373 | L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ |
370 | } | 374 | } |
371 | res = L->func; /* res == final position of 1st result */ | ||
372 | L->ci = ci->previous; /* back to caller */ | 375 | L->ci = ci->previous; /* back to caller */ |
373 | L->func -= L->func->stkci.previous; | 376 | L->func -= L->func->stkci.previous; |
374 | lua_assert(L->func == L->ci->func); | 377 | lua_assert(L->func == L->ci->func); |
@@ -402,12 +405,12 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
402 | int n; /* number of returns */ | 405 | int n; /* number of returns */ |
403 | checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ | 406 | checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ |
404 | ci = next_ci(L); /* now 'enter' new function */ | 407 | ci = next_ci(L); /* now 'enter' new function */ |
405 | ci->nresults = nresults; | 408 | func->stkci.nresults = nresults; |
406 | func->stkci.previous = func - L->func; | 409 | func->stkci.previous = func - L->func; |
407 | L->func = ci->func = func; | 410 | L->func = ci->func = func; |
408 | ci->top = L->top + LUA_MINSTACK; | 411 | setfunctop(func, L->top + LUA_MINSTACK); |
409 | lua_assert(ci->top <= L->stack_last); | 412 | lua_assert(functop(func) <= L->stack_last); |
410 | ci->callstatus = 0; | 413 | callstatus(func) = 0; |
411 | if (L->hookmask & LUA_MASKCALL) | 414 | if (L->hookmask & LUA_MASKCALL) |
412 | luaD_hook(L, LUA_HOOKCALL, -1); | 415 | luaD_hook(L, LUA_HOOKCALL, -1); |
413 | lua_unlock(L); | 416 | lua_unlock(L); |
@@ -427,13 +430,14 @@ int luaD_precall (lua_State *L, StkId func, int nresults) { | |||
427 | if (p->is_vararg) | 430 | if (p->is_vararg) |
428 | luaT_adjustvarargs(L, p, n); | 431 | luaT_adjustvarargs(L, p, n); |
429 | ci = next_ci(L); /* now 'enter' new function */ | 432 | ci = next_ci(L); /* now 'enter' new function */ |
430 | ci->nresults = nresults; | 433 | func->stkci.nresults = nresults; |
431 | func->stkci.previous = func - L->func; | 434 | func->stkci.previous = func - L->func; |
435 | func->stkci.framesize = fsize + 1; /* size includes function itself */ | ||
432 | L->func = ci->func = func; | 436 | L->func = ci->func = func; |
433 | L->top = ci->top = func + 1 + fsize; | 437 | L->top = func + 1 + fsize; |
434 | lua_assert(ci->top <= L->stack_last); | 438 | lua_assert(functop(func) <= L->stack_last); |
435 | ci->u.l.savedpc = p->code; /* starting point */ | 439 | ci->u.l.savedpc = p->code; /* starting point */ |
436 | ci->callstatus = CIST_LUA; | 440 | callstatus(func) = 0; |
437 | if (L->hookmask & LUA_MASKCALL) | 441 | if (L->hookmask & LUA_MASKCALL) |
438 | callhook(L, ci); | 442 | callhook(L, ci); |
439 | return 0; | 443 | return 0; |
@@ -493,18 +497,19 @@ void luaD_callnoyield (lua_State *L, StkId func, int nResults) { | |||
493 | */ | 497 | */ |
494 | static void finishCcall (lua_State *L, int status) { | 498 | static void finishCcall (lua_State *L, int status) { |
495 | CallInfo *ci = L->ci; | 499 | CallInfo *ci = L->ci; |
500 | StkId func = L->func; | ||
496 | int n; | 501 | int n; |
497 | /* must have a continuation and must be able to call it */ | 502 | /* must have a continuation and must be able to call it */ |
498 | lua_assert(ci->u.c.k != NULL && L->nny == 0); | 503 | lua_assert(ci->u.c.k != NULL && L->nny == 0); |
499 | /* error status can only happen in a protected call */ | 504 | /* error status can only happen in a protected call */ |
500 | lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); | 505 | lua_assert((callstatus(func) & CIST_YPCALL) || status == LUA_YIELD); |
501 | if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ | 506 | if (callstatus(func) & CIST_YPCALL) { /* was inside a pcall? */ |
502 | ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ | 507 | callstatus(func) &= ~CIST_YPCALL; /* continuation is also inside it */ |
503 | L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ | 508 | L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ |
504 | } | 509 | } |
505 | /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already | 510 | /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already |
506 | handled */ | 511 | handled */ |
507 | adjustresults(L, ci->nresults); | 512 | adjustresults(L, func->stkci.nresults); |
508 | lua_unlock(L); | 513 | lua_unlock(L); |
509 | n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ | 514 | n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ |
510 | lua_lock(L); | 515 | lua_lock(L); |
@@ -525,7 +530,7 @@ static void unroll (lua_State *L, void *ud) { | |||
525 | if (ud != NULL) /* error status? */ | 530 | if (ud != NULL) /* error status? */ |
526 | finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ | 531 | finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ |
527 | while (L->ci != &L->base_ci) { /* something in the stack */ | 532 | while (L->ci != &L->base_ci) { /* something in the stack */ |
528 | if (!isLua(L->ci)) /* C function? */ | 533 | if (!isLua(L->func)) /* C function? */ |
529 | finishCcall(L, LUA_YIELD); /* complete its execution */ | 534 | finishCcall(L, LUA_YIELD); /* complete its execution */ |
530 | else { /* Lua function */ | 535 | else { /* Lua function */ |
531 | luaV_finishOp(L); /* finish interrupted instruction */ | 536 | luaV_finishOp(L); /* finish interrupted instruction */ |
@@ -542,7 +547,7 @@ static void unroll (lua_State *L, void *ud) { | |||
542 | static CallInfo *findpcall (lua_State *L) { | 547 | static CallInfo *findpcall (lua_State *L) { |
543 | CallInfo *ci; | 548 | CallInfo *ci; |
544 | for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ | 549 | for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ |
545 | if (ci->callstatus & CIST_YPCALL) | 550 | if (callstatus(ci->func) & CIST_YPCALL) |
546 | return ci; | 551 | return ci; |
547 | } | 552 | } |
548 | return NULL; /* no pending pcall */ | 553 | return NULL; /* no pending pcall */ |
@@ -564,7 +569,7 @@ static int recover (lua_State *L, int status) { | |||
564 | seterrorobj(L, status, oldtop); | 569 | seterrorobj(L, status, oldtop); |
565 | L->ci = ci; | 570 | L->ci = ci; |
566 | L->func = ci->func; | 571 | L->func = ci->func; |
567 | L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ | 572 | L->allowhook = getoah(callstatus(L->func)); /* restore original 'allowhook' */ |
568 | L->nny = 0; /* should be zero to be yieldable */ | 573 | L->nny = 0; /* should be zero to be yieldable */ |
569 | luaD_shrinkstack(L); | 574 | luaD_shrinkstack(L); |
570 | L->errfunc = ci->u.c.old_errfunc; | 575 | L->errfunc = ci->u.c.old_errfunc; |
@@ -604,7 +609,7 @@ static void resume (lua_State *L, void *ud) { | |||
604 | else { /* resuming from previous yield */ | 609 | else { /* resuming from previous yield */ |
605 | lua_assert(L->status == LUA_YIELD); | 610 | lua_assert(L->status == LUA_YIELD); |
606 | L->status = LUA_OK; /* mark that it is running (again) */ | 611 | L->status = LUA_OK; /* mark that it is running (again) */ |
607 | if (isLua(ci)) /* yielded inside a hook? */ | 612 | if (isLua(L->func)) /* yielded inside a hook? */ |
608 | luaV_execute(L); /* just continue running Lua code */ | 613 | luaV_execute(L); /* just continue running Lua code */ |
609 | else { /* 'common' yield */ | 614 | else { /* 'common' yield */ |
610 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ | 615 | if (ci->u.c.k != NULL) { /* does it have a continuation function? */ |
@@ -649,7 +654,7 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, | |||
649 | if (errorstatus(status)) { /* unrecoverable error? */ | 654 | if (errorstatus(status)) { /* unrecoverable error? */ |
650 | L->status = cast_byte(status); /* mark thread as 'dead' */ | 655 | L->status = cast_byte(status); /* mark thread as 'dead' */ |
651 | seterrorobj(L, status, L->top); /* push error message */ | 656 | seterrorobj(L, status, L->top); /* push error message */ |
652 | L->ci->top = L->top; | 657 | L->func->stkci.framesize = L->top - L->func; |
653 | } | 658 | } |
654 | else lua_assert(status == L->status); /* normal end or yield */ | 659 | else lua_assert(status == L->status); /* normal end or yield */ |
655 | } | 660 | } |
@@ -671,6 +676,7 @@ LUA_API int lua_isyieldable (lua_State *L) { | |||
671 | LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | 676 | LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, |
672 | lua_KFunction k) { | 677 | lua_KFunction k) { |
673 | CallInfo *ci = L->ci; | 678 | CallInfo *ci = L->ci; |
679 | StkId func = L->func; | ||
674 | luai_userstateyield(L, nresults); | 680 | luai_userstateyield(L, nresults); |
675 | lua_lock(L); | 681 | lua_lock(L); |
676 | api_checknelems(L, nresults); | 682 | api_checknelems(L, nresults); |
@@ -681,7 +687,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
681 | luaG_runerror(L, "attempt to yield from outside a coroutine"); | 687 | luaG_runerror(L, "attempt to yield from outside a coroutine"); |
682 | } | 688 | } |
683 | L->status = LUA_YIELD; | 689 | L->status = LUA_YIELD; |
684 | if (isLua(ci)) { /* inside a hook? */ | 690 | if (isLua(func)) { /* inside a hook? */ |
685 | api_check(L, k == NULL, "hooks cannot continue after yielding"); | 691 | api_check(L, k == NULL, "hooks cannot continue after yielding"); |
686 | ci->u2.nyield = 0; /* no results */ | 692 | ci->u2.nyield = 0; /* no results */ |
687 | } | 693 | } |
@@ -691,7 +697,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, | |||
691 | ci->u2.nyield = nresults; /* save number of results */ | 697 | ci->u2.nyield = nresults; /* save number of results */ |
692 | luaD_throw(L, LUA_YIELD); | 698 | luaD_throw(L, LUA_YIELD); |
693 | } | 699 | } |
694 | lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ | 700 | lua_assert(callstatus(func) & CIST_HOOKED); /* must be inside a hook */ |
695 | lua_unlock(L); | 701 | lua_unlock(L); |
696 | return 0; /* return to 'luaD_hook' */ | 702 | return 0; /* return to 'luaD_hook' */ |
697 | } | 703 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lgc.c,v 2.235 2017/10/11 12:38:45 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.236 2017/10/31 15:29:28 roberto Exp roberto $ |
3 | ** Garbage Collector | 3 | ** Garbage Collector |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -866,9 +866,9 @@ static void GCTM (lua_State *L, int propagateerrors) { | |||
866 | setobj2s(L, L->top, tm); /* push finalizer... */ | 866 | setobj2s(L, L->top, tm); /* push finalizer... */ |
867 | setobj2s(L, L->top + 1, &v); /* ... and its argument */ | 867 | setobj2s(L, L->top + 1, &v); /* ... and its argument */ |
868 | L->top += 2; /* and (next line) call the finalizer */ | 868 | L->top += 2; /* and (next line) call the finalizer */ |
869 | L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ | 869 | callstatus(L->func) |= CIST_FIN; /* will run a finalizer */ |
870 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); | 870 | status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); |
871 | L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ | 871 | callstatus(L->func) &= ~CIST_FIN; /* not running a finalizer anymore */ |
872 | L->allowhook = oldah; /* restore hooks */ | 872 | L->allowhook = oldah; /* restore hooks */ |
873 | g->gcrunning = running; /* restore state */ | 873 | g->gcrunning = running; /* restore state */ |
874 | if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ | 874 | if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lobject.h,v 2.125 2017/06/29 15:06:44 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.126 2017/10/31 17:54:35 roberto Exp roberto $ |
3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -313,10 +313,21 @@ typedef union StackValue { | |||
313 | TValue val; | 313 | TValue val; |
314 | struct { | 314 | struct { |
315 | TValuefields; | 315 | TValuefields; |
316 | lu_byte callstatus_; | ||
316 | unsigned short previous; /* difference to previous 'func' */ | 317 | unsigned short previous; /* difference to previous 'func' */ |
318 | short nresults; /* expected number of results from this function */ | ||
319 | unsigned short framesize; /* stack space available for this function */ | ||
317 | } stkci; | 320 | } stkci; |
318 | } StackValue; | 321 | } StackValue; |
319 | 322 | ||
323 | #define callstatus(ar) ((ar)->stkci.callstatus_) | ||
324 | |||
325 | /* top of a function (first element after its frame) */ | ||
326 | #define functop(func) ((func) + (func)->stkci.framesize) | ||
327 | |||
328 | /* set top of a function to a specific value */ | ||
329 | #define setfunctop(func,v) ((func)->stkci.framesize = (v) - (func)) | ||
330 | |||
320 | 331 | ||
321 | typedef StackValue *StkId; /* index to stack elements */ | 332 | typedef StackValue *StkId; /* index to stack elements */ |
322 | 333 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.c,v 2.142 2017/10/11 12:38:45 roberto Exp roberto $ | 2 | ** $Id: lstate.c,v 2.143 2017/10/31 17:54:35 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -152,12 +152,12 @@ static void stack_init (lua_State *L1, lua_State *L) { | |||
152 | /* initialize first ci */ | 152 | /* initialize first ci */ |
153 | ci = &L1->base_ci; | 153 | ci = &L1->base_ci; |
154 | ci->next = ci->previous = NULL; | 154 | ci->next = ci->previous = NULL; |
155 | ci->callstatus = 0; | ||
156 | L1->func = ci->func = L1->top; | 155 | L1->func = ci->func = L1->top; |
157 | L1->func->stkci.previous = 0; /* end of linked list */ | 156 | L1->func->stkci.previous = 0; /* end of linked list */ |
157 | L1->func->stkci.framesize = LUA_MINSTACK + 1; | ||
158 | callstatus(L1->func) = 0; | ||
158 | setnilvalue(s2v(L1->top)); /* 'function' entry for this 'ci' */ | 159 | setnilvalue(s2v(L1->top)); /* 'function' entry for this 'ci' */ |
159 | L1->top++; | 160 | L1->top++; |
160 | ci->top = L1->top + LUA_MINSTACK; | ||
161 | L1->ci = ci; | 161 | L1->ci = ci; |
162 | } | 162 | } |
163 | 163 | ||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lstate.h,v 2.145 2017/10/31 17:54:35 roberto Exp roberto $ | 2 | ** $Id: lstate.h,v 2.146 2017/11/02 11:28:56 roberto Exp roberto $ |
3 | ** Global State | 3 | ** Global State |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -86,7 +86,6 @@ typedef struct stringtable { | |||
86 | */ | 86 | */ |
87 | typedef struct CallInfo { | 87 | typedef struct CallInfo { |
88 | StkId func; /* function index in the stack */ | 88 | StkId func; /* function index in the stack */ |
89 | StkId top; /* top for this function */ | ||
90 | struct CallInfo *previous, *next; /* dynamic call link */ | 89 | struct CallInfo *previous, *next; /* dynamic call link */ |
91 | union { | 90 | union { |
92 | struct { /* only for Lua functions */ | 91 | struct { /* only for Lua functions */ |
@@ -102,8 +101,6 @@ typedef struct CallInfo { | |||
102 | ptrdiff_t funcidx; /* called-function index */ | 101 | ptrdiff_t funcidx; /* called-function index */ |
103 | int nyield; /* number of values yielded */ | 102 | int nyield; /* number of values yielded */ |
104 | } u2; | 103 | } u2; |
105 | short nresults; /* expected number of results from this function */ | ||
106 | unsigned short callstatus; | ||
107 | } CallInfo; | 104 | } CallInfo; |
108 | 105 | ||
109 | 106 | ||
@@ -111,17 +108,16 @@ typedef struct CallInfo { | |||
111 | ** Bits in CallInfo status | 108 | ** Bits in CallInfo status |
112 | */ | 109 | */ |
113 | #define CIST_OAH (1<<0) /* original value of 'allowhook' */ | 110 | #define CIST_OAH (1<<0) /* original value of 'allowhook' */ |
114 | #define CIST_LUA (1<<1) /* call is running a Lua function */ | 111 | #define CIST_HOOKED (1<<1) /* call is running a debug hook */ |
115 | #define CIST_HOOKED (1<<2) /* call is running a debug hook */ | 112 | #define CIST_FRESH (1<<2) /* call is running on a fresh invocation |
116 | #define CIST_FRESH (1<<3) /* call is running on a fresh invocation | ||
117 | of luaV_execute */ | 113 | of luaV_execute */ |
118 | #define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ | 114 | #define CIST_YPCALL (1<<3) /* call is a yieldable protected call */ |
119 | #define CIST_TAIL (1<<5) /* call was tail called */ | 115 | #define CIST_TAIL (1<<4) /* call was tail called */ |
120 | #define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ | 116 | #define CIST_HOOKYIELD (1<<5) /* last hook called yielded */ |
121 | #define CIST_LEQ (1<<7) /* using __lt for __le */ | 117 | #define CIST_LEQ (1<<6) /* using __lt for __le */ |
122 | #define CIST_FIN (1<<8) /* call is running a finalizer */ | 118 | #define CIST_FIN (1<<7) /* call is running a finalizer */ |
123 | 119 | ||
124 | #define isLua(ci) ((ci)->callstatus & CIST_LUA) | 120 | #define isLua(func) isLfunction(s2v(func)) |
125 | 121 | ||
126 | /* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ | 122 | /* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ |
127 | #define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) | 123 | #define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltests.c,v 2.226 2017/11/01 18:20:48 roberto Exp roberto $ | 2 | ** $Id: ltests.c,v 2.227 2017/11/02 11:28:56 roberto Exp roberto $ |
3 | ** Internal Module for Debugging of the Lua Implementation | 3 | ** Internal Module for Debugging of the Lua Implementation |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -310,7 +310,7 @@ static void checkLclosure (global_State *g, LClosure *cl) { | |||
310 | 310 | ||
311 | 311 | ||
312 | static int lua_checkpc (CallInfo *ci) { | 312 | static int lua_checkpc (CallInfo *ci) { |
313 | if (!isLua(ci)) return 1; | 313 | if (!isLua(ci->func)) return 1; |
314 | else { | 314 | else { |
315 | StkId f = ci->func; | 315 | StkId f = ci->func; |
316 | Proto *p = clLvalue(s2v(f))->p; | 316 | Proto *p = clLvalue(s2v(f))->p; |
@@ -327,10 +327,11 @@ static void checkstack (global_State *g, lua_State *L1) { | |||
327 | lua_assert(!isdead(g, L1)); | 327 | lua_assert(!isdead(g, L1)); |
328 | for (uv = L1->openupval; uv != NULL; uv = uv->u.open.next) | 328 | for (uv = L1->openupval; uv != NULL; uv = uv->u.open.next) |
329 | lua_assert(upisopen(uv)); /* must be open */ | 329 | lua_assert(upisopen(uv)); /* must be open */ |
330 | for (ci = L1->ci; ci != NULL; ci = ci->previous) { | 330 | for (ci = L1->ci; ci != NULL; ci = ci->previous) |
331 | lua_assert(ci->top <= L1->stack_last); | ||
332 | lua_assert(lua_checkpc(ci)); | 331 | lua_assert(lua_checkpc(ci)); |
333 | } | 332 | for (o = L1->func; o->stkci.previous != 0; o -= o->stkci.previous) |
333 | lua_assert(functop(o) <= L1->stack_last); | ||
334 | lua_assert(o == L1->stack); | ||
334 | if (L1->stack) { /* complete thread? */ | 335 | if (L1->stack) { /* complete thread? */ |
335 | for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++) | 336 | for (o = L1->stack; o < L1->stack_last + EXTRA_STACK; o++) |
336 | checkliveness(L1, s2v(o)); /* entire stack must have valid values */ | 337 | checkliveness(L1, s2v(o)); /* entire stack must have valid values */ |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: ltm.c,v 2.44 2017/09/27 18:59:08 roberto Exp roberto $ | 2 | ** $Id: ltm.c,v 2.45 2017/10/04 15:49:05 roberto Exp roberto $ |
3 | ** Tag methods | 3 | ** Tag methods |
4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
5 | */ | 5 | */ |
@@ -108,7 +108,7 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, | |||
108 | setobj2s(L, func + 3, p3); /* 3rd argument */ | 108 | setobj2s(L, func + 3, p3); /* 3rd argument */ |
109 | L->top += 4; | 109 | L->top += 4; |
110 | /* metamethod may yield only when called from Lua code */ | 110 | /* metamethod may yield only when called from Lua code */ |
111 | if (isLua(L->ci)) | 111 | if (isLua(L->func)) |
112 | luaD_call(L, func, 0); | 112 | luaD_call(L, func, 0); |
113 | else | 113 | else |
114 | luaD_callnoyield(L, func, 0); | 114 | luaD_callnoyield(L, func, 0); |
@@ -124,7 +124,7 @@ void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, | |||
124 | setobj2s(L, func + 2, p2); /* 2nd argument */ | 124 | setobj2s(L, func + 2, p2); /* 2nd argument */ |
125 | L->top += 3; | 125 | L->top += 3; |
126 | /* metamethod may yield only when called from Lua code */ | 126 | /* metamethod may yield only when called from Lua code */ |
127 | if (isLua(L->ci)) | 127 | if (isLua(L->func)) |
128 | luaD_call(L, func, 1); | 128 | luaD_call(L, func, 1); |
129 | else | 129 | else |
130 | luaD_callnoyield(L, func, 1); | 130 | luaD_callnoyield(L, func, 1); |
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | ** $Id: lvm.c,v 2.300 2017/10/31 17:54:35 roberto Exp roberto $ | 2 | ** $Id: lvm.c,v 2.301 2017/11/01 18:20:48 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 | */ |
@@ -390,9 +390,9 @@ int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r) { | |||
390 | else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* try 'le' */ | 390 | else if ((res = luaT_callorderTM(L, l, r, TM_LE)) >= 0) /* try 'le' */ |
391 | return res; | 391 | return res; |
392 | else { /* try 'lt': */ | 392 | else { /* try 'lt': */ |
393 | L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ | 393 | callstatus(L->func) |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ |
394 | res = luaT_callorderTM(L, r, l, TM_LT); | 394 | res = luaT_callorderTM(L, r, l, TM_LT); |
395 | L->ci->callstatus ^= CIST_LEQ; /* clear mark */ | 395 | callstatus(L->func) ^= CIST_LEQ; /* clear mark */ |
396 | if (res < 0) | 396 | if (res < 0) |
397 | luaG_ordererror(L, l, r); | 397 | luaG_ordererror(L, l, r); |
398 | return !res; /* result is negated */ | 398 | return !res; /* result is negated */ |
@@ -679,9 +679,9 @@ void luaV_finishOp (lua_State *L) { | |||
679 | case OP_LE: case OP_LT: case OP_EQ: { | 679 | case OP_LE: case OP_LT: case OP_EQ: { |
680 | int res = !l_isfalse(s2v(L->top - 1)); | 680 | int res = !l_isfalse(s2v(L->top - 1)); |
681 | L->top--; | 681 | L->top--; |
682 | if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ | 682 | if (callstatus(base - 1) & CIST_LEQ) { /* "<=" using "<" ? */ |
683 | lua_assert(op == OP_LE); | 683 | lua_assert(op == OP_LE); |
684 | ci->callstatus ^= CIST_LEQ; /* clear mark */ | 684 | callstatus(base - 1) ^= CIST_LEQ; /* clear mark */ |
685 | res = !res; /* negate result */ | 685 | res = !res; /* negate result */ |
686 | } | 686 | } |
687 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); | 687 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); |
@@ -700,17 +700,17 @@ void luaV_finishOp (lua_State *L) { | |||
700 | } | 700 | } |
701 | /* move final result to final position */ | 701 | /* move final result to final position */ |
702 | setobjs2s(L, L->func + 1 + GETARG_A(inst), L->top - 1); | 702 | setobjs2s(L, L->func + 1 + GETARG_A(inst), L->top - 1); |
703 | L->top = ci->top; /* restore top */ | 703 | L->top = functop(base - 1); /* restore top */ |
704 | break; | 704 | break; |
705 | } | 705 | } |
706 | case OP_TFORCALL: { | 706 | case OP_TFORCALL: { |
707 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); | 707 | lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); |
708 | L->top = ci->top; /* correct top */ | 708 | L->top = functop(base - 1); /* correct top */ |
709 | break; | 709 | break; |
710 | } | 710 | } |
711 | case OP_CALL: { | 711 | case OP_CALL: { |
712 | if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ | 712 | if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ |
713 | L->top = ci->top; /* adjust results */ | 713 | L->top = functop(base - 1); /* adjust results */ |
714 | break; | 714 | break; |
715 | } | 715 | } |
716 | case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: | 716 | case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: |
@@ -775,9 +775,9 @@ void luaV_finishOp (lua_State *L) { | |||
775 | 775 | ||
776 | 776 | ||
777 | #define checkGC(L,c) \ | 777 | #define checkGC(L,c) \ |
778 | { luaC_condGC(L, L->top = (c), /* limit of live values */ \ | 778 | { luaC_condGC(L, L->top = (c), /* limit of live values */ \ |
779 | Protect(L->top = ci->top)); /* restore top */ \ | 779 | {Protect((void)0); L->top = functop(base - 1);}); /* restore top */ \ |
780 | luai_threadyield(L); } | 780 | luai_threadyield(L); } |
781 | 781 | ||
782 | 782 | ||
783 | /* fetch an instruction and prepare its execution */ | 783 | /* fetch an instruction and prepare its execution */ |
@@ -796,16 +796,15 @@ void luaV_execute (lua_State *L) { | |||
796 | CallInfo *ci = L->ci; | 796 | CallInfo *ci = L->ci; |
797 | LClosure *cl; | 797 | LClosure *cl; |
798 | TValue *k; | 798 | TValue *k; |
799 | StkId base; /* local copy of 'L->func + 1' */ | 799 | StkId base = L->func + 1; /* local copy of 'L->func + 1' */ |
800 | int mask; /* local copy of 'L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)' */ | 800 | int mask; /* local copy of 'L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)' */ |
801 | const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */ | 801 | const Instruction *pc; /* local copy of 'ci->u.l.savedpc' */ |
802 | ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ | 802 | callstatus(base - 1) |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ |
803 | newframe: /* reentry point when frame changes (call/return) */ | 803 | newframe: /* reentry point when frame changes (call/return) */ |
804 | lua_assert(ci == L->ci); | 804 | lua_assert(ci == L->ci); |
805 | cl = clLvalue(s2v(L->func)); /* local reference to function's closure */ | 805 | cl = clLvalue(s2v(L->func)); /* local reference to function's closure */ |
806 | k = cl->p->k; /* local reference to function's constant table */ | 806 | k = cl->p->k; /* local reference to function's constant table */ |
807 | updatemask(L); | 807 | updatemask(L); |
808 | base = L->func + 1; | ||
809 | pc = ci->u.l.savedpc; | 808 | pc = ci->u.l.savedpc; |
810 | /* main loop of interpreter */ | 809 | /* main loop of interpreter */ |
811 | for (;;) { | 810 | for (;;) { |
@@ -1276,7 +1275,7 @@ void luaV_execute (lua_State *L) { | |||
1276 | rb = base + b; | 1275 | rb = base + b; |
1277 | setobjs2s(L, ra, rb); | 1276 | setobjs2s(L, ra, rb); |
1278 | checkGC(L, (ra >= rb ? ra + 1 : rb)); | 1277 | checkGC(L, (ra >= rb ? ra + 1 : rb)); |
1279 | L->top = ci->top; /* restore top */ | 1278 | L->top = functop(base - 1); /* restore top */ |
1280 | vmbreak; | 1279 | vmbreak; |
1281 | } | 1280 | } |
1282 | vmcase(OP_CLOSE) { | 1281 | vmcase(OP_CLOSE) { |
@@ -1355,11 +1354,12 @@ void luaV_execute (lua_State *L) { | |||
1355 | Protect(isC = luaD_precall(L, ra, nresults)); | 1354 | Protect(isC = luaD_precall(L, ra, nresults)); |
1356 | if (isC) { /* C function? */ | 1355 | if (isC) { /* C function? */ |
1357 | if (nresults >= 0) /* fixed number of results? */ | 1356 | if (nresults >= 0) /* fixed number of results? */ |
1358 | L->top = ci->top; /* correct top */ | 1357 | L->top = functop(base - 1); /* correct top */ |
1359 | /* else leave top for next instruction */ | 1358 | /* else leave top for next instruction */ |
1360 | } | 1359 | } |
1361 | else { /* Lua function */ | 1360 | else { /* Lua function */ |
1362 | ci = L->ci; | 1361 | ci = L->ci; |
1362 | base = L->func + 1; | ||
1363 | goto newframe; /* restart luaV_execute over new Lua function */ | 1363 | goto newframe; /* restart luaV_execute over new Lua function */ |
1364 | } | 1364 | } |
1365 | vmbreak; | 1365 | vmbreak; |
@@ -1386,12 +1386,14 @@ void luaV_execute (lua_State *L) { | |||
1386 | /* move new frame into old one */ | 1386 | /* move new frame into old one */ |
1387 | for (aux = 0; nfunc + aux < lim; aux++) | 1387 | for (aux = 0; nfunc + aux < lim; aux++) |
1388 | setobjs2s(L, ofunc + aux, nfunc + aux); | 1388 | setobjs2s(L, ofunc + aux, nfunc + aux); |
1389 | oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ | 1389 | ofunc->stkci.framesize = L->top - nfunc; |
1390 | L->top = functop(ofunc); /* correct top */ | ||
1390 | oci->u.l.savedpc = nci->u.l.savedpc; | 1391 | oci->u.l.savedpc = nci->u.l.savedpc; |
1391 | oci->callstatus |= CIST_TAIL; /* function was tail called */ | 1392 | callstatus(ofunc) |= CIST_TAIL; /* function was tail called */ |
1392 | ci = L->ci = oci; /* remove new frame */ | 1393 | ci = L->ci = oci; /* remove new frame */ |
1394 | base = ofunc + 1; | ||
1393 | L->func = ofunc; | 1395 | L->func = ofunc; |
1394 | lua_assert(L->top == ofunc + 1 + getproto(s2v(ofunc))->maxstacksize); | 1396 | lua_assert(L->top == base + getproto(s2v(ofunc))->maxstacksize); |
1395 | goto newframe; /* restart luaV_execute over new Lua function */ | 1397 | goto newframe; /* restart luaV_execute over new Lua function */ |
1396 | } | 1398 | } |
1397 | vmbreak; | 1399 | vmbreak; |
@@ -1401,14 +1403,15 @@ void luaV_execute (lua_State *L) { | |||
1401 | if (cl->p->sizep > 0) luaF_close(L, base); | 1403 | if (cl->p->sizep > 0) luaF_close(L, base); |
1402 | savepc(L); | 1404 | savepc(L); |
1403 | b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); | 1405 | b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); |
1404 | if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ | 1406 | if (callstatus(base - 1) & CIST_FRESH) /* local 'base' still from callee */ |
1405 | return; /* external invocation: return */ | 1407 | return; /* external invocation: return */ |
1406 | else { /* invocation via reentry: continue execution */ | 1408 | else { /* invocation via reentry: continue execution */ |
1407 | ci = L->ci; | 1409 | ci = L->ci; |
1408 | if (b) L->top = ci->top; | 1410 | base = L->func + 1; |
1409 | lua_assert(isLua(ci)); | 1411 | if (b) L->top = functop(base - 1); |
1412 | lua_assert(isLua(L->func)); | ||
1410 | lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); | 1413 | lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); |
1411 | goto newframe; /* restart luaV_execute over new Lua function */ | 1414 | goto newframe; /* restart luaV_execute over previous Lua function */ |
1412 | } | 1415 | } |
1413 | } | 1416 | } |
1414 | vmcase(OP_FORLOOP) { | 1417 | vmcase(OP_FORLOOP) { |
@@ -1473,7 +1476,7 @@ void luaV_execute (lua_State *L) { | |||
1473 | setobjs2s(L, cb, ra); | 1476 | setobjs2s(L, cb, ra); |
1474 | L->top = cb + 3; /* func. + 2 args (state and index) */ | 1477 | L->top = cb + 3; /* func. + 2 args (state and index) */ |
1475 | Protect(luaD_call(L, cb, GETARG_C(i))); | 1478 | Protect(luaD_call(L, cb, GETARG_C(i))); |
1476 | L->top = ci->top; | 1479 | L->top = functop(base - 1); |
1477 | i = *(pc++); /* go to next instruction */ | 1480 | i = *(pc++); /* go to next instruction */ |
1478 | ra = RA(i); | 1481 | ra = RA(i); |
1479 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP); | 1482 | lua_assert(GET_OPCODE(i) == OP_TFORLOOP); |
@@ -1507,7 +1510,8 @@ void luaV_execute (lua_State *L) { | |||
1507 | last--; | 1510 | last--; |
1508 | luaC_barrierback(L, h, val); | 1511 | luaC_barrierback(L, h, val); |
1509 | } | 1512 | } |
1510 | L->top = ci->top; /* correct top (in case of previous open call) */ | 1513 | /* correct top (in case of previous open call) */ |
1514 | L->top = functop(base - 1); | ||
1511 | vmbreak; | 1515 | vmbreak; |
1512 | } | 1516 | } |
1513 | vmcase(OP_CLOSURE) { | 1517 | vmcase(OP_CLOSURE) { |