diff options
| -rw-r--r-- | lgc.c | 19 | ||||
| -rw-r--r-- | lobject.h | 37 |
2 files changed, 44 insertions, 12 deletions
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lgc.c,v 2.250 2018/02/23 13:16:18 roberto Exp roberto $ | 2 | ** $Id: lgc.c,v 2.251 2018/02/23 13:21:27 roberto Exp roberto $ |
| 3 | ** Garbage Collector | 3 | ** Garbage Collector |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -118,11 +118,15 @@ static lu_mem atomic (lua_State *L); | |||
| 118 | static GCObject **getgclist (GCObject *o) { | 118 | static GCObject **getgclist (GCObject *o) { |
| 119 | switch (o->tt) { | 119 | switch (o->tt) { |
| 120 | case LUA_TTABLE: return &gco2t(o)->gclist; | 120 | case LUA_TTABLE: return &gco2t(o)->gclist; |
| 121 | case LUA_TUSERDATA: return &gco2u(o)->gclist; | ||
| 122 | case LUA_TLCL: return &gco2lcl(o)->gclist; | 121 | case LUA_TLCL: return &gco2lcl(o)->gclist; |
| 123 | case LUA_TCCL: return &gco2ccl(o)->gclist; | 122 | case LUA_TCCL: return &gco2ccl(o)->gclist; |
| 124 | case LUA_TTHREAD: return &gco2th(o)->gclist; | 123 | case LUA_TTHREAD: return &gco2th(o)->gclist; |
| 125 | case LUA_TPROTO: return &gco2p(o)->gclist; | 124 | case LUA_TPROTO: return &gco2p(o)->gclist; |
| 125 | case LUA_TUSERDATA: { | ||
| 126 | Udata *u = gco2u(o); | ||
| 127 | lua_assert(u->nuvalue > 0); | ||
| 128 | return &u->gclist; | ||
| 129 | } | ||
| 126 | default: lua_assert(0); return 0; | 130 | default: lua_assert(0); return 0; |
| 127 | } | 131 | } |
| 128 | } | 132 | } |
| @@ -290,8 +294,17 @@ static void reallymarkobject (global_State *g, GCObject *o) { | |||
| 290 | markvalue(g, uv->v); /* mark its content */ | 294 | markvalue(g, uv->v); /* mark its content */ |
| 291 | break; | 295 | break; |
| 292 | } | 296 | } |
| 297 | case LUA_TUSERDATA: { | ||
| 298 | Udata *u = gco2u(o); | ||
| 299 | if (u->nuvalue == 0) { /* no user values? */ | ||
| 300 | markobjectN(g, u->metatable); /* mark its metatable */ | ||
| 301 | gray2black(o); /* nothing else to mark */ | ||
| 302 | break; | ||
| 303 | } | ||
| 304 | /* else *//* FALLTHROUGH */ | ||
| 305 | } | ||
| 293 | case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE: | 306 | case LUA_TLCL: case LUA_TCCL: case LUA_TTABLE: |
| 294 | case LUA_TUSERDATA: case LUA_TTHREAD: case LUA_TPROTO: { | 307 | case LUA_TTHREAD: case LUA_TPROTO: { |
| 295 | linkobjgclist(o, g->gray); | 308 | linkobjgclist(o, g->gray); |
| 296 | break; | 309 | break; |
| 297 | } | 310 | } |
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | ** $Id: lobject.h,v 2.138 2018/02/25 12:48:16 roberto Exp roberto $ | 2 | ** $Id: lobject.h,v 2.139 2018/02/25 12:52:32 roberto Exp roberto $ |
| 3 | ** Type definitions for Lua objects | 3 | ** Type definitions for Lua objects |
| 4 | ** See Copyright Notice in lua.h | 4 | ** See Copyright Notice in lua.h |
| 5 | */ | 5 | */ |
| @@ -70,7 +70,7 @@ typedef struct TValue { | |||
| 70 | #define rttype(o) ((o)->tt_) | 70 | #define rttype(o) ((o)->tt_) |
| 71 | 71 | ||
| 72 | /* tag with no variants (bits 0-3) */ | 72 | /* tag with no variants (bits 0-3) */ |
| 73 | #define novariant(x) ((x) & 0x0F) | 73 | #define novariant(t) ((t) & 0x0F) |
| 74 | 74 | ||
| 75 | /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ | 75 | /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ |
| 76 | #define ttyperaw(t) ((t) & 0x3F) | 76 | #define ttyperaw(t) ((t) & 0x3F) |
| @@ -379,7 +379,7 @@ typedef union UTString { | |||
| 379 | */ | 379 | */ |
| 380 | 380 | ||
| 381 | #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) | 381 | #define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) |
| 382 | #define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA)) | 382 | #define ttisfulluserdata(o) checktype((o), LUA_TUSERDATA) |
| 383 | 383 | ||
| 384 | #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) | 384 | #define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) |
| 385 | #define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc)) | 385 | #define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc)) |
| @@ -403,7 +403,8 @@ typedef union UValue { | |||
| 403 | 403 | ||
| 404 | 404 | ||
| 405 | /* | 405 | /* |
| 406 | ** Header for userdata; memory area follows the end of this structure. | 406 | ** Header for userdata with user values; |
| 407 | ** memory area follows the end of this structure. | ||
| 407 | */ | 408 | */ |
| 408 | typedef struct Udata { | 409 | typedef struct Udata { |
| 409 | CommonHeader; | 410 | CommonHeader; |
| @@ -415,15 +416,33 @@ typedef struct Udata { | |||
| 415 | } Udata; | 416 | } Udata; |
| 416 | 417 | ||
| 417 | 418 | ||
| 418 | /* computes the offset of the memory area of a userdata */ | ||
| 419 | #define udatamemoffset(nuv) (sizeof(Udata) + (sizeof(UValue) * ((nuv) - 1))) | ||
| 420 | |||
| 421 | /* | 419 | /* |
| 422 | ** Get the address of the memory block inside 'Udata'. | 420 | ** Header for userdata with no user values. These userdata do not need |
| 421 | ** to be gray during GC, and therefore do not need a 'gclist' field. | ||
| 422 | ** To simplify, the code always use 'Udata' for both kinds of userdata, | ||
| 423 | ** making sure it never accesses 'gclist' on userdata with no user values. | ||
| 424 | ** This structure here is used only to compute the correct size for | ||
| 425 | ** this representation. (The 'bindata' field in its end ensures correct | ||
| 426 | ** alignment for binary data following this header.) | ||
| 423 | */ | 427 | */ |
| 428 | typedef struct Udata0 { | ||
| 429 | CommonHeader; | ||
| 430 | unsigned short nuvalue; /* number of user values */ | ||
| 431 | size_t len; /* number of bytes */ | ||
| 432 | struct Table *metatable; | ||
| 433 | union {LUAI_MAXALIGN;} bindata; | ||
| 434 | } Udata0; | ||
| 435 | |||
| 436 | |||
| 437 | /* compute the offset of the memory area of a userdata */ | ||
| 438 | #define udatamemoffset(nuv) \ | ||
| 439 | ((nuv) == 0 ? offsetof(Udata0, bindata) \ | ||
| 440 | : offsetof(Udata, uv) + (sizeof(UValue) * (nuv))) | ||
| 441 | |||
| 442 | /* get the address of the memory block inside 'Udata' */ | ||
| 424 | #define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue)) | 443 | #define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue)) |
| 425 | 444 | ||
| 426 | /* computes the size of a userdata */ | 445 | /* compute the size of a userdata */ |
| 427 | #define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb)) | 446 | #define sizeudata(nuv,nb) (udatamemoffset(nuv) + (nb)) |
| 428 | 447 | ||
| 429 | /* }================================================================== */ | 448 | /* }================================================================== */ |
