From 98923ae1189f062b8b94120d47a56892db25493f Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Fri, 1 Dec 2017 18:28:16 +0100 Subject: [PATCH] altos/lisp: Split out frame vals from frame struct This lets the frame be resized without moving the base structure. The plan is to allow all frames to be resized, not just the global frame. Signed-off-by: Keith Packard --- src/lisp/ao_lisp.h | 38 +++++-- src/lisp/ao_lisp_error.c | 5 +- src/lisp/ao_lisp_frame.c | 207 +++++++++++++++++++--------------- src/lisp/ao_lisp_make_const.c | 5 +- src/lisp/ao_lisp_mem.c | 42 +++++++ src/lisp/ao_lisp_poly.c | 4 + 6 files changed, 200 insertions(+), 101 deletions(-) diff --git a/src/lisp/ao_lisp.h b/src/lisp/ao_lisp.h index 858212dd..96a7a05f 100644 --- a/src/lisp/ao_lisp.h +++ b/src/lisp/ao_lisp.h @@ -92,12 +92,13 @@ extern uint8_t ao_lisp_pool[AO_LISP_POOL + AO_LISP_POOL_EXTRA] __attribute__((a #define AO_LISP_ATOM 4 #define AO_LISP_BUILTIN 5 #define AO_LISP_FRAME 6 -#define AO_LISP_LAMBDA 7 -#define AO_LISP_STACK 8 -#define AO_LISP_BOOL 9 -#define AO_LISP_BIGINT 10 -#define AO_LISP_FLOAT 11 -#define AO_LISP_NUM_TYPE 12 +#define AO_LISP_FRAME_VALS 7 +#define AO_LISP_LAMBDA 8 +#define AO_LISP_STACK 9 +#define AO_LISP_BOOL 10 +#define AO_LISP_BIGINT 11 +#define AO_LISP_FLOAT 12 +#define AO_LISP_NUM_TYPE 13 /* Leave two bits for types to use as they please */ #define AO_LISP_OTHER_TYPE_MASK 0x3f @@ -154,11 +155,17 @@ struct ao_lisp_val { ao_poly val; }; +struct ao_lisp_frame_vals { + uint8_t type; + uint8_t size; + struct ao_lisp_val vals[]; +}; + struct ao_lisp_frame { uint8_t type; uint8_t num; ao_poly prev; - struct ao_lisp_val vals[]; + ao_poly vals; }; struct ao_lisp_bool { @@ -221,6 +228,16 @@ ao_lisp_frame_poly(struct ao_lisp_frame *frame) { return ao_lisp_poly(frame, AO_LISP_OTHER); } +static inline struct ao_lisp_frame_vals * +ao_lisp_poly_frame_vals(ao_poly poly) { + return ao_lisp_ref(poly); +} + +static inline ao_poly +ao_lisp_frame_vals_poly(struct ao_lisp_frame_vals *vals) { + return ao_lisp_poly(vals, AO_LISP_OTHER); +} + enum eval_state { eval_sexpr, /* Evaluate an sexpr */ eval_val, /* Value computed */ @@ -528,6 +545,12 @@ ao_lisp_stack_fetch(int id) { return ao_lisp_poly_stack(ao_lisp_poly_fetch(id)); } +void +ao_lisp_frame_stash(int id, struct ao_lisp_frame *frame); + +struct ao_lisp_frame * +ao_lisp_frame_fetch(int id); + /* bool */ extern const struct ao_lisp_type ao_lisp_bool_type; @@ -713,6 +736,7 @@ ao_lisp_read_eval_print(void); /* frame */ extern const struct ao_lisp_type ao_lisp_frame_type; +extern const struct ao_lisp_type ao_lisp_frame_vals_type; #define AO_LISP_FRAME_FREE 6 diff --git a/src/lisp/ao_lisp_error.c b/src/lisp/ao_lisp_error.c index d1c9b941..ba135834 100644 --- a/src/lisp/ao_lisp_error.c +++ b/src/lisp/ao_lisp_error.c @@ -57,6 +57,7 @@ ao_lisp_error_frame(int indent, char *name, struct ao_lisp_frame *frame) tabs(indent); printf ("%s{", name); if (frame) { + struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(frame->vals); if (frame->type & AO_LISP_FRAME_PRINT) printf("recurse..."); else { @@ -66,9 +67,9 @@ ao_lisp_error_frame(int indent, char *name, struct ao_lisp_frame *frame) tabs(indent); printf(" "); } - ao_lisp_poly_write(frame->vals[f].atom); + ao_lisp_poly_write(vals->vals[f].atom); printf(" = "); - ao_lisp_poly_write(frame->vals[f].val); + ao_lisp_poly_write(vals->vals[f].val); printf("\n"); } if (frame->prev) diff --git a/src/lisp/ao_lisp_frame.c b/src/lisp/ao_lisp_frame.c index ebdb7757..dd29e079 100644 --- a/src/lisp/ao_lisp_frame.c +++ b/src/lisp/ao_lisp_frame.c @@ -15,37 +15,77 @@ #include "ao_lisp.h" static inline int -frame_num_size(int num) +frame_vals_num_size(int num) { - return sizeof (struct ao_lisp_frame) + num * sizeof (struct ao_lisp_val); + return sizeof (struct ao_lisp_frame_vals) + num * sizeof (struct ao_lisp_val); } +static int +frame_vals_size(void *addr) +{ + struct ao_lisp_frame_vals *vals = addr; + return frame_vals_num_size(vals->size); +} + +static void +frame_vals_mark(void *addr) +{ + struct ao_lisp_frame_vals *vals = addr; + int f; + + for (f = 0; f < vals->size; f++) { + struct ao_lisp_val *v = &vals->vals[f]; + + ao_lisp_poly_mark(v->val, 0); + MDBG_MOVE("frame mark atom %s %d val %d at %d\n", + ao_lisp_poly_atom(v->atom)->name, + MDBG_OFFSET(ao_lisp_ref(v->atom)), + MDBG_OFFSET(ao_lisp_ref(v->val)), f); + } +} + +static void +frame_vals_move(void *addr) +{ + struct ao_lisp_frame_vals *vals = addr; + int f; + + for (f = 0; f < vals->size; f++) { + struct ao_lisp_val *v = &vals->vals[f]; + + ao_lisp_poly_move(&v->atom, 0); + ao_lisp_poly_move(&v->val, 0); + MDBG_MOVE("frame move atom %s %d val %d at %d\n", + ao_lisp_poly_atom(v->atom)->name, + MDBG_OFFSET(ao_lisp_ref(v->atom)), + MDBG_OFFSET(ao_lisp_ref(v->val)), f); + } +} + +const struct ao_lisp_type ao_lisp_frame_vals_type = { + .mark = frame_vals_mark, + .size = frame_vals_size, + .move = frame_vals_move, + .name = "frame_vals" +}; + static int frame_size(void *addr) { - struct ao_lisp_frame *frame = addr; - return frame_num_size(frame->num); + (void) addr; + return sizeof (struct ao_lisp_frame); } static void frame_mark(void *addr) { struct ao_lisp_frame *frame = addr; - int f; for (;;) { MDBG_MOVE("frame mark %d\n", MDBG_OFFSET(frame)); if (!AO_LISP_IS_POOL(frame)) break; - for (f = 0; f < frame->num; f++) { - struct ao_lisp_val *v = &frame->vals[f]; - - ao_lisp_poly_mark(v->val, 0); - MDBG_MOVE("frame mark atom %s %d val %d at %d\n", - ao_lisp_poly_atom(v->atom)->name, - MDBG_OFFSET(ao_lisp_ref(v->atom)), - MDBG_OFFSET(ao_lisp_ref(v->val)), f); - } + ao_lisp_poly_mark(frame->vals, 0); frame = ao_lisp_poly_frame(frame->prev); MDBG_MOVE("frame next %d\n", MDBG_OFFSET(frame)); if (!frame) @@ -59,7 +99,6 @@ static void frame_move(void *addr) { struct ao_lisp_frame *frame = addr; - int f; for (;;) { struct ao_lisp_frame *prev; @@ -68,16 +107,7 @@ frame_move(void *addr) MDBG_MOVE("frame move %d\n", MDBG_OFFSET(frame)); if (!AO_LISP_IS_POOL(frame)) break; - for (f = 0; f < frame->num; f++) { - struct ao_lisp_val *v = &frame->vals[f]; - - ao_lisp_poly_move(&v->atom, 0); - ao_lisp_poly_move(&v->val, 0); - MDBG_MOVE("frame move atom %s %d val %d at %d\n", - ao_lisp_poly_atom(v->atom)->name, - MDBG_OFFSET(ao_lisp_ref(v->atom)), - MDBG_OFFSET(ao_lisp_ref(v->val)), f); - } + ao_lisp_poly_move(&frame->vals, 0); prev = ao_lisp_poly_frame(frame->prev); if (!prev) break; @@ -104,8 +134,9 @@ const struct ao_lisp_type ao_lisp_frame_type = { void ao_lisp_frame_write(ao_poly p) { - struct ao_lisp_frame *frame = ao_lisp_poly_frame(p); - int f; + struct ao_lisp_frame *frame = ao_lisp_poly_frame(p); + struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(frame->vals); + int f; printf ("{"); if (frame) { @@ -116,9 +147,9 @@ ao_lisp_frame_write(ao_poly p) for (f = 0; f < frame->num; f++) { if (f != 0) printf(", "); - ao_lisp_poly_write(frame->vals[f].atom); + ao_lisp_poly_write(vals->vals[f].atom); printf(" = "); - ao_lisp_poly_write(frame->vals[f].val); + ao_lisp_poly_write(vals->vals[f].val); } if (frame->prev) ao_lisp_poly_write(frame->prev); @@ -131,11 +162,13 @@ ao_lisp_frame_write(ao_poly p) static int ao_lisp_frame_find(struct ao_lisp_frame *frame, int top, ao_poly atom) { - int l = 0; - int r = top - 1; + struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(frame->vals); + int l = 0; + int r = top - 1; + while (l <= r) { int m = (l + r) >> 1; - if (frame->vals[m].atom < atom) + if (vals->vals[m].atom < atom) l = m + 1; else r = m - 1; @@ -146,62 +179,57 @@ ao_lisp_frame_find(struct ao_lisp_frame *frame, int top, ao_poly atom) ao_poly * ao_lisp_frame_ref(struct ao_lisp_frame *frame, ao_poly atom) { - int l = ao_lisp_frame_find(frame, frame->num, atom); + struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(frame->vals); + int l = ao_lisp_frame_find(frame, frame->num, atom); if (l >= frame->num) return NULL; - if (frame->vals[l].atom != atom) + if (vals->vals[l].atom != atom) return NULL; - return &frame->vals[l].val; + return &vals->vals[l].val; } -int -ao_lisp_frame_set(struct ao_lisp_frame *frame, ao_poly atom, ao_poly val) -{ - while (frame) { - if (!AO_LISP_IS_CONST(frame)) { - ao_poly *ref = ao_lisp_frame_ref(frame, atom); - if (ref) { - *ref = val; - return 1; - } - } - frame = ao_lisp_poly_frame(frame->prev); - } - return 0; -} +struct ao_lisp_frame *ao_lisp_frame_free_list[AO_LISP_FRAME_FREE]; -ao_poly -ao_lisp_frame_get(struct ao_lisp_frame *frame, ao_poly atom) +static struct ao_lisp_frame_vals * +ao_lisp_frame_vals_new(int num) { - while (frame) { - ao_poly *ref = ao_lisp_frame_ref(frame, atom); - if (ref) - return *ref; - frame = ao_lisp_poly_frame(frame->prev); - } - return AO_LISP_NIL; -} + struct ao_lisp_frame_vals *vals; -struct ao_lisp_frame *ao_lisp_frame_free_list[AO_LISP_FRAME_FREE]; + vals = ao_lisp_alloc(frame_vals_num_size(num)); + if (!vals) + return NULL; + vals->type = AO_LISP_FRAME_VALS; + vals->size = num; + return vals; +} struct ao_lisp_frame * ao_lisp_frame_new(int num) { - struct ao_lisp_frame *frame; + struct ao_lisp_frame *frame; + struct ao_lisp_frame_vals *vals; - if (num < AO_LISP_FRAME_FREE && (frame = ao_lisp_frame_free_list[num])) + if (num < AO_LISP_FRAME_FREE && (frame = ao_lisp_frame_free_list[num])) { ao_lisp_frame_free_list[num] = ao_lisp_poly_frame(frame->prev); - else { - frame = ao_lisp_alloc(frame_num_size(num)); + vals = ao_lisp_poly_frame_vals(frame->vals); + } else { + frame = ao_lisp_alloc(sizeof (struct ao_lisp_frame)); if (!frame) return NULL; + frame->type = AO_LISP_FRAME; + frame->num = 0; + frame->prev = AO_LISP_NIL; + frame->vals = AO_LISP_NIL; + ao_lisp_poly_stash(0, ao_lisp_frame_poly(frame)); + vals = ao_lisp_frame_vals_new(num); + frame = ao_lisp_poly_frame(ao_lisp_poly_fetch(0)); + frame->vals = ao_lisp_frame_vals_poly(vals); } - frame->type = AO_LISP_FRAME; frame->num = num; frame->prev = AO_LISP_NIL; - memset(frame->vals, '\0', num * sizeof (struct ao_lisp_val)); + memset(vals, '\0', vals->size * sizeof (struct ao_lisp_val)); return frame; } @@ -227,47 +255,46 @@ ao_lisp_frame_free(struct ao_lisp_frame *frame) } static struct ao_lisp_frame * -ao_lisp_frame_realloc(struct ao_lisp_frame **frame_ref, int new_num) +ao_lisp_frame_realloc(struct ao_lisp_frame *frame, int new_num) { - struct ao_lisp_frame *frame = *frame_ref; - struct ao_lisp_frame *new; - int copy; + struct ao_lisp_frame_vals *vals; + struct ao_lisp_frame_vals *new_vals; + int copy; if (new_num == frame->num) return frame; - new = ao_lisp_frame_new(new_num); - if (!new) + ao_lisp_frame_stash(0, frame); + new_vals = ao_lisp_frame_vals_new(new_num); + if (!new_vals) return NULL; - /* - * Re-fetch the frame as it may have moved - * during the allocation - */ - frame = *frame_ref; + frame = ao_lisp_frame_fetch(0); + vals = ao_lisp_poly_frame_vals(frame->vals); copy = new_num; if (copy > frame->num) copy = frame->num; - memcpy(new->vals, frame->vals, copy * sizeof (struct ao_lisp_val)); - new->prev = frame->prev; - ao_lisp_frame_free(frame); - return new; + memcpy(new_vals->vals, vals->vals, copy * sizeof (struct ao_lisp_val)); + frame->vals = ao_lisp_frame_vals_poly(new_vals); + frame->num = new_num; + return frame; } void ao_lisp_frame_bind(struct ao_lisp_frame *frame, int num, ao_poly atom, ao_poly val) { - int l = ao_lisp_frame_find(frame, num, atom); + struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(frame->vals); + int l = ao_lisp_frame_find(frame, num, atom); - memmove(&frame->vals[l+1], - &frame->vals[l], + memmove(&vals->vals[l+1], + &vals->vals[l], (num - l) * sizeof (struct ao_lisp_val)); - frame->vals[l].atom = atom; - frame->vals[l].val = val; + vals->vals[l].atom = atom; + vals->vals[l].val = val; } int ao_lisp_frame_add(struct ao_lisp_frame **frame_ref, ao_poly atom, ao_poly val) { - struct ao_lisp_frame *frame = *frame_ref; + struct ao_lisp_frame *frame = *frame_ref; ao_poly *ref = frame ? ao_lisp_frame_ref(frame, atom) : NULL; if (!ref) { @@ -276,14 +303,14 @@ ao_lisp_frame_add(struct ao_lisp_frame **frame_ref, ao_poly atom, ao_poly val) ao_lisp_poly_stash(1, val); if (frame) { f = frame->num; - frame = ao_lisp_frame_realloc(frame_ref, f + 1); + frame = ao_lisp_frame_realloc(frame, f + 1); } else { f = 0; frame = ao_lisp_frame_new(1); + *frame_ref = frame; } if (!frame) return 0; - *frame_ref = frame; atom = ao_lisp_poly_fetch(0); val = ao_lisp_poly_fetch(1); ao_lisp_frame_bind(frame, frame->num - 1, atom, val); diff --git a/src/lisp/ao_lisp_make_const.c b/src/lisp/ao_lisp_make_const.c index f23d34db..f9bb5452 100644 --- a/src/lisp/ao_lisp_make_const.c +++ b/src/lisp/ao_lisp_make_const.c @@ -326,10 +326,11 @@ main(int argc, char **argv) ao_lisp_collect(AO_LISP_COLLECT_FULL); for (f = 0; f < ao_lisp_frame_global->num; f++) { - val = ao_has_macro(ao_lisp_frame_global->vals[f].val); + struct ao_lisp_frame_vals *vals = ao_lisp_poly_frame_vals(ao_lisp_frame_global->vals); + val = ao_has_macro(vals->vals[f].val); if (val != AO_LISP_NIL) { printf("error: function %s contains unresolved macro: ", - ao_lisp_poly_atom(ao_lisp_frame_global->vals[f].atom)->name); + ao_lisp_poly_atom(vals->vals[f].atom)->name); ao_lisp_poly_write(val); printf("\n"); exit(1); diff --git a/src/lisp/ao_lisp_mem.c b/src/lisp/ao_lisp_mem.c index dc0008c4..890eba1b 100644 --- a/src/lisp/ao_lisp_mem.c +++ b/src/lisp/ao_lisp_mem.c @@ -148,6 +148,7 @@ struct ao_lisp_root { static struct ao_lisp_cons *save_cons[2]; static char *save_string[2]; +static struct ao_lisp_frame *save_frame[1]; static ao_poly save_poly[3]; static const struct ao_lisp_root ao_lisp_root[] = { @@ -167,6 +168,10 @@ static const struct ao_lisp_root ao_lisp_root[] = { .type = &ao_lisp_string_type, .addr = (void **) &save_string[1], }, + { + .type = &ao_lisp_frame_type, + .addr = (void **) &save_frame[0], + }, { .type = NULL, .addr = (void **) (void *) &save_poly[0] @@ -455,6 +460,7 @@ static const struct ao_lisp_type *ao_lisp_types[AO_LISP_NUM_TYPE] = { [AO_LISP_ATOM] = &ao_lisp_atom_type, [AO_LISP_BUILTIN] = &ao_lisp_builtin_type, [AO_LISP_FRAME] = &ao_lisp_frame_type, + [AO_LISP_FRAME_VALS] = &ao_lisp_frame_vals_type, [AO_LISP_LAMBDA] = &ao_lisp_lambda_type, [AO_LISP_STACK] = &ao_lisp_stack_type, [AO_LISP_BOOL] = &ao_lisp_bool_type, @@ -620,6 +626,29 @@ ao_lisp_collect(uint8_t style) * Mark interfaces for objects */ + +/* + * Mark a block of memory with an explicit size + */ + +int +ao_lisp_mark_block(void *addr, int size) +{ + int offset; + if (!AO_LISP_IS_POOL(addr)) + return 1; + + offset = pool_offset(addr); + MDBG_MOVE("mark memory %d\n", MDBG_OFFSET(addr)); + if (busy(ao_lisp_busy, offset)) { + MDBG_MOVE("already marked\n"); + return 1; + } + mark(ao_lisp_busy, offset); + note_chunk(offset, size); + return 0; +} + /* * Note a reference to memory and collect information about a few * object sizes at a time @@ -891,3 +920,16 @@ ao_lisp_string_fetch(int id) return string; } +void +ao_lisp_frame_stash(int id, struct ao_lisp_frame *frame) +{ + save_frame[id] = frame; +} + +struct ao_lisp_frame * +ao_lisp_frame_fetch(int id) +{ + struct ao_lisp_frame *frame = save_frame[id]; + save_frame[id] = NULL; + return frame; +} diff --git a/src/lisp/ao_lisp_poly.c b/src/lisp/ao_lisp_poly.c index e93e1192..d14f4151 100644 --- a/src/lisp/ao_lisp_poly.c +++ b/src/lisp/ao_lisp_poly.c @@ -44,6 +44,10 @@ static const struct ao_lisp_funcs ao_lisp_funcs[AO_LISP_NUM_TYPE] = { .write = ao_lisp_frame_write, .display = ao_lisp_frame_write, }, + [AO_LISP_FRAME_VALS] = { + .write = NULL, + .display = NULL, + }, [AO_LISP_LAMBDA] = { .write = ao_lisp_lambda_write, .display = ao_lisp_lambda_write, -- 2.30.2