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)); |
