summaryrefslogtreecommitdiffstats
path: root/struct.c
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-09-04 07:15:34 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-09-04 07:15:34 -0700
commitf81e83b591e18fae2efc27252a6e1717b35ecead (patch)
tree5b0271072ade488fa8267908256b044f5d1bc22e /struct.c
parent51e5d6643fa63478a4ddc1a0ec5570879675ae11 (diff)
downloadtxr-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.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/struct.c b/struct.c
index faaa5aa9..0db801fa 100644
--- a/struct.c
+++ b/struct.c
@@ -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);