+ int i;
+ int top;
+#if DBG_MEM
+ int loops = 0;
+ int marked;
+ int moved;
+ struct ao_lisp_record *mark_record = NULL, *move_record = NULL;
+
+ MDBG_MOVE("collect %d\n", ao_lisp_collects);
+ marked = moved = 0;
+#endif
+
+ ++ao_lisp_collects;
+
+ /* Clear references to all caches */
+ for (i = 0; i < (int) AO_LISP_CACHE; i++)
+ *ao_lisp_cache[i] = NULL;
+ chunk_low = 0;
+ top = 0;
+ for (;;) {
+ MDBG_DO(loops++);
+ MDBG_MOVE("move chunks from %d to %d\n", chunk_low, top);
+ /* Find the sizes of the first chunk of objects to move */
+ memset(ao_lisp_chunk, '\0', sizeof (ao_lisp_chunk));
+ walk(ao_lisp_mark_ref, ao_lisp_poly_mark_ref);
+#if DBG_MEM
+ marked = total_marked;
+
+ ao_lisp_record_free(mark_record);
+ mark_record = ao_lisp_record_save();
+ if (mark_record && move_record)
+ ao_lisp_record_compare("mark", move_record, mark_record);
+
+ if (moved && moved != marked)
+ ao_lisp_abort();
+#endif
+
+ DUMP_BUSY();
+
+ /* Find the first moving object */
+ for (i = 0; i < AO_LISP_NCHUNK; i++) {
+ uint16_t size = ao_lisp_chunk[i].size;
+
+ if (!size)
+ break;
+
+ if (ao_lisp_chunk[i].old_addr > top)
+ break;
+#if DBG_MEM
+ if (ao_lisp_chunk[i].old_addr != top)
+ ao_lisp_abort();
+#endif
+
+ top += size;
+ MDBG_MOVE("chunk %d %d not moving\n",
+ ao_lisp_chunk[i].old_addr,
+ ao_lisp_chunk[i].size);
+ chunk_low = ao_lisp_chunk[i].old_addr + size;
+ }
+
+ chunk_first = i;
+ /* Copy all of the objects */
+ for (; i < AO_LISP_NCHUNK; i++) {
+ uint16_t size = ao_lisp_chunk[i].size;
+
+ if (!size)
+ break;
+
+ MDBG_MOVE("chunk %d %d -> %d\n",
+ ao_lisp_chunk[i].old_addr,
+ size,
+ top);
+ ao_lisp_chunk[i].new_addr = top;
+ memmove(&ao_lisp_pool[top],
+ &ao_lisp_pool[ao_lisp_chunk[i].old_addr],
+ size);
+ top += size;
+ chunk_low = ao_lisp_chunk[i].old_addr + size;
+ }
+
+ chunk_last = i;
+
+ if (chunk_first < chunk_last) {
+ /* Relocate all references to the objects */
+ walk(ao_lisp_move, ao_lisp_poly_move);
+
+#if DBG_MEM
+ ao_lisp_record_free(move_record);
+ move_record = ao_lisp_record_save();
+ if (mark_record && move_record)
+ ao_lisp_record_compare("move", mark_record, move_record);
+
+ moved = total_marked;
+ if (moved != marked)
+ ao_lisp_abort();
+#endif
+ }
+
+ if (chunk_last != AO_LISP_NCHUNK)
+ break;
+ }
+ ao_lisp_top = top;
+
+ MDBG_DO(memset(ao_lisp_chunk, '\0', sizeof (ao_lisp_chunk));
+ walk(ao_lisp_mark_ref, ao_lisp_poly_mark_ref));
+
+// printf ("collect. top %d loops %d\n", top, loops);