aboutsummaryrefslogtreecommitdiff
path: root/lgc.c
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-20 13:52:50 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2018-02-20 13:52:50 -0300
commitca6fe7449a74efde6f959605dbe77acf3e64ca0b (patch)
treea6190e813ff712f7db750d4ecd3afd3ac9c0dbab /lgc.c
parent1afd5a152dc8b3a304236dc4e07bca38ea5eb53a (diff)
downloadlua-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.c33
1 files changed, 17 insertions, 16 deletions
diff --git a/lgc.c b/lgc.c
index 77ccae0a..3421bd8a 100644
--- a/lgc.c
+++ b/lgc.c
@@ -113,6 +113,7 @@ static lu_mem atomic (lua_State *L);
113static GCObject **getgclist (GCObject *o) { 113static 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*/
271static void reallymarkobject (global_State *g, GCObject *o) { 272static 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
594static 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));