diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-06-15 11:58:59 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-06-15 11:58:59 -0300 |
| commit | d49b2887282b86a5e6f40a386511aa8040f3c7b0 (patch) | |
| tree | 0d85ba5e27fb06723b3f49f4c10cb9e2e717d2ae | |
| parent | 69e84805e48b0253007bd0daf481ce7955367d73 (diff) | |
| download | lua-d49b2887282b86a5e6f40a386511aa8040f3c7b0.tar.gz lua-d49b2887282b86a5e6f40a386511aa8040f3c7b0.tar.bz2 lua-d49b2887282b86a5e6f40a386511aa8040f3c7b0.zip | |
'luaE_shrinkCI' shouldn't remove first free CallInfo
Due to emergency collections, 'luaE_shrinkCI' can be called while Lua
is building a new CallInfo, which for a while is still a free CallInfo.
| -rw-r--r-- | lstate.c | 22 |
1 files changed, 14 insertions, 8 deletions
| @@ -186,20 +186,26 @@ void luaE_freeCI (lua_State *L) { | |||
| 186 | 186 | ||
| 187 | 187 | ||
| 188 | /* | 188 | /* |
| 189 | ** free half of the CallInfo structures not in use by a thread | 189 | ** free half of the CallInfo structures not in use by a thread, |
| 190 | ** keeping the first one. | ||
| 190 | */ | 191 | */ |
| 191 | void luaE_shrinkCI (lua_State *L) { | 192 | void luaE_shrinkCI (lua_State *L) { |
| 192 | CallInfo *ci = L->ci; | 193 | CallInfo *ci = L->ci->next; /* first free CallInfo */ |
| 193 | CallInfo *next; | 194 | CallInfo *next; |
| 194 | CallInfo *next2; /* next's next */ | 195 | if (ci == NULL) |
| 196 | return; /* no extra elements */ | ||
| 195 | L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ | 197 | L->nCcalls += L->nci; /* add removed elements back to 'nCcalls' */ |
| 196 | /* while there are two nexts */ | 198 | while ((next = ci->next) != NULL) { /* two extra elements? */ |
| 197 | while ((next = ci->next) != NULL && (next2 = next->next) != NULL) { | 199 | CallInfo *next2 = next->next; /* next's next */ |
| 198 | ci->next = next2; /* remove next from the list */ | 200 | ci->next = next2; /* remove next from the list */ |
| 199 | next2->previous = ci; | ||
| 200 | luaM_free(L, next); /* free next */ | ||
| 201 | L->nci--; | 201 | L->nci--; |
| 202 | ci = next2; /* keep next's next */ | 202 | luaM_free(L, next); /* free next */ |
| 203 | if (next2 == NULL) | ||
| 204 | break; /* no more elements */ | ||
| 205 | else { | ||
| 206 | next2->previous = ci; | ||
| 207 | ci = next2; /* continue */ | ||
| 208 | } | ||
| 203 | } | 209 | } |
| 204 | L->nCcalls -= L->nci; /* adjust result */ | 210 | L->nCcalls -= L->nci; /* adjust result */ |
| 205 | } | 211 | } |
