aboutsummaryrefslogtreecommitdiff
path: root/lfunc.c
diff options
context:
space:
mode:
Diffstat (limited to 'lfunc.c')
-rw-r--r--lfunc.c40
1 files changed, 29 insertions, 11 deletions
diff --git a/lfunc.c b/lfunc.c
index b4c04bd0..f5889a21 100644
--- a/lfunc.c
+++ b/lfunc.c
@@ -155,6 +155,15 @@ static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) {
155 155
156 156
157/* 157/*
158** Maximum value for deltas in 'tbclist', dependent on the type
159** of delta. (This macro assumes that an 'L' is in scope where it
160** is used.)
161*/
162#define MAXDELTA \
163 ((256ul << ((sizeof(L->stack->tbclist.delta) - 1) * 8)) - 1)
164
165
166/*
158** Insert a variable in the list of to-be-closed variables. 167** Insert a variable in the list of to-be-closed variables.
159*/ 168*/
160void luaF_newtbcupval (lua_State *L, StkId level) { 169void luaF_newtbcupval (lua_State *L, StkId level) {
@@ -162,13 +171,11 @@ void luaF_newtbcupval (lua_State *L, StkId level) {
162 if (l_isfalse(s2v(level))) 171 if (l_isfalse(s2v(level)))
163 return; /* false doesn't need to be closed */ 172 return; /* false doesn't need to be closed */
164 checkclosemth(L, level); /* value must have a close method */ 173 checkclosemth(L, level); /* value must have a close method */
165 while (level - L->tbclist > USHRT_MAX) { /* is delta too large? */ 174 while (cast_uint(level - L->tbclist) > MAXDELTA) {
166 L->tbclist += USHRT_MAX; /* create a dummy node at maximum delta */ 175 L->tbclist += MAXDELTA; /* create a dummy node at maximum delta */
167 L->tbclist->tbclist.delta = USHRT_MAX; 176 L->tbclist->tbclist.delta = 0;
168 L->tbclist->tbclist.isdummy = 1;
169 } 177 }
170 level->tbclist.delta = level - L->tbclist; 178 level->tbclist.delta = cast(unsigned short, level - L->tbclist);
171 level->tbclist.isdummy = 0;
172 L->tbclist = level; 179 L->tbclist = level;
173} 180}
174 181
@@ -202,6 +209,19 @@ void luaF_closeupval (lua_State *L, StkId level) {
202 209
203 210
204/* 211/*
212** Remove firt element from the tbclist plus its dummy nodes.
213*/
214static void poptbclist (lua_State *L) {
215 StkId tbc = L->tbclist;
216 lua_assert(tbc->tbclist.delta > 0); /* first element cannot be dummy */
217 tbc -= tbc->tbclist.delta;
218 while (tbc > L->stack && tbc->tbclist.delta == 0)
219 tbc -= MAXDELTA; /* remove dummy nodes */
220 L->tbclist = tbc;
221}
222
223
224/*
205** Close all upvalues and to-be-closed variables up to the given stack 225** Close all upvalues and to-be-closed variables up to the given stack
206** level. 226** level.
207*/ 227*/
@@ -210,11 +230,9 @@ void luaF_close (lua_State *L, StkId level, int status, int yy) {
210 luaF_closeupval(L, level); /* first, close the upvalues */ 230 luaF_closeupval(L, level); /* first, close the upvalues */
211 while (L->tbclist >= level) { /* traverse tbc's down to that level */ 231 while (L->tbclist >= level) { /* traverse tbc's down to that level */
212 StkId tbc = L->tbclist; /* get variable index */ 232 StkId tbc = L->tbclist; /* get variable index */
213 L->tbclist -= tbc->tbclist.delta; /* remove it from list */ 233 poptbclist(L); /* remove it from list */
214 if (!tbc->tbclist.isdummy) { /* not a dummy entry? */ 234 prepcallclosemth(L, tbc, status, yy); /* close variable */
215 prepcallclosemth(L, tbc, status, yy); /* close variable */ 235 level = restorestack(L, levelrel);
216 level = restorestack(L, levelrel);
217 }
218 } 236 }
219} 237}
220 238