Граф, достижимый из корневого набора, переносится в новую векторную память, а указатели пересылки сохраняют и общие хвосты, и циклы.
Вопрос для размышления
Как сборщик может уплотнять живую память без дублирования разделяемых объектов и без бесконечного зацикливания при наличии циклов?
Различение from-space и изначально пустого to-space
Копирование только указателей на пары, достижимых из переданных корней root
Установка записи forwarding перед рекурсивным копированием полей
Повторное использование одного нового указателя для каждой повторной ссылки на старую ячейку
Сохранение цикла через распознавание указателя forwarding
Измерение освобожденных ячеек и продвижения указателя free
copy-value возвращает атомы без изменений. Для указателя на пару процедура сначала проверяет запись forwarding по старому индексу. При отсутствии записи выделяется одна ячейка placeholder в to-space и записывается новый указатель еще до перехода по любому из полей. Затем car и cdr рекурсивно копируются в эту ячейку placeholder. Запись нового указателя в первую очередь делает конечной обработку как разделяемых данных, так и циклов.
В первой куче выделено пять ячеек, но только три из них достижимы из двух корней root. Скопированные ячейки left и right указывают на один скопированный разделяемый хвост shared, тогда как обе ячейки мусора сохраняют ложные записи forwarding. Вторая куча содержит цикл на себя, поэтому копирование cdr снова встречает старый указатель и сразу повторно использует уже установленный новый указатель. Эта конечная программа выполняет один явный сбор мусора в пределах фиксированной емкости semispace.
Сборка мусора для графа с разделением возвращает (5 3 2 (a shared) (b shared) #t #f #f). Сборка циклического графа возвращает (1 node #t #f).
На что обратить внимание в трассе
В графе с разделением проследите переход первого старого указателя shared в новое выделение памяти, а второго вхождения в существующую запись forwarding. Убедитесь, что старые индексы 3 и 4 никогда не посещаются. В цикле найдите запись forwarding до того, как рекурсивное копирование cdr снова достигнет старого узла.
Попробуйте сами
Измените программу и сравните результат.
Добавьте третий корень root, указывающий прямо на разделяемый хвост shared, затем измените скопированный хвост. Спрогнозируйте новое количество выделенных ячеек и каждое наблюдение через root. Затем поменяйте местами semispace и выделите еще одну ячейку.
Показать подсказку
Дополнительный корень root к уже пересланному объекту не добавляет скопированных ячеек. После сборки мусора все клиенты должны использовать перезаписанные корни root в to-space, а не устаревшие указатели из from-space.