altos/scheme: Use memory manager mark code to note recursive print
[fw/altos] / src / scheme / ao_scheme_mem.c
index afa06d546d8b78a2c601a161a408a55f252cce6f..c7d6b1f8c2f3c345e5d2305373c182d4f2794e5a 100644 (file)
@@ -178,7 +178,7 @@ struct ao_scheme_root {
 };
 
 static struct ao_scheme_cons   *save_cons[2];
-static char                    *save_string[2];
+static struct ao_scheme_string *save_string[2];
 static struct ao_scheme_frame  *save_frame[1];
 static ao_poly                 save_poly[3];
 
@@ -280,6 +280,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];
@@ -488,7 +492,9 @@ dump_busy(void)
 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,
-       [AO_SCHEME_STRING] = &ao_scheme_string_type,
+#ifdef AO_SCHEME_FEATURE_BIGINT
+       [AO_SCHEME_BIGINT] = &ao_scheme_bigint_type,
+#endif
        [AO_SCHEME_OTHER] = (void *) 0x1,
        [AO_SCHEME_ATOM] = &ao_scheme_atom_type,
        [AO_SCHEME_BUILTIN] = &ao_scheme_builtin_type,
@@ -497,9 +503,7 @@ static const struct ao_scheme_type * const ao_scheme_types[AO_SCHEME_NUM_TYPE] =
        [AO_SCHEME_LAMBDA] = &ao_scheme_lambda_type,
        [AO_SCHEME_STACK] = &ao_scheme_stack_type,
        [AO_SCHEME_BOOL] = &ao_scheme_bool_type,
-#ifdef AO_SCHEME_FEATURE_BIGINT
-       [AO_SCHEME_BIGINT] = &ao_scheme_bigint_type,
-#endif
+       [AO_SCHEME_STRING] = &ao_scheme_string_type,
 #ifdef AO_SCHEME_FEATURE_FLOAT
        [AO_SCHEME_FLOAT] = &ao_scheme_float_type,
 #endif
@@ -533,6 +537,7 @@ uint64_t ao_scheme_loops[2];
 #endif
 
 int ao_scheme_last_top;
+int ao_scheme_collect_counts;
 
 int
 ao_scheme_collect(uint8_t style)
@@ -549,6 +554,7 @@ ao_scheme_collect(uint8_t style)
        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_DO(++ao_scheme_collecting);
 
        ao_scheme_reset_stack();
 
@@ -556,6 +562,14 @@ ao_scheme_collect(uint8_t style)
        if (ao_scheme_last_top == 0)
                style = AO_SCHEME_COLLECT_FULL;
 
+       /* One in a while, just do a full collect */
+
+       if (ao_scheme_collect_counts >= 128)
+               style = AO_SCHEME_COLLECT_FULL;
+
+       if (style == AO_SCHEME_COLLECT_FULL)
+               ao_scheme_collect_counts = 0;
+
        /* Clear references to all caches */
        for (i = 0; i < (int) AO_SCHEME_CACHE; i++)
                *ao_scheme_cache[i] = NULL;
@@ -672,6 +686,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;
 }
 
@@ -984,16 +999,16 @@ ao_scheme_poly_fetch(int id)
 }
 
 void
-ao_scheme_string_stash(int id, char *string)
+ao_scheme_string_stash(int id, struct ao_scheme_string *string)
 {
        assert(save_string[id] == NULL);
        save_string[id] = string;
 }
 
-char *
+struct ao_scheme_string *
 ao_scheme_string_fetch(int id)
 {
-       char *string = save_string[id];
+       struct ao_scheme_string *string = save_string[id];
        save_string[id] = NULL;
        return string;
 }
@@ -1012,3 +1027,53 @@ ao_scheme_frame_fetch(int id)
        save_frame[id] = NULL;
        return frame;
 }
+
+int
+ao_scheme_print_mark_addr(void *addr)
+{
+       int     offset;
+
+#if DBG_MEM
+       if (ao_scheme_collecting)
+               ao_scheme_abort();
+#endif
+
+       if (!AO_SCHEME_IS_POOL(addr))
+               return 1;
+
+       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;
+}
+
+int
+ao_scheme_print_mark_poly(ao_poly p)
+{
+       uint8_t type = ao_scheme_poly_base_type(p);
+
+       if (type == AO_SCHEME_INT)
+               return 1;
+       return ao_scheme_print_mark_addr(ao_scheme_ref(p));
+}
+
+/* Notes that printing has started */
+void
+ao_scheme_print_start(void)
+{
+       ao_scheme_printing++;
+}
+
+/* Notes that printing has ended */
+void
+ao_scheme_print_stop(void)
+{
+       ao_scheme_printing--;
+       if (ao_scheme_printing == 0)
+               ao_scheme_print_cleared = 0;
+}