пятница, 3 августа 2012 г.

Реализация высокоуровневых языков программирования



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

Реализация высокоуровневых языков программирования
Высокоуровневый язык программирования определяет программную абстрак­цию: программист выражает алгоритм с использованием языка, а компилятор должен транслировать эту программу в целевой язык. Вообще говоря, высо­коуровневые языки программирования проще для программирования, но менее эффективны, т.е. целевые программы работают более медленно. Программисты, использующие низкоуровневые языки, обладают большими возможностями кон­троля над выполняемыми вычислениями и могут, в принципе, получать более эффективный код. К сожалению, на низкоуровневых языках труднее писать программы, и, что еще хуже, эти языки менее переносимы, программы на них более подвержены ошибкам и их труднее сопровождать. Оптимизирующие компиля­торы включают технологии для повышения производительности генерируемого кода, тем самым компенсируя неэффективность высокоуровневых абстракций.
Пример 1.2. Ключевое слово register в языке программирования С представляет собой пример взаимодействия между методами компиляции и эволюцией языка.
Когда язык С создавался в средине 1970-х годов, считалось необходимым позво­лить программисту определять, какие переменные должны размещаться в реги­страх. Однако после разработки эффективных методов распределения регистров такое управление стало излишним, и большинство современных программ не ис­пользуют эту возможность языка.
Более того, программы, использующие ключевое слово register, могут проиг­рывать в эффективности, поскольку программисты — не лучшие знатоки в низ­коуровневых вопросах наподобие распределения регистров. Выбор оптимального распределения регистров очень сильно зависит от архитектуры конкретной маши­ны. Следование принятым программистом решениям о низкоуровневом распре­делении ресурсов может в действительности привести к падению производитель­ности, в особенности при работе программы на других машинах, а не на той, для которой она создавалась.
Многие распространенные языки программирования смещаются в сторону увеличения уровня абстракции. Доминирующим языком программирования в 1980-е годы был С, но уже в 1990-х годах во многих новых проектах исполь­зовался язык программирования С++; разработанный в 1995 году язык програм­мирования Java быстро приобрел популярность к концу 1990-х годов. Новые воз­можности языков программирования приводили к новым исследованиям в обла­сти оптимизации кода. Далее будут рассмотрены основные возможности языков программирования, которые стимулировали значительное развитие технологий компиляции.
Практически все распространенные языки программирования, включая С, For­tran и Cobol, поддерживают определяемые пользователем агрегированные типы данных, такие как массивы и структуры, а также высокоуровневые средства управ­ления потоком выполнения, такие как циклы и вызовы процедур. Если огра­ничиться непосредственной трансляцией каждой высокоуровневой конструкции или операции обращения к данным, результат получится очень неэффективным. Разработанная оптимизация потоков данных (data-flow optimization) анализиру­ет потоки данных в программе и удаляет избыточность таких конструкций. Она генерирует код, который напоминает код, написанный на низком уровне профес­сиональным программистом.
Объектная ориентированность впервые появилась в языке Simula в 1967 го­ду и вошла в такие языки, как Smalltalk, С++, С# и Java. Ключевыми идеями, лежащими в основе объектной ориентированности, являются
-   абстракция данных;
-    наследование свойств.
Они делают программы более модульными и упрощают их поддержку. Объект- но-ориентированные программы отличаются от программ, написанных на других
языках программирования, тем, что они состоят из большего количества проце­дур меньшего размера (которые в объектно-ориентированном программировании называются методами). Таким образом, оптимизация должна быть способна пе­решагнуть границы процедур в исходной программе. Здесь оказалось особенно полезным встраивание процедур, представляющее собой замену вызова процеду­ры ее телом. Была также разработана оптимизация, ускоряющая диспетчеризацию виртуальных методов.
Java обладает многими облегчающими программирование возможностями, ко­торые появились ранее в других языках программирования. Язык Java безопасен с точки зрения типов, т.е. объект не может использоваться вместо объекта несвя­занного типа. Обращение к массивам выполняется с проверкой выхода за пределы массива. Java не имеет указателей и не использует соответствующую арифметику. Этот язык программирования имеет встроенную систему сборки мусора, которая автоматически освобождает выделенную для переменных память, которая больше не используется. Все эти возможности упрощают программирование, но приводят к дополнительным накладным расходам времени выполнения. Разработанная для языка программирования Java оптимизация снижает накладные расходы, напри­мер, устраняя излишние проверки диапазонов и выделяя память для объектов, недоступных извне процедуры, в стеке, а не в куче. Разработаны также эффек­тивные алгоритмы для минимизации накладных расходов по сборке мусора.
Кроме прочего, язык программирования Java разработан для поддержки пе­реносимости и мобильного кода. Программы распространяются в виде байт-ко­да Java, который либо интерпретируется, либо компилируется в машинный код динамически, т.е. в процессе выполнения. Динамическая компиляция изучалась также и в других контекстах, когда информация извлекается динамически, во вре­мя выполнения, и используется для получения более оптимизированного кода. При такой динамической оптимизации важно минимизировать время компиля­ции, которое является частью накладных расходов выполнения программы. Рас­пространенная методика состоит в компиляции и оптимизации только тех частей программы, которые будут часто выполняться.

Комментариев нет:

Отправить комментарий