Реализация локальных процедур и лямбда-функций. |
1. Заголовок или название темы должно быть информативным !
2. Все тексты фрагментов программ должны помещаться в теги [code] ... [/code] или [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ" и используйте ПОИСК !
4. НЕ используйте форум для личного общения!
5. Самое главное - это раздел теоретический, т.е. никаких задач и программ (за исключением небольших фрагментов) - для этого есть отдельный раздел!
Реализация локальных процедур и лямбда-функций. |
TarasBer |
7.12.2011 16:27
Сообщение
#1
|
Злостный любитель Группа: Пользователи Сообщений: 1 755 Пол: Мужской Репутация: 62 |
Возьмём такой код и посмотрим, что будет делать компилятор.
Внутренняя функция должна иметь какой-то доступ к параметрам внешней. А так как параметры внешней расположены на стеке, то они не имеют фиксированного адреса (т.к. может быть вызов f-g-h или f-h, и внутри h переенные могут быть расположены как сразу за переменными f, так и после переменных g). И их адрес даже не обязательно фиксирован относитель начала стека на момент вызова внутренней функции. Поэтому внутренняя функция имеет потайной параметр - указатель на вершину стека на момент вызова внешней функции. Через него и происходит адресация к переменным внешней функции. Кстати, именно из-за этого локальные функции в Д7 нельзя передавать никуда по указателю. В других языках либо введено понятие "ссылка на функцию", которые хранит указатель на допольнительные данные, либо вообще все указатели хранят доп.информацию, либо ещё как-то выкручиваются, не знаю, как. Но мне стало интересно, а как происходит работа с внутренней внутренней функцией. Передаются ли в неё два параметра (на вершины стеков внешних функций), или как-то ещё. Оказалось, что передаётся один параметр - указатель на локальные переменные первой внутренней функции. Чтобы получить доступ к внешним локальным переменным, делается двойное разыменование: сначала разываменовываем указатель на переменные первой внутренней, среди них находим указатель на переменные внешней и уже его разыменовываем. Эффективность такого подхода меня очень пугает. Почему был выбран именно такой вариант вместо передачи двух указателей? Однако компилятор Д7 таки проводит оптимизации! Если внутренняя функция не обращается к переменым внешней, то в неё не передается указатель на стек. Увы, это единственная замеченная мной оптимизация. Можно было сделать и больше оптимизаций. Например, если внутренняя функция не вызывается ни в каких других внутренних функциях, то для неё вершина стека фиксирована относительно вершины стека внешней, то есть указатель передавать не надо. Этой оптимизации в Д7 нету. Или, например, если используются только несколько параметров внешней (не более двух), то передать по ссылке только их, а не весь блок локальных переменных (тут надо понимать, что "передача по ссылке" - это не обязательно передача указателя, это может быть и передача самого значения с копированием обратно, причём передача хоть в регистре, что уберёт ненужную возню с разыменованиями и двойными разыменованиями). Ну и про локальные лямбды, передаваемые наружу, у меня тоже есть некоторые вопросы, но об этом я спрошу в следующий раз. -------------------- |
Текстовая версия | 28.09.2024 22:56 |