Я смотрю на некоторый выходной собственный код компилятора Hotspot VM JIT. Метод, который я анализирую, использует множество локальных переменных. Я ожидал, что это повлияет на распределение регистров и вызовет загрузку/сохранение в память и из памяти. Однако я не вижу никаких инструкций по загрузке/сохранению в нативном коде. В связи с этим у меня есть 2 связанных вопроса.
Я читал, что виртуальная машина Java имеет архитектуру на основе стека, в которой вместо использования регистров в качестве блокнота для вычислений используется стек. Таким образом, компилятор JIT также следует модели на основе стека или модели на основе регистров?
Если JIT основан на регистрах, что делает JIT-компилятор при исчерпании регистров? Использует ли JIT-компилятор какой-либо другой метод для обработки этого случая, или это тот случай, когда я не вижу загрузки/сохранения в память и из памяти просто потому, что у меня недостаточно локальных переменных?
Ответ 1 · рейтинг 2 · the8472
Прежде всего, ваш вопрос зависит от используемой вами архитектуры JVM и ЦП.
Я предполагаю, что вы говорите о точке доступа.
Таким образом, компилятор JIT также следует модели на основе стека или модели на основе регистров?
Байт-код работает со стеком, но он транслируется через несколько уровней, последний из которых основан на регистрах.
Если JIT основан на регистрах, что делает JIT-компилятор при исчерпании регистров?
Он может попасть в стек или может применить другие оптимизации для уменьшения нагрузки на регистры, в зависимости от их стоимости.
Но также возможно, что на предыдущих этапах оптимизации уже был создан код, который помещается в доступные регистры. Тот факт, что вы используете N локальных переменных в своем методе, не означает, что вам потребуется N регистров в любой момент времени.
Взгляните на вики OpenJDK, там есть несколько страниц о распределении регистров, а также более ранние этапы оптимизации.