Приложение A: оптимизация

Следующий набор псевдо-команд представляет быстрые варианты команд виртуальной машины языка Ява. Они используются, чтобы улучшить скорость интерпретирования байт-кодов. Они не являются частью описания виртуальной машины или множества инструкций, и невидимы вне реализации виртуальной машины языка Ява. Однако, внутри реализации виртуальной машины они используются для эффективной оптимизации.

Компилятор языка Ява — первоначальный код из множества команд виртуальной машины языка Ява, которое состоит из non-_quick команд. Если используются _quick псевдо-команды, то каждое выполнение non-_quick команды с _quick вариантом является перезаписыванием с исполнением _quick варианта. Последующее выполнение этой команды будет иметь _quick вариант.

Во всех случаях, если команда имеет альтернативную версию с suffix _quick, команда ссылается на константный пул. Если используется _quick оптимизация, каждая non-_quick команда с _quick вариантом выполняет следующее:

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

Заметьте: некоторые из описанных методов только поддерживают смещение байта со знаком в таблице объектов метода; для объектов с 256 или более методами некоторые

вызовы не могут быть "убыстрены” только этими байткодами. Мы также нуждаемся в определении или изменении существующих getfield и putfield байткодов, чтобы получить смещение более чем на байт.

Это Приложение не дает значений кода операции для псевдо-команды, так как они невидимые и могут изменяться.

A.1 Обработка константного пула

Когда класс читается, создается массив constant_pool размера nconstants и присваивается полю класса. constant_pool[0] устанавливается на точку динамически размещенного массива, которая указывает какие поля в constant_pool уже обработаны. Элементы от сonstant_pool[1] до сonstant_pool[nconstants - 1] устанавливаются, чтобы указывать на поле "типа", соответствующее данной константе.

Когда выполняется инструкция, ссылающаяся на константный пул, генерируется индекс, и проверяется значение constant_pool[0] чтобы узнать, разрешен ли уже этот индекс. Если да, то возвращается значение constant_pool[index]. Если нет, то значение constant_pool[index] определяется как фактический указатель или данные, и записывается в сonstant_pool[index].

A. 2 Помещение констант на стек (_quick варианты)

ldc1_quick

Помещение элемента константного пула на стек

ldc1_quick

indexbyte1

Стек: ... = > ..., item

 

indexbyte1 представляет собой беззнаковый 8-битный индекс константного пула текущего класса. item индекса помещается на стек.

ldc2_quick

Помещение элемента константного пула на стек

ldc2_quick

indexbyte1

indexbyte2

Стек: ... = > ..., item

 

indexbyte1 и indexbyte2 используются для конструирования индекса константного пула текущего класса. Находится constant индекса и item его помещается на стек.

ldc2w_quick

Помещение длинного целого или числа с плавающей точкой двойной точности из константного пула на стек.

ldc2w_quick

indexbyte1

indexbyte2

Стек: ... = > ..., constant-word1, constant-word2

 

indexbyte1 и indexbyte2 используются для конструирования индекса константного пула текущего класса. constant индекса помещается на стек.

A. 3 Управление массивами (_quick варианты).

anewarray_quick

Создание нового массива из ссылок на объекты.

anewarray_quick

indexbyte1

indexbyte2

Стек: ..., size = > result

 

size должна быть целой. Она представляет собой число элементов в новом массиве. indexbyte1 и indexbyte2 используются для построения индекса в константном пуле текущего класса. Вход должен быть классом.

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

Если размер меньше чем ноль, генерируется NegativeArraySizeException . Если не достаточно памяти для размещения массива, генерируется OutOfMemoryError .

multianewarray_quick

Размещение нового многомерного массива.

multianewarray_quick

indexbyte1

indexbyte2

dimensions

Стек: ..., size1, size2, ... sizen = > result

 

Каждая size должна быть целой. Каждая представляет собой число элементов в размерности массива.

indexbyte1 и indexbyte2 используются для построения индекса в константном пуле текущего класса. Результирующий вход должен быть классом.

dimensions имеют следующие аспекты:

Если любой из аргументов size на стеке - меньше чем ноль, генерируется NegativeArraySizeException. Если не достаточно памяти для размещения массива, генерируется OutOfMemoryError.

result - ссылка на новый объект массива.

Заметьте: Необходимо дать исчерпывающие объяснения относительно массива из массивов.

А. 4 Управляющие объектные поля (_quick варианты)

putfield_quick

Устанавливает поля в объекте

putfield_quick

offset

unused

Стек: ..., objectref, value = > ...

 

objectref должна быть ссылкой на объект. value должно быть значением типа,

соответствующего определенному полю. offset - смещение для поля в этом объекте. value - значение, соответствующее этому offset в объекте. И objectref и value извлекаются из стека.

Если objectref пустая ссылка (null ), то генерируется NullPointerException.

putfield2_quick

Устанавливает длинное целое или двойное вещественное поле в объекте

putfield2_quick

offset

unused

Стек: ..., objectref, value-word1, value-word2= > ...

 

objectref должна быть ссылкой на объект. value должно быть значением типа, соответствующего определенному полю. offset - смещение для поля в этом объекте. value - значение, соответствующее этому offset в объекте. И objectref и value извлекаются из стека.

Если objectref пустая ссылка (null ), то генерируется NullPointerException.

getfield_quick

Узнает значение поля объекта

getfield_quick

offset

unused

Стек: ..., objectref = > ..., value

 

objectref должна соответствовать объекту. Значение value, соответствующее offset в

вызываемом при помощи objectref объекте заменяет objectref, лежащую на вершине стека.

Если objectref пустая ссылка (null ), то генерируется NullPointerException.

getfield2_quick

Узнает значение поля объекта

getfield2_quick

offset

unused

Стек: ..., objectref = > ..., value-word1, value-word2

 

objectref должна соответствовать объекту. Значение value, соответствующее offset в

вызываемом при помощи objectref объекте заменяет objectref, лежащую на вершине стека.

Если objectref пустая ссылка (null), то генерируется NullPointerException.

putstatic_quick

Устанавливает статическое поле в классе

putstatic_quick

indexbyte1

indexbyte2

Стек: ..., value = > ...

 

indexbyte1 и indexbyte2 используются для формирования индекса в константном пуле

текущего класса. Элементом константного пула будет ссылка поля на статическое поле класса. Значение должно иметь тип, соответствующий этому полю. Поле будет установлено так, что в качестве значение у него будет value.

putstatic2_quick

Устанавливает статическое поле в классе

putstatic2_quick

indexbyte1

indexbyte2

Стек: ..., value-word1, value-word2 = > ...

 

indexbyte1 и indexbyte2 используются для формирования индекса в константном пуле текущего класса. Элементом константного пула будет ссылка поля на статическое поле класса. Поле должно быть или длинным целым или вещественным числом двойной точности. Значение должно иметь тип, соответствующий этому полю. Поле будет установлено так, что в качестве значения у него будет value.

getstatic_quick

Узнает значение статического поля класса

getstatic_quick

indexbyte1

indexbyte2

Стек: ..., = > ..., value

 

indexbyte1 и indexbyte2 используются для формирования индекса в константном пуле текущего класса. Элементом константного пула будет ссылка поля на статическое поле класса. Значение которого(того поля) заменяет обработчика в стеке.

getstatic2_quick

Узнает значение статического поля класса

getstatic2_quick

indexbyte1

indexbyte2

Стек: ..., = > ..., value-word1, value-word2

 

indexbyte1 и indexbyte2 используются для формирования индекса в константном пуле текущего класса. Элементом константного пула будет ссылка поля на статическое поле класса. Поле должно быть длинным целым или вещественным числом двойной

точности. Значение этого поля заменяет обработчика в стеке.

A. 5 Вызов метода (_quick варианты)

invokevirtual_quick

Вызывает метод экземпляра, диспетчеризация основана на типе во время выполнения

invokevirtual_quick

offset

nargs

Стек: ..., objectref, [arg1, [arg2 ...]] = > ...

 

Стек операндов должен содержать objectref, ссылку на объект и параметры nargs-1. Определяется блок метода, соответствующий offset в таблице метода объекта,

как определено динамическим типом объекта. Блок метода указывает тип метода (исходный, синхронизированный, и т.д.).

Если тип метода является синхронизированным,то вводится монитор, связанный с объектом.

Основа массива из локальных переменных для новой структуры стека Ява назначена, чтобы указывать на objectref в стеке, создавая objectref и обеспечивающий параметры (arg1, arg2, ...) первые nargs локальные переменные новой структуры. Общее количество локальных переменных, используемых методом определено, и среда выполнения нового фрейма помещается на стек после того, как освободится достаточный участок памяти для локальных переменных. Основа стека операндов для этого метода вызова применяется к первому слову после среды выполнения. После этого(В заключение), выполнение продолжается с первой команды(ой), соответствующей методу.

Если objectref является пустой (null), то генерируется NullPointerException. При переполнении стека в течение метода вызывания генерируется StackOverflowError.

invokevirtualobject_quick

Вызывает метод экземпляра из класса java.lang.Object, определенного для увеличения(прибыли,пользы) массивов

 

invokevirtualobject_quick

offset

nargs

Стек: ..., objectref, [arg1, [arg2 ...]] = > ...

 

Стек операндов должен содержать objectref, ссылка на объект или на массив и параметры nargs-1. Определяется блок метода соответствующий offset в таблице метода java.lang.Object. Блок метода указывает тип метода (исходный, синхронизированный, и т.д.).

Если тип метода является синхронизированным, то вводится монитор связанный с обработчиком.

Основа массива из локальных переменных для новой структуры стека Ява назначена, чтобы указывать на objectref в стеке, создавая objectref и обеспечивающий параметры (arg1, arg2, ...) первые nargs локальные переменные новой структуры. Общее количество локальных переменных, используемых методом определено, и среда выполнения нового фрейма помещается на стек после того, как освободится достаточный участок памяти для локальных переменных. Основа стека операндов для этого метода вызова применяется к первому слову после среды выполнения. После этого(В заключение), выполнение продолжается с первой команды(ой), соответствующей методу.

Если objectref является пустой (null), то генерируется NullPointerException. При переполнении стека в течение метода вызывания генерируется StackOverflowError.

invokenonvirtual_quick

Вызывает метод экземпляра, диспетчеризация которого основана на собирать-разовом типе

 

invokenonvirtual_quick

indexbyte1

indexbyte2

Стек: ..., objectref, [arg1, [arg2 ...]] = > ...

 

Стек операндов должен содержать objectref, ссылка на объект и некоторые

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

Если тип метода является синхронизированным, то вводится монитор, связанный с объектом.

Основа массива из локальных переменных для новой структуры стека Ява назначена, чтобы указывать на objectref в стеке, создавая objectref и обеспечивающий параметры (arg1, arg2, ...) первые nargs локальные переменные новой структуры. Общее количество локальных переменных, используемых методом определено, и среда выполнения нового фрейма помещается на стек после того, как освободится достаточный участок памяти для локальных переменных. Основа стека операндов для этого метода вызова применяется к первому слову после среды выполнения. После этого(В заключение), выполнение продолжается с первой команды(ой), соответствующей методу.

Если objectref является пустой (null), то генерируется NullPointerException. При переполнении стека в течение метода вызывания генерируется StackOverflowError.

invokestatic_quick

Вызывает метод класса (статический)

invokestatic_quick

indexbyte1

indexbyte2

Стек: ..., [arg1, [arg2 ...]] = > ...

 

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

Если тип метода является синхронизированным, то вводится монитор, связанный с

классом метода.

Основа массива из локальных переменных для новой структуры стека Ява назначена, чтобы указывать на первый параметр стека, обеспечивая параметры (arg1, arg2, ...) первые nargs локальные переменные новой структуры. Общее количество локальных переменных, используемых методом определено, и среда выполнения нового фрейма помещается на стек после того, как освободится достаточный участок памяти для локальных переменных. Основа стека операндов для этого метода вызова применяется к первому слову после среды выполнения. После этого(В заключение), выполнение продолжается с первой команды(ой), соответствующей методу.

Если objectref является пустой (null), то генерируется NullPointerException. При переполнении стека в течение метода вызывания генерируется StackOverflowError.

 

invokeinterface_quick

Вызывает метод интерфейса

invokeinterface_quick

idbyte1

idbyte2

nargs

guess

Стек: ..., objectref, [arg1, [arg2 ...]] = > ...

 

Стек операндов должен содержать objectref, ссылку на объект, и параметры nargs-1. idbyte1 и idbyte2 используются для формирования индекса в константном пуле текущего класса. Элемент, соответствующий этому индексу в константном пуле содержит полную сигнатуру метода. Указатель на таблицу метода объекта определяется из дескриптора объекта.

Сигнатуру метода ищут в таблице метода объекта. Как Сокращенный, сигнатуру метода в guess слота ищут сначала. Если это не приводит к нужному результату, то производится полный поиск в таблице метода. Гарантируется, что сигнатура метода будет точно соответствовать одной из сигнатур метода в таблице.

Результатом поисковой таблицы является блок метода. Блок метода указывает тип метода (исходный, синхронизированный, и т.д.) но число доступных параметров (nargs) берется из байткода.

Если тип метода является синхронизированным, то вводится монитор, связанный с обработчиком.

Основа массива из локальных переменных для новой структуры стека Ява назначена, чтобы указывать на handle в стеке, создавая handle и обеспечивая параметры (arg1, arg2, ...) первые nargs локальные переменные новой структуры. Общее количество локальных переменных, используемых методом определено, и среда выполнения нового фрейма помещается на стек после того, как освободится достаточный участок памяти для локальных переменных. Основа стека операндов для этого метода вызова применяется к первому слову после среды выполнения. После этого(В заключение), выполнение продолжается с первой команды(ой), соответствующей методу.

Если objectref является пустой (null), то генерируется NullPointerException. При переполнении стека в течение метода вызывания генерируется StackOverflowError.

guess является последним guess(предположением). Периодически(Каждый раз через), guess(предположение) применяется к смещению метода, которое использовалось.

A. 6 Операции с различными объектами (_quick варианты)

new_quick

Создает новый объект

new_quick

indexbyte1

indexbyte2

Стек: ... = > ..., objectref

 

indexbyte1 и indexbyte2 используются для формирования индекса в константном пуле текущего класса. Элемент, соответствующий этому индексу, должен быть классом. Затем создается новый элемент(образец) этого класса и objectref, ссылка на этот объект, помещается в стек.

checkcast_quick

Проверяет принадлежности объекта данному типу

checkcast_quick

indexbyte1

indexbyte2

Стек: ..., objectref = > ..., objectref

 

objectref должна быть ссылкой на объект. indexbyte1 и indexbyte2 используются для формирования индекса в константном пуле текущего класса. Объект, соответветствующий этому индексу константного пула уже должен быть определен.

checkcast затем определяет, может ли objectref приводиться к ссылке на объект класса класса(класс объекта класса). Пустая (null) ссылка может приводиться к любомуклассу, и иначе суперклассы типа objectref ищут класс. Если класс определен, чтобы быть суперклассом типа objectref, или если objectref является пустой(null), он может приводиться к objectref, которая не может приводиться к классу, то генерируется

ClassCastException.

Заметьте: здесь (и вероятно в других местах) мы принимаем, что приведения не изменяют

ссылок; это - зависимая(не объективная) реализация.

 

instanceof_quick

instanceof_quick

indexbyte1

indexbyte2

Проверяет принадлежность объекта данному типу

Стек: ..., objectref = > ..., result

 

objectref должна быть ссылкой на объект. indexbyte1 и indexbyte2 используются для формирования индекса в константном пуле текущего класса. Объект, соответветствующий этому индексу константного пула уже должен быть определен.

instanseof определяет, может ли objectref приводиться к объекту класса класса(класс объекта класса). Пустая (null) ссылка может приводиться к любому классу, и иначе суперклассы типа objectref ищут класс. Если класс определен, чтобы быть суперклассом типа objectref, то result принимает значение 1(true). Иначе result принимает значение (false). Если программа обработки является пустой(null), то result принимает значени 0 (false).