X-Git-Url: https://git.gag.com/?a=blobdiff_plain;ds=sidebyside;f=src%2Fscheme%2Fao_scheme_mem.c;h=94cbdfc1edb33852ce00ee5c6d1292d4975c0caf;hb=16061947d4376b41e596d87f97ec53ec29d17644;hp=e7e89b89490ea902b81f23e92bebb987beefd305;hpb=32f6877288ea6b7eb1cae9a42fbe8e2c5dbb2f08;p=fw%2Faltos diff --git a/src/scheme/ao_scheme_mem.c b/src/scheme/ao_scheme_mem.c index e7e89b89..94cbdfc1 100644 --- a/src/scheme/ao_scheme_mem.c +++ b/src/scheme/ao_scheme_mem.c @@ -71,11 +71,17 @@ _ao_scheme_reset_stack(char *x) #define ao_scheme_reset_stack() #endif +#if DBG_MEM +#define DBG_MEM_RECORD 1 +#endif + #if DBG_MEM int dbg_move_depth; int dbg_mem = DBG_MEM_START; int dbg_validate = 0; +#endif +#if DBG_MEM_RECORD struct ao_scheme_record { struct ao_scheme_record *next; const struct ao_scheme_type *type; @@ -129,9 +135,9 @@ ao_scheme_record_save(void) } static void -ao_scheme_record_compare(char *where, - struct ao_scheme_record *a, - struct ao_scheme_record *b) +ao_scheme_record_compare(const char *where, + struct ao_scheme_record *a, + struct ao_scheme_record *b) { while (a && b) { if (a->type != b->type || a->size != b->size) { @@ -168,6 +174,7 @@ ao_scheme_record_compare(char *where, #else #define ao_scheme_record_reset() +#define ao_scheme_record(t,a,s) #endif uint8_t ao_scheme_exception; @@ -177,47 +184,34 @@ struct ao_scheme_root { void **addr; }; -static struct ao_scheme_cons *save_cons[2]; -static struct ao_scheme_string *save_string[2]; -static struct ao_scheme_frame *save_frame[1]; -static ao_poly save_poly[3]; +#define AO_SCHEME_NUM_STASH 6 +static ao_poly stash_poly[AO_SCHEME_NUM_STASH]; +static int stash_poly_ptr; static const struct ao_scheme_root ao_scheme_root[] = { { - .type = &ao_scheme_cons_type, - .addr = (void **) &save_cons[0], - }, - { - .type = &ao_scheme_cons_type, - .addr = (void **) &save_cons[1], - }, - { - .type = &ao_scheme_string_type, - .addr = (void **) &save_string[0], - }, - { - .type = &ao_scheme_string_type, - .addr = (void **) &save_string[1], + .type = NULL, + .addr = (void **) (void *) &stash_poly[0] }, { - .type = &ao_scheme_frame_type, - .addr = (void **) &save_frame[0], + .type = NULL, + .addr = (void **) (void *) &stash_poly[1] }, { .type = NULL, - .addr = (void **) (void *) &save_poly[0] + .addr = (void **) (void *) &stash_poly[2] }, { .type = NULL, - .addr = (void **) (void *) &save_poly[1] + .addr = (void **) (void *) &stash_poly[3] }, { .type = NULL, - .addr = (void **) (void *) &save_poly[2] + .addr = (void **) (void *) &stash_poly[4] }, { - .type = &ao_scheme_atom_type, - .addr = (void **) &ao_scheme_atoms + .type = NULL, + .addr = (void **) (void *) &stash_poly[5] }, { .type = &ao_scheme_frame_type, @@ -247,6 +241,20 @@ static const struct ao_scheme_root ao_scheme_root[] = { .type = &ao_scheme_cons_type, .addr = (void **) &ao_scheme_read_stack, }, +#ifdef AO_SCHEME_FEATURE_PORT + { + .type = NULL, + .addr = (void **) (void *) &ao_scheme_stdin, + }, + { + .type = NULL, + .addr = (void **) (void *) &ao_scheme_stdout, + }, + { + .type = NULL, + .addr = (void **) (void *) &ao_scheme_stderr, + }, +#endif #ifdef AO_SCHEME_MAKE_CONST { .type = &ao_scheme_bool_type, @@ -280,6 +288,10 @@ static const void ** const ao_scheme_cache[] = { #define AO_SCHEME_BUSY_SIZE ((AO_SCHEME_POOL + 31) / 32) +static int ao_scheme_printing, ao_scheme_print_cleared; +#if DBG_MEM +static int ao_scheme_collecting; +#endif static uint8_t ao_scheme_busy[AO_SCHEME_BUSY_SIZE]; static uint8_t ao_scheme_cons_note[AO_SCHEME_BUSY_SIZE]; static uint8_t ao_scheme_cons_last[AO_SCHEME_BUSY_SIZE]; @@ -295,14 +307,14 @@ struct ao_scheme_chunk { }; }; -#define AO_SCHEME_NCHUNK 64 +#define AO_SCHEME_NCHUNK (AO_SCHEME_POOL / 64) static struct ao_scheme_chunk ao_scheme_chunk[AO_SCHEME_NCHUNK]; /* Offset of an address within the pool. */ static inline uint16_t pool_offset(void *addr) { #if DBG_MEM - if (!AO_SCHEME_IS_POOL(addr)) + if (!ao_scheme_is_pool_addr(addr)) ao_scheme_abort(); #endif return ((uint8_t *) addr) - ao_scheme_pool; @@ -386,6 +398,9 @@ note_chunk(uint16_t offset, uint16_t size) /* Off the left side */ if (l == 0 && chunk_last && offset > ao_scheme_chunk[0].old_offset) ao_scheme_abort(); + + if (l < chunk_last && ao_scheme_chunk[l].old_offset == offset) + ao_scheme_abort(); #endif /* Shuffle existing entries right */ @@ -465,26 +480,46 @@ static void dump_busy(void) { int i; - MDBG_MOVE("busy:"); + printf("busy:"); for (i = 0; i < ao_scheme_top; i += 4) { if ((i & 0xff) == 0) { - MDBG_MORE("\n"); - MDBG_MOVE("%s", ""); + printf("\n\t"); } else if ((i & 0x1f) == 0) - MDBG_MORE(" "); + printf(" "); if (busy(ao_scheme_busy, i)) - MDBG_MORE("*"); + printf("*"); else - MDBG_MORE("-"); + printf("-"); } - MDBG_MORE ("\n"); + printf ("\n"); } #define DUMP_BUSY() dump_busy() #else #define DUMP_BUSY() #endif +#if MDBG_DUMP +static void +dump_atoms(int show_marked) +{ + struct ao_scheme_atom *atom; + + printf("atoms {\n"); + for (atom = ao_scheme_atoms; atom; atom = ao_scheme_poly_atom(atom->next)) { + printf("\t%d: %s", MDBG_OFFSET(atom), atom->name); + if (show_marked) + printf(" %s", ao_scheme_marked(atom) ? "referenced" : "unreferenced"); + printf("\n"); + } + printf("}\n"); + +} +#define DUMP_ATOMS(a) dump_atoms(a) +#else +#define DUMP_ATOMS(a) +#endif + static const struct ao_scheme_type * const ao_scheme_types[AO_SCHEME_NUM_TYPE] = { [AO_SCHEME_CONS] = &ao_scheme_cons_type, [AO_SCHEME_INT] = NULL, @@ -506,6 +541,9 @@ static const struct ao_scheme_type * const ao_scheme_types[AO_SCHEME_NUM_TYPE] = #ifdef AO_SCHEME_FEATURE_VECTOR [AO_SCHEME_VECTOR] = &ao_scheme_vector_type, #endif +#ifdef AO_SCHEME_FEATURE_PORT + [AO_SCHEME_PORT] = &ao_scheme_port_type, +#endif }; static int @@ -544,12 +582,13 @@ ao_scheme_collect(uint8_t style) #if DBG_MEM_STATS int loops = 0; #endif -#if DBG_MEM +#if DBG_MEM_RECORD struct ao_scheme_record *mark_record = NULL, *move_record = NULL; - - MDBG_MOVE("collect %d\n", ao_scheme_collects[style]); #endif - MDBG_DO(ao_scheme_frame_write(ao_scheme_frame_poly(ao_scheme_frame_global))); + MDBG_MOVE("collect %lu\n", ao_scheme_collects[style]); + + MDBG_DO(ao_scheme_frame_write(stdout, ao_scheme_frame_poly(ao_scheme_frame_global), true)); + MDBG_DO(++ao_scheme_collecting); ao_scheme_reset_stack(); @@ -574,27 +613,29 @@ ao_scheme_collect(uint8_t style) chunk_low = top = ao_scheme_last_top; } for (;;) { -#if DBG_MEM_STATS - loops++; -#endif MDBG_MOVE("move chunks from %d to %d\n", chunk_low, top); /* Find the sizes of the first chunk of objects to move */ reset_chunks(); walk(ao_scheme_mark_ref, ao_scheme_poly_mark_ref); -#if DBG_MEM +#ifdef AO_SCHEME_FEATURE_PORT + ao_scheme_port_check_references(); +#endif + ao_scheme_atom_check_references(); + +#if DBG_MEM_RECORD ao_scheme_record_free(mark_record); mark_record = ao_scheme_record_save(); if (mark_record && move_record) ao_scheme_record_compare("mark", move_record, mark_record); #endif + DUMP_ATOMS(1); DUMP_BUSY(); /* Find the first moving object */ for (i = 0; i < chunk_last; i++) { uint16_t size = ao_scheme_chunk[i].size; - #if DBG_MEM if (!size) ao_scheme_abort(); @@ -613,6 +654,20 @@ ao_scheme_collect(uint8_t style) top += size; } + /* Short-circuit the rest of the loop when all of the + * found objects aren't moving. This isn't strictly + * necessary as the rest of the loop is structured to + * work in this case, but GCC 7.2.0 with optimization + * greater than 2 generates incorrect code for this... + */ + if (i == AO_SCHEME_NCHUNK) { + chunk_low = chunk_high; +#if DBG_MEM_STATS + loops++; +#endif + continue; + } + /* * Limit amount of chunk array used in mapping moves * to the active region @@ -645,15 +700,26 @@ ao_scheme_collect(uint8_t style) if (chunk_first < chunk_last) { /* Relocate all references to the objects */ walk(ao_scheme_move, ao_scheme_poly_move); + ao_scheme_atom_move(); +#ifdef AO_SCHEME_FEATURE_PORT + /* the set of open ports gets relocated but not marked, so + * just deal with it separately + */ + ao_scheme_poly_move(&ao_scheme_open_ports, 0); +#endif -#if DBG_MEM +#if DBG_MEM_RECORD ao_scheme_record_free(move_record); move_record = ao_scheme_record_save(); if (mark_record && move_record) ao_scheme_record_compare("move", mark_record, move_record); #endif + DUMP_ATOMS(0); } +#if DBG_MEM_STATS + loops++; +#endif /* If we ran into the end of the heap, then * there's no need to keep walking */ @@ -681,6 +747,7 @@ ao_scheme_collect(uint8_t style) #if DBG_MEM_STACK fprintf(stderr, "max collect stack depth %lu\n", mem_collect_max_depth); #endif + MDBG_DO(--ao_scheme_collecting); return AO_SCHEME_POOL - ao_scheme_top; } @@ -695,7 +762,7 @@ ao_scheme_cons_check(struct ao_scheme_cons *cons) reset_chunks(); walk(ao_scheme_mark_ref, ao_scheme_poly_mark_ref); while (cons) { - if (!AO_SCHEME_IS_POOL(cons)) + if (!ao_scheme_is_pool_addr(cons)) break; offset = pool_offset(cons); if (busy(ao_scheme_busy, offset)) { @@ -724,7 +791,7 @@ int ao_scheme_mark_memory(const struct ao_scheme_type *type, void *addr) { int offset; - if (!AO_SCHEME_IS_POOL(addr)) + if (!ao_scheme_is_pool_addr(addr)) return 1; offset = pool_offset(addr); @@ -745,7 +812,7 @@ static int ao_scheme_mark(const struct ao_scheme_type *type, void *addr) { int ret; - MDBG_MOVE("mark %d\n", MDBG_OFFSET(addr)); + MDBG_MOVE("mark offset %d\n", MDBG_OFFSET(addr)); MDBG_MOVE_IN(); ret = ao_scheme_mark_memory(type, addr); if (!ret) { @@ -776,7 +843,7 @@ ao_scheme_poly_mark(ao_poly p, uint8_t do_note_cons) return 1; addr = ao_scheme_ref(p); - if (!AO_SCHEME_IS_POOL(addr)) + if (!ao_scheme_is_pool_addr(addr)) return 1; if (type == AO_SCHEME_CONS && do_note_cons) { @@ -794,7 +861,7 @@ ao_scheme_poly_mark(ao_poly p, uint8_t do_note_cons) ao_scheme_abort(); #endif - MDBG_MOVE("mark %d\n", MDBG_OFFSET(addr)); + MDBG_MOVE("poly_mark offset %d\n", MDBG_OFFSET(addr)); MDBG_MOVE_IN(); ret = ao_scheme_mark_memory(lisp_type, addr); if (!ret) { @@ -836,7 +903,7 @@ ao_scheme_move_memory(const struct ao_scheme_type *type, void **ref) void *addr = *ref; uint16_t offset, orig_offset; - if (!AO_SCHEME_IS_POOL(addr)) + if (!ao_scheme_is_pool_addr(addr)) return 1; (void) type; @@ -846,7 +913,7 @@ ao_scheme_move_memory(const struct ao_scheme_type *type, void **ref) offset = move_map(orig_offset); if (offset != orig_offset) { MDBG_MOVE("update ref %d %d -> %d\n", - AO_SCHEME_IS_POOL(ref) ? MDBG_OFFSET(ref) : -1, + ao_scheme_is_pool_addr(ref) ? MDBG_OFFSET(ref) : -1, orig_offset, offset); *ref = ao_scheme_pool + offset; } @@ -855,7 +922,7 @@ ao_scheme_move_memory(const struct ao_scheme_type *type, void **ref) return 1; } mark(ao_scheme_busy, offset); - MDBG_DO(ao_scheme_record(type, addr, ao_scheme_size(type, addr))); + ao_scheme_record(type, addr, ao_scheme_size(type, addr)); return 0; } @@ -886,7 +953,7 @@ ao_scheme_poly_move(ao_poly *ref, uint8_t do_note_cons) return 1; addr = ao_scheme_ref(p); - if (!AO_SCHEME_IS_POOL(addr)) + if (!ao_scheme_is_pool_addr(addr)) return 1; orig_offset = pool_offset(addr); @@ -922,14 +989,22 @@ ao_scheme_poly_move(ao_poly *ref, uint8_t do_note_cons) if (offset != orig_offset) { ao_poly np = ao_scheme_poly(ao_scheme_pool + offset, ao_scheme_poly_base_type(p)); MDBG_MOVE("poly %d moved %d -> %d\n", - type, orig_offset, offset); + ao_scheme_poly_type(np), orig_offset, offset); *ref = np; } return ret; } +int +ao_scheme_marked(void *addr) +{ + if (!ao_scheme_is_pool_addr(addr)) + return 1; + return busy(ao_scheme_busy, pool_offset(addr)); +} + #if DBG_MEM -void +static void ao_scheme_validate(void) { chunk_low = 0; @@ -963,61 +1038,80 @@ ao_scheme_alloc(int size) } void -ao_scheme_cons_stash(int id, struct ao_scheme_cons *cons) +ao_scheme_poly_stash(ao_poly p) { - assert(save_cons[id] == 0); - save_cons[id] = cons; + assert(stash_poly_ptr < AO_SCHEME_NUM_STASH); + stash_poly[stash_poly_ptr++] = p; } -struct ao_scheme_cons * -ao_scheme_cons_fetch(int id) +ao_poly +ao_scheme_poly_fetch(void) { - struct ao_scheme_cons *cons = save_cons[id]; - save_cons[id] = NULL; - return cons; -} + ao_poly p; -void -ao_scheme_poly_stash(int id, ao_poly poly) -{ - assert(save_poly[id] == AO_SCHEME_NIL); - save_poly[id] = poly; + assert (stash_poly_ptr > 0); + p = stash_poly[--stash_poly_ptr]; + stash_poly[stash_poly_ptr] = AO_SCHEME_NIL; + return p; } -ao_poly -ao_scheme_poly_fetch(int id) +int +ao_scheme_print_mark_addr(void *addr) { - ao_poly poly = save_poly[id]; - save_poly[id] = AO_SCHEME_NIL; - return poly; + int offset; + +#if DBG_MEM + if (ao_scheme_collecting) + ao_scheme_abort(); +#endif + + if (!ao_scheme_is_pool_addr(addr)) + return 0; + + if (!ao_scheme_print_cleared) { + ao_scheme_print_cleared = 1; + memset(ao_scheme_busy, '\0', sizeof (ao_scheme_busy)); + } + offset = pool_offset(addr); + if (busy(ao_scheme_busy, offset)) + return 1; + mark(ao_scheme_busy, offset); + return 0; } void -ao_scheme_string_stash(int id, struct ao_scheme_string *string) +ao_scheme_print_clear_addr(void *addr) { - assert(save_string[id] == NULL); - save_string[id] = string; -} + int offset; -struct ao_scheme_string * -ao_scheme_string_fetch(int id) -{ - struct ao_scheme_string *string = save_string[id]; - save_string[id] = NULL; - return string; +#if DBG_MEM + if (ao_scheme_collecting) + ao_scheme_abort(); +#endif + + if (!ao_scheme_is_pool_addr(addr)) + return; + + if (!ao_scheme_print_cleared) + return; + offset = pool_offset(addr); + clear(ao_scheme_busy, offset); } +/* Notes that printing has started */ void -ao_scheme_frame_stash(int id, struct ao_scheme_frame *frame) +ao_scheme_print_start(void) { - assert(save_frame[id] == NULL); - save_frame[id] = frame; + ao_scheme_printing++; } -struct ao_scheme_frame * -ao_scheme_frame_fetch(int id) +/* Notes that printing has ended. Returns 1 if printing is still going on */ +int +ao_scheme_print_stop(void) { - struct ao_scheme_frame *frame = save_frame[id]; - save_frame[id] = NULL; - return frame; + ao_scheme_printing--; + if (ao_scheme_printing != 0) + return 1; + ao_scheme_print_cleared = 0; + return 0; }