diff options
author | Kaz Kylheku <kaz@kylheku.com> | 2019-09-04 07:15:34 -0700 |
---|---|---|
committer | Kaz Kylheku <kaz@kylheku.com> | 2019-09-04 07:15:34 -0700 |
commit | f81e83b591e18fae2efc27252a6e1717b35ecead (patch) | |
tree | 5b0271072ade488fa8267908256b044f5d1bc22e /struct.c | |
parent | 51e5d6643fa63478a4ddc1a0ec5570879675ae11 (diff) | |
download | txr-f81e83b591e18fae2efc27252a6e1717b35ecead.tar.gz txr-f81e83b591e18fae2efc27252a6e1717b35ecead.tar.bz2 txr-f81e83b591e18fae2efc27252a6e1717b35ecead.zip |
structs: special slot generalization.
This lays the groundwork for optimizing access to more special
slots. Currently the equal method is handled specially; if a
type has an equal method, then this is cached for fast access,
so we are not doing a slot lookup each time the method needs
to be called. We would like a small array of such methods,
with minimal code duplication.
* struct.c (enum special_slot): New enum.
(struct struct_type): Scalar member eqmslot replaced by
spslot array.
(make_struct_type): Initialize elements of new array to null;
don't initialize removed eqmslot member.
(invalidate_special_slot_nonexistence): New static function.
(static_slot_set, static_slot_ens_rec): Use
invalidate_special_slot_nonexistence instead of open code.
(get_static_special_slot): General function for obtaining and
caching a special slot. Based on implementation of
get_equal_method.
(get_equal_method): Rewritten as a simple call to
get_special-static_slot.
Diffstat (limited to 'struct.c')
-rw-r--r-- | struct.c | 47 |
1 files changed, 34 insertions, 13 deletions
@@ -72,13 +72,18 @@ struct stslot { #define stslot_loc(s) mkloc(*(s)->home, (s)->home_type) #define stslot_place(s) (*(s)->home) +enum special_slot { + equal_meth, + num_special_slots +}; + struct struct_type { val self; val name; cnum id; cnum nslots; cnum nstslots; - struct stslot *eqmslot; + struct stslot *spslot[num_special_slots]; val super; struct struct_type *super_handle; val slots; @@ -316,12 +321,12 @@ val make_struct_type(val name, val super, val iter; cnum sl, stsl; struct stslot null_ptr = { nil, 0, 0, nil }; + int i; st->self = stype; st->name = name; st->id = c_num(id); st->nslots = st->nstslots = 0; - st->eqmslot = 0; st->slots = all_slots; st->super = super; st->stslot = 0; @@ -332,6 +337,9 @@ val make_struct_type(val name, val super, st->postinitfun = default_null_arg(postinitfun); st->dvtypes = nil; + for (i = 0; i < num_special_slots; i++) + st->spslot[i] = 0; + gc_finalize(stype, struct_type_finalize_f, nil); st->stslot = coerce(struct stslot *, @@ -1085,6 +1093,15 @@ val static_slot(val stype, val sym) no_such_static_slot(self, stype, sym); } +static void invalidate_special_slot_nonexistence(struct struct_type *st) +{ + int i; + for (i = 0; i < num_special_slots; i++) { + if (st->spslot[i] == coerce(struct stslot *, -1)) + st->spslot[i] = 0; + } +} + val static_slot_set(val stype, val sym, val newval) { val self = lit("static-slot-set"); @@ -1093,8 +1110,7 @@ val static_slot_set(val stype, val sym, val newval) if (symbolp(sym)) { loc ptr = lookup_static_slot(st, sym); if (!nullocp(ptr)) { - if (st->eqmslot == coerce(struct stslot *, -1)) - st->eqmslot = 0; + invalidate_special_slot_nonexistence(st); return set(ptr, newval); } } @@ -1180,8 +1196,7 @@ static val static_slot_ens_rec(val stype, val sym, val newval, no_error_p = default_null_arg(no_error_p); - if (st->eqmslot == coerce(struct stslot *, -1)) - st->eqmslot = 0; + invalidate_special_slot_nonexistence(st); if (stsl != 0 && opt_compat && opt_compat <= 151) { set(stslot_loc(stsl), newval); @@ -1585,24 +1600,30 @@ static ucnum struct_inst_hash(val obj, int *count, ucnum seed) return out; } -static val get_equal_method(struct struct_type *st) +static val get_special_static_slot(struct struct_type *st, + struct stslot **pstsl, val stslot) { - if (st->eqmslot == coerce(struct stslot *, -1)) { + if (*pstsl == coerce(struct stslot *, -1)) { return nil; - } else if (st->eqmslot) { - struct stslot *stsl = st->eqmslot; + } else if (*pstsl) { + struct stslot *stsl = *pstsl; return stslot_place(stsl); } else { - struct stslot *stsl = lookup_static_slot_desc(st, equal_s); + struct stslot *stsl = lookup_static_slot_desc(st, stslot); if (stsl != 0) { - st->eqmslot = stsl; + *pstsl = stsl; return stslot_place(stsl); } - st->eqmslot = coerce(struct stslot *, -1); + *pstsl = coerce(struct stslot *, -1); return nil; } } +static val get_equal_method(struct struct_type *st) +{ + return get_special_static_slot(st, &st->spslot[equal_meth], equal_s); +} + static val struct_inst_equalsub(val obj) { struct struct_inst *si = coerce(struct struct_inst *, obj->co.handle); |