diff options
Diffstat (limited to 'src/lua/lfunc.c')
| -rw-r--r-- | src/lua/lfunc.c | 40 |
1 files changed, 29 insertions, 11 deletions
diff --git a/src/lua/lfunc.c b/src/lua/lfunc.c index b4c04bd..f5889a2 100644 --- a/src/lua/lfunc.c +++ b/src/lua/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 | */ |
| 160 | void luaF_newtbcupval (lua_State *L, StkId level) { | 169 | void 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 | */ | ||
| 214 | static 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 | ||
