Бывают ситуации, когда оптимизация хвостового вызова потенциально может нарушить ABI или, по крайней мере, будет очень сложной для реализации в семантическом сохранении. Например, подумайте о независимом от позиции коде в разделяемых библиотеках: некоторые платформы позволяют программам динамически связываться с библиотеками, чтобы сохранить основную память, когда разные приложения зависят от одной и той же функциональности. В таких случаях библиотека загружается один раз и отображается в каждую из виртуальной памяти программы, как если бы это было единственное приложение в системе. В UNIX, а также в некоторых других системах это достигается за счет использования независимого от положения кода для библиотек, поэтому адресация относится скорее к смещению, чем к абсолютному, к фиксированному адресному пространству. Однако на многих платформах независимый от положения код не должен быть оптимизирован для хвостового вызова. Проблема заключается в том, что смещения для навигации по программе должны храниться в реестрах; на Intel 32-бит, %ebx
используется, который является зарегистрированным регистром; другие платформы следуют этому понятию. В отличие от функций, использующих обычные вызовы, те, кто развертывает хвостовые вызовы, должны восстанавливать регистры, сохраненные вызываемым абонентом, до того, как они отключаются к подпрограмме, а не когда они возвращаются. Обычно это не проблема, потому что на данный момент самая главная функция вызова не заботится о значении, хранящемся в %ebx
, но независимый от позиции код зависит от этого значения от каждой команды перехода, вызова или ветвления.
Другие проблемы могут быть ожидающими очистки в объектно-ориентированных языках (C++), что означает, что последний вызов в функции на самом деле не является последним вызовом - очистками являются. Следовательно, компилятор обычно не оптимизирует, если это так.
Также setjmp
и longjmp
проблематичны, конечно, так как это эффективно означает, что функция может завершить выполнение более одного раза, прежде чем она на самом деле закончится. Трудно или невозможно оптимизировать во время компиляции!
Есть, вероятно, больше технических причин, о которых можно подумать. Это лишь некоторые соображения.
Связано: http://stackoverflow.com/questions/2250727/regarding-stack-reuse-of-a-function-calling-itself –