aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-08-06 14:06:56 -0300
committerRoberto Ierusalimschy <roberto@inf.puc-rio.br>2002-08-06 14:06:56 -0300
commit634344d61fb4bd7ebd033d37b814a0083e55b5a2 (patch)
tree01794c51e00c7ec1faec1e08fe2963ee75b1a139
parenta2fa48a570b01b2a2cd37f01799f08f693fc5892 (diff)
downloadlua-634344d61fb4bd7ebd033d37b814a0083e55b5a2.tar.gz
lua-634344d61fb4bd7ebd033d37b814a0083e55b5a2.tar.bz2
lua-634344d61fb4bd7ebd033d37b814a0083e55b5a2.zip
new API for weak mode
-rw-r--r--lapi.c27
-rw-r--r--lbaselib.c25
-rw-r--r--lgc.c63
-rw-r--r--lobject.h6
-rw-r--r--ltable.c3
-rw-r--r--ltablib.c8
-rw-r--r--ltm.c6
-rw-r--r--ltm.h11
-rw-r--r--lua.h4
9 files changed, 88 insertions, 65 deletions
diff --git a/lapi.c b/lapi.c
index d7b8c376..49ee0864 100644
--- a/lapi.c
+++ b/lapi.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lapi.c,v 1.206 2002/08/05 14:43:38 roberto Exp roberto $ 2** $Id: lapi.c,v 1.207 2002/08/06 15:32:22 roberto Exp roberto $
3** Lua API 3** Lua API
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -464,6 +464,20 @@ LUA_API void lua_newtable (lua_State *L) {
464} 464}
465 465
466 466
467LUA_API const char *lua_getmode (lua_State *L, int index) {
468 static const char *const modes[] = {"", "k", "v", "kv"};
469 int mode = 0;
470 TObject *t;
471 lua_lock(L);
472 t = luaA_index(L, index);
473 api_check(L, ttistable(t));
474 if (hvalue(t)->mode & WEAKKEY) mode += 1;
475 if (hvalue(t)->mode & WEAKVALUE) mode += 2;
476 lua_unlock(L);
477 return modes[mode];
478}
479
480
467LUA_API int lua_getmetatable (lua_State *L, int objindex) { 481LUA_API int lua_getmetatable (lua_State *L, int objindex) {
468 StkId obj; 482 StkId obj;
469 Table *mt; 483 Table *mt;
@@ -555,6 +569,17 @@ LUA_API void lua_rawseti (lua_State *L, int index, int n) {
555} 569}
556 570
557 571
572LUA_API void lua_setmode (lua_State *L, int index, const char *mode) {
573 TObject *t;
574 lua_lock(L);
575 t = luaA_index(L, index);
576 api_check(L, ttistable(t));
577 hvalue(t)->mode &= ~(WEAKKEY | WEAKVALUE); /* clear bits */
578 if (strchr(mode, 'k')) hvalue(t)->mode |= WEAKKEY;
579 if (strchr(mode, 'v')) hvalue(t)->mode |= WEAKVALUE;
580 lua_unlock(L);
581}
582
558LUA_API int lua_setmetatable (lua_State *L, int objindex) { 583LUA_API int lua_setmetatable (lua_State *L, int objindex) {
559 TObject *obj, *mt; 584 TObject *obj, *mt;
560 int res = 1; 585 int res = 1;
diff --git a/lbaselib.c b/lbaselib.c
index b05a1b15..9658a1c6 100644
--- a/lbaselib.c
+++ b/lbaselib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lbaselib.c,v 1.92 2002/08/05 14:46:02 roberto Exp roberto $ 2** $Id: lbaselib.c,v 1.93 2002/08/06 15:32:22 roberto Exp roberto $
3** Basic library 3** Basic library
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -81,6 +81,21 @@ static int luaB_error (lua_State *L) {
81} 81}
82 82
83 83
84static int luaB_getmode (lua_State *L) {
85 luaL_check_type(L, 1, LUA_TTABLE);
86 lua_pushstring(L, lua_getmode(L, 1));
87 return 1;
88}
89
90
91static int luaB_setmode (lua_State *L) {
92 luaL_check_type(L, 1, LUA_TTABLE);
93 lua_setmode(L, 1, luaL_check_string(L, 2));
94 lua_settop(L, 1);
95 return 1;
96}
97
98
84static int luaB_getmetatable (lua_State *L) { 99static int luaB_getmetatable (lua_State *L) {
85 luaL_check_any(L, 1); 100 luaL_check_any(L, 1);
86 if (!lua_getmetatable(L, 1)) { 101 if (!lua_getmetatable(L, 1)) {
@@ -460,6 +475,8 @@ static const luaL_reg base_funcs[] = {
460 {"setmetatable", luaB_setmetatable}, 475 {"setmetatable", luaB_setmetatable},
461 {"getglobals", luaB_getglobals}, 476 {"getglobals", luaB_getglobals},
462 {"setglobals", luaB_setglobals}, 477 {"setglobals", luaB_setglobals},
478 {"getmode", luaB_getmode},
479 {"setmode", luaB_setmode},
463 {"next", luaB_next}, 480 {"next", luaB_next},
464 {"ipairs", luaB_ipairs}, 481 {"ipairs", luaB_ipairs},
465 {"pairs", luaB_pairs}, 482 {"pairs", luaB_pairs},
@@ -572,11 +589,7 @@ static void base_open (lua_State *L) {
572 /* `newproxy' needs a weaktable as upvalue */ 589 /* `newproxy' needs a weaktable as upvalue */
573 lua_pushliteral(L, "newproxy"); 590 lua_pushliteral(L, "newproxy");
574 lua_newtable(L); /* new table `w' */ 591 lua_newtable(L); /* new table `w' */
575 lua_pushvalue(L, -1); /* `w' will be its own metatable */ 592 lua_setmode(L, -1, "k");
576 lua_setmetatable(L, -2);
577 lua_pushliteral(L, "__mode");
578 lua_pushliteral(L, "k");
579 lua_rawset(L, -3); /* metatable(w).__mode = "k" */
580 lua_pushcclosure(L, luaB_newproxy, 1); 593 lua_pushcclosure(L, luaB_newproxy, 1);
581 lua_rawset(L, -3); /* set global `newproxy' */ 594 lua_rawset(L, -3); /* set global `newproxy' */
582 lua_rawset(L, -1); /* set global _G */ 595 lua_rawset(L, -1); /* set global _G */
diff --git a/lgc.c b/lgc.c
index 3b2c3fa4..7dde65c3 100644
--- a/lgc.c
+++ b/lgc.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lgc.c,v 1.143 2002/07/17 16:25:13 roberto Exp $ 2** $Id: lgc.c,v 1.144 2002/08/05 14:50:39 roberto Exp roberto $
3** Garbage Collector 3** Garbage Collector
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -35,12 +35,6 @@ typedef struct GCState {
35#define ismarked(x) ((x)->mark != (x)) 35#define ismarked(x) ((x)->mark != (x))
36 36
37 37
38/* `Table.flag' bits to indicate whether table is key-weak and/or value-weak */
39#define KEYWEAKBIT (TM_MODE+1) /* ORDER TM */
40#define VALUEWEAKBIT (TM_MODE+2)
41#define KEYWEAK (1<<KEYWEAKBIT)
42#define VALUEWEAK (1<<VALUEWEAKBIT)
43
44 38
45/* mark tricks for userdata */ 39/* mark tricks for userdata */
46#define isudmarked(u) (u->uv.len & 1) 40#define isudmarked(u) (u->uv.len & 1)
@@ -221,19 +215,15 @@ static void removekey (Node *n) {
221 215
222static void traversetable (GCState *st, Table *h) { 216static void traversetable (GCState *st, Table *h) {
223 int i; 217 int i;
224 const TObject *mode;
225 int weakkey = 0; 218 int weakkey = 0;
226 int weakvalue = 0; 219 int weakvalue = 0;
227 marktable(st, h->metatable); 220 marktable(st, h->metatable);
228 lua_assert(h->lsizenode || h->node == G(st->L)->dummynode); 221 lua_assert(h->lsizenode || h->node == G(st->L)->dummynode);
229 mode = fasttm(st->L, h->metatable, TM_MODE); 222 if (h->mode & (WEAKKEY | WEAKVALUE)) { /* weak table? */
230 if (mode && ttisstring(mode)) { /* weak table? */ 223 weakkey = h->mode & WEAKKEY;
224 weakvalue = h->mode & WEAKVALUE;
231 h->mark = st->toclear; /* must be cleared after GC, ... */ 225 h->mark = st->toclear; /* must be cleared after GC, ... */
232 st->toclear = h; /* ...put in the appropriate list */ 226 st->toclear = h; /* ... so put in the appropriate list */
233 weakkey = (strchr(svalue(mode), 'k') != NULL);
234 weakvalue = (strchr(svalue(mode), 'v') != NULL);
235 h->flags &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
236 h->flags |= (weakkey << KEYWEAKBIT) | (weakvalue << VALUEWEAKBIT);
237 } 227 }
238 if (!weakvalue) { 228 if (!weakvalue) {
239 i = sizearray(h); 229 i = sizearray(h);
@@ -284,14 +274,14 @@ static int hasmark (const TObject *o) {
284static void cleartablekeys (GCState *st) { 274static void cleartablekeys (GCState *st) {
285 Table *h; 275 Table *h;
286 for (h = st->toclear; h; h = h->mark) { 276 for (h = st->toclear; h; h = h->mark) {
287 int i; 277 lua_assert(h->mode & (WEAKKEY | WEAKVALUE));
288 if (!(h->flags & KEYWEAK)) continue; 278 if ((h->mode & WEAKKEY)) { /* table may have collected keys? */
289 lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'k')); 279 int i = sizenode(h);
290 i = sizenode(h); 280 while (i--) {
291 while (i--) { 281 Node *n = node(h, i);
292 Node *n = node(h, i); 282 if (!hasmark(key(n))) /* key was collected? */
293 if (!hasmark(key(n))) 283 removekey(n); /* remove entry from table */
294 removekey(n); /* ... and key */ 284 }
295 } 285 }
296 } 286 }
297} 287}
@@ -303,20 +293,19 @@ static void cleartablekeys (GCState *st) {
303static void cleartablevalues (GCState *st) { 293static void cleartablevalues (GCState *st) {
304 Table *h; 294 Table *h;
305 for (h = st->toclear; h; h = h->mark) { 295 for (h = st->toclear; h; h = h->mark) {
306 int i; 296 if ((h->mode & WEAKVALUE)) { /* table may have collected values? */
307 if (!(h->flags & VALUEWEAK)) continue; 297 int i = sizearray(h);
308 lua_assert(strchr(svalue(fasttm(st->L, h->metatable, TM_MODE)), 'v')); 298 while (i--) {
309 i = sizearray(h); 299 TObject *o = &h->array[i];
310 while (i--) { 300 if (!hasmark(o)) /* value was collected? */
311 TObject *o = &h->array[i]; 301 setnilvalue(o); /* remove value */
312 if (!hasmark(o)) 302 }
313 setnilvalue(o); /* remove value */ 303 i = sizenode(h);
314 } 304 while (i--) {
315 i = sizenode(h); 305 Node *n = node(h, i);
316 while (i--) { 306 if (!hasmark(val(n))) /* value was collected? */
317 Node *n = node(h, i); 307 removekey(n); /* remove entry from table */
318 if (!hasmark(val(n))) 308 }
319 removekey(n); /* ... and key */
320 } 309 }
321 } 310 }
322} 311}
diff --git a/lobject.h b/lobject.h
index e3dc6f95..805be05e 100644
--- a/lobject.h
+++ b/lobject.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lobject.h,v 1.140 2002/07/17 16:25:13 roberto Exp $ 2** $Id: lobject.h,v 1.141 2002/08/05 14:08:02 roberto Exp roberto $
3** Type definitions for Lua objects 3** Type definitions for Lua objects
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -223,8 +223,12 @@ typedef struct Table {
223 int sizearray; /* size of `array' array */ 223 int sizearray; /* size of `array' array */
224 lu_byte flags; /* 1<<p means tagmethod(p) is not present */ 224 lu_byte flags; /* 1<<p means tagmethod(p) is not present */
225 lu_byte lsizenode; /* log2 of size of `node' array */ 225 lu_byte lsizenode; /* log2 of size of `node' array */
226 lu_byte mode;
226} Table; 227} Table;
227 228
229/* bit masks for `mode' */
230#define WEAKKEY 1
231#define WEAKVALUE 2
228 232
229 233
230/* 234/*
diff --git a/ltable.c b/ltable.c
index 576c615e..6ef7aa57 100644
--- a/ltable.c
+++ b/ltable.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltable.c,v 1.114 2002/07/17 16:25:13 roberto Exp $ 2** $Id: ltable.c,v 1.115 2002/08/05 14:45:32 roberto Exp roberto $
3** Lua tables (hash) 3** Lua tables (hash)
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -309,6 +309,7 @@ Table *luaH_new (lua_State *L, int narray, int lnhash) {
309 G(L)->roottable = t; 309 G(L)->roottable = t;
310 t->mark = t; 310 t->mark = t;
311 t->flags = cast(lu_byte, ~0); 311 t->flags = cast(lu_byte, ~0);
312 t->mode = 0;
312 /* temporary values (kept only if some malloc fails) */ 313 /* temporary values (kept only if some malloc fails) */
313 t->array = NULL; 314 t->array = NULL;
314 t->sizearray = 0; 315 t->sizearray = 0;
diff --git a/ltablib.c b/ltablib.c
index 11c8cc66..4842a688 100644
--- a/ltablib.c
+++ b/ltablib.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltablib.c,v 1.9 2002/07/01 19:25:28 roberto Exp roberto $ 2** $Id: ltablib.c,v 1.10 2002/07/08 16:51:20 roberto Exp roberto $
3** Library for Table Manipulation 3** Library for Table Manipulation
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -288,11 +288,7 @@ static const luaL_reg tab_funcs[] = {
288 288
289LUALIB_API int lua_tablibopen (lua_State *L) { 289LUALIB_API int lua_tablibopen (lua_State *L) {
290 lua_newtable(L); /* create N (table to store num. elements in tables) */ 290 lua_newtable(L); /* create N (table to store num. elements in tables) */
291 lua_pushvalue(L, -1); 291 lua_setmode(L, -1, "k"); /* make it a weak table */
292 lua_setmetatable(L, -2); /* make it its own metatable */
293 lua_pushliteral(L, "__mode");
294 lua_pushliteral(L, "k");
295 lua_rawset(L, -3); /* make it a weak table */
296 luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 1); 292 luaL_opennamedlib(L, LUA_TABLIBNAME, tab_funcs, 1);
297 return 0; 293 return 0;
298} 294}
diff --git a/ltm.c b/ltm.c
index 70fd9807..cd70f6ba 100644
--- a/ltm.c
+++ b/ltm.c
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.c,v 1.98 2002/07/17 16:25:13 roberto Exp $ 2** $Id: ltm.c,v 1.99 2002/08/05 14:09:06 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -26,7 +26,7 @@ const char *const luaT_typenames[] = {
26void luaT_init (lua_State *L) { 26void luaT_init (lua_State *L) {
27 static const char *const luaT_eventname[] = { /* ORDER TM */ 27 static const char *const luaT_eventname[] = { /* ORDER TM */
28 "__index", "__newindex", 28 "__index", "__newindex",
29 "__gc", "__eq", "__mode", 29 "__gc", "__eq",
30 "__gettable", "__settable", 30 "__gettable", "__settable",
31 "__add", "__sub", "__mul", "__div", 31 "__add", "__sub", "__mul", "__div",
32 "__pow", "__unm", "__lt", "__le", 32 "__pow", "__unm", "__lt", "__le",
@@ -46,7 +46,7 @@ void luaT_init (lua_State *L) {
46*/ 46*/
47const TObject *luaT_gettm (Table *events, TMS event, TString *ename) { 47const TObject *luaT_gettm (Table *events, TMS event, TString *ename) {
48 const TObject *tm = luaH_getstr(events, ename); 48 const TObject *tm = luaH_getstr(events, ename);
49 lua_assert(event <= TM_MODE); 49 lua_assert(event <= TM_EQ);
50 if (ttisnil(tm)) { /* no tag method? */ 50 if (ttisnil(tm)) { /* no tag method? */
51 events->flags |= (1u<<event); /* cache this fact */ 51 events->flags |= (1u<<event); /* cache this fact */
52 return NULL; 52 return NULL;
diff --git a/ltm.h b/ltm.h
index d6eab0eb..168280b7 100644
--- a/ltm.h
+++ b/ltm.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: ltm.h,v 1.37 2002/06/25 19:17:22 roberto Exp roberto $ 2** $Id: ltm.h,v 1.38 2002/07/01 17:06:58 roberto Exp roberto $
3** Tag methods 3** Tag methods
4** See Copyright Notice in lua.h 4** See Copyright Notice in lua.h
5*/ 5*/
@@ -12,12 +12,6 @@
12 12
13 13
14/* 14/*
15** Important: garbage collection uses two extra bits of `Table.flags'
16** (after TM_MODE), so the maximum number of `fast tag methods' is six
17** (at least while `flags' is a byte).
18*/
19
20/*
21* WARNING: if you change the order of this enumeration, 15* WARNING: if you change the order of this enumeration,
22* grep "ORDER TM" 16* grep "ORDER TM"
23*/ 17*/
@@ -25,8 +19,7 @@ typedef enum {
25 TM_INDEX, 19 TM_INDEX,
26 TM_NEWINDEX, 20 TM_NEWINDEX,
27 TM_GC, 21 TM_GC,
28 TM_EQ, 22 TM_EQ, /* last tag method with `fast' access */
29 TM_MODE, /* last tag method with `fast' access */
30 TM_GETTABLE, 23 TM_GETTABLE,
31 TM_SETTABLE, 24 TM_SETTABLE,
32 TM_ADD, 25 TM_ADD,
diff --git a/lua.h b/lua.h
index 2bc32fa6..dc64fb34 100644
--- a/lua.h
+++ b/lua.h
@@ -1,5 +1,5 @@
1/* 1/*
2** $Id: lua.h,v 1.148 2002/08/05 14:51:47 roberto Exp roberto $ 2** $Id: lua.h,v 1.149 2002/08/06 15:32:22 roberto Exp roberto $
3** Lua - An Extensible Extension Language 3** Lua - An Extensible Extension Language
4** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil 4** Tecgraf: Computer Graphics Technology Group, PUC-Rio, Brazil
5** http://www.lua.org mailto:info@lua.org 5** http://www.lua.org mailto:info@lua.org
@@ -166,6 +166,7 @@ LUA_API void lua_rawget (lua_State *L, int index);
166LUA_API void lua_rawgeti (lua_State *L, int index, int n); 166LUA_API void lua_rawgeti (lua_State *L, int index, int n);
167LUA_API void lua_newtable (lua_State *L); 167LUA_API void lua_newtable (lua_State *L);
168LUA_API int lua_getmetatable (lua_State *L, int objindex); 168LUA_API int lua_getmetatable (lua_State *L, int objindex);
169LUA_API const char *lua_getmode (lua_State *L, int index);
169LUA_API void lua_getglobals (lua_State *L, int level); 170LUA_API void lua_getglobals (lua_State *L, int level);
170 171
171 172
@@ -175,6 +176,7 @@ LUA_API void lua_getglobals (lua_State *L, int level);
175LUA_API void lua_settable (lua_State *L, int index); 176LUA_API void lua_settable (lua_State *L, int index);
176LUA_API void lua_rawset (lua_State *L, int index); 177LUA_API void lua_rawset (lua_State *L, int index);
177LUA_API void lua_rawseti (lua_State *L, int index, int n); 178LUA_API void lua_rawseti (lua_State *L, int index, int n);
179LUA_API void lua_setmode (lua_State *L, int index, const char *mode);
178LUA_API int lua_setmetatable (lua_State *L, int objindex); 180LUA_API int lua_setmetatable (lua_State *L, int objindex);
179LUA_API int lua_setglobals (lua_State *L, int level); 181LUA_API int lua_setglobals (lua_State *L, int level);
180 182