commit a1ca4a6a0cbdbcfb8a78abf45226e2553cdd0615
parent cf7acde64025ee001879f419d0919e8e1d1e4e6d
Author: Andres Navarro <canavarro82@gmail.com>
Date: Tue, 19 Apr 2011 00:44:33 -0300
Added support for weak keys and weak values in both gc code & table constructor.
Diffstat:
4 files changed, 36 insertions(+), 48 deletions(-)
diff --git a/src/kgc.c b/src/kgc.c
@@ -166,27 +166,17 @@ size_t klispC_separateudata (lua_State *L, int all) {
static int32_t traversetable (klisp_State *K, Table *h) {
int32_t i;
- int32_t weakkey = 0;
- int32_t weakvalue = 0;
-// const TValue *mode;
- if (h->metatable) /* Never happens in klisp */
- markobject(K, h->metatable);
-/*klisp: mode = gfasttm(g, h->metatable, TM_MODE); *//* ??? */
- /* TODO use other way of marking tables as weak or whatever */
-// if (mode && ttisstring(mode)) { /* is there a weak mode? */
-// weakkey = (strchr(svalue(mode), 'k') != NULL);
-// weakvalue = (strchr(svalue(mode), 'v') != NULL);
- weakkey = h->flags & 1;
- weakkey = (h->flags & 2) >> 1; /* XXX: this is just to compile
- */
- if (weakkey || weakvalue) { /* is really weak? */
- h->gct &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
- h->gct |= cast(uint16_t, (weakkey << KEYWEAKBIT) |
- (weakvalue << VALUEWEAKBIT));
- h->gclist = K->weak; /* must be cleared after GC, ... */
- K->weak = obj2gco(h); /* ... so put in the appropriate list */
- }
-// }
+ TValue tv = gc2table(h);
+ int32_t weakkey = ktable_has_weak_keys(tv)? 1 : 0;
+ int32_t weakvalue = ktable_has_weak_values(tv)? 1 : 0;
+
+ if (weakkey || weakvalue) { /* is really weak? */
+ h->gct &= ~(KEYWEAK | VALUEWEAK); /* clear bits */
+ h->gct |= cast(uint16_t, (weakkey << KEYWEAKBIT) |
+ (weakvalue << VALUEWEAKBIT));
+ h->gclist = K->weak; /* must be cleared after GC, ... */
+ K->weak = obj2gco(h); /* ... so put in the appropriate list */
+ }
if (weakkey && weakvalue) return 1;
if (!weakvalue) {
i = h->sizearray;
@@ -542,19 +532,11 @@ void klispC_freeall (klisp_State *K) {
}
-#if 0 /* klisp: keep this around */
-static void markmt (global_State *g) {
- int i;
- for (i=0; i<NUM_TAGS; i++)
- if (g->mt[i]) markobject(g, g->mt[i]);
-}
-#endif
-
/* mark root set */
static void markroot (klisp_State *K) {
K->gray = NULL;
- K->grayagain = NULL; /* for now in klisp this isn't used */
- K->weak = NULL; /* for now in klisp this isn't used */
+ K->grayagain = NULL;
+ K->weak = NULL;
/* TEMP: this is quite awfull, think of other way to do this */
/* MAYBE: some of these could be FIXED */
@@ -594,7 +576,6 @@ static void markroot (klisp_State *K) {
markvalue(K, K->dummy_pair1);
markvalue(K, K->dummy_pair2);
markvalue(K, K->dummy_pair3);
-/* markmt(g); */
K->gcstate = GCSpropagate;
}
@@ -607,11 +588,7 @@ static void atomic (klisp_State *K) {
/* remark weak tables */
K->gray = K->weak;
K->weak = NULL;
-#if 0 /* keep around */
- markmt(g); /* mark basic metatables (again) */
- propagateall(g);
-#endif
- /* klisp: for now in klisp this isn't used */
+
/* remark gray again */
K->gray = K->grayagain;
K->grayagain = NULL;
diff --git a/src/kobject.h b/src/kobject.h
@@ -421,16 +421,17 @@ typedef struct Node {
typedef struct __attribute__ ((__packed__)) {
CommonHeader;
- uint8_t flags; /* 1<<p means tagmethod(p) is not present */
uint8_t lsizenode; /* log2 of size of `node' array */
- uint16_t tpadding; /* to avoid disturbing the alignment */
- struct Table *metatable; /* is this necessary in klisp? */
+ uint8_t t1padding;
+ uint16_t t2padding; /* to avoid disturbing the alignment */
TValue *array; /* array part */
Node *node;
Node *lastfree; /* any free position is before this position */
int32_t sizearray; /* size of `array' array */
} Table;
+/* The weak flags are in kflags */
+
/*
** `module' operation for hashing (size is always a power of 2)
*/
@@ -668,6 +669,16 @@ int32_t kmark_count;
#define kport_is_output(o_) ((tv_get_kflags(o_) & K_FLAG_OUTPUT_PORT) != 0)
#define kport_is_closed(o_) ((tv_get_kflags(o_) & K_FLAG_CLOSED_PORT) != 0)
+#define K_FLAG_WEAK_KEYS 0x01
+#define K_FLAG_WEAK_VALUES 0x02
+
+#define ktable_has_weak_keys(o_) \
+ ((tv_get_kflags(o_) & K_FLAG_WEAK_KEYS) != 0)
+#define ktable_has_weak_values(o_) \
+ ((tv_get_kflags(o_) & K_FLAG_WEAK_VALUES) != 0)
+
+
+
/* can't be inline because we also use pointers to them,
(at least gcc doesn't bother to create them and the linker fails) */
bool kis_input_port(TValue o);
diff --git a/src/ktable.c b/src/ktable.c
@@ -382,14 +382,14 @@ static void rehash (klisp_State *K, Table *t, const TValue ek) {
** }=============================================================
*/
-
-TValue klispH_new (klisp_State *K, int32_t narray, int32_t nhash)
+/* wflags should be either or both of K_FLAG_WEAK_KEYS or K_FLAG_WEAK VALUES */
+TValue klispH_new (klisp_State *K, int32_t narray, int32_t nhash,
+ int32_t wflags)
{
+ klisp_assert((wflags & (K_FLAG_WEAK_KEYS | K_FLAG_WEAK_VALUES)) ==
+ wflags);
Table *t = klispM_new(K, Table);
- /* MAYBE I could use kflags instead of flags? */
- klispC_link(K, (GCObject *) t, K_TTABLE, 0);
- t->metatable = NULL;
- t->flags = (uint8_t) (~0);
+ klispC_link(K, (GCObject *) t, K_TTABLE, wflags);
/* temporary values (kept only if some malloc fails) */
t->array = NULL;
t->sizearray = 0;
@@ -526,7 +526,6 @@ const TValue *klispH_get (Table *t, TValue key)
TValue *klispH_set (klisp_State *K, Table *t, TValue key)
{
const TValue *p = klispH_get(t, key);
- t->flags = 0; /* ???: klisp: what's the purpose of this?? */
if (p != &knil)
return cast(TValue *, p);
else {
diff --git a/src/ktable.h b/src/ktable.h
@@ -28,7 +28,8 @@ const TValue *klispH_getstr (Table *t, String *key);
TValue *klispH_setstr (klisp_State *K, Table *t, String *key);
const TValue *klispH_get (Table *t, TValue key);
TValue *klispH_set (klisp_State *K, Table *t, TValue key);
-TValue klispH_new (klisp_State *K, int32_t narray, int32_t lnhash);
+TValue klispH_new (klisp_State *K, int32_t narray, int32_t nhash,
+ int32_t wflags);
void klispH_resizearray (klisp_State *K, Table *t, int32_t nasize);
void klispH_free (klisp_State *K, Table *t);
int32_t klispH_next (klisp_State *K, Table *t, TValue *key, TValue *data);