Параметры и возврат11 / 19

Кадр стека: что движок хранит для вызова

Аргументы, локальные значения и место возврата у каждого вызова свои.

В предыдущем уроке мы рассмотрели Call Stack — стек вызовов. Каждая запись в нём должна помогать движку продолжить конкретный вызов: помнить его данные и куда вернуть управление.

Рассмотрим два вызова одной функции:

function double(value) {
  const result = value * 2;
  return result;
}
const first = double(3);
const second = double(8);
  1. При double(3) движку нужны значения value = 3 и result = 6. После return число 6 попадёт в first.
  2. Первый вызов завершается, его кадр снимается со стека.
  3. Вызов double(8) получает свой кадр: теперь value = 8, result = 16, а результат нужно вернуть в second.
Первый вызов · перед return
Кадр double(3)
Аргумент
value = 3
Локальное значение
result = 6
Куда вернуть результат
В присваивание first
return 6После возврата: first = 6
Следующий вызов · перед return
Кадр double(8)
Аргумент
value = 8
Локальное значение
result = 16
Куда вернуть результат
В присваивание second
return 16После возврата: second = 16
Два момента выполнения программы. Первый вызов уже завершён, когда начинается второй. Показаны данные вызовов, а не точное расположение памяти V8.

При вложенных вызовах кадр вызывающей функции остаётся в стеке, пока выполняется вызванная. Благодаря этому после return движок может продолжить предыдущую функцию с её данными. Это работает и при рекурсии, когда функция вызывает саму себя.

Спецификация описывает состояние выполнения через контексты исполнения. Кадры стека — способ организовать это состояние внутри движка.

Основной вывод

Кадр стека хранит состояние конкретного вызова функции: данные, нужные для её выполнения, и сведения о том, куда вернуться после return.

Проверить по первоисточнику ↗

ECMA-262 · Execution Contexts↗Как спецификация описывает состояние отдельных вызовов и стек контекстов исполнения.V8 · Stack frames↗Команда V8 о состоянии вызова, локальных значениях и возврате управления.