use khash for registers

This commit is contained in:
Yuichi Nishiwaki 2015-06-25 07:14:29 +09:00
parent 0fb87449fc
commit 11ed51b236
3 changed files with 41 additions and 21 deletions

View File

@ -622,16 +622,20 @@ gc_mark_phase(pic_state *pic)
do {
struct pic_object *key;
pic_value val;
xh_entry *it;
khiter_t it;
khash_t(reg) *h;
struct pic_reg *reg;
j = 0;
reg = pic->regs;
while (reg != NULL) {
for (it = xh_begin(&reg->hash); it != NULL; it = xh_next(it)) {
key = xh_key(it, struct pic_object *);
val = xh_val(it, pic_value);
h = &reg->hash;
for (it = kh_begin(h); it != kh_end(h); ++it) {
if (! kh_exist(h, it))
continue;
key = kh_key(h, it);
val = kh_val(h, it);
if (gc_obj_is_marked(key) && gc_value_need_mark(val)) {
gc_mark(pic, val);
++j;
@ -718,7 +722,7 @@ gc_finalize_object(pic_state *pic, struct pic_object *obj)
}
case PIC_TT_REG: {
struct pic_reg *reg = (struct pic_reg *)obj;
xh_destroy(&reg->hash);
kh_destroy(reg, &reg->hash);
break;
}
case PIC_TT_CP: {
@ -813,14 +817,17 @@ static void
gc_sweep_phase(pic_state *pic)
{
struct heap_page *page = pic->heap->pages;
xh_entry *it, *next;
khiter_t it;
khash_t(reg) *h;
/* registries */
while (pic->regs != NULL) {
for (it = xh_begin(&pic->regs->hash); it != NULL; it = next) {
next = xh_next(it);
if (! gc_obj_is_marked(xh_key(it, struct pic_object *))) {
xh_del_ptr(&pic->regs->hash, xh_key(it, struct pic_object *));
h = &pic->regs->hash;
for (it = kh_begin(h); it != kh_end(h); ++it) {
if (! kh_exist(h, it))
continue;
if (! gc_obj_is_marked(kh_key(h, it))) {
kh_del(reg, h, it);
}
}
pic->regs = pic->regs->prev;

View File

@ -9,9 +9,11 @@
extern "C" {
#endif
KHASH_DECLARE(reg, void *, pic_value)
struct pic_reg {
PIC_OBJECT_HEADER
xhash hash;
khash_t(reg) hash;
struct pic_reg *prev; /* for GC */
};

View File

@ -4,6 +4,8 @@
#include "picrin.h"
KHASH_DEFINE(reg, void *, pic_value, kh_ptr_hash_func, kh_ptr_hash_equal)
struct pic_reg *
pic_make_reg(pic_state *pic)
{
@ -11,7 +13,7 @@ pic_make_reg(pic_state *pic)
reg = (struct pic_reg *)pic_obj_alloc(pic, sizeof(struct pic_reg), PIC_TT_REG);
reg->prev = NULL;
xh_init_ptr(&reg->hash, sizeof(pic_value));
kh_init(reg, &reg->hash);
return reg;
}
@ -19,35 +21,44 @@ pic_make_reg(pic_state *pic)
pic_value
pic_reg_ref(pic_state *pic, struct pic_reg *reg, void *key)
{
xh_entry *e;
khash_t(reg) *h = &reg->hash;
khiter_t it;
e = xh_get_ptr(&reg->hash, key);
if (! e) {
it = kh_get(reg, h, key);
if (it == kh_end(h)) {
pic_errorf(pic, "element not found for a key: ~s", pic_obj_value(key));
}
return xh_val(e, pic_value);
return kh_val(h, it);
}
void
pic_reg_set(pic_state PIC_UNUSED(*pic), struct pic_reg *reg, void *key, pic_value val)
{
xh_put_ptr(&reg->hash, key, &val);
khash_t(reg) *h = &reg->hash;
int ret;
khiter_t it;
it = kh_put(reg, h, key, &ret);
kh_val(h, it) = val;
}
bool
pic_reg_has(pic_state PIC_UNUSED(*pic), struct pic_reg *reg, void *key)
{
return xh_get_ptr(&reg->hash, key) != NULL;
return kh_get(reg, &reg->hash, key) != kh_end(&reg->hash);
}
void
pic_reg_del(pic_state *pic, struct pic_reg *reg, void *key)
{
if (xh_get_ptr(&reg->hash, key) == NULL) {
khash_t(reg) *h = &reg->hash;
khiter_t it;
it = kh_get(reg, h, key);
if (it == kh_end(h)) {
pic_errorf(pic, "no slot named ~s found in register", pic_obj_value(key));
}
xh_del_ptr(&reg->hash, key);
kh_del(reg, h, it);
}