Когда вы вызываете функцию, подобную этой
f 42 (g x y)
тогда поведение во время выполнения выглядит примерно так:
p1 = malloc(2 * sizeof(Word))
p1[0] = &Tag_for_Int
p1[1] = 42
p2 = malloc(3 * sizeof(Word))
p2[0] = &Code_for_g_x_y
p2[1] = x
p2[2] = y
f(p1, p2)
То есть аргументы обычно передаются в виде указателей на объекты в куче, как в Java, но в отличие от Java эти объекты могут представлять приостановленные вычисления, или thunks , такие как (g x y
/ p2
) в нашем примере. Без оптимизации эта модель выполнения довольно неэффективна, но есть способы избежать многих из этих накладных расходов.
GHC выполняет много операций вставки и распаковки. Встраивание устраняет накладные расходы при вызове функции и часто обеспечивает дальнейшую оптимизацию. Распаковка означает изменение соглашения о вызовах, в приведенном выше примере мы могли бы передать 42
напрямую, вместо создания объекта кучи p1
.
Анализ строгости определяет, гарантированно ли оценивается аргумент. В этом случае нам не нужно создавать thunk, но полностью вычислить выражение, а затем передать окончательный результат в качестве аргумента.
Кэшируются небольшие объекты (в настоящее время только 8 бит Char
с и Int
с). То есть вместо выделения нового указателя для каждого объекта возвращается указатель на кэшированный объект. Несмотря на то, что объект изначально размещен в куче, сборщик мусора будет дублировать их позже (только малые Int
с и Char
с). Поскольку объекты неизменны, это безопасно.
Ограниченный анализ побега. Для локальных функций некоторые аргументы могут передаваться в стеке, поскольку к моменту возврата внешней функции они известны как мертвый код.
Редактировать : (более) более подробную информацию см. В «Внедрение ленивых функциональных языков на стандартном оборудовании: G-машина без меток Spineless» . Этот документ использует «push / enter» в качестве соглашения о вызовах. В новых версиях GHC используется соглашение о вызовах eval / apply. Для обсуждения компромиссов и причин этого переключения см. «Как сделать быстрое карри: push / enter vs eval / apply»