В настоящее время я работаю над сборщиком мусора поколений. Это означает, что просматриваются только самые последние объекты, а уцелевшие объекты (= доступные из известных корней) продвигаются к более старому поколению. Это работает нормально, когда объекты указывают на другие объекты того же или более старого поколения. Однако, когда старые объекты указывают на более новые, и поскольку обходятся только более новые объекты, указанные объекты будут собираться неправильно. Чтобы избежать этого, такие объекты помечаются и просматриваются явно во время каждой фазы GC.
Очевидно, что такие «родительские» объекты изменяемы, поскольку неизменяемые по своей конструкции всегда указывают на существующие объекты. Таким образом, чтобы стать «родителем», объект должен быть изменен после повышения, чтобы он указывал на более новый объект.
Чтобы узнать, какие объекты старшего поколения указывают на младшие поколения, я ищу способ прозрачно отслеживать изменения памяти. Для этого я использую защиту памяти и обработку сигналов/исключений. Страницы памяти устанавливаются только для чтения, что вызывает возбуждение сигнала/исключения всякий раз, когда они записываются, и в этом случае я снова устанавливаю защиту памяти на чтение-запись и регистрирую адрес где-то для дальнейшей обработки, а по возвращении ответственный код для исключения возобновляется нормально. Таким образом, когда срабатывает GC, я знаю, где искать потенциальных родителей для обхода.
В Linux я использую комбинацию обработки сигналов mprotect/SIGSEGV. В Windows я намереваюсь использовать VirtualProtect, но не нашел эквивалента обработки SIGSEGV. Итак, мои вопросы:
Как бы вы сделали это в Windows? API обработки исключений кажется довольно запутанным.
Есть ли лучший способ узнать, какие области памяти изменяются, чтобы мне не приходилось вести всю эту бухгалтерию?
Мой код написан на простом C. В настоящее время мне нужно, чтобы вызывающий код явно помечал измененные объекты, но это утомительно и подвержено ошибкам, поэтому я ищу прозрачный способ сделать это.
Заранее спасибо, Фред