klisp

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

commit cf7acde64025ee001879f419d0919e8e1d1e4e6d
parent 4455f55f7071a1f9f31690e95ebde743d8cfd850
Author: Andres Navarro <canavarro82@gmail.com>
Date:   Tue, 19 Apr 2011 00:11:51 -0300

Added some code to gc for tables. Still incomplete.

Diffstat:
Msrc/Makefile | 2+-
Msrc/kgc.c | 101+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/kobject.h | 3+++
3 files changed, 59 insertions(+), 47 deletions(-)

diff --git a/src/Makefile b/src/Makefile @@ -145,4 +145,4 @@ kgstrings.o: kgstrings.c kgstrings.h kghelpers.h kstate.h klisp.h \ kobject.h kerror.h kapplicative.h koperative.h kcontinuation.h \ ksymbol.h kgnumbers.h imath.o: kobject.h kstate.h kmem.h kerror.h -kgc.o: kgc.c kgc.h kobject.h kmem.h kstate.h kport.h imath.h +kgc.o: kgc.c kgc.h kobject.h kmem.h kstate.h kport.h imath.h ktable.h diff --git a/src/kgc.c b/src/kgc.c @@ -17,6 +17,7 @@ #include "kmem.h" #include "kport.h" #include "imath.h" +#include "ktable.h" /* XXX */ #include "kwrite.h" @@ -68,14 +69,11 @@ #define setthreshold(g) (g->GCthreshold = (g->estimate/100) * g->gcpause) -/* klisp no need for it yet */ -#if 0 static void removeentry (Node *n) { klisp_assert(ttisnil(gval(n))); - if (iscollectable(gkey(n))) - setttype(gkey(n), LUA_TDEADKEY); /* dead key; remove it */ + if (iscollectable(gkey(n)->this))/* dead key; remove it */ + gkey(n)->this = gc2deadkey(gcvalue(gkey(n)->this)); } -#endif static void reallymarkobject (klisp_State *K, GCObject *o) { @@ -108,6 +106,7 @@ static void reallymarkobject (klisp_State *K, GCObject *o) case K_TENCAPSULATION: case K_TPROMISE: case K_TPORT: + case K_TTABLE: o->gch.gclist = K->gray; K->gray = o; break; @@ -163,48 +162,54 @@ size_t klispC_separateudata (lua_State *L, int all) { return deadmem; } +#endif -static int traversetable (global_State *g, Table *h) { - int i; - int weakkey = 0; - int weakvalue = 0; - const TValue *mode; - if (h->metatable) - markobject(g, h->metatable); - mode = gfasttm(g, h->metatable, TM_MODE); - if (mode && ttisstring(mode)) { /* is there a weak mode? */ - weakkey = (strchr(svalue(mode), 'k') != NULL); - weakvalue = (strchr(svalue(mode), 'v') != NULL); +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 = g->weak; /* must be cleared after GC, ... */ - g->weak = obj2gco(h); /* ... so put in the appropriate list */ + 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; while (i--) - markvalue(g, &h->array[i]); + markvalue(K, h->array[i]); } i = sizenode(h); while (i--) { Node *n = gnode(h, i); - klisp_assert(ttype(gkey(n)) != LUA_TDEADKEY || ttisnil(gval(n))); + klisp_assert(ttype(gkey(n)->this) != K_TDEADKEY || + ttisnil(gval(n))); if (ttisnil(gval(n))) removeentry(n); /* remove empty entries */ else { - klisp_assert(!ttisnil(gkey(n))); - if (!weakkey) markvalue(g, gkey(n)); - if (!weakvalue) markvalue(g, gval(n)); + klisp_assert(!ttisnil(gkey(n)->this)); + if (!weakkey) markvalue(K, gkey(n)->this); + if (!weakvalue) markvalue(K, gval(n)); } } return weakkey || weakvalue; } - +#if 0 /* ** All marks are conditional because a GC may happen while the ** prototype is still being created @@ -242,16 +247,6 @@ static int32_t propagatemark (klisp_State *K) { uint8_t type = o->gch.tt; switch (type) { -#if 0 /* klisp: keep around */ - case LUA_TTABLE: { - Table *h = gco2h(o); - K->gray = h->gclist; - if (traversetable(K, h)) /* table is weak? */ - black2gray(o); /* keep it gray */ - return sizeof(Table) + sizeof(TValue) * h->sizearray + - sizeof(Node) * sizenode(h); - } -#endif /* case K_TBIGINT: bigints are never gray */ case K_TPAIR: { Pair *p = cast(Pair *, o); @@ -326,6 +321,13 @@ static int32_t propagatemark (klisp_State *K) { markvalue(K, p->filename); return sizeof(Port); } + case K_TTABLE: { + Table *h = cast(Table *, o); + if (traversetable(K, h)) /* table is weak? */ + black2gray(o); /* keep it gray */ + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * sizenode(h); + } default: fprintf(stderr, "Unknown GCObject type (in GC propagate): %d\n", type); @@ -340,7 +342,6 @@ static size_t propagateall (klisp_State *K) { return m; } -#if 0 /* klisp: keep around */ /* ** The next function tells whether a key or value can be cleared from ** a weak table. Non-collectable objects are never removed from weak @@ -348,14 +349,19 @@ static size_t propagateall (klisp_State *K) { ** other objects: if really collected, cannot keep them; for userdata ** being finalized, keep them in keys, but not in values */ -static int iscleared (const TValue *o, int iskey) { +static int32_t iscleared (TValue o, int iskey) { if (!iscollectable(o)) return 0; +#if 0 /* klisp: strings may be mutable... */ if (ttisstring(o)) { stringmark(rawtsvalue(o)); /* strings are `values', so are never weak */ return 0; } - return iswhite(gcvalue(o)) || - (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); +#endif + return iswhite(gcvalue(o)); + +/* klisp: keep around for later + || (ttisuserdata(o) && (!iskey && isfinalized(uvalue(o)))); +*/ } @@ -364,15 +370,15 @@ static int iscleared (const TValue *o, int iskey) { */ static void cleartable (GCObject *l) { while (l) { - Table *h = gco2h(l); - int i = h->sizearray; + Table *h = (Table *) (l); + int32_t i = h->sizearray; klisp_assert(testbit(h->gct, VALUEWEAKBIT) || testbit(h->gct, KEYWEAKBIT)); if (testbit(h->gct, VALUEWEAKBIT)) { while (i--) { TValue *o = &h->array[i]; - if (iscleared(o, 0)) /* value was collected? */ - setnilvalue(o); /* remove value */ + if (iscleared(*o, 0)) /* value was collected? */ + *o = KNIL; /* remove value */ } } i = sizenode(h); @@ -380,14 +386,13 @@ static void cleartable (GCObject *l) { Node *n = gnode(h, i); if (!ttisnil(gval(n)) && /* non-empty entry? */ (iscleared(key2tval(n), 1) || iscleared(gval(n), 0))) { - setnilvalue(gval(n)); /* remove value ... */ + gval(n) = KNIL; /* remove value ... */ removeentry(n); /* remove entry from table */ } } l = h->gclist; } } -#endif static void freeobj (klisp_State *K, GCObject *o) { /* TODO use specific functions like in bigint & lua */ @@ -437,6 +442,9 @@ static void freeobj (klisp_State *K, GCObject *o) { kclose_port(K, gc2port(o)); klispM_free(K, (Port *)o); break; + case K_TTABLE: + klispH_free(K, (Table *)o); + break; default: /* shouldn't happen */ fprintf(stderr, "Unknown GCObject type (in GC free): %d\n", @@ -614,8 +622,9 @@ static void atomic (klisp_State *K) { udsize = klispC_separateudata(L, 0); /* separate userdata to be finalized */ marktmu(g); /* mark `preserved' userdata */ udsize += propagateall(g); /* remark, to propagate `preserveness' */ - cleartable(g->weak); /* remove collected objects from weak tables */ #endif + cleartable(K->weak); /* remove collected objects from weak tables */ + /* flip current white */ K->currentwhite = cast(uint16_t, otherwhite(K)); K->sweepgc = &K->rootgc; diff --git a/src/kobject.h b/src/kobject.h @@ -162,6 +162,7 @@ typedef struct __attribute__ ((__packed__)) GCheader { #define K_TPORT 39 #define K_TTABLE 40 +/* for tables */ #define K_TDEADKEY 60 /* this is used to test for numbers, as returned by ttype */ @@ -190,6 +191,7 @@ typedef struct __attribute__ ((__packed__)) GCheader { #define K_TAG_EOF K_MAKE_VTAG(K_TEOF) #define K_TAG_BOOLEAN K_MAKE_VTAG(K_TBOOLEAN) #define K_TAG_CHAR K_MAKE_VTAG(K_TCHAR) +#define K_TAG_DEADKEY K_MAKE_VTAG(K_TDEADKEY) #define K_TAG_USER K_MAKE_VTAG(K_TUSER) @@ -557,6 +559,7 @@ const TValue knewline; #define gc2prom(o_) (gc2tv(K_TAG_PROMISE, o_)) #define gc2port(o_) (gc2tv(K_TAG_PORT, o_)) #define gc2table(o_) (gc2tv(K_TAG_TABLE, o_)) +#define gc2deadkey(o_) (gc2tv(K_TAG_DEADKEY, o_)) /* Macro to convert a TValue into a specific heap allocated object */ #define tv2bigint(v_) ((Bigint *) gcvalue(v_))