update changelog for Debian build
[fw/altos] / src / scheme / ao_scheme_mem.c
index c7d6b1f8c2f3c345e5d2305373c182d4f2794e5a..c92150722d1e8dbe2439544f1b3e2293248094e6 100644 (file)
@@ -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,43 +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 = NULL,
+               .addr = (void **) (void *) &stash_poly[0]
        },
        {
-               .type = &ao_scheme_string_type,
-               .addr = (void **) &save_string[1],
+               .type = NULL,
+               .addr = (void **) (void *) &stash_poly[1]
        },
        {
-               .type = &ao_scheme_frame_type,
-               .addr = (void **) &save_frame[0],
+               .type = NULL,
+               .addr = (void **) (void *) &stash_poly[2]
        },
        {
                .type = NULL,
-               .addr = (void **) (void *) &save_poly[0]
+               .addr = (void **) (void *) &stash_poly[3]
        },
        {
                .type = NULL,
-               .addr = (void **) (void *) &save_poly[1]
+               .addr = (void **) (void *) &stash_poly[4]
        },
        {
                .type = NULL,
-               .addr = (void **) (void *) &save_poly[2]
+               .addr = (void **) (void *) &stash_poly[5]
        },
        {
                .type = &ao_scheme_atom_type,
@@ -306,7 +304,7 @@ 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;
@@ -390,6 +388,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 */
@@ -469,20 +470,19 @@ 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
@@ -548,11 +548,11 @@ 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_MOVE("collect %lu\n", ao_scheme_collects[style]);
+
        MDBG_DO(ao_scheme_frame_write(ao_scheme_frame_poly(ao_scheme_frame_global)));
        MDBG_DO(++ao_scheme_collecting);
 
@@ -579,15 +579,12 @@ 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
 
+#if DBG_MEM_RECORD
                ao_scheme_record_free(mark_record);
                mark_record = ao_scheme_record_save();
                if (mark_record && move_record)
@@ -599,7 +596,6 @@ ao_scheme_collect(uint8_t style)
                /* 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();
@@ -618,6 +614,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
@@ -651,7 +661,7 @@ ao_scheme_collect(uint8_t style)
                        /* Relocate all references to the objects */
                        walk(ao_scheme_move, ao_scheme_poly_move);
 
-#if DBG_MEM
+#if DBG_MEM_RECORD
                        ao_scheme_record_free(move_record);
                        move_record = ao_scheme_record_save();
                        if (mark_record && move_record)
@@ -659,6 +669,9 @@ ao_scheme_collect(uint8_t style)
 #endif
                }
 
+#if DBG_MEM_STATS
+               loops++;
+#endif
                /* If we ran into the end of the heap, then
                 * there's no need to keep walking
                 */
@@ -701,7 +714,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)) {
@@ -730,7 +743,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);
@@ -782,7 +795,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) {
@@ -842,7 +855,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;
@@ -852,7 +865,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;
        }
@@ -861,7 +874,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;
 }
 
@@ -892,7 +905,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);
@@ -928,14 +941,14 @@ 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;
 }
 
 #if DBG_MEM
-void
+static void
 ao_scheme_validate(void)
 {
        chunk_low = 0;
@@ -969,63 +982,21 @@ ao_scheme_alloc(int size)
 }
 
 void
-ao_scheme_cons_stash(int id, struct ao_scheme_cons *cons)
-{
-       assert(save_cons[id] == 0);
-       save_cons[id] = cons;
-}
-
-struct ao_scheme_cons *
-ao_scheme_cons_fetch(int id)
-{
-       struct ao_scheme_cons *cons = save_cons[id];
-       save_cons[id] = NULL;
-       return cons;
-}
-
-void
-ao_scheme_poly_stash(int id, ao_poly poly)
+ao_scheme_poly_stash(ao_poly p)
 {
-       assert(save_poly[id] == AO_SCHEME_NIL);
-       save_poly[id] = poly;
+       assert(stash_poly_ptr < AO_SCHEME_NUM_STASH);
+       stash_poly[stash_poly_ptr++] = p;
 }
 
 ao_poly
-ao_scheme_poly_fetch(int id)
+ao_scheme_poly_fetch(void)
 {
-       ao_poly poly = save_poly[id];
-       save_poly[id] = AO_SCHEME_NIL;
-       return poly;
-}
+       ao_poly p;
 
-void
-ao_scheme_string_stash(int id, struct ao_scheme_string *string)
-{
-       assert(save_string[id] == NULL);
-       save_string[id] = string;
-}
-
-struct ao_scheme_string *
-ao_scheme_string_fetch(int id)
-{
-       struct ao_scheme_string *string = save_string[id];
-       save_string[id] = NULL;
-       return string;
-}
-
-void
-ao_scheme_frame_stash(int id, struct ao_scheme_frame *frame)
-{
-       assert(save_frame[id] == NULL);
-       save_frame[id] = frame;
-}
-
-struct ao_scheme_frame *
-ao_scheme_frame_fetch(int id)
-{
-       struct ao_scheme_frame *frame = save_frame[id];
-       save_frame[id] = NULL;
-       return frame;
+       assert (stash_poly_ptr > 0);
+       p = stash_poly[--stash_poly_ptr];
+       stash_poly[stash_poly_ptr] = AO_SCHEME_NIL;
+       return p;
 }
 
 int
@@ -1038,8 +1009,8 @@ ao_scheme_print_mark_addr(void *addr)
                ao_scheme_abort();
 #endif
 
-       if (!AO_SCHEME_IS_POOL(addr))
-               return 1;
+       if (!ao_scheme_is_pool_addr(addr))
+               return 0;
 
        if (!ao_scheme_print_cleared) {
                ao_scheme_print_cleared = 1;
@@ -1052,14 +1023,23 @@ ao_scheme_print_mark_addr(void *addr)
        return 0;
 }
 
-int
-ao_scheme_print_mark_poly(ao_poly p)
+void
+ao_scheme_print_clear_addr(void *addr)
 {
-       uint8_t type = ao_scheme_poly_base_type(p);
+       int     offset;
 
-       if (type == AO_SCHEME_INT)
-               return 1;
-       return ao_scheme_print_mark_addr(ao_scheme_ref(p));
+#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 */
@@ -1069,11 +1049,13 @@ ao_scheme_print_start(void)
        ao_scheme_printing++;
 }
 
-/* Notes that printing has ended */
-void
+/* Notes that printing has ended. Returns 1 if printing is still going on */
+int
 ao_scheme_print_stop(void)
 {
        ao_scheme_printing--;
-       if (ao_scheme_printing == 0)
-               ao_scheme_print_cleared = 0;
+       if (ao_scheme_printing != 0)
+               return 1;
+       ao_scheme_print_cleared = 0;
+       return 0;
 }