klisp

an open source interpreter for the Kernel Programming Language.
git clone http://git.hanabi.in/repos/klisp.git
Log | Files | Refs | README

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:
Msrc/kgc.c | 51++++++++++++++-------------------------------------
Msrc/kobject.h | 17++++++++++++++---
Msrc/ktable.c | 13++++++-------
Msrc/ktable.h | 3++-
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);