Bläddra i källkod

new implementation for userdatas, without `keys'

Roberto Ierusalimschy 24 år sedan
förälder
incheckning
d5b83ead90
17 ändrade filer med 215 tillägg och 220 borttagningar
  1. 25 20
      lapi.c
  2. 5 5
      lbaselib.c
  3. 3 3
      lcode.c
  4. 7 9
      ldblib.c
  5. 29 33
      lgc.c
  6. 49 45
      liolib.c
  7. 19 15
      lobject.h
  8. 7 5
      lstate.c
  9. 2 2
      lstate.h
  10. 23 49
      lstring.c
  11. 14 6
      lstring.h
  12. 2 2
      ltable.c
  13. 21 17
      ltests.c
  14. 3 3
      ltm.c
  15. 2 2
      ltm.h
  16. 2 2
      lua.c
  17. 2 2
      lua.h

+ 25 - 20
lapi.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lapi.c,v 1.141 2001/04/23 16:35:45 roberto Exp roberto $
+** $Id: lapi.c,v 1.142 2001/06/05 18:17:01 roberto Exp roberto $
 ** Lua API
 ** See Copyright Notice in lua.h
 */
@@ -284,8 +284,7 @@ LUA_API void *lua_touserdata (lua_State *L, int index) {
   void *p;
   lua_lock(L);
   o = luaA_indexAcceptable(L, index);
-  p = (o == NULL || ttype(o) != LUA_TUSERDATA) ? NULL :
-                                                    tsvalue(o)->u.d.value;
+  p = (o == NULL || ttype(o) != LUA_TUSERDATA) ? NULL : uvalue(o)->value;
   lua_unlock(L);
   return p;
 }
@@ -360,16 +359,6 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) {
 }
 
 
-LUA_API int lua_pushuserdata (lua_State *L, void *u) {
-  int isnew;
-  lua_lock(L);
-  isnew = luaS_createudata(L, u, L->top);
-  api_incr_top(L);
-  lua_unlock(L);
-  return isnew;
-}
-
-
 
 /*
 ** get functions (Lua -> stack)
@@ -673,7 +662,7 @@ LUA_API void lua_settag (lua_State *L, int tag) {
       hvalue(L->top-1)->htag = tag;
       break;
     case LUA_TUSERDATA:
-      tsvalue(L->top-1)->u.d.tag = tag;
+      uvalue(L->top-1)->tag = tag;
       break;
     default:
       luaO_verror(L, l_s("cannot change the tag of a %.20s"),
@@ -771,20 +760,34 @@ LUA_API void lua_concat (lua_State *L, int n) {
 }
 
 
+static Udata *pushnewudata (lua_State *L, size_t size) {
+  Udata *u = luaS_newudata(L, size);
+  setuvalue(L->top, u);
+  api_incr_top(L);
+  return uvalue(L->top-1);
+}
+
+
 LUA_API void *lua_newuserdata (lua_State *L, size_t size) {
-  TString *ts;
+  Udata *u;
   void *p;
   lua_lock(L);
-  if (size == 0) size = 1;
-  ts = luaS_newudata(L, size, NULL);
-  setuvalue(L->top, ts);
-  api_incr_top(L);
-  p = ts->u.d.value;
+  u = pushnewudata(L, size);
+  p = u->value;
   lua_unlock(L);
   return p;
 }
 
 
+LUA_API void lua_newuserdatabox (lua_State *L, void *p) {
+  Udata *u;
+  lua_lock(L);
+  u = pushnewudata(L, 0);
+  u->value = p;
+  lua_unlock(L);
+}
+
+
 LUA_API int lua_getweakmode (lua_State *L, int index) {
   StkId t;
   int mode;
@@ -806,6 +809,7 @@ LUA_API void  lua_setweakmode (lua_State *L, int mode) {
 
 
 
+#if 0
 /*
 ** deprecated function
 */
@@ -819,3 +823,4 @@ LUA_API void lua_pushusertag (lua_State *L, void *u, int tag) {
 }
   }
 }
+#endif

+ 5 - 5
lbaselib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lbaselib.c,v 1.35 2001/04/23 16:35:45 roberto Exp roberto $
+** $Id: lbaselib.c,v 1.36 2001/06/05 19:41:31 roberto Exp roberto $
 ** Basic library
 ** See Copyright Notice in lua.h
 */
@@ -170,11 +170,11 @@ static int luaB_settag (lua_State *L) {
 }
 
 static int luaB_weakmode (lua_State *L) {
-  const char *mode = luaL_check_string(L, 2);
+  const l_char *mode = luaL_check_string(L, 2);
   luaL_checktype(L, 1, LUA_TTABLE);
   if (*mode == l_c('?')) {
-    char buff[3];
-    char *s = buff;
+    l_char buff[3];
+    l_char *s = buff;
     int imode = lua_getweakmode(L, 1);
     if (imode & LUA_WEAK_KEY) *s++ = 'k';
     if (imode & LUA_WEAK_VALUE) *s++ = 'v';
@@ -300,7 +300,7 @@ static int passresults (lua_State *L, int status, int oldtop) {
     if (nresults > 0)
       return nresults;  /* results are already on the stack */
     else {
-      lua_pushuserdata(L, NULL);  /* at least one result to signal no errors */
+      lua_newuserdatabox(L, NULL); /* at least one result to signal no errors */
       return 1;
     }
   }

+ 3 - 3
lcode.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lcode.c,v 1.68 2001/04/23 16:35:45 roberto Exp roberto $
+** $Id: lcode.c,v 1.69 2001/06/05 18:17:01 roberto Exp roberto $
 ** Code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -226,12 +226,12 @@ static int addk (FuncState *fs, TObject *k) {
 
 int luaK_stringk (FuncState *fs, TString *s) {
   Proto *f = fs->f;
-  int c = s->u.s.constindex;
+  int c = s->constindex;
   if (c >= fs->nk || ttype(&f->k[c]) != LUA_TSTRING || tsvalue(&f->k[c]) != s) {
     TObject o;
     setsvalue(&o, s);
     c = addk(fs, &o);
-    s->u.s.constindex = c;  /* hint for next time */
+    s->constindex = c;  /* hint for next time */
   }
   return c;
 }

+ 7 - 9
ldblib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ldblib.c,v 1.35 2001/03/07 18:09:25 roberto Exp roberto $
+** $Id: ldblib.c,v 1.36 2001/03/26 14:31:49 roberto Exp roberto $
 ** Interface from Lua to its debug API
 ** See Copyright Notice in lua.h
 */
@@ -111,15 +111,13 @@ static int setlocal (lua_State *L) {
 
 
 
-/* dummy variables (to define unique addresses) */
-static const l_char key1[] = l_s("ab");
-#define KEY_CALLHOOK	((void *)key1)
-#define KEY_LINEHOOK	((void *)(key1+1))
+#define KEY_CALLHOOK	l_s("luadblibCallhook")
+#define KEY_LINEHOOK	l_s("luadblibLinehook")
 
 
-static void hookf (lua_State *L, void *key) {
+static void hookf (lua_State *L, const l_char *key) {
   lua_getregistry(L);
-  lua_pushuserdata(L, key);
+  lua_pushstring(L, key);
   lua_gettable(L, -2);
   if (lua_isfunction(L, -1)) {
     lua_pushvalue(L, -3);  /* original argument (below table and function) */
@@ -143,7 +141,7 @@ static void linef (lua_State *L, lua_Debug *ar) {
 }
 
 
-static void sethook (lua_State *L, void *key, lua_Hook hook,
+static void sethook (lua_State *L, const l_char *key, lua_Hook hook,
                      lua_Hook (*sethookf)(lua_State * L, lua_Hook h)) {
   lua_settop(L, 1);
   if (lua_isnil(L, 1))
@@ -153,7 +151,7 @@ static void sethook (lua_State *L, void *key, lua_Hook hook,
   else
     luaL_argerror(L, 1, l_s("function expected"));
   lua_getregistry(L);
-  lua_pushuserdata(L, key);
+  lua_pushstring(L, key);
   lua_pushvalue(L, -1);  /* dup key */
   lua_gettable(L, -3);   /* get old value */
   lua_pushvalue(L, -2);  /* key (again) */

+ 29 - 33
lgc.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lgc.c,v 1.98 2001/06/05 18:17:01 roberto Exp roberto $
+** $Id: lgc.c,v 1.99 2001/06/05 19:27:32 roberto Exp roberto $
 ** Garbage Collector
 ** See Copyright Notice in lua.h
 */
@@ -82,9 +82,12 @@ static void marktable (GCState *st, Hash *h) {
 
 static void markobject (GCState *st, TObject *o) {
   switch (ttype(o)) {
-    case LUA_TUSERDATA:  case LUA_TSTRING:
+    case LUA_TSTRING:
       strmark(tsvalue(o));
       break;
+    case LUA_TUSERDATA:
+      uvalue(o)->marked = 1;
+      break;
     case LUA_TFUNCTION:
       markclosure(st, clvalue(o));
       break;
@@ -190,8 +193,10 @@ static void markall (lua_State *L) {
 
 static int hasmark (const TObject *o) {
   switch (ttype(o)) {
-    case LUA_TSTRING: case LUA_TUSERDATA:
+    case LUA_TSTRING:
       return tsvalue(o)->marked;
+    case LUA_TUSERDATA:
+      return uvalue(o)->marked;
     case LUA_TTABLE:
       return ismarked(hvalue(o));
     case LUA_TFUNCTION:
@@ -275,9 +280,21 @@ static void collecttable (lua_State *L) {
 }
 
 
-static void checktab (lua_State *L, stringtable *tb) {
-  if (tb->nuse < (ls_nstr)(tb->size/4) && tb->size > MINPOWER2)
-    luaS_resize(L, tb, tb->size/2);  /* table is too big */
+static void collectudata (lua_State *L) {
+  Udata **p = &G(L)->rootudata;
+  Udata *next;
+  while ((next = *p) != NULL) {
+    if (next->marked) {
+      next->marked = 0;  /* unmark */
+      p = &next->next;
+    }
+    else {  /* collect */
+      int tag = next->tag;
+      *p = next->next;
+      next->next = G(L)->TMtable[tag].collected;  /* chain udata */
+      G(L)->TMtable[tag].collected = next;
+    }
+  }
 }
 
 
@@ -299,33 +316,12 @@ static void collectstrings (lua_State *L, int all) {
       }
     }
   }
-  checktab(L, &G(L)->strt);
+  if (G(L)->strt.nuse < (ls_nstr)(G(L)->strt.size/4) &&
+      G(L)->strt.size > MINPOWER2)
+    luaS_resize(L, G(L)->strt.size/2);  /* table is too big */
 }
 
 
-static void collectudata (lua_State *L, int all) {
-  int i;
-  for (i=0; i<G(L)->udt.size; i++) {  /* for each list */
-    TString **p = &G(L)->udt.hash[i];
-    TString *next;
-    while ((next = *p) != NULL) {
-      lua_assert(next->marked <= 1);
-      if (next->marked && !all) {  /* preserve? */
-        next->marked = 0;
-        p = &next->nexthash;
-      } 
-      else {  /* collect */
-        int tag = next->u.d.tag;
-        *p = next->nexthash;
-        next->nexthash = G(L)->TMtable[tag].collected;  /* chain udata */
-        G(L)->TMtable[tag].collected = next;
-        G(L)->udt.nuse--;
-      }
-    }
-  }
-  checktab(L, &G(L)->udt);
-}
-
 
 #define MINBUFFER	256
 static void checkMbuffer (lua_State *L) {
@@ -356,10 +352,10 @@ static void callgcTMudata (lua_State *L) {
   int tag;
   G(L)->GCthreshold = 2*G(L)->nblocks;  /* avoid GC during tag methods */
   for (tag=G(L)->ntag-1; tag>=0; tag--) {  /* for each tag (in reverse order) */
-    TString *udata;
+    Udata *udata;
     while ((udata = G(L)->TMtable[tag].collected) != NULL) {
       TObject obj;
-      G(L)->TMtable[tag].collected = udata->nexthash;  /* remove it from list */
+      G(L)->TMtable[tag].collected = udata->next;  /* remove it from list */
       setuvalue(&obj, udata);
       callgcTM(L, &obj);
       luaM_free(L, udata, sizeudata(udata->len));
@@ -370,7 +366,7 @@ static void callgcTMudata (lua_State *L) {
 
 void luaC_collect (lua_State *L, int all) {
   lua_lockgc(L);
-  collectudata(L, all);
+  collectudata(L);
   callgcTMudata(L);
   collectstrings(L, all);
   collecttable(L);

+ 49 - 45
liolib.c

@@ -1,5 +1,5 @@
 /*
-** $Id: liolib.c,v 1.111 2001/03/26 14:31:49 roberto Exp roberto $
+** $Id: liolib.c,v 1.112 2001/04/23 16:35:45 roberto Exp roberto $
 ** Standard I/O (and system) library
 ** See Copyright Notice in lua.h
 */
@@ -48,15 +48,17 @@ int pclose(); */
 #define OUTFILE 1
 #define NOFILE	2
 
-#define FILEHANDLE	l_s("FileHandle")
+#define FILEHANDLE		l_s("FileHandle")
+#define CLOSEDFILEHANDLE	l_s("ClosedFileHandle")
 
 
 static const l_char *const filenames[] = {l_s("_INPUT"), l_s("_OUTPUT")};
+static const l_char *const basicfiles[] = {l_s("_STDIN"), l_s("_STDOUT")};
 
 
 static int pushresult (lua_State *L, int i) {
   if (i) {
-    lua_pushuserdata(L, NULL);
+    lua_newuserdatabox(L, NULL);
     return 1;
   }
   else {
@@ -81,16 +83,15 @@ static int pushresult (lua_State *L, int i) {
 static FILE *getopthandle (lua_State *L, int inout) {
   FILE *p = (FILE *)lua_touserdata(L, 1);
   if (p != NULL) {  /* is it a userdata ? */
-    if (!checkfile(L, 1)) {
-      if (strcmp(lua_xtypename(L, 1), l_s("ClosedFileHandle")) == 0)
+    if (!checkfile(L, 1)) {  /* not a valid file handle? */
+      if (strcmp(lua_xtypename(L, 1), CLOSEDFILEHANDLE) == 0)
         luaL_argerror(L, 1, l_s("file is closed"));
       else
         luaL_argerror(L, 1, l_s("(invalid value)"));
     }
-    /* move it to stack top */
-    lua_pushvalue(L, 1); lua_remove(L, 1);
+    lua_pushvalue(L, 1); lua_remove(L, 1);  /* move it to stack top */
   }
-  else if (inout != NOFILE) {  /* try global value */
+  else {  /* try global value */
     lua_getglobal(L, filenames[inout]);
     if (!checkfile(L,-1))
       luaL_verror(L, l_s("global variable `%.10s' is not a valid file handle"),
@@ -101,46 +102,50 @@ static FILE *getopthandle (lua_State *L, int inout) {
 }
 
 
-static void pushfile (lua_State *L, FILE *f) {
-  lua_pushusertag(L, f, lua_name2tag(L, FILEHANDLE));
+static void newfile (lua_State *L, FILE *f) {
+  lua_newuserdatabox(L, f);
+  lua_settag(L, lua_name2tag(L, FILEHANDLE));
 }
 
 
-static void setfilebyname (lua_State *L, FILE *f, const l_char *name) {
-  pushfile(L, f);
+static void newfilewithname (lua_State *L, FILE *f, const l_char *name) {
+  newfile(L, f);
   lua_setglobal(L, name);
 }
 
 
-#define setfile(L,f,inout)	(setfilebyname(L,f,filenames[inout]))
-
-
-static int setreturn (lua_State *L, FILE *f, int inout) {
+static int setnewfile (lua_State *L, FILE *f, int inout) {
   if (f == NULL)
     return pushresult(L, 0);
   else {
-    if (inout != NOFILE)
-      setfile(L, f, inout);
-    pushfile(L, f);
+    newfile(L, f);
+    if (inout != NOFILE) {
+      lua_pushvalue(L, -1);
+      lua_setglobal(L, filenames[inout]);
+    }
     return 1;
   }
 }
 
 
-static int closefile (lua_State *L, FILE *f) {
-  if (f == stdin || f == stdout || f == stderr)
-    return 1;
-  else {
-    lua_pushuserdata(L, f);
-    lua_settag(L, lua_name2tag(L, l_s("ClosedFileHandle")));
-    return (CLOSEFILE(L, f) == 0);
-  }
+static void resetfile (lua_State *L, int inout) {
+  lua_getglobal(L, basicfiles[inout]);
+  lua_setglobal(L, filenames[inout]);
 }
 
 
 static int io_close (lua_State *L) {
-  FILE *f = (FILE *)luaL_check_userdata(L, 1, FILEHANDLE);
-  return pushresult(L, closefile(L, f));
+  FILE *f;
+  int status;
+  lua_settop(L, 1);
+  f = luaL_check_userdata(L, 1, FILEHANDLE);
+  if (f == stdin || f == stdout || f == stderr)
+    status = 1;
+  else {
+    lua_settag(L, lua_name2tag(L, CLOSEDFILEHANDLE));
+    status = (CLOSEFILE(L, f) == 0);
+  }
+  return pushresult(L, status);
 }
 
 
@@ -154,12 +159,12 @@ static int file_collect (lua_State *L) {
 
 static int io_open (lua_State *L) {
   FILE *f = fopen(luaL_check_string(L, 1), luaL_check_string(L, 2));
-  return setreturn(L, f, NOFILE);
+  return setnewfile(L, f, NOFILE);
 }
 
 
 static int io_tmpfile (lua_State *L) {
-  return setreturn(L, tmpfile(), NOFILE);
+  return setnewfile(L, tmpfile(), NOFILE);
 }
 
 
@@ -167,16 +172,15 @@ static int io_tmpfile (lua_State *L) {
 static int io_fromto (lua_State *L, int inout, const l_char *mode) {
   FILE *current;
   if (lua_isnull(L, 1)) {
-    closefile(L, getopthandle(L, inout));
-    current = (inout == 0) ? stdin : stdout;    
+    getopthandle(L, inout);
+    resetfile(L, inout);
+    return io_close(L);
   }
-  else if (checkfile(L, 1))  /* deprecated option */
-    current = (FILE *)lua_touserdata(L, 1);
   else {
     const l_char *s = luaL_check_string(L, 1);
     current = (*s == l_c('|')) ? popen(s+1, mode) : fopen(s, mode);
+    return setnewfile(L, current, inout);
   }
-  return setreturn(L, current, inout);
 }
 
 
@@ -192,7 +196,7 @@ static int io_writeto (lua_State *L) {
 
 static int io_appendto (lua_State *L) {
   FILE *current = fopen(luaL_check_string(L, 1), l_s("a"));
-  return setreturn(L, current, OUTFILE);
+  return setnewfile(L, current, OUTFILE);
 }
 
 
@@ -388,8 +392,8 @@ static int io_seek (lua_State *L) {
 
 
 static int io_flush (lua_State *L) {
-  FILE *f = getopthandle(L, NOFILE);
-  luaL_arg_check(L, f || lua_isnull(L, 1), 1, l_s("invalid file handle"));
+  FILE *f = (lua_isnull(L, 1)) ? (FILE *)NULL :
+                                 (FILE *)luaL_check_userdata(L, 1, FILEHANDLE);
   return pushresult(L, fflush(f) == 0);
 }
 
@@ -679,14 +683,14 @@ static const luaL_reg iolib[] = {
 
 LUALIB_API int lua_iolibopen (lua_State *L) {
   int iotag = lua_newxtype(L, FILEHANDLE, LUA_TUSERDATA);
-  lua_newxtype(L, l_s("ClosedFileHandle"), LUA_TUSERDATA);
+  lua_newxtype(L, CLOSEDFILEHANDLE, LUA_TUSERDATA);
   luaL_openl(L, iolib);
   /* predefined file handles */
-  setfile(L, stdin, INFILE);
-  setfile(L, stdout, OUTFILE);
-  setfilebyname(L, stdin, l_s("_STDIN"));
-  setfilebyname(L, stdout, l_s("_STDOUT"));
-  setfilebyname(L, stderr, l_s("_STDERR"));
+  newfilewithname(L, stdin, basicfiles[INFILE]);
+  newfilewithname(L, stdout, basicfiles[OUTFILE]);
+  newfilewithname(L, stderr, l_s("_STDERR"));
+  resetfile(L, INFILE);
+  resetfile(L, OUTFILE);
   /* close files when collected */
   lua_pushcfunction(L, file_collect);
   lua_settagmethod(L, iotag, l_s("gc"));

+ 19 - 15
lobject.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.h,v 1.102 2001/04/11 14:42:41 roberto Exp roberto $
+** $Id: lobject.h,v 1.103 2001/06/05 18:17:01 roberto Exp roberto $
 ** Type definitions for Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -29,6 +29,7 @@
 
 typedef union {
   struct TString *ts;
+  struct Udata *u;
   struct Closure *cl;
   struct Hash *h;
   lua_Number n;		/* LUA_TNUMBER */
@@ -45,6 +46,7 @@ typedef struct lua_TObject {
 #define ttype(o)        ((o)->tt)
 #define nvalue(o)       ((o)->value.n)
 #define tsvalue(o)      ((o)->value.ts)
+#define uvalue(o)      ((o)->value.u)
 #define clvalue(o)      ((o)->value.cl)
 #define hvalue(o)       ((o)->value.h)
 
@@ -57,7 +59,7 @@ typedef struct lua_TObject {
   { TObject *_o=(obj); _o->tt=LUA_TSTRING; _o->value.ts=(x); }
 
 #define setuvalue(obj,x) \
-  { TObject *_o=(obj); _o->tt=LUA_TUSERDATA; _o->value.ts=(x); }
+  { TObject *_o=(obj); _o->tt=LUA_TUSERDATA; _o->value.u=(x); }
 
 #define setclvalue(obj,x) \
   { TObject *_o=(obj); _o->tt=LUA_TFUNCTION; _o->value.cl=(x); }
@@ -78,38 +80,40 @@ typedef TObject *StkId;  /* index to stack elements */
 /*
 ** String headers for string table
 */
-
 typedef struct TString {
-  union {
-    struct {  /* for strings */
-      lu_hash hash;
-      int constindex;  /* hint to reuse constants */
-    } s;
-    struct {  /* for userdata */
-      int tag;
-      void *value;
-    } d;
-  } u;
+  lu_hash hash;
+  int constindex;  /* hint to reuse constants */
   size_t len;
   int marked;
   struct TString *nexthash;  /* chain for hash table */
 } TString;
 
 
+
 /*
 ** type equivalent to TString, but with maximum alignment requirements
 */
 union L_UTString {
   TString ts;
-  union L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
+  union L_Umaxalign dummy;  /* ensures maximum alignment for strings */
 };
 
 
-
 #define getstr(ts)	((l_char *)((union L_UTString *)(ts) + 1))
 #define svalue(o)       getstr(tsvalue(o))
 
 
+
+typedef struct Udata {
+  int tag;
+  void *value;
+  size_t len;
+  int marked;
+  struct Udata *next;  /* chain for list of all udata */
+} Udata;
+
+
+
 /*
 ** Function Prototypes
 */

+ 7 - 5
lstate.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.c,v 1.61 2001/03/26 14:31:49 roberto Exp roberto $
+** $Id: lstate.c,v 1.62 2001/04/17 17:35:54 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -49,14 +49,15 @@ static void f_luaopen (lua_State *L, void *ud) {
   }
   else {  /* create a new global state */
     L->G = luaM_new(L, global_State);
-    G(L)->strt.size = G(L)->udt.size = 0;
-    G(L)->strt.nuse = G(L)->udt.nuse = 0;
-    G(L)->strt.hash = G(L)->udt.hash = NULL;
+    G(L)->strt.size = 0;
+    G(L)->strt.nuse = 0;
+    G(L)->strt.hash = NULL;
     G(L)->Mbuffer = NULL;
     G(L)->Mbuffsize = 0;
     G(L)->rootproto = NULL;
     G(L)->rootcl = NULL;
     G(L)->roottable = NULL;
+    G(L)->rootudata = NULL;
     G(L)->TMtable = NULL;
     G(L)->sizeTM = 0;
     G(L)->ntag = 0;
@@ -67,7 +68,7 @@ static void f_luaopen (lua_State *L, void *ud) {
     G(L)->registry = luaH_new(L, 0);
     G(L)->weakregistry = luaH_new(L, 0);
     G(L)->weakregistry->weakmode = LUA_WEAK_VALUE;  /* make weakregistry weak */
-    luaS_init(L);
+    luaS_resize(L, MINPOWER2);
     luaX_init(L);
     luaT_init(L);
     G(L)->GCthreshold = 4*G(L)->nblocks;
@@ -115,6 +116,7 @@ static void close_state (lua_State *L, lua_State *OL) {
     lua_assert(G(L)->rootproto == NULL);
     lua_assert(G(L)->rootcl == NULL);
     lua_assert(G(L)->roottable == NULL);
+    lua_assert(G(L)->rootudata == NULL);
     luaS_freeall(L);
     luaM_freearray(L, G(L)->TMtable, G(L)->sizeTM, struct TM);
     luaM_freearray(L, G(L)->Mbuffer, G(L)->Mbuffsize, l_char);

+ 2 - 2
lstate.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstate.h,v 1.55 2001/03/07 18:09:25 roberto Exp roberto $
+** $Id: lstate.h,v 1.56 2001/04/17 17:35:54 roberto Exp roberto $
 ** Global State
 ** See Copyright Notice in lua.h
 */
@@ -53,8 +53,8 @@ typedef struct global_State {
   Proto *rootproto;  /* list of all prototypes */
   Closure *rootcl;  /* list of all closures */
   Hash *roottable;  /* list of all tables */
+  Udata *rootudata;   /* list of all userdata */
   stringtable strt;  /* hash table for strings */
-  stringtable udt;   /* hash table for udata */
   Hash *type2tag;  /* hash table from type names to tags */
   Hash *registry;  /* (strong) registry table */
   Hash *weakregistry;  /* weakregistry table */

+ 23 - 49
lstring.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.c,v 1.61 2001/02/23 17:17:25 roberto Exp roberto $
+** $Id: lstring.c,v 1.62 2001/03/26 14:31:49 roberto Exp roberto $
 ** String table (keeps all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -17,22 +17,15 @@
 
 
 
-void luaS_init (lua_State *L) {
-  luaS_resize(L, &G(L)->strt, MINPOWER2);
-  luaS_resize(L, &G(L)->udt, MINPOWER2);
-}
-
-
 void luaS_freeall (lua_State *L) {
   lua_assert(G(L)->strt.nuse==0);
   luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size, TString *);
-  lua_assert(G(L)->udt.nuse==0);
-  luaM_freearray(L, G(L)->udt.hash, G(L)->udt.size, TString *);
 }
 
 
-void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
+void luaS_resize (lua_State *L, int newsize) {
   TString **newhash = luaM_newvector(L, newsize, TString *);
+  stringtable *tb = &G(L)->strt;
   int i;
   for (i=0; i<newsize; i++) newhash[i] = NULL;
   /* rehash */
@@ -40,7 +33,7 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
     TString *p = tb->hash[i];
     while (p) {  /* for each node in the list */
       TString *next = p->nexthash;  /* save next */
-      lu_hash h = (tb == &G(L)->strt) ? p->u.s.hash : IntPoint(p->u.d.value);
+      lu_hash h = p->hash;
       int h1 = lmod(h, newsize);  /* new position */
       lua_assert((int)(h%newsize) == lmod(h, newsize));
       p->nexthash = newhash[h1];  /* chain it in new position */
@@ -54,16 +47,6 @@ void luaS_resize (lua_State *L, stringtable *tb, int newsize) {
 }
 
 
-static void newentry (lua_State *L, stringtable *tb, TString *ts, int h) {
-  ts->nexthash = tb->hash[h];  /* chain new entry */
-  tb->hash[h] = ts;
-  tb->nuse++;
-  if (tb->nuse > (ls_nstr)tb->size && tb->size <= MAX_INT/2)  /* too crowded? */
-    luaS_resize(L, tb, tb->size*2);
-}
-
-
-
 TString *luaS_newlstr (lua_State *L, const l_char *str, size_t l) {
   TString *ts;
   lu_hash h = l;  /* seed */
@@ -80,39 +63,30 @@ TString *luaS_newlstr (lua_State *L, const l_char *str, size_t l) {
   ts->marked = 0;
   ts->nexthash = NULL;
   ts->len = l;
-  ts->u.s.hash = h;
-  ts->u.s.constindex = 0;
+  ts->hash = h;
+  ts->constindex = 0;
   memcpy(getstr(ts), str, l*sizeof(l_char));
   getstr(ts)[l] = 0;  /* ending 0 */
-  newentry(L, &G(L)->strt, ts, lmod(h, G(L)->strt.size));  /* insert it */
+  h = lmod(h, G(L)->strt.size);
+  ts->nexthash = G(L)->strt.hash[h];  /* chain new entry */
+  G(L)->strt.hash[h] = ts;
+  G(L)->strt.nuse++;
+  if (G(L)->strt.nuse > (ls_nstr)G(L)->strt.size &&
+      G(L)->strt.size <= MAX_INT/2)
+    luaS_resize(L, G(L)->strt.size*2);  /* too crowded */
   return ts;
 }
 
 
-TString *luaS_newudata (lua_State *L, size_t s, void *udata) {
-  TString *ts = (TString *)luaM_malloc(L, sizeudata(s));
-  ts->marked = 0;
-  ts->nexthash = NULL;
-  ts->len = s;
-  ts->u.d.tag = 0;
-  ts->u.d.value = (s > 0) ? getstr(ts) : udata;
-  /* insert it on table */
-  newentry(L, &G(L)->udt, ts, lmod(IntPoint(ts->u.d.value), G(L)->udt.size));
-  return ts;
-}
-
-
-int luaS_createudata (lua_State *L, void *udata, TObject *o) {
-  int h1 = lmod(IntPoint(udata), G(L)->udt.size);
-  TString *ts;
-  for (ts = G(L)->udt.hash[h1]; ts; ts = ts->nexthash) {
-    if (udata == ts->u.d.value) {
-      setuvalue(o, ts);
-      return 0;
-    }
-  }
-  /* not found */
-  setuvalue(o, luaS_newudata(L, 0, udata));
-  return 1;
+Udata *luaS_newudata (lua_State *L, size_t s) {
+  Udata *u = (Udata *)luaM_malloc(L, sizeudata(s));
+  u->marked = 0;
+  u->len = s;
+  u->tag = 0;
+  u->value = ((union L_UUdata *)(u) + 1);
+  /* chain it on udata list */
+  u->next = G(L)->rootudata;
+  G(L)->rootudata = u;
+  return u;
 }
 

+ 14 - 6
lstring.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lstring.h,v 1.30 2001/02/20 18:15:33 roberto Exp roberto $
+** $Id: lstring.h,v 1.31 2001/02/23 17:17:25 roberto Exp roberto $
 ** String table (keep all strings handled by Lua)
 ** See Copyright Notice in lua.h
 */
@@ -13,6 +13,16 @@
 
 
 
+/*
+** type equivalent to Udata, but with maximum alignment requirements
+*/
+union L_UUdata {
+  Udata u;
+  union L_Umaxalign dummy;  /* ensures maximum alignment for `local' udata */
+};
+
+
+
 /*
 ** any TString with mark>=FIXMARK is never collected.
 ** Marks>=RESERVEDMARK are used to identify reserved words.
@@ -24,16 +34,14 @@
 #define sizestring(l)	((lu_mem)sizeof(union L_UTString)+ \
                          ((lu_mem)(l)+1)*sizeof(l_char))
 
-#define sizeudata(l)	((lu_mem)sizeof(union L_UTString)+(l))
+#define sizeudata(l)	((lu_mem)sizeof(union L_UUdata)+(l))
 
 #define luaS_new(L, s)	(luaS_newlstr(L, s, strlen(s)))
 #define luaS_newliteral(L, s)	(luaS_newlstr(L, l_s("") s, \
                                  (sizeof(s)/sizeof(l_char))-1))
 
-void luaS_init (lua_State *L);
-void luaS_resize (lua_State *L, stringtable *tb, int newsize);
-TString *luaS_newudata (lua_State *L, size_t s, void *udata);
-int luaS_createudata (lua_State *L, void *udata, TObject *o);
+void luaS_resize (lua_State *L, int newsize);
+Udata *luaS_newudata (lua_State *L, size_t s);
 void luaS_freeall (lua_State *L);
 TString *luaS_newlstr (lua_State *L, const l_char *str, size_t l);
 

+ 2 - 2
ltable.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltable.c,v 1.78 2001/03/26 14:31:49 roberto Exp roberto $
+** $Id: ltable.c,v 1.79 2001/04/11 14:42:41 roberto Exp roberto $
 ** Lua tables (hash)
 ** See Copyright Notice in lua.h
 */
@@ -33,7 +33,7 @@
 
 
 #define hashnum(t,n)		(&t->node[lmod((lu_hash)(ls_hash)(n), t->size)])
-#define hashstr(t,str)		(&t->node[lmod((str)->u.s.hash, t->size)])
+#define hashstr(t,str)		(&t->node[lmod((str)->hash, t->size)])
 #define hashpointer(t,p)	(&t->node[lmod(IntPoint(p), t->size)])
 
 

+ 21 - 17
ltests.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltests.c,v 1.80 2001/04/23 16:35:45 roberto Exp roberto $
+** $Id: ltests.c,v 1.81 2001/06/05 18:17:01 roberto Exp roberto $
 ** Internal Module for Debugging of the Lua Implementation
 ** See Copyright Notice in lua.h
 */
@@ -290,7 +290,7 @@ static int mem_query (lua_State *L) {
 static int hash_query (lua_State *L) {
   if (lua_isnull(L, 2)) {
     luaL_arg_check(L, lua_tag(L, 1) == LUA_TSTRING, 1, l_s("string expected"));
-    lua_pushnumber(L, tsvalue(luaA_index(L, 1))->u.s.hash);
+    lua_pushnumber(L, tsvalue(luaA_index(L, 1))->hash);
   }
   else {
     Hash *t;
@@ -339,8 +339,7 @@ static int table_query (lua_State *L) {
 
 
 static int string_query (lua_State *L) {
-  stringtable *tb = (*luaL_check_string(L, 1) == l_c('s')) ? &G(L)->strt :
-                                                        &G(L)->udt;
+  stringtable *tb = &G(L)->strt;
   int s = luaL_opt_int(L, 2, 0) - 1;
   if (s==-1) {
     lua_pushnumber(L ,tb->nuse);
@@ -390,19 +389,22 @@ static int unref (lua_State *L) {
 }
 
 static int newuserdata (lua_State *L) {
-  if (lua_isnumber(L, 2)) {
-    int tag = luaL_check_int(L, 2);
-    int res = lua_pushuserdata(L, (void *)luaL_check_int(L, 1));
-    if (tag) lua_settag(L, tag);
-    pushbool(L, res);
-    return 2;
-  }
-  else {
-    size_t size = luaL_check_int(L, 1);
-    l_char *p = (l_char *)lua_newuserdata(L, size);
-    while (size--) *p++ = l_c('\0');
-    return 1;
-  }
+  size_t size = luaL_check_int(L, 1);
+  l_char *p = (l_char *)lua_newuserdata(L, size);
+  while (size--) *p++ = l_c('\0');
+  return 1;
+}
+
+static int newuserdatabox (lua_State *L) {
+  lua_newuserdatabox(L, (void *)luaL_check_int(L, 1));
+  return 1;
+}
+
+static int settag (lua_State *L) {
+  luaL_checkany(L, 1);
+  lua_pushvalue(L, 1);  /* push value */
+  lua_settag(L, luaL_check_int(L, 2));
+  return 1;  /* return value */
 }
 
 static int udataval (lua_State *L) {
@@ -691,6 +693,8 @@ static const struct luaL_reg tests_funcs[] = {
   {l_s("d2s"), d2s},
   {l_s("s2d"), s2d},
   {l_s("newuserdata"), newuserdata},
+  {l_s("newuserdatabox"), newuserdatabox},
+  {l_s("settag"), settag},
   {l_s("udataval"), udataval},
   {l_s("newtag"), newtag},
   {l_s("doonnewstack"), doonnewstack},

+ 3 - 3
ltm.c

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.c,v 1.70 2001/03/02 17:27:50 roberto Exp roberto $
+** $Id: ltm.c,v 1.71 2001/03/26 14:31:49 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -127,7 +127,7 @@ LUA_API int lua_copytagmethods (lua_State *L, int tagto, int tagfrom) {
 int luaT_tag (const TObject *o) {
   int t = ttype(o);
   switch (t) {
-    case LUA_TUSERDATA: return tsvalue(o)->u.d.tag;
+    case LUA_TUSERDATA: return uvalue(o)->tag;
     case LUA_TTABLE:    return hvalue(o)->htag;
     default:            return t;
   }
@@ -140,7 +140,7 @@ const l_char *luaT_typename (global_State *G, const TObject *o) {
   TString *ts;
   switch (t) {
     case LUA_TUSERDATA:
-      tag = tsvalue(o)->u.d.tag;
+      tag = uvalue(o)->tag;
       break;
     case LUA_TTABLE:
       tag = hvalue(o)->htag;

+ 2 - 2
ltm.h

@@ -1,5 +1,5 @@
 /*
-** $Id: ltm.h,v 1.23 2001/02/09 20:22:29 roberto Exp roberto $
+** $Id: ltm.h,v 1.24 2001/02/23 17:17:25 roberto Exp roberto $
 ** Tag methods
 ** See Copyright Notice in lua.h
 */
@@ -53,7 +53,7 @@ typedef enum {
 
 struct TM {
   Closure *method[TM_N];
-  TString *collected;  /* list of garbage-collected udata with this tag */
+  Udata *collected;  /* list of garbage-collected udata with this tag */
   TString *name;  /* type name */
   int basictype;
 };

+ 2 - 2
lua.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.c,v 1.65 2001/03/09 18:05:05 roberto Exp roberto $
+** $Id: lua.c,v 1.66 2001/03/26 14:31:49 roberto Exp roberto $
 ** Lua stand-alone interpreter
 ** See Copyright Notice in lua.h
 */
@@ -308,7 +308,7 @@ static void getstacksize (int argc, l_char *argv[], struct Options *opt) {
 
 
 static void register_getargs (l_char *argv[]) {
-  lua_pushuserdata(L, argv);
+  lua_newuserdatabox(L, argv);
   lua_pushcclosure(L, l_getargs, 1);
   lua_setglobal(L, l_s("getargs"));
 }

+ 2 - 2
lua.h

@@ -1,5 +1,5 @@
 /*
-** $Id: lua.h,v 1.96 2001/04/17 17:35:54 roberto Exp roberto $
+** $Id: lua.h,v 1.97 2001/04/23 16:35:45 roberto Exp roberto $
 ** Lua - An Extensible Extension Language
 ** TeCGraf: Grupo de Tecnologia em Computacao Grafica, PUC-Rio, Brazil
 ** e-mail: [email protected]
@@ -150,7 +150,6 @@ LUA_API void  lua_pushnumber (lua_State *L, lua_Number n);
 LUA_API void  lua_pushlstring (lua_State *L, const lua_char *s, size_t len);
 LUA_API void  lua_pushstring (lua_State *L, const lua_char *s);
 LUA_API void  lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
-LUA_API int   lua_pushuserdata (lua_State *L, void *u);
 
 
 /*
@@ -218,6 +217,7 @@ LUA_API int   lua_getn (lua_State *L, int index);
 LUA_API void  lua_concat (lua_State *L, int n);
 
 LUA_API void *lua_newuserdata (lua_State *L, size_t size);
+LUA_API void  lua_newuserdatabox (lua_State *L, void *u);
 
 LUA_API void  lua_setweakmode (lua_State *L, int mode);
 LUA_API int  lua_getweakmode (lua_State *L, int index);