diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-02-15 07:11:36 -0800 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-02-15 07:11:36 -0800 |
commit | acb7f1a837a124488a46f0c83876e2d0ca222f24 (patch) | |
tree | 9673646ba83be35df0fa70582186c01928643ce2 /struct.c | |
parent | cf5bf659c31063541471fe50419b86dcb8f68e16 (diff) | |
download | txr-acb7f1a837a124488a46f0c83876e2d0ca222f24.tar.gz txr-acb7f1a837a124488a46f0c83876e2d0ca222f24.tar.bz2 txr-acb7f1a837a124488a46f0c83876e2d0ca222f24.zip |
structs: recycle IDs of dead struct types.
* struct.c (nelem): New macro.
(struct struct_id_recycle): New struct type.
(struct_id_counter): Initialize to 1 instead of zero.
(get_struct_id, recycle_struct_id): New static functions.
(struct_type_finalize): From each slot symbol, remove the
struct type's ID from it slot cache, and finally recycle the
struct type ID.
(make_struct_type): Use get_struct_id to obtain an ID for the
new struct type, rather than directly incrementing the global
counter.
Diffstat (limited to 'struct.c')
-rw-r--r-- | struct.c | 78 |
1 files changed, 71 insertions, 7 deletions
@@ -49,9 +49,11 @@ #include "struct.h" #define max(a, b) ((a) > (b) ? (a) : (b)) +#define nelem(array) (sizeof (array) / sizeof (array)[0]) #define STATIC_SLOT_BASE 0x10000000 + struct stslot { val home_type; cnum home_offs; @@ -88,11 +90,18 @@ struct struct_inst { val slot[1]; }; +struct struct_id_recycle { + struct struct_id_recycle *next; + cnum id[64]; + int fill; +}; + val struct_type_s, meth_s, print_s, make_struct_lit_s; val init_k, postinit_k; val slot_s; -static cnum struct_id_counter; +static cnum struct_id_counter = 1; +static struct struct_id_recycle *struct_id_stack; static val struct_type_hash; static val slot_hash; static val struct_type_finalize_f; @@ -190,15 +199,72 @@ static noreturn void no_such_struct(val ctx, val sym) ctx, sym, nao); } +static val get_struct_id(val self) +{ + struct struct_id_recycle *stk = struct_id_stack; + + if (stk != 0) { + cnum id = stk->id[--stk->fill]; + if (stk->fill == 0) { + struct_id_stack = stk->next; + free(stk); + } + return num_fast(id); + } + + if (struct_id_counter > NUM_MAX) + uw_throwf(error_s, lit("~a: struct ID overflow"), self, nao); + + return num_fast(struct_id_counter++); +} + +static void recycle_struct_id(cnum id) +{ + struct struct_id_recycle *stk = struct_id_stack; + + if (id == struct_id_counter - 1) { + struct_id_counter = id; + return; + } + + if (stk != 0) { + if (stk->fill < nelem (stk->id)) { + stk->id[stk->fill++] = id; + return; + } + } + + { + struct struct_id_recycle *nstk = convert(struct struct_id_recycle *, + chk_calloc(1, sizeof *stk)); + nstk->next = stk; + struct_id_stack = nstk; + recycle_struct_id(id); + } +} + static val struct_type_finalize(val obj) { struct struct_type *st = coerce(struct struct_type *, obj->co.handle); val id = num(st->id); - val slot; + val iter; - for (slot = st->slots; slot; slot = cdr(slot)) - remhash(slot_hash, cons(car(slot), id)); + for (iter = st->slots; iter; iter = cdr(iter)) { + val slot = car(iter); + slot_cache_t slot_cache = slot->s.slot_cache; + int i, j; + remhash(slot_hash, cons(slot, id)); + + for (i = 0; i < SLOT_CACHE_SIZE; i++) + for (j = 0; j < 4; j++) + if (slot_cache[i][j].id == st->id) { + slot_cache[i][j].id = 0; + slot_cache[i][j].slot = 0; + } + } + + recycle_struct_id(st->id); return nil; } @@ -277,16 +343,14 @@ val make_struct_type(val name, val super, } else if (!eql(length(uniq(slots)), length(slots))) { uw_throwf(error_s, lit("~a: slot names must not repeat"), self, nao); - } else if (struct_id_counter == NUM_MAX) { - uw_throwf(error_s, lit("~a: struct ID overflow"), self, nao); } else { + val id = get_struct_id(self); struct struct_type *st = coerce(struct struct_type *, chk_malloc(sizeof *st)); struct struct_type *su = if3(super, stype_handle(&super, self), 0); val super_slots = if2(su, su->slots); val all_slots = uniq(append2(super_slots, append2(static_slots, slots))); val stype = cobj(coerce(mem_t *, st), struct_type_s, &struct_type_ops); - val id = num_fast(++struct_id_counter); val iter; cnum sl, stsl; cnum stsl_upb = c_num(plus(length(static_slots), |