Explorar o código

userdata can have any Lua value as uservalue

Roberto Ierusalimschy %!s(int64=11) %!d(string=hai) anos
pai
achega
c86b9da022
Modificáronse 7 ficheiros con 37 adicións e 30 borrados
  1. 5 13
      lapi.c
  2. 2 5
      ldblib.c
  3. 7 4
      lgc.c
  4. 14 2
      lobject.h
  5. 3 3
      lstring.c
  6. 2 2
      lstring.h
  7. 4 1
      ltests.c

+ 5 - 13
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);

+ 2 - 5
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;

+ 7 - 4
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: {

+ 14 - 2
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

+ 3 - 3
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;
 }
 

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

+ 4 - 1
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: {