summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2019-09-04 21:37:48 -0700
committerKaz Kylheku <kaz@kylheku.com>2019-09-04 21:37:48 -0700
commit1f47e0a98f45ac2e60e2e23d827fd2f8da6b4962 (patch)
tree3bccf1dddb9f762ef5375c5da7da47e4aa4be786
parent7c996aaf65a2e77281177bb8132b675e8bba133d (diff)
downloadtxr-1f47e0a98f45ac2e60e2e23d827fd2f8da6b4962.tar.gz
txr-1f47e0a98f45ac2e60e2e23d827fd2f8da6b4962.tar.bz2
txr-1f47e0a98f45ac2e60e2e23d827fd2f8da6b4962.zip
structs: lazily allocate special slots array.
A type which we never ask for a special slot need not waste space the array. * struct.c (struct struct_type): Change spslot from array to pointer. (make_struct_type): Initialize spslot pointer to zero. (struct_type_destroy): Free the dynamic array. (invalidate_special_slot_nonexistence): Do nothing if the spslot pointer is null. (get_special_static_slot): Dynamically allocate the array if the spslot pointer is null, and update that pointer, before doing anything else. The parameter signature changes; instead of a pointer to an element of the stslot array, we pass the index. (get_equal_method): Pass the index of the equal method special slot, rather than the address of the array entry.
-rw-r--r--struct.c53
1 files changed, 30 insertions, 23 deletions
diff --git a/struct.c b/struct.c
index 0db801fa..232b2060 100644
--- a/struct.c
+++ b/struct.c
@@ -83,7 +83,6 @@ struct struct_type {
cnum id;
cnum nslots;
cnum nstslots;
- struct stslot *spslot[num_special_slots];
val super;
struct struct_type *super_handle;
val slots;
@@ -93,6 +92,7 @@ struct struct_type {
val postinitfun;
val dvtypes;
struct stslot *stslot;
+ struct stslot **spslot;
};
struct struct_inst {
@@ -321,7 +321,6 @@ 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;
@@ -336,9 +335,7 @@ val make_struct_type(val name, val super,
st->boactor = boactor;
st->postinitfun = default_null_arg(postinitfun);
st->dvtypes = nil;
-
- for (i = 0; i < num_special_slots; i++)
- st->spslot[i] = 0;
+ st->spslot = 0;
gc_finalize(stype, struct_type_finalize_f, nil);
@@ -482,6 +479,7 @@ static void struct_type_destroy(val obj)
{
struct struct_type *st = coerce(struct struct_type *, obj->co.handle);
free(st->stslot);
+ free(st->spslot);
free(st);
}
@@ -1095,10 +1093,12 @@ val static_slot(val stype, val 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;
+ if (st->spslot != 0) {
+ int i;
+ for (i = 0; i < num_special_slots; i++) {
+ if (st->spslot[i] == coerce(struct stslot *, -1))
+ st->spslot[i] = 0;
+ }
}
}
@@ -1601,27 +1601,34 @@ static ucnum struct_inst_hash(val obj, int *count, ucnum seed)
}
static val get_special_static_slot(struct struct_type *st,
- struct stslot **pstsl, val stslot)
+ enum special_slot idx, val stslot)
{
- if (*pstsl == coerce(struct stslot *, -1)) {
- return nil;
- } else if (*pstsl) {
- struct stslot *stsl = *pstsl;
- return stslot_place(stsl);
- } else {
- struct stslot *stsl = lookup_static_slot_desc(st, stslot);
- if (stsl != 0) {
- *pstsl = stsl;
- return stslot_place(stsl);
+ if (st->spslot == 0)
+ st->spslot = coerce(struct stslot **,
+ chk_calloc(num_special_slots, sizeof *st->spslot));
+
+ {
+ struct stslot *spsl = st->spslot[idx];
+
+ if (spsl == coerce(struct stslot *, -1)) {
+ return nil;
+ } else if (spsl) {
+ return stslot_place(spsl);
+ } else {
+ struct stslot *stsl = lookup_static_slot_desc(st, stslot);
+ if (stsl != 0) {
+ st->spslot[idx] = stsl;
+ return stslot_place(stsl);
+ }
+ st->spslot[idx] = coerce(struct stslot *, -1);
+ return nil;
}
- *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);
+ return get_special_static_slot(st, equal_meth, equal_s);
}
static val struct_inst_equalsub(val obj)