SSA представление обновления переменной в пределах объема

Когда компилятор использует форму SSA для представления кода, обновления локальных переменных становятся новыми переменными. Но это не всегда работает, когда переменная находится во вложенной области видимости, например (с использованием синтаксиса JavaScript для иллюстрации, ситуация может возникнуть во многих языках):

function f() {
    var x = 1;
    function g() {
        x++;
    }
    ...
}

Какой обычный способ представить это?

1 ответ

Решение

Изменяемая свободная переменная, используемая в замыкании (x в вашем примере) должен быть неявно "в штучной упаковке".

Есть две проблемы для рассмотрения. Во-первых, время жизни: переменная может пережить область, в которой она была создана. (f мог вернуться gили сохраните его в постоянном контейнере.) Во-вторых, совместное использование: переменная может быть изменена f, gили любая другая функция, созданная f,

Самое простое решение состоит в том, чтобы изменить переменную на "коробку" (контейнер одного объекта, который является значением переменной). Само поле является неизменным (то есть имя всегда относится к одному и тому же полю). Модификация и ссылка на значение переменной становятся методами установки и получения контейнера. Конечно, хранилище для значения должно быть динамически выделено и восстановлено, когда больше не нужно (как с любым контейнером).

В некоторых случаях доступны оптимизации - возможно, даже в большинстве случаев.

Во-первых, если переменная никогда не изменяется, может быть возможно дать каждому закрытию копию значения вместо упаковки значения.

Во-вторых, если переменная не является общей, она не закрывается какой-либо другой функцией, созданной выполнением f и на него не ссылаются f после создания g - переменная может быть просто перемещена в gзакрытие.

В действительности, в обоих вышеупомянутых случаях само закрытие становится боксом, но это имеет то преимущество, что не требует отдельного динамического выделения.

Доказательство правильности этих оптимизаций в конкретной программе требует хорошего статического анализа. Первый прост, поскольку модификацию легко обнаружить синтаксически, но второй требует анализа потока (по крайней мере).

Выше я использовал консервативное описание обстоятельств, при которых может применяться оптимизация, что требует только простого анализа потока; обнаружение других возможных приложений является более сложным.

Другие вопросы по тегам