Т. Пратт, М. Зелковиц - Языки программирования - разработка и реализация (4-е издание_ 2002) (1160801), страница 114
Текст из файла (страница 114)
Если локальная среда подпрограммы 5цЬ из листинга 9.6 должна быть сохранена в промежутках между вызовами, тогда одна таблица локальной среды, содержащая сохраняемые псременныс, размещается в сегменте кода подпрограммы 5иЬ как некоторая его часть (рис. 9.5). 9.2, Атрибуты управления данными 413 тому, как было бы сохранено значение константы в сегменте кода). Если предположить, что каждая сохраняемая переменная объявлена в начале подпрограммы 5вЬ, то в таком случае компилятор сможет определить размер каждой переменной из таблицы локальной среды и вычислить смещение от начала сегмента кода (базовый адрес) до начала области памяти, выделяемой под объект данных.
Когда какой-либо оператор из сегмента кода ссылается на переменную у во время выполнения, смещение этой переменной добавляется к базовому адресу сегмента кода для определения местоположения объекта данных, ассоциированного с именем у. Сам идентификатор У не нужен во время выполнения, поэтому он вообще не сохраняется. Такая реализация сохранения для локальной среды не требует каких-либо специальных действий для сохранения значений объектов данных; значения объектов, сохраненные на момент завершения вызова подпрограммгя 5цЬ, будут находиться в тех же областях памяти и при следующем ее вызове. Также не требуется каких-либо специальных действий для перехода от одной локальной среды к другой, когда одна подпрограмма вызывает другую. Поскольку код и локальные данные для каждой подпрограммы являются частью одного и того же сегмента кода, передача управления сегменту кода другой подпрограммы автоматически приводит к переходу ца среду локальных ссылок атой вызванной подпрограммы.
Удаление локальных сред. Если локальная среда подпрограммы 5вЬ подлежит удалению между вызовами и должна создаваться заново при каждом входе н подпрограмму, тогда таблица локальной среды, содержащая удаляемые переменные, должна храниться в памяти как часть записи активации подпрограммы 5вЬ. Предположим, что запись активации при входе в подпрограмму 5цЬ создается в центральном стеке и удаляется из него при выходе из подпрограммы, как описано в разделе 9.1, тогда удаление среды локальных ссылок происходит автоматически. В предположении, что каждая подлежащая удалению локальная переменная объявляется в начале определения подпрограммы 5вЬ, компилятор опять-таки сможет определить количество переменных и размер каждой переменной, содержащейся в таблице локальной среды, и вычислить смещение начала области размещения каждого объекта данных относительно начала записи активации (базовый адрес).
Напомним, что во время выполнения поддерживается указатель СГР (указатель текущей среды ссылок), так что в любой точке выполнения программы он указывает на базовый адрес записи активации в стеке подпрограммы, выполняющейся в данный момент. Если выполняется подпрограмма 5цЬ и ссылается на переменную У, то местоположение объекта данных, ассоциированного с у, определяется посредством добавления смещения переменной т к содержимому указателя СГР. Сам идентификатор у также ие требуется хранить в записи активации; для выполнения подпрограммы нужны только обьекты данных. Такая реализация изображена на рис.
9.6. Пунктирная стрелка показывает смещение, вычисленное для ссылки на переменную у. Следуя общей модели реализации подпрограмм, описанной в разделе 8.3.2, достаточно легко реализовать оба подхода к моделировыгию среды ссылок — с удалением и сохранением локальных переменных. Несколько дополнительных моментов заслуживают внимания. 4Ч 4 Глава 9. Управление подпрограммами н зов Рнс. 9.6. Расположение удаляемых лохальных переменных н ссыпки на ннх 1. Для простой структуры вызова-возврата, описанной в начале втой главы, сохранение и удаление в отсутствие рекурсии приводит, по существу, к такой же самой реализации, поскольку не существует более одной записи активации, которая может быть размещена статически.
Но если для переменных используются начальные значения, то возможны два различных подхода к реализации инициализации переменных (см, задачу 2), 2. Отдельньсе переменныеслегкостьюмогутбыть реализованыобоимиспособами — те переменные, которые требуется сохранить, располага|отся в сегменте кода, а те, которые нужно уничтожить, размещаются в записи активации. Этот способ используется в Р1.,'1: сохраняемые переменные объявляются с атрибутом ЯТЛТ1С, а удаляемые переменные обьявляются как А1)ТОМАТ1С.
3. Имя подпрозри сны, которое ассоциируется с объявлением подпрограммы в среде локальных ссылок, всегда может рассматриваться как сохраняемое. Лссоциация имени и определения может быть представлена указателем в сегменте кода, который указывает на сегмент кода, представляющий подпрограмму. 4. Инн формальнохо пирамеглра представляется обьекгом данных, коз орый заново инициализирустся новым значением прн каждом вызове подпрограммы, как описано в разделе 9.3. Такая инициализация предотвращает сохранение старого значения формального параметра между вызовами подпрограммы, Таким образом, формальные параметры всегда трактуются как удаляемые ассоциации.
5. Если допускается рехургмвный вызов подпрограмм, то в один и тот же момент времени в центральном стеке может находиться несколько записей активации одной и той же подпрограммы Боб, Если переменная У трактуется как подлежащая удалению, то в каждой записи активации должен содержаться свой 9.3.
Передача параметров 415 отдельный обьект с именем У, и во время выполнения каждой активации он будет ссылаться на свою собственную локальную копию объекта У. Обычно желательно иметь отдельные копии объекта У в каждой активации, поэтому в языках, допускающих рекурсивные подпрограммы (нли иные структуры управления подпрограммами, приводящие к одновременному существованию в памяти нескольких активаций одной подпрограммы), как правило, используются удаляемые локальные среды.
Тем не менее часто сохранение некоторых локальных переменных имеет большое значение. Например, в языке АЕООЕ 60 локальныс псремснныс, объявленные с атрибутом оно, становятся сохраняемыми переменными, хотя содержащая это объявление подпрограмма может быть рекурсивной. Если несколько активаций подпрограммы бцЬ ссылаются на сохраняемую переменную 1', то существует только один объект данных т, который используется во всех активациях подпрограммы 5пЬ, причем его значение сохраняется от одной активации до другой.
Преимущества и недостатки. Оба описанных подхода используются в большом количестве языков, в том числе и в наиболее важных языках. Подход с сохранением локальных данных позволяет писать подпрограммы, чувстиллельпые к лредысиории, поскольку результат каждого обращения к подпрограмме зависит не только от входных данных, цо и от значений локальных данных, вычисленных во время предыдущих активаций. Подход с удалением локальных данных не позволяет сохранять их между вызовами, поэтому, если требуется сохранить между вызовами подпрограммы значение какой-либо переменной, она должна быть объявлена как нслок'щьпая для данной подпрограммы. Для рекурсивных подпрограмм, однако, удаление локальных переменных является более естественной стратегией. Такой подход обладает также тем преимуществом, что в атом случае экономится место в памяти, так как требуется хранить таблицы локальных сред только тех подпрограмм, которые выполняются или выполнение которых приостановлено (но не завершено).
Таблицы локальных сред для всех подпрограмм существук>т на протяжении всего времени выполнения программы с использованием сохранения. 9.3. Передача параметров Строго локальный объект данных используется в пределах одной среды локальных ссылок, то есть внутри одной подпрограммы. Но часто объекты данных используются совместно несколькими подпрограммами таким образом, что операции, определенные в каждой из подпрограмм, могут использовать зтн данные. Объект данных может передаваться как явный параметр межлу подпрограммами, но возможны такие ситуации, когда использование явных параметров неудобно.
Рассмотрим, например, множество подпрограмм, которос использует общую таблицу данных. Все подпрограммы должны иметь доступ к этой таблице, по передавать ее каждый раз прн вызове очередной подпрограммы в виде явного параметра слишком утомительно. Такое совместное использование общих данных основывается на совместном использовании ассоциаций для идентификаторов. Если три подпрограммы Р, 0 и к должны иметь доступ к одной и той жс переменной Х, то подходящим решением будет просто позволить идентификатору Х иметь одну и ту 416 Глава 9.
Управление подпрограммами же ассоциацию в каждой подпрограмме. Ассоциация для г становится частью локальной среды для одной из подпрограмм, и она же становится общей частью нвлокальной среды двух других. Совместное использование объектов данных при помощи нелокальной среды является важной альтернативой совместному использованию данных через передачу параметров. Явная передача параметров и результатов — основной альтернативный метод совместного использования данных подпрограммами. В отличие от использования сред нелокальных ссылок, где для решения этой задачи определенные нелокальные имена должны быть сделаны видимыми для подпрограммы, объекты данных, передаваемые как параметры и результаты, передаются без присоединения к ним имени. В получающей данные подпрограмме каждому объекту данных дается новое локальное имя, которое будет использоваться для ссылок на этот объект.