diff options
| author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-06-16 09:54:20 -0300 |
|---|---|---|
| committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2020-06-16 09:54:20 -0300 |
| commit | 6d7cd31feec58011a593cf732274a33dcc1bcb53 (patch) | |
| tree | a464a23b3636c45c10b998046671573422fe075c | |
| parent | 993c58fde3a85c27f52f094002ec57dabca81028 (diff) | |
| download | lua-6d7cd31feec58011a593cf732274a33dcc1bcb53.tar.gz lua-6d7cd31feec58011a593cf732274a33dcc1bcb53.tar.bz2 lua-6d7cd31feec58011a593cf732274a33dcc1bcb53.zip | |
Fixed missing GC barriers in compiler and undump
While building a new prototype, the GC needs barriers for every object
(strings and nested prototypes) that is attached to the new prototype.
| -rw-r--r-- | lparser.c | 3 | ||||
| -rw-r--r-- | lundump.c | 33 |
2 files changed, 22 insertions, 14 deletions
| @@ -737,6 +737,7 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { | |||
| 737 | fs->firstlabel = ls->dyd->label.n; | 737 | fs->firstlabel = ls->dyd->label.n; |
| 738 | fs->bl = NULL; | 738 | fs->bl = NULL; |
| 739 | f->source = ls->source; | 739 | f->source = ls->source; |
| 740 | luaC_objbarrier(ls->L, f, f->source); | ||
| 740 | f->maxstacksize = 2; /* registers 0/1 are always valid */ | 741 | f->maxstacksize = 2; /* registers 0/1 are always valid */ |
| 741 | enterblock(fs, bl, 0); | 742 | enterblock(fs, bl, 0); |
| 742 | } | 743 | } |
| @@ -1959,6 +1960,7 @@ static void mainfunc (LexState *ls, FuncState *fs) { | |||
| 1959 | env->idx = 0; | 1960 | env->idx = 0; |
| 1960 | env->kind = VDKREG; | 1961 | env->kind = VDKREG; |
| 1961 | env->name = ls->envn; | 1962 | env->name = ls->envn; |
| 1963 | luaC_objbarrier(ls->L, fs->f, env->name); | ||
| 1962 | luaX_next(ls); /* read first token */ | 1964 | luaX_next(ls); /* read first token */ |
| 1963 | statlist(ls); /* parse main body */ | 1965 | statlist(ls); /* parse main body */ |
| 1964 | check(ls, TK_EOS); | 1966 | check(ls, TK_EOS); |
| @@ -1977,6 +1979,7 @@ LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, | |||
| 1977 | sethvalue2s(L, L->top, lexstate.h); /* anchor it */ | 1979 | sethvalue2s(L, L->top, lexstate.h); /* anchor it */ |
| 1978 | luaD_inctop(L); | 1980 | luaD_inctop(L); |
| 1979 | funcstate.f = cl->p = luaF_newproto(L); | 1981 | funcstate.f = cl->p = luaF_newproto(L); |
| 1982 | luaC_objbarrier(L, cl, cl->p); | ||
| 1980 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ | 1983 | funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ |
| 1981 | luaC_objbarrier(L, funcstate.f, funcstate.f->source); | 1984 | luaC_objbarrier(L, funcstate.f, funcstate.f->source); |
| 1982 | lexstate.buff = buff; | 1985 | lexstate.buff = buff; |
| @@ -105,30 +105,33 @@ static lua_Integer loadInteger (LoadState *S) { | |||
| 105 | 105 | ||
| 106 | 106 | ||
| 107 | /* | 107 | /* |
| 108 | ** Load a nullable string. | 108 | ** Load a nullable string into prototype 'p'. |
| 109 | */ | 109 | */ |
| 110 | static TString *loadStringN (LoadState *S) { | 110 | static TString *loadStringN (LoadState *S, Proto *p) { |
| 111 | lua_State *L = S->L; | ||
| 112 | TString *ts; | ||
| 111 | size_t size = loadSize(S); | 113 | size_t size = loadSize(S); |
| 112 | if (size == 0) | 114 | if (size == 0) /* no string? */ |
| 113 | return NULL; | 115 | return NULL; |
| 114 | else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ | 116 | else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ |
| 115 | char buff[LUAI_MAXSHORTLEN]; | 117 | char buff[LUAI_MAXSHORTLEN]; |
| 116 | loadVector(S, buff, size); | 118 | loadVector(S, buff, size); /* load string into buffer */ |
| 117 | return luaS_newlstr(S->L, buff, size); | 119 | ts = luaS_newlstr(L, buff, size); /* create string */ |
| 118 | } | 120 | } |
| 119 | else { /* long string */ | 121 | else { /* long string */ |
| 120 | TString *ts = luaS_createlngstrobj(S->L, size); | 122 | ts = luaS_createlngstrobj(L, size); /* create string */ |
| 121 | loadVector(S, getstr(ts), size); /* load directly in final place */ | 123 | loadVector(S, getstr(ts), size); /* load directly in final place */ |
| 122 | return ts; | ||
| 123 | } | 124 | } |
| 125 | luaC_objbarrier(L, p, ts); | ||
| 126 | return ts; | ||
| 124 | } | 127 | } |
| 125 | 128 | ||
| 126 | 129 | ||
| 127 | /* | 130 | /* |
| 128 | ** Load a non-nullable string. | 131 | ** Load a non-nullable string into prototype 'p'. |
| 129 | */ | 132 | */ |
| 130 | static TString *loadString (LoadState *S) { | 133 | static TString *loadString (LoadState *S, Proto *p) { |
| 131 | TString *st = loadStringN(S); | 134 | TString *st = loadStringN(S, p); |
| 132 | if (st == NULL) | 135 | if (st == NULL) |
| 133 | error(S, "bad format for constant string"); | 136 | error(S, "bad format for constant string"); |
| 134 | return st; | 137 | return st; |
| @@ -174,7 +177,7 @@ static void loadConstants (LoadState *S, Proto *f) { | |||
| 174 | break; | 177 | break; |
| 175 | case LUA_VSHRSTR: | 178 | case LUA_VSHRSTR: |
| 176 | case LUA_VLNGSTR: | 179 | case LUA_VLNGSTR: |
| 177 | setsvalue2n(S->L, o, loadString(S)); | 180 | setsvalue2n(S->L, o, loadString(S, f)); |
| 178 | break; | 181 | break; |
| 179 | default: lua_assert(0); | 182 | default: lua_assert(0); |
| 180 | } | 183 | } |
| @@ -191,6 +194,7 @@ static void loadProtos (LoadState *S, Proto *f) { | |||
| 191 | f->p[i] = NULL; | 194 | f->p[i] = NULL; |
| 192 | for (i = 0; i < n; i++) { | 195 | for (i = 0; i < n; i++) { |
| 193 | f->p[i] = luaF_newproto(S->L); | 196 | f->p[i] = luaF_newproto(S->L); |
| 197 | luaC_objbarrier(S->L, f, f->p[i]); | ||
| 194 | loadFunction(S, f->p[i], f->source); | 198 | loadFunction(S, f->p[i], f->source); |
| 195 | } | 199 | } |
| 196 | } | 200 | } |
| @@ -229,18 +233,18 @@ static void loadDebug (LoadState *S, Proto *f) { | |||
| 229 | for (i = 0; i < n; i++) | 233 | for (i = 0; i < n; i++) |
| 230 | f->locvars[i].varname = NULL; | 234 | f->locvars[i].varname = NULL; |
| 231 | for (i = 0; i < n; i++) { | 235 | for (i = 0; i < n; i++) { |
| 232 | f->locvars[i].varname = loadStringN(S); | 236 | f->locvars[i].varname = loadStringN(S, f); |
| 233 | f->locvars[i].startpc = loadInt(S); | 237 | f->locvars[i].startpc = loadInt(S); |
| 234 | f->locvars[i].endpc = loadInt(S); | 238 | f->locvars[i].endpc = loadInt(S); |
| 235 | } | 239 | } |
| 236 | n = loadInt(S); | 240 | n = loadInt(S); |
| 237 | for (i = 0; i < n; i++) | 241 | for (i = 0; i < n; i++) |
| 238 | f->upvalues[i].name = loadStringN(S); | 242 | f->upvalues[i].name = loadStringN(S, f); |
| 239 | } | 243 | } |
| 240 | 244 | ||
| 241 | 245 | ||
| 242 | static void loadFunction (LoadState *S, Proto *f, TString *psource) { | 246 | static void loadFunction (LoadState *S, Proto *f, TString *psource) { |
| 243 | f->source = loadStringN(S); | 247 | f->source = loadStringN(S, f); |
| 244 | if (f->source == NULL) /* no source in dump? */ | 248 | if (f->source == NULL) /* no source in dump? */ |
| 245 | f->source = psource; /* reuse parent's source */ | 249 | f->source = psource; /* reuse parent's source */ |
| 246 | f->linedefined = loadInt(S); | 250 | f->linedefined = loadInt(S); |
| @@ -310,6 +314,7 @@ LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { | |||
| 310 | setclLvalue2s(L, L->top, cl); | 314 | setclLvalue2s(L, L->top, cl); |
| 311 | luaD_inctop(L); | 315 | luaD_inctop(L); |
| 312 | cl->p = luaF_newproto(L); | 316 | cl->p = luaF_newproto(L); |
| 317 | luaC_objbarrier(L, cl, cl->p); | ||
| 313 | loadFunction(&S, cl->p, NULL); | 318 | loadFunction(&S, cl->p, NULL); |
| 314 | lua_assert(cl->nupvalues == cl->p->sizeupvalues); | 319 | lua_assert(cl->nupvalues == cl->p->sizeupvalues); |
| 315 | luai_verifycode(L, buff, cl->p); | 320 | luai_verifycode(L, buff, cl->p); |
