В.А. Серебряков - Теория и реализация языков программирования (1134641), страница 30
Текст из файла (страница 30)
Промежуточное представление программыend40 1 end0 2 endКонец тела процедуры.Начало тела модуля.Оператор присваивания.Левая часть — переменная Z.Тип присваиваемого значения.Вызов локальной процедуры DIF.Фактические параметры Xи Y.Конец вызова.Конец тела модуля.8.4. Виртуальная машина JavaПрограммы на языке Java транслируются в специальное промежуточноепредставление, которое затем интерпретируется так называемой «виртуальноймашиной Java». Виртуальная машина Java представляет собой магазиннуюмашину: она не имеет памяти прямого доступа, все операции выполняютсянад операндами, расположенными на верхушке магазина. Чтобы, например,выполнить операцию с участием константы (или переменной), ее необходимопредварительно загрузить на верхушку магазина.
Код операции — всегда одинбайт. Если операция имеет операнды, то они располагаются в следующихбайтах.К элементарным типам данных, с которыми работает машина, относятсяshort, integer, long, float, double (все знаковые).8.4.1. Организация памяти. Машина имеет следующие регистры:pc — счетчик команд;optop — указатель вершины магазина операций;frame — указатель на область исполняемого метода в магазине;vars — указатель на 0-ю переменную исполняемого метода.Все регистры 32-разрядные.
Магазинный фрейм имеет три компоненты: локальные переменные, среду исполнения, магазин операндов. Локальные переменные отсчитываются от адреса в регистре vars. Среда исполнения служитдля поддержания самого магазина. Она включает указатель на предыдущийфрейм, указатель на собственные локальные переменные, на базу стекаопераций и на верхушку магазина.
Кроме того, здесь же хранится некотораядополнительная информация, например, для отладчика.Куча сбора мусора содержит экземпляры объектов, которые создаютсяи уничтожаются автоматически. Область методов содержит коды, таблицысимволов и т. п.С каждым классом связана область констант. Она содержит имена полей,методов и другую подобную информацию, которая используется методами.8.4. Виртуальная машина Java1578.4.2.
Набор команд виртуальной машины. Виртуальная Java-машинаимеет следующие команды:помещение констант в магазин,помещение локальных переменных в магазин,запоминание значений из магазина в локальных переменных,обработка массивов,управление магазином,арифметические команды,логические команды,преобразования типов,передача управления,возврат из функции,табличный переход,обработка полей объектов,вызов метода,обработка исключительных ситуаций,прочие операции над объектами,мониторы,отладка.Рассмотрим некоторые команды подробнее.8.4.2.1.
Помещение локальных переменных в магазин. Команда iload—загрузить целое из локальной переменной.Операндом является смещение переменной в области локальных переменных. Указываемое значение копируется на верхушку магазина операций.Имеются аналогичные команды для помещения плавающих, двойных целых,двойных плавающих и т. п.Команда istore— сохранить целое в локальной переменной.Операндом операции является смещение переменной в области локальныхпеременных.
Значение с верхушки магазина операций копируется в указываемую область локальных переменных. Имеются аналогичные команды дляпомещения плавающих, двойных целых, двойных плавающих и т. п.8.4.2.2. Вызов метода. Команда invokevirtual.При трансляции объектно-ориентированных языков программированияиз-за возможности перекрытия виртуальных методов, вообще говоря, нельзястатически протранслировать вызов метода объекта. Это связано с тем, чтоесли метод перекрыт в производном классе и вызывается метод объектапеременной, то статически неизвестно, объект какого класса (базового илипроизводного) хранится в переменной. Поэтому с каждым объектом связывается таблица всех его виртуальных методов: для каждого метода там158Глава 8.
Промежуточное представление программыпомещается указатель на его реализацию в соответствии с принадлежностьюсамого объекта классу в иерархии классов.В языке Java различные классы могут реализовывать один и тот же интерфейс. Если объявлена переменная или параметр типа интерфейс, то динамически нельзя определить, объект какого класса присвоен переменной:interface I;class C1 implements I;class C2 implements I;I O;C1 O1;C2 O2;...O=O1;...O=O2;...В этой точке программы, вообще говоря, нельзя сказать, какого типазначение хранится в переменной O. Кроме того, при работе программы на языке Java имеется возможность использования методов из других пакетов.Для реализации этого механизма в Java-машине используется динамическоесвязывание.Предполагается, что магазин операндов содержит handle (указательна описание) объекта или массива и некоторое количество аргументов.
Операнд операции используется для конструирования индекса в области константтекущего класса. Элемент по этому индексу в области констант содержитполную сигнатуру метода. Сигнатура метода описывает типы параметрови возвращаемого значения. Из handle объекта извлекается указатель на таблицу методов объекта.
Просматривается сигнатура метода в таблице методов.Результатом этого просмотра является индекс в таблицу методов именованного класса, для которого найден указатель на блок метода. Блок методауказывает тип метода (native, synchronized и т. п.) и число аргументов,ожидаемых в магазине операндов.Если метод помечен как synchronized, то запускается монитор, связанный с handle. Базис массива локальных переменных для нового магазинного фрейма устанавливается так, что он указывает на handle в магазине.Определяется общее число локальных переменных, используемых методом,и, после того как отведено необходимое место для локальных переменных,окружение исполнения нового фрейма помещается в магазин.
База магазинаоперандов для этого вызова метода устанавливается на первое слово послеокружения исполнения. Затем исполнение продолжается с первой инструкциивызванного метода.8.5. Организация информации в генераторе кода1598.4.2.3. Обработка исключительных ситуаций. Команда athrow — возбудить исключительную ситуацию.С каждым методом связан список операторов catch. Каждый операторcatch описывает диапазон инструкций, для которых он активен, и тип исключения, который он обрабатывает.
Кроме того, с оператором связан наборреализующих его инструкций. При возникновении исключительной ситуациипросматривается список операторов catch, чтобы установить соответствие.Исключительная ситуация соответствует оператору catch, если инструкция,вызвавшая исключительную ситуацию, находится в соответствующем диапазоне, а сама исключительная ситуация принадлежит подтипу типа ситуаций, которые обрабатывает оператор catch. Если соответствующий операторcatch найден, то управление передается обработчику. Если нет — текущий магазинный фрейм удаляется, и исключительная ситуация возбуждаетсявновь.Порядок операторов catch в списке важен. Интерпретатор передает управление первому подходящему оператору catch.8.5.
Организация информации в генераторе кодаСинтаксическое дерево в чистом виде несет только информацию о структуре программы. На самом деле в процессе генерации кода требуется такжеинформация о переменных (например, их адреса), процедурах (также адреса,уровни), метках и т. п. Для представления этой информации возможны различные решения. Наиболее распространены два:– информация хранится в таблицах генератора кода;– информация хранится в соответствующих вершинах дерева.Рассмотрим, например, структуру таблиц, которые могут быть использованы в сочетании с Лидер-представлением.
Поскольку Лидер-представлениене содержит информации об адресах переменных, то эту информацию нужноформировать в процессе обработки объявлений и хранить в таблицах. Этокасается и описаний массивов, записей и т. п. Кроме того, в таблицах такжедолжна содержаться информация о процедурах (адреса, уровни, модули,в которых процедуры описаны, и т. п.).При входе в процедуру в таблице уровней процедур заводится новый вход— указатель на таблицу описаний.
При выходе указатель восстанавливаетсяна старое значение. Если промежуточное представление — дерево, то информация может храниться в вершинах самого дерева.160Глава 8. Промежуточное представление программы8.6. Уровень промежуточного представленияКак видно из приведенных примеров, промежуточное представление программы может быть в различной степени близким либо к исходной программе,либо к машине.
Например, промежуточное представление может содержатьадреса переменных, и тогда оно уже не может быть перенесено на другуюмашину. С другой стороны, промежуточное представление может содержатьраздел описаний программы, и тогда информацию об адресах можно извлечьиз обработки описаний. В то же время ясно, что первое более эффективно,чем второе. Операторы управления в промежуточном представлении могутбыть представлены в исходном виде (в виде операторов языка if, for, whileи т. п.), а могут содержаться в виде переходов.
В первом случае некотораяинформация может быть извлечена из самой структуры (например, для оператора for — информация о переменной цикла, которую, может быть, разумнохранить на регистре, для оператора case — информация о таблице метоки т. п.). Во втором случае представление проще и унифицированней.Некоторые формы промежуточного представления удобны для различногорода оптимизаций, некоторые — нет (например, косвенные тройки, в отличиеот префиксной записи, позволяют эффективное перемещение кода).Глава 9ГЕНЕРАЦИЯ КОДАЗадача генератора кода — построение для программы на входном языкеэквивалентной машинной программы. Обычно в качестве входа для генератора кода служит некоторое промежуточное представление программы.Генерация кода включает ряд специфических независимых подзадач: распределение памяти (в частности, распределение регистров), выбор команд,генерацию объектного (или загрузочного) модуля.
Конечно, независимостьэтих подзадач относительна: например, при выборе команд нельзя не учитывать схему распределения памяти, и, наоборот, схема распределения памяти(в частности, регистров) ведет к генерации той или иной последовательностикоманд. Однако удобно и практично эти задачи все же разделять, обращаяпри этом внимание на их взаимодействие.В какой-то мере схема генератора кода зависит от формы промежуточногопредставления. Ясно, что генерация кода из дерева отличается от генерациикода из троек, а генерация кода из префиксной записи отличается от генерации кода из ориентированного графа. В то же время все генераторыкода имеют много общего, и основные применяемые алгоритмы различаются,как правило, только в деталях, связанных с используемым промежуточнымпредставлением.В дальнейшем в качестве промежуточного представления мы будем использовать префиксную нотацию.
А именно, алгоритмы генерации кода будемизлагать в виде атрибутных схем со входным языком Лидер.9.1. Модель машиныПри изложении алгоритмов генерации кода мы будем следовать некотороймодели машины, в основу которой положена система команд микропроцессораMotorola MC68020. В микропроцессоре имеется регистр — счетчик командPC, 8 регистров данных и 8 адресных регистров.В системе команд используются следующие способы адресации:ABS — абсолютная: исполнительным адресом является значение адресноговыражения.IMM — непосредственный операнд: операндом команды является константа, заданная в адресном выражении.6 В.А.