From d5b83ead90fba27faa344c72406d85987d2460a4 Mon Sep 17 00:00:00 2001 From: Roberto Ierusalimschy Date: Wed, 6 Jun 2001 15:00:19 -0300 Subject: [PATCH] new implementation for userdatas, without `keys' --- lapi.c | 45 ++++++++++++++------------ lbaselib.c | 10 +++--- lcode.c | 6 ++-- ldblib.c | 16 ++++------ lgc.c | 62 +++++++++++++++++------------------ liolib.c | 94 ++++++++++++++++++++++++++++-------------------------- lobject.h | 34 +++++++++++--------- lstate.c | 12 ++++--- lstate.h | 4 +-- lstring.c | 72 +++++++++++++---------------------------- lstring.h | 20 ++++++++---- ltable.c | 4 +-- ltests.c | 38 ++++++++++++---------- ltm.c | 6 ++-- ltm.h | 4 +-- lua.c | 4 +-- lua.h | 4 +-- 17 files changed, 215 insertions(+), 220 deletions(-) diff --git a/lapi.c b/lapi.c index 36e0aef7..7f4c6e7f 100644 --- a/lapi.c +++ b/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 diff --git a/lbaselib.c b/lbaselib.c index 78fd6795..2c41aae1 100644 --- a/lbaselib.c +++ b/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; } } diff --git a/lcode.c b/lcode.c index 2658e602..8c43084e 100644 --- a/lcode.c +++ b/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; } diff --git a/ldblib.c b/ldblib.c index d5604f51..d3f0bca3 100644 --- a/ldblib.c +++ b/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) */ diff --git a/lgc.c b/lgc.c index a82039dd..86b7d092 100644 --- a/lgc.c +++ b/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; iudt.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); diff --git a/liolib.c b/liolib.c index fa9830bf..dda79529 100644 --- a/liolib.c +++ b/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")); diff --git a/lobject.h b/lobject.h index 97f77a97..ebcdbbb7 100644 --- a/lobject.h +++ b/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 */ diff --git a/lstate.c b/lstate.c index 63e15283..194e92c1 100644 --- a/lstate.c +++ b/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); diff --git a/lstate.h b/lstate.h index 7c0e808d..a1965fb8 100644 --- a/lstate.h +++ b/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 */ diff --git a/lstring.c b/lstring.c index 4318070d..e9d165cc 100644 --- a/lstring.c +++ b/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; ihash[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; } diff --git a/lstring.h b/lstring.h index ad6cca52..130b3a81 100644 --- a/lstring.h +++ b/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); diff --git a/ltable.c b/ltable.c index c3e4d382..c4a2c789 100644 --- a/ltable.c +++ b/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)]) diff --git a/ltests.c b/ltests.c index 95d7813d..b666a917 100644 --- a/ltests.c +++ b/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}, diff --git a/ltm.c b/ltm.c index b66d3d46..756728cf 100644 --- a/ltm.c +++ b/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; diff --git a/ltm.h b/ltm.h index 53572bd2..e233f1ef 100644 --- a/ltm.h +++ b/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; }; diff --git a/lua.c b/lua.c index fc2e89b0..34333f6f 100644 --- a/lua.c +++ b/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")); } diff --git a/lua.h b/lua.h index 6e1254ba..d391ccb0 100644 --- a/lua.h +++ b/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: info@lua.org @@ -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);