From c86b9da02276652a22426b2a5a194ba1f070fcf4 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 19 Feb 2014 10:52:42 -0300 Subject: [PATCH] userdata can have any Lua value as uservalue --- lapi.c | 18 +++++------------- ldblib.c | 7 ++----- lgc.c | 11 +++++++---- lobject.h | 16 ++++++++++++++-- lstring.c | 6 +++--- lstring.h | 4 ++-- ltests.c | 5 ++++- 7 files changed, 37 insertions(+), 30 deletions(-) diff --git a/lapi.c b/lapi.c index c0ba24c1..b50aff40 100644 --- a/lapi.c +++ b/lapi.c @@ -1,5 +1,5 @@ /* -** $Id: lapi.c,v 2.196 2014/02/14 16:43:14 roberto Exp roberto $ +** $Id: lapi.c,v 2.197 2014/02/15 13:12:01 roberto Exp roberto $ ** Lua API ** See Copyright Notice in lua.h */ @@ -740,10 +740,7 @@ LUA_API void lua_getuservalue (lua_State *L, int idx) { lua_lock(L); o = index2addr(L, idx); api_check(L, ttisfulluserdata(o), "full userdata expected"); - if (uvalue(o)->env) { - sethvalue(L, L->top, uvalue(o)->env); - } else - setnilvalue(L->top); + getuservalue(L, rawuvalue(o), L->top); api_incr_top(L); lua_unlock(L); } @@ -878,13 +875,8 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { api_checknelems(L, 1); o = index2addr(L, idx); api_check(L, ttisfulluserdata(o), "full userdata expected"); - if (ttisnil(L->top - 1)) - uvalue(o)->env = NULL; - else { - api_check(L, ttistable(L->top - 1), "table expected"); - uvalue(o)->env = hvalue(L->top - 1); - luaC_objbarrier(L, gcvalue(o), hvalue(L->top - 1)); - } + setuservalue(L, rawuvalue(o), L->top - 1); + luaC_barrier(L, gcvalue(o), L->top - 1); L->top--; lua_unlock(L); } @@ -1189,7 +1181,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) { Udata *u; lua_lock(L); luaC_checkGC(L); - u = luaS_newudata(L, size, NULL); + u = luaS_newudata(L, size); setuvalue(L, L->top, u); api_incr_top(L); lua_unlock(L); diff --git a/ldblib.c b/ldblib.c index 2b48113d..10328f3a 100644 --- a/ldblib.c +++ b/ldblib.c @@ -1,5 +1,5 @@ /* -** $Id: ldblib.c,v 1.134 2013/07/10 20:57:05 roberto Exp roberto $ +** $Id: ldblib.c,v 1.135 2013/07/22 16:05:53 roberto Exp roberto $ ** Interface from Lua to its debug API ** See Copyright Notice in lua.h */ @@ -69,11 +69,8 @@ static int db_getuservalue (lua_State *L) { static int db_setuservalue (lua_State *L) { - if (lua_type(L, 1) == LUA_TLIGHTUSERDATA) - luaL_argerror(L, 1, "full userdata expected, got light userdata"); luaL_checktype(L, 1, LUA_TUSERDATA); - if (!lua_isnoneornil(L, 2)) - luaL_checktype(L, 2, LUA_TTABLE); + luaL_checkany(L, 2); lua_settop(L, 2); lua_setuservalue(L, 1); return 1; diff --git a/lgc.c b/lgc.c index c210b67e..93e22f0f 100644 --- a/lgc.c +++ b/lgc.c @@ -1,5 +1,5 @@ /* -** $Id: lgc.c,v 2.176 2014/02/18 13:39:37 roberto Exp roberto $ +** $Id: lgc.c,v 2.177 2014/02/18 13:46:26 roberto Exp roberto $ ** Garbage Collector ** See Copyright Notice in lua.h */ @@ -233,12 +233,15 @@ static void reallymarkobject (global_State *g, GCObject *o) { break; } case LUA_TUSERDATA: { + TValue uvalue; markobject(g, gco2u(o)->metatable); /* mark its metatable */ gray2black(o); g->GCmemtrav += sizeudata(gco2u(o)); - o = obj2gco(gco2u(o)->env); - if (o && iswhite(o)) - goto reentry; /* reallymarkobject(g, gco2u(o)->env); */ + getuservalue(g->mainthread, rawgco2u(o), &uvalue); + if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ + o = gcvalue(&uvalue); + goto reentry; + } break; } case LUA_TLCL: { diff --git a/lobject.h b/lobject.h index 23bbe74f..6dd741e1 100644 --- a/lobject.h +++ b/lobject.h @@ -1,5 +1,5 @@ /* -** $Id: lobject.h,v 2.83 2013/12/04 12:15:22 roberto Exp roberto $ +** $Id: lobject.h,v 2.85 2014/02/19 13:51:09 roberto Exp roberto $ ** Type definitions for Lua objects ** See Copyright Notice in lua.h */ @@ -331,13 +331,25 @@ typedef union Udata { L_Umaxalign dummy; /* ensures maximum alignment for `local' udata */ struct { CommonHeader; + lu_byte ttuv_; /* user value's tag */ struct Table *metatable; - struct Table *env; size_t len; /* number of bytes */ + union Value user_; /* user value */ } uv; } Udata; +#define setuservalue(L,u,o) \ + { const TValue *io=(o); Udata *iu = (u); \ + iu->uv.user_ = io->value_; iu->uv.ttuv_ = io->tt_; \ + checkliveness(G(L),io); } + + +#define getuservalue(L,u,o) \ + { TValue *io=(o); const Udata *iu = (u); \ + io->value_ = iu->uv.user_; io->tt_ = iu->uv.ttuv_; \ + checkliveness(G(L),io); } + /* ** Description of an upvalue for function prototypes diff --git a/lstring.c b/lstring.c index c73e521c..793e4880 100644 --- a/lstring.c +++ b/lstring.c @@ -1,5 +1,5 @@ /* -** $Id: lstring.c,v 2.35 2013/09/11 12:26:14 roberto Exp roberto $ +** $Id: lstring.c,v 2.36 2013/09/11 14:56:15 roberto Exp roberto $ ** String table (keeps all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -172,14 +172,14 @@ TString *luaS_new (lua_State *L, const char *str) { } -Udata *luaS_newudata (lua_State *L, size_t s, Table *e) { +Udata *luaS_newudata (lua_State *L, size_t s) { Udata *u; if (s > MAX_SIZE - sizeof(Udata)) luaM_toobig(L); u = &luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s)->u; u->uv.len = s; u->uv.metatable = NULL; - u->uv.env = e; + setuservalue(L, u, luaO_nilobject); return u; } diff --git a/lstring.h b/lstring.h index e6f08106..c9fc5d63 100644 --- a/lstring.h +++ b/lstring.h @@ -1,5 +1,5 @@ /* -** $Id: lstring.h,v 1.51 2013/08/21 19:21:16 roberto Exp roberto $ +** $Id: lstring.h,v 1.52 2013/08/21 20:09:51 roberto Exp roberto $ ** String table (keep all strings handled by Lua) ** See Copyright Notice in lua.h */ @@ -37,7 +37,7 @@ LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); LUAI_FUNC int luaS_eqstr (TString *a, TString *b); LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, Table *e); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); diff --git a/ltests.c b/ltests.c index 931fc1c8..65e2ad26 100644 --- a/ltests.c +++ b/ltests.c @@ -1,5 +1,5 @@ /* -** $Id: ltests.c,v 2.165 2014/02/15 13:12:01 roberto Exp roberto $ +** $Id: ltests.c,v 2.166 2014/02/18 13:46:26 roberto Exp roberto $ ** Internal Module for Debugging of the Lua Implementation ** See Copyright Notice in lua.h */ @@ -322,8 +322,11 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) { lua_assert(g->gcstate != GCSpause || iswhite(o)); switch (gch(o)->tt) { case LUA_TUSERDATA: { + TValue uservalue; Table *mt = gco2u(o)->metatable; if (mt) checkobjref(g, o, mt); + getuservalue(g->mainthread, rawgco2u(o), &uservalue); + checkobjref(g, o, &uservalue); break; } case LUA_TTABLE: {