Browse Source

type 'Udata' refers directly to structure inside the union (union
used only for aligning purposes now)

Roberto Ierusalimschy 11 years ago
parent
commit
bb12903120
7 changed files with 48 additions and 35 deletions
  1. 5 5
      lapi.c
  2. 2 2
      lgc.c
  3. 29 16
      lobject.h
  4. 3 4
      lstate.h
  5. 5 5
      lstring.c
  6. 2 1
      lstring.h
  7. 2 2
      ltests.c

+ 5 - 5
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 2.226 2014/07/17 13:53:37 roberto Exp roberto $
+** $Id: lapi.c,v 2.227 2014/07/18 12:17:54 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -420,7 +420,7 @@ LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) {
 LUA_API void *lua_touserdata (lua_State *L, int idx) {
   StkId o = index2addr(L, idx);
   switch (ttnov(o)) {
-    case LUA_TUSERDATA: return (rawuvalue(o) + 1);
+    case LUA_TUSERDATA: return getudatamem(uvalue(o));
     case LUA_TLIGHTUSERDATA: return pvalue(o);
     default: return NULL;
   }
@@ -706,7 +706,7 @@ LUA_API int lua_getuservalue (lua_State *L, int idx) {
   lua_lock(L);
   o = index2addr(L, idx);
   api_check(ttisfulluserdata(o), "full userdata expected");
-  getuservalue(L, rawuvalue(o), L->top);
+  getuservalue(L, uvalue(o), L->top);
   api_incr_top(L);
   lua_unlock(L);
   return ttnov(L->top - 1);
@@ -842,7 +842,7 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) {
   api_checknelems(L, 1);
   o = index2addr(L, idx);
   api_check(ttisfulluserdata(o), "full userdata expected");
-  setuservalue(L, rawuvalue(o), L->top - 1);
+  setuservalue(L, uvalue(o), L->top - 1);
   luaC_barrier(L, gcvalue(o), L->top - 1);
   L->top--;
   lua_unlock(L);
@@ -1142,7 +1142,7 @@ LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
   setuvalue(L, L->top, u);
   api_incr_top(L);
   lua_unlock(L);
-  return u + 1;
+  return getudatamem(u);
 }
 
 

+ 2 - 2
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 2.186 2014/07/18 12:17:54 roberto Exp roberto $
+** $Id: lgc.c,v 2.187 2014/07/18 13:36:14 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -237,7 +237,7 @@ static void reallymarkobject (global_State *g, GCObject *o) {
       markobject(g, gco2u(o)->metatable);  /* mark its metatable */
       gray2black(o);
       g->GCmemtrav += sizeudata(gco2u(o));
-      getuservalue(g->mainthread, rawgco2u(o), &uvalue);
+      getuservalue(g->mainthread, gco2u(o), &uvalue);
       if (valiswhite(&uvalue)) {  /* markvalue(g, &uvalue); */
         o = gcvalue(&uvalue);
         goto reentry;

+ 29 - 16
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 2.97 2014/07/18 12:17:54 roberto Exp roberto $
+** $Id: lobject.h,v 2.98 2014/07/18 13:36:14 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -157,8 +157,7 @@ typedef struct lua_TValue TValue;
 #define gcvalue(o)	check_exp(iscollectable(o), val_(o).gc)
 #define pvalue(o)	check_exp(ttislightuserdata(o), val_(o).p)
 #define tsvalue(o)	check_exp(ttisstring(o), gco2ts(val_(o).gc))
-#define rawuvalue(o)	check_exp(ttisfulluserdata(o), rawgco2u(val_(o).gc))
-#define uvalue(o)	(&rawuvalue(o)->uv)
+#define uvalue(o)	check_exp(ttisfulluserdata(o), gco2u(val_(o).gc))
 #define clvalue(o)	check_exp(ttisclosure(o), gco2cl(val_(o).gc))
 #define clLvalue(o)	check_exp(ttisLclosure(o), gco2lcl(val_(o).gc))
 #define clCvalue(o)	check_exp(ttisCclosure(o), gco2ccl(val_(o).gc))
@@ -214,7 +213,7 @@ typedef struct lua_TValue TValue;
 
 #define setuvalue(L,obj,x) \
   { TValue *io = (obj); Udata *x_ = (x); \
-    val_(io).gc = obj2gco(&x_->uv); settt_(io, ctb(LUA_TUSERDATA)); \
+    val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \
     checkliveness(G(L),io); }
 
 #define setthvalue(L,obj,x) \
@@ -324,7 +323,7 @@ typedef union UTString {
 */
 #define getaddrstr(ts)	(cast(char *, (ts)) + sizeof(UTString))
 #define getstr(ts)  \
-	((void)(ts)->extra, cast(const char*, getaddrstr(ts)))
+  check_exp(sizeof((ts)->extra), cast(const char*, getaddrstr(ts)))
 
 /* get the actual string (array of bytes) from a Lua value */
 #define svalue(o)       getstr(tsvalue(o))
@@ -332,28 +331,42 @@ typedef union UTString {
 
 /*
 ** Header for userdata; memory area follows the end of this structure
+** (aligned according to 'UUdata'; see next).
 */
-typedef union Udata {
-  L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
-  struct {
-    CommonHeader;
-    lu_byte ttuv_;  /* user value's tag */
-    struct Table *metatable;
-    size_t len;  /* number of bytes */
-    union Value user_;  /* user value */
-  } uv;
+typedef struct Udata {
+  CommonHeader;
+  lu_byte ttuv_;  /* user value's tag */
+  struct Table *metatable;
+  size_t len;  /* number of bytes */
+  union Value user_;  /* user value */
 } Udata;
 
 
+/*
+** Ensures that address after this type is always fully aligned.
+*/
+typedef union UUdata {
+  L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
+  Udata uv;
+} UUdata;
+
+
+/*
+**  Get the address of memory block inside 'Udata'.
+** (Access to 'ttuv_' ensures that value is really a 'Udata'.)
+*/
+#define getudatamem(u)  \
+  check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata)))
+
 #define setuservalue(L,u,o) \
 	{ const TValue *io=(o); Udata *iu = (u); \
-	  iu->uv.user_ = io->value_; iu->uv.ttuv_ = io->tt_; \
+	  iu->user_ = io->value_; iu->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_; \
+	  io->value_ = iu->user_; io->tt_ = iu->ttuv_; \
 	  checkliveness(G(L),io); }
 
 

+ 3 - 4
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 2.111 2014/07/18 12:17:54 roberto Exp roberto $
+** $Id: lstate.h,v 2.112 2014/07/18 13:36:14 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -175,7 +175,7 @@ struct lua_State {
 union GCUnion {
   GCObject gc;  /* common header */
   struct TString ts;
-  union Udata u;
+  struct Udata u;
   union Closure cl;
   struct Table h;
   struct Proto p;
@@ -188,8 +188,7 @@ union GCUnion {
 /* macros to convert a GCObject into a specific value */
 #define gco2ts(o)  \
 	check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts))
-#define rawgco2u(o)  check_exp((o)->tt == LUA_TUSERDATA, &((cast_u(o))->u))
-#define gco2u(o)	(&rawgco2u(o)->uv)
+#define gco2u(o)  check_exp((o)->tt == LUA_TUSERDATA, &((cast_u(o))->u))
 #define gco2lcl(o)  check_exp((o)->tt == LUA_TLCL, &((cast_u(o))->cl.l))
 #define gco2ccl(o)  check_exp((o)->tt == LUA_TCCL, &((cast_u(o))->cl.c))
 #define gco2cl(o)  \

+ 5 - 5
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 2.41 2014/07/18 12:17:54 roberto Exp roberto $
+** $Id: lstring.c,v 2.42 2014/07/18 13:36:14 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -170,10 +170,10 @@ Udata *luaS_newudata (lua_State *L, size_t s) {
   GCObject *o;
   if (s > MAX_SIZE - sizeof(Udata))
     luaM_toobig(L);
-  o = luaC_newobj(L, LUA_TUSERDATA, sizeof(Udata) + s);
-  u = rawgco2u(o);
-  u->uv.len = s;
-  u->uv.metatable = NULL;
+  o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s));
+  u = gco2u(o);
+  u->len = s;
+  u->metatable = NULL;
   setuservalue(L, u, luaO_nilobject);
   return u;
 }

+ 2 - 1
lstring.h

@@ -15,7 +15,8 @@
 #define sizelstring(l)  (sizeof(union UTString) + ((l) + 1) * sizeof(char))
 #define sizestring(s)	sizelstring((s)->len)
 
-#define sizeudata(u)	(sizeof(union Udata)+(u)->len)
+#define sizeludata(l)	(sizeof(union UUdata) + (l))
+#define sizeudata(u)	sizeludata((u)->len)
 
 #define luaS_newliteral(L, s)	(luaS_newlstr(L, "" s, \
                                  (sizeof(s)/sizeof(char))-1))

+ 2 - 2
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 2.178 2014/07/18 12:17:54 roberto Exp roberto $
+** $Id: ltests.c,v 2.179 2014/07/18 13:36:14 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -319,7 +319,7 @@ static void checkobject (global_State *g, GCObject *o, int maybedead) {
         TValue uservalue;
         Table *mt = gco2u(o)->metatable;
         checkobjref(g, o, mt);
-        getuservalue(g->mainthread, rawgco2u(o), &uservalue);
+        getuservalue(g->mainthread, gco2u(o), &uservalue);
         checkvalref(g, o, &uservalue);
         break;
       }