commit d5b83ead90fba27faa344c72406d85987d2460a4
parent da673d31aaa05e8dff60c0b601b9f15c4f9182a8
Author: Roberto Ierusalimschy <roberto@inf.puc-rio.br>
Date: Wed, 6 Jun 2001 14:59:57 -0300
new implementation for userdatas, without `keys'
Diffstat:
M | lapi.c | | | 45 | +++++++++++++++++++++++++-------------------- |
M | lbaselib.c | | | 10 | +++++----- |
M | lcode.c | | | 6 | +++--- |
M | ldblib.c | | | 16 | +++++++--------- |
M | lgc.c | | | 62 | +++++++++++++++++++++++++++++--------------------------------- |
M | liolib.c | | | 94 | +++++++++++++++++++++++++++++++++++++++++-------------------------------------- |
M | lobject.h | | | 34 | +++++++++++++++++++--------------- |
M | lstate.c | | | 12 | +++++++----- |
M | lstate.h | | | 4 | ++-- |
M | lstring.c | | | 72 | +++++++++++++++++++++++------------------------------------------------- |
M | lstring.h | | | 20 | ++++++++++++++------ |
M | ltable.c | | | 4 | ++-- |
M | ltests.c | | | 38 | +++++++++++++++++++++----------------- |
M | ltm.c | | | 6 | +++--- |
M | ltm.h | | | 4 | ++-- |
M | lua.c | | | 4 | ++-- |
M | lua.h | | | 4 | ++-- |
17 files changed, 215 insertions(+), 220 deletions(-)
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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);
diff --git 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
@@ -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
@@ -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
@@ -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
@@ -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;
}
diff --git 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
*/
@@ -14,6 +14,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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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);