diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-20 13:52:50 -0300 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-02-20 13:52:50 -0300 |
commit | ca6fe7449a74efde6f959605dbe77acf3e64ca0b (patch) | |
tree | a6190e813ff712f7db750d4ecd3afd3ac9c0dbab /lgc.c | |
parent | 1afd5a152dc8b3a304236dc4e07bca38ea5eb53a (diff) | |
download | lua-ca6fe7449a74efde6f959605dbe77acf3e64ca0b.tar.gz lua-ca6fe7449a74efde6f959605dbe77acf3e64ca0b.tar.bz2 lua-ca6fe7449a74efde6f959605dbe77acf3e64ca0b.zip |
userdata can have multiple user values
Diffstat (limited to 'lgc.c')
-rw-r--r-- | lgc.c | 33 |
1 files changed, 17 insertions, 16 deletions
@@ -113,6 +113,7 @@ static lu_mem atomic (lua_State *L); | |||
113 | static GCObject **getgclist (GCObject *o) { | 113 | static GCObject **getgclist (GCObject *o) { |
114 | switch (o->tt) { | 114 | switch (o->tt) { |
115 | case LUA_TTABLE: return &gco2t(o)->gclist; | 115 | case LUA_TTABLE: return &gco2t(o)->gclist; |
116 | case LUA_TUSERDATA: return &gco2u(o)->gclist; | ||
116 | case LUA_TLCL: return &gco2lcl(o)->gclist; | 117 | case LUA_TLCL: return &gco2lcl(o)->gclist; |
117 | case LUA_TCCL: return &gco2ccl(o)->gclist; | 118 | case LUA_TCCL: return &gco2ccl(o)->gclist; |
118 | case LUA_TTHREAD: return &gco2th(o)->gclist; | 119 | case LUA_TTHREAD: return &gco2th(o)->gclist; |
@@ -269,7 +270,6 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { | |||
269 | ** to avoid barriers, as their values will be revisited by the thread.) | 270 | ** to avoid barriers, as their values will be revisited by the thread.) |
270 | */ | 271 | */ |
271 | static void reallymarkobject (global_State *g, GCObject *o) { | 272 | static void reallymarkobject (global_State *g, GCObject *o) { |
272 | reentry: | ||
273 | white2gray(o); | 273 | white2gray(o); |
274 | switch (o->tt) { | 274 | switch (o->tt) { |
275 | case LUA_TSHRSTR: | 275 | case LUA_TSHRSTR: |
@@ -277,17 +277,6 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
277 | gray2black(o); | 277 | gray2black(o); |
278 | break; | 278 | break; |
279 | } | 279 | } |
280 | case LUA_TUSERDATA: { | ||
281 | TValue uvalue; | ||
282 | markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ | ||
283 | gray2black(o); | ||
284 | getuservalue(g->mainthread, gco2u(o), &uvalue); | ||
285 | if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ | ||
286 | o = gcvalue(&uvalue); | ||
287 | goto reentry; | ||
288 | } | ||
289 | break; | ||
290 | } | ||
291 | case LUA_TUPVAL: { | 280 | case LUA_TUPVAL: { |
292 | UpVal *uv = gco2upv(o); | 281 | UpVal *uv = gco2upv(o); |
293 | if (!upisopen(uv)) /* open upvalues are kept gray */ | 282 | if (!upisopen(uv)) /* open upvalues are kept gray */ |
@@ -296,7 +285,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
296 | break; | 285 | break; |
297 | } | 286 | } |
298 | case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE: | 287 | case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE: |
299 | case LUA_TTHREAD: case LUA_TPROTO: { | 288 | case LUA_TUSERDATA: case LUA_TTHREAD: case LUA_TPROTO: { |
300 | linkobjgclist(o, g->gray); | 289 | linkobjgclist(o, g->gray); |
301 | break; | 290 | break; |
302 | } | 291 | } |
@@ -602,6 +591,15 @@ static int traversethread (global_State *g, lua_State *th) { | |||
602 | } | 591 | } |
603 | 592 | ||
604 | 593 | ||
594 | static int traverseudata (global_State *g, Udata *u) { | ||
595 | int i; | ||
596 | markobjectN(g, u->metatable); /* mark its metatable */ | ||
597 | for (i = 0; i < u->nuvalue; i++) | ||
598 | markvalue(g, &u->uv[i].uv); | ||
599 | return 1 + u->nuvalue; | ||
600 | } | ||
601 | |||
602 | |||
605 | /* | 603 | /* |
606 | ** traverse one gray object, turning it to black (except for threads, | 604 | ** traverse one gray object, turning it to black (except for threads, |
607 | ** which are always gray). | 605 | ** which are always gray). |
@@ -612,6 +610,7 @@ static lu_mem propagatemark (global_State *g) { | |||
612 | g->gray = *getgclist(o); /* remove from 'gray' list */ | 610 | g->gray = *getgclist(o); /* remove from 'gray' list */ |
613 | switch (o->tt) { | 611 | switch (o->tt) { |
614 | case LUA_TTABLE: return traversetable(g, gco2t(o)); | 612 | case LUA_TTABLE: return traversetable(g, gco2t(o)); |
613 | case LUA_TUSERDATA: return traverseudata(g, gco2u(o)); | ||
615 | case LUA_TLCL: return traverseLclosure(g, gco2lcl(o)); | 614 | case LUA_TLCL: return traverseLclosure(g, gco2lcl(o)); |
616 | case LUA_TCCL: return traverseCclosure(g, gco2ccl(o)); | 615 | case LUA_TCCL: return traverseCclosure(g, gco2ccl(o)); |
617 | case LUA_TPROTO: return traverseproto(g, gco2p(o)); | 616 | case LUA_TPROTO: return traverseproto(g, gco2p(o)); |
@@ -742,9 +741,11 @@ static void freeobj (lua_State *L, GCObject *o) { | |||
742 | case LUA_TTHREAD: | 741 | case LUA_TTHREAD: |
743 | luaE_freethread(L, gco2th(o)); | 742 | luaE_freethread(L, gco2th(o)); |
744 | break; | 743 | break; |
745 | case LUA_TUSERDATA: | 744 | case LUA_TUSERDATA: { |
746 | luaM_freemem(L, o, sizeudata(gco2u(o))); | 745 | Udata *u = gco2u(o); |
746 | luaM_freemem(L, o, sizeudata(u->nuvalue, u->len)); | ||
747 | break; | 747 | break; |
748 | } | ||
748 | case LUA_TSHRSTR: | 749 | case LUA_TSHRSTR: |
749 | luaS_remove(L, gco2ts(o)); /* remove it from hash table */ | 750 | luaS_remove(L, gco2ts(o)); /* remove it from hash table */ |
750 | luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); | 751 | luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); |
@@ -1065,7 +1066,7 @@ static GCObject **correctgraylist (GCObject **p) { | |||
1065 | GCObject *curr; | 1066 | GCObject *curr; |
1066 | while ((curr = *p) != NULL) { | 1067 | while ((curr = *p) != NULL) { |
1067 | switch (curr->tt) { | 1068 | switch (curr->tt) { |
1068 | case LUA_TTABLE: { | 1069 | case LUA_TTABLE: case LUA_TUSERDATA: { |
1069 | GCObject **next = getgclist(curr); | 1070 | GCObject **next = getgclist(curr); |
1070 | if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ | 1071 | if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ |
1071 | lua_assert(isgray(curr)); | 1072 | lua_assert(isgray(curr)); |