Подтвердить что ты не робот

Сбор сбор мусора на скомпилированных языках

При реализации точной сборки мусора всегда возникает проблема выяснить, какие слова в стеке являются указателями, а какие - другие виды данных, такие как целые числа или числа с плавающей запятой. Интерпретированные языки обычно решают эту проблему, делая все указателем; компиляторы для некоторых языков, такие как Lisp, как правило, решают его, используя биты тегов, чтобы различать указатели и целые числа.

Но как насчет компиляторов JIT для таких языков, как Java и С#, которые поддерживают полные целые числа машинных слов и чисел с плавающей запятой? Как они сообщают, какие из содержимого стека и регистры процессора являются указателями?

4b9b3361

Ответ 1

Байт-код для таких языков всегда содержит полную информацию о типе. Он сохраняется либо в метаданных (например, для типов аргументов), либо неявна в коде операции (например, могут быть разные коды операций для добавления целого числа или числа с плавающей запятой).

При оптимизации кода компилятор может получить доступ к этой информации и использовать ее для улучшения оптимизации. Он также использует информацию для генерации метаданных для скомпилированного кода в определенных точках безопасности GC.

Безопасная точка GC - это место в коде, где безопасно прерывать поток для планирования другого потока или выполнения сбора мусора. В безопасных точках GC мы располагаем необходимыми метаданными, чтобы узнать, какие регистры содержат указатели, а какие нет. Например, в JVM Hotspot цикл всегда содержит чтение из специального места в памяти. Результат этого чтения не используется, но если адрес, считываемый инструкцией, защищен от чтения, возникает ошибка страницы. Это можно использовать для прерывания потока в произвольные моменты времени, просто установив эту страницу только для чтения. Как только поток прерывается, мы смотрим на счетчик программ и просматриваем метаданные, например, в хеш-таблице.

Другими местами, которые должны быть безопасными точками GC, являются сайты выделения: распределение может завершиться неудачей и вызвать GC. Вы можете уменьшить количество безопасных точек, выделив память сразу для нескольких объектов.

Изменить: обратите внимание, что использование GC-безопасных точек является лишь одним из многих вариантов. Другой вариант, как упоминалось SK-logic, заключается в использовании отдельных стеков для указателей и не указателей. Затем ясно, что все элементы одного стека должны проходить через GC, но ни один из других. Тем не менее, вы все равно должны быть осторожны с указателями в регистрах. Например, всякий раз, когда в регистре есть живой указатель, тот же указатель должен также существовать в стеке.

Третий вариант - использовать теневой стек, который содержит связанный список указателей, чтобы укладывать корни, живущие в реальном стеке. Подробнее см. Статью "Точная сборка мусора в неработоспособной среде" Фергуса Хендерсона (PDF).

Ответ 2

Языки, такие как Java и С#, задаются таким образом, что они не требуют точной коллекции. Реализация может использовать консервативный сборщик, где шаблоны битов, которые выглядят как указатель, рассматриваются как указатель (но могут действительно быть целым числом или float). Например, Boehm collector является консервативным сборщиком, который может использоваться для языков JIT.