From f92522c7579d28a8ecd02d527483440656376a4b Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Thu, 27 Aug 2020 07:09:14 -0700 Subject: OOP: optimization in dupe base check. Hypothesis: the majority of struct types will not be used as inheritance bases, and most of those that are bases will not be appear as duplicate bases. If we put a flag into a type which indicates that it has been used as a duplicate base, we can check that flag to do less work when initializing an object. * struct.c (struct struct_type): New flag, dupe. (get_duplicate_supers): Each time we find a duplicate supertype, we set its dupe flag. (make_struct_type): Allocate the struct type with chk_calloc instead of chk_malloc, so the flag is initialized to zero. Remove initializations of some members to zero: those of nslots, ntslots, stslot and spslot. (call_initfun_chain, call_postinitfun_chain): Don't bother search for st in the root's array of duplicates if st is not marked with the dupe flag. --- struct.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/struct.c b/struct.c index 5564f3c4..04b5ee7d 100644 --- a/struct.c +++ b/struct.c @@ -91,6 +91,7 @@ struct struct_type { val dvtypes; struct stslot *stslot; struct stslot **spslot; + unsigned dupe : 1; }; struct struct_inst { @@ -335,8 +336,10 @@ static val get_duplicate_supers(val supers, val self) ucnum mask = (ucnum) 1 << pos; if ((mask & bloom) != 0) { - if (memq(super, all_supers) != iter && !memq(super, dup_supers)) + if (memq(super, all_supers) != iter && !memq(super, dup_supers)) { ptail = list_collect(ptail, super); + st->dupe = 1; + } } bloom |= mask; @@ -443,7 +446,7 @@ val make_struct_type(val name, val supers, self, nao); } else { struct struct_type *st = coerce(struct struct_type *, - chk_malloc(sizeof *st)); + chk_calloc(1, sizeof *st)); val dup_supers = if3(opt_compat && opt_compat <= 242, nil, get_duplicate_supers(supers, self)); cnum nsupers = c_num(length(supers), self); @@ -464,12 +467,10 @@ val make_struct_type(val name, val supers, st->self = stype; st->name = name; st->id = c_num(id, self); - st->nslots = st->nstslots = 0; st->slots = all_slots; st->nsupers = nsupers; st->ndsupers = ndsupers; st->supers = supers; - st->stslot = 0; st->sus = sus; st->dsus = dsus; st->stinitfun = static_initfun; @@ -477,7 +478,6 @@ val make_struct_type(val name, val supers, st->boactor = boactor; st->postinitfun = default_null_arg(postinitfun); st->dvtypes = nil; - st->spslot = 0; gc_finalize(stype, struct_type_finalize_f, nil); @@ -676,7 +676,7 @@ static void call_initfun_chain(struct struct_type *st, val strct, if (st) { cnum i; - if (st != root) + if (st != root && st->dupe) for (i = 0; i < root->ndsupers; i++) { if (st == root->dsus[i]) { const int bits_ucnum = sizeof *seen * CHAR_BIT; @@ -703,7 +703,7 @@ static void call_postinitfun_chain(struct struct_type *st, val strct, int derived_first = (opt_compat && opt_compat <= 148); cnum i; - if (st != root) + if (st != root && st->dupe) for (i = 0; i < root->ndsupers; i++) { if (st == root->dsus[i]) { const int bits_ucnum = sizeof *seen * CHAR_BIT; -- cgit v1.2.3