@SergeySerge11

Какой смысл команды dup в JVM байт коде? И что за индексы локальных переменных?

Зачем нужна такая команда, почему нельзя было сделать в исходном коде компилятора cpu() методе просто не уменьшать StackPointer счетчик для следующей команды(ну или команду такую, которая не уменьшала стекПоинтер). В итоге еще и 1 операцию сложения убрали, и команды нету?
Вообще не понимаю тонны команд(точнее их логику не понимаю), я думал что Байт Код более высокоуровневый. Но там столько лишних операций. Как тот же стек. Постоянно такое
#1 : astore_1
#2 : aload_1

Для ассемблера 2-ая инструкция будет лишней. так как регистр ни куда не убежит. И такого всякого очень много.

И что вообще за индексы локальных переменных. Почему их только 256 может быть? о есть ограничение на 256 переменных? Или 256 байт области? Потому что если это не 256 байт какой-то области, относительно чего-то, то получается что есть таблица трансляции индексов в адреса, что в итоге лишняя операция. Когда можно было вместо 1 байта, 2-4 байта сразу Offset записать.
Надеюсь тут логику уловили. То есть вопрос, для команды iload_2 1 байтовой, получается интерпретатор, должен вычислить для текущего метода, адрес начала локальной переменной "_2", которая будет скорей всего где-то на расстояние 0-65555 от инструкции. Предполагаю что-то типа return localsVar[2]
То есть на этапе генерации байт кода, сюда можно было после команды, просто адрес сразу впихнуть. И скорость выполнения должна же быть быстрее.
Или что типа есть хоть какая выгода в том что бы сжимать код, вроде как сам код относительно ресурсов, файлов, и прочего ни чего не весит.
  • Вопрос задан
  • 193 просмотра
Решения вопроса 1
mayton2019
@mayton2019 Куратор тега Java
Bigdata Engineer
Какой смысл команды dup в JVM байт коде?

Жаль что ты не программировал на калькуляторе МК 60. Это целая эпоха.

Значит есть разные пути к вычислению арифметики. Например если тебе надо возвести в квадрат число 5 на регистровой машине - то ты должен загрузить регистр R1 числом. Потом регистр R2. И потом найти такую команду умножения которая свяжет регистры R1 и R2 и перемножит и сохранит еще где-то результат. В силу современного зоопарка процессоров практически нереально создать такой абстрактный байткод который бы эффективно отображался на опкоды разных железяк. Поэтому решили забить на регистровую машину. И использовать стек как хранилище операндов для операций. Разумеется в JVM есть и аналоги регистров но с ними не выполняются операции. ЕМНИП. Если хошь что-то сложить или вызвать функцию - то положи на стек и там-же получи результат. И если вернуться к возведению числа 5 в квадрат это может быть так

положить 5 на стек.
дублировать
вызвать функцию умножения


На каком-нибудь языке Forth это было-бы тремя командами
5 DUP * .
Результат - на вершине стека.

Это кратко записывается. Но это несет абсолютно ту-же смысловую нагрузку для арифметики.

Почему их только 256 может быть?

А чорт его знает. Так решили. Решили что 256 регистров это капец какой максимум для процедуры или функции. Послушай ради интереса видосы про процессор Эльбрус. Там тоже интересно с регистрами сделано.

о есть на этапе генерации байт кода, сюда можно было после команды, просто адрес сразу впихнуть. И скорость выполнения должна же быть быстрее.

Я думаю что твое предположение о том какой код соберет JIT не совсем верное.
Вместо спора я предлагаю взять какой-то тестовый сценарий и подсмотреть какой
будет собран код. Я знаю что скептики Java обычно после изучения вопроса глубже
меняют свою точку зрения. Ну по крайней мере перестают считать Java
"медленным покемоном". Java действительно была слоупоком во времена Jdk 1.1.
Но щас это не так.

Несколько лет назад я мерял производительность floating-point вычислений на приложении
которое рендерит зеркальные шары. И разница между С++ и Java была не сильно большая.
10 секунд на сях и 12 секунд на втором языке соотв. Хотя этот тест узкий и он просто
показывает частный случай.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
sergey-gornostaev
@sergey-gornostaev Куратор тега Java
Седой и строгий
Когда разрабатываешь сложные системы, стоит оперировать простыми абстракциями. А виртуальная машина - это очень сложно. Попытки кроилова на количестве операций в байткоде приведут к необходимости писать более сложный, менее стабильный и менее производительный код виртуальной машины.

Значения локальных переменных хранятся в нативном массиве, выделяемом в каждом кадре стека вызовов. Для примитивных типов в нём хранятся сами значения, для ссылочных - ссылки в кучу. На этапе генерации байткода потому нельзя впихивать напрямую адреса, что байткод должен быть переносимым, неизвестно как может быть устроена память машин, на которых его могут выполнять.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
Bell Integrator Ульяновск
До 400 000 ₽
Bell Integrator Хабаровск
До 400 000 ₽
Bell Integrator Ижевск
До 400 000 ₽
19 апр. 2024, в 03:01
1000 руб./за проект
18 апр. 2024, в 21:56
2000 руб./за проект
18 апр. 2024, в 21:00
150 руб./за проект