userdata can have multiple user values
This commit is contained in:
33
lgc.c
33
lgc.c
@@ -113,6 +113,7 @@ static lu_mem atomic (lua_State *L);
|
||||
static GCObject **getgclist (GCObject *o) {
|
||||
switch (o->tt) {
|
||||
case LUA_TTABLE: return &gco2t(o)->gclist;
|
||||
case LUA_TUSERDATA: return &gco2u(o)->gclist;
|
||||
case LUA_TLCL: return &gco2lcl(o)->gclist;
|
||||
case LUA_TCCL: return &gco2ccl(o)->gclist;
|
||||
case LUA_TTHREAD: return &gco2th(o)->gclist;
|
||||
@@ -269,7 +270,6 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) {
|
||||
** to avoid barriers, as their values will be revisited by the thread.)
|
||||
*/
|
||||
static void reallymarkobject (global_State *g, GCObject *o) {
|
||||
reentry:
|
||||
white2gray(o);
|
||||
switch (o->tt) {
|
||||
case LUA_TSHRSTR:
|
||||
@@ -277,17 +277,6 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
||||
gray2black(o);
|
||||
break;
|
||||
}
|
||||
case LUA_TUSERDATA: {
|
||||
TValue uvalue;
|
||||
markobjectN(g, gco2u(o)->metatable); /* mark its metatable */
|
||||
gray2black(o);
|
||||
getuservalue(g->mainthread, gco2u(o), &uvalue);
|
||||
if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */
|
||||
o = gcvalue(&uvalue);
|
||||
goto reentry;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LUA_TUPVAL: {
|
||||
UpVal *uv = gco2upv(o);
|
||||
if (!upisopen(uv)) /* open upvalues are kept gray */
|
||||
@@ -296,7 +285,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
|
||||
break;
|
||||
}
|
||||
case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE:
|
||||
case LUA_TTHREAD: case LUA_TPROTO: {
|
||||
case LUA_TUSERDATA: case LUA_TTHREAD: case LUA_TPROTO: {
|
||||
linkobjgclist(o, g->gray);
|
||||
break;
|
||||
}
|
||||
@@ -602,6 +591,15 @@ static int traversethread (global_State *g, lua_State *th) {
|
||||
}
|
||||
|
||||
|
||||
static int traverseudata (global_State *g, Udata *u) {
|
||||
int i;
|
||||
markobjectN(g, u->metatable); /* mark its metatable */
|
||||
for (i = 0; i < u->nuvalue; i++)
|
||||
markvalue(g, &u->uv[i].uv);
|
||||
return 1 + u->nuvalue;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
** traverse one gray object, turning it to black (except for threads,
|
||||
** which are always gray).
|
||||
@@ -612,6 +610,7 @@ static lu_mem propagatemark (global_State *g) {
|
||||
g->gray = *getgclist(o); /* remove from 'gray' list */
|
||||
switch (o->tt) {
|
||||
case LUA_TTABLE: return traversetable(g, gco2t(o));
|
||||
case LUA_TUSERDATA: return traverseudata(g, gco2u(o));
|
||||
case LUA_TLCL: return traverseLclosure(g, gco2lcl(o));
|
||||
case LUA_TCCL: return traverseCclosure(g, gco2ccl(o));
|
||||
case LUA_TPROTO: return traverseproto(g, gco2p(o));
|
||||
@@ -742,9 +741,11 @@ static void freeobj (lua_State *L, GCObject *o) {
|
||||
case LUA_TTHREAD:
|
||||
luaE_freethread(L, gco2th(o));
|
||||
break;
|
||||
case LUA_TUSERDATA:
|
||||
luaM_freemem(L, o, sizeudata(gco2u(o)));
|
||||
case LUA_TUSERDATA: {
|
||||
Udata *u = gco2u(o);
|
||||
luaM_freemem(L, o, sizeudata(u->nuvalue, u->len));
|
||||
break;
|
||||
}
|
||||
case LUA_TSHRSTR:
|
||||
luaS_remove(L, gco2ts(o)); /* remove it from hash table */
|
||||
luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen));
|
||||
@@ -1065,7 +1066,7 @@ static GCObject **correctgraylist (GCObject **p) {
|
||||
GCObject *curr;
|
||||
while ((curr = *p) != NULL) {
|
||||
switch (curr->tt) {
|
||||
case LUA_TTABLE: {
|
||||
case LUA_TTABLE: case LUA_TUSERDATA: {
|
||||
GCObject **next = getgclist(curr);
|
||||
if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */
|
||||
lua_assert(isgray(curr));
|
||||
|
||||
Reference in New Issue
Block a user