Я изучаю дизайн JIT относительно динамических языков реализация VM. Я не сделал большого блока с 8086/8088 дней, просто немного здесь или там, так быть хорошим, если я не в духе.
Насколько я понимаю x86 (IA-32) архитектура все еще имеет тот же основной ограниченный набор регистров сегодня, что это всегда делало, но внутреннее количество регистра выросло чрезвычайно, но эти внутренние регистры не общедоступны и используются с переименованием регистра для достижения параллельной конвейерной обработки кода, который иначе не мог быть parallelizable. Я понимаю эту оптимизацию вполне прилично, но мое чувство, в то время как эта оптимизация помогает в полной пропускной способности и для параллельных алгоритмов, ограниченный набор регистров, мы все еще застреваем с результатами в большем количестве проливания регистра, наверху таким образом, что, если x86 имел дважды, или увеличивают в четыре раза регистры, доступные нам, в типичном потоке команд может быть значительно меньше кодов операций нажатия/поп? Или есть ли другой процессор optmizations, которые также оптимизируют это далеко, что я не знаю? В основном, если у меня есть единица кода, который имеет 4 регистра для работы с для целочисленной работы, но моя единица имеет дюжину переменных, у меня есть потенциально нажатие/поп для каждых приблизительно 2 инструкций.
Какие-либо ссылки на исследования, или еще лучше, личный опыт?
Править: x86_64 имеет 16 регистров, который является двойным x86-32, спасибо за исправление и информацию.
В дополнение к переименованию регистров, чтобы скрыть пузырьки из-за задержек инструкций, большинство архитектур x86 достаточно умны, чтобы подсчитывать нажатия и отжатия и переименовывать их в регистры. Помните, что декодер инструкций в x86 фактически выполняет своего рода JIT-компиляцию, превращая поток инструкций x86 в небольшую программу микрокода, хранящуюся в кэше трассировки. Часть этого процесса включает перехват загрузок стека с небольшим смещением и превращение их в регистры. Таким образом, что-то вроде (откровенно глупое и чисто для примера):
lwz eax,[ebp]
lwz ebx,[ebp+4]
add eax,[edx+0]
push eax
lwz eax,[ebp+8]
add eax,ebx
pop ebx
add eax,ebx
превращается в что-то вроде (притворимся, что внутренние регистры называются eg r0...r16):
lw r3, edx
lw r1, ebp
lw r2, ebp+4 ; the constant '4' is usually stored as an immediate operand
add r1,r2
or r4,r1,r1 ;; move r1 to r4
lw r1, ebp+8
add r1,r2
or r2,r4,r4
add r1,r2
Конечно, волшебно умный декодер (в отличие от того, который реально укладывается в количество транзисторов) уничтожит некоторые из ненужных движений, но я хочу сказать, что push/pop и stores/loads в esp+(некоторое небольшое число)
фактически превращаются в теневые регистры.
Два пункта:
(1) x86-64 удваивает количество регистров до 16
(2) в современных процессорах x86, инструкция, которая использует область памяти, которая уже находится в кэше L1, почти так же быстро, как та же операция с регистровый операнд, поэтому вы можете думать о L1 как о "регистровой памяти"