在封闭范围内更新变量的 SSA 表示
SSA representation of updating a variable in enclosing scope
当编译器使用 SSA 形式表示代码时,对局部变量的更新成为新变量。但是,当变量在封闭范围内时,这并不总是有效,例如(使用 JavaScript 语法来说明,这种情况可能出现在许多语言中):
function f() {
var x = 1;
function g() {
x++;
}
...
}
通常的表示方式是什么?
闭包中使用的可变自由变量(在您的示例中为x
)需要隐式"boxed"。
有两个问题需要考虑。首先,生命周期:变量可能比创建它的范围更长。 (f
可以returng
,或者存储在持久容器中。)其次,共享:变量可以被f
、g
或f
.
创建的任何其他函数
最简单的解决方案是将变量更改为 "box"(一个对象的容器,它是变量的值)。盒子本身是不可变的(也就是说,名称总是指向同一个盒子)。对变量值的修改和引用成为容器setter和getter方法。当然,值的存储必须在不再需要时动态分配和回收(与任何容器一样)。
在某些情况下可以进行优化——甚至可能是大多数情况。
首先,如果变量从未被修改,则可以为每个闭包提供值的副本而不是装箱值。
其次,如果变量是非共享的——它不会被执行 f
创建的任何其他函数关闭,并且在创建 [=12] 之后它不会被 f
引用=] -- 变量可以简单地移动到 g
的闭包中。
实际上,在上述两种情况下,闭包本身都变成了盒子,但这具有不需要单独动态分配的优点。
证明这些优化在特定程序中的有效性需要良好的静态分析。第一个很简单,因为修改很容易在语法上检测到,但第二个需要流分析(至少)。
在上面,我对可能应用优化的情况使用了保守的描述,只需要简单的流程分析;检测其他可能的应用程序更复杂。
当编译器使用 SSA 形式表示代码时,对局部变量的更新成为新变量。但是,当变量在封闭范围内时,这并不总是有效,例如(使用 JavaScript 语法来说明,这种情况可能出现在许多语言中):
function f() {
var x = 1;
function g() {
x++;
}
...
}
通常的表示方式是什么?
闭包中使用的可变自由变量(在您的示例中为x
)需要隐式"boxed"。
有两个问题需要考虑。首先,生命周期:变量可能比创建它的范围更长。 (f
可以returng
,或者存储在持久容器中。)其次,共享:变量可以被f
、g
或f
.
最简单的解决方案是将变量更改为 "box"(一个对象的容器,它是变量的值)。盒子本身是不可变的(也就是说,名称总是指向同一个盒子)。对变量值的修改和引用成为容器setter和getter方法。当然,值的存储必须在不再需要时动态分配和回收(与任何容器一样)。
在某些情况下可以进行优化——甚至可能是大多数情况。
首先,如果变量从未被修改,则可以为每个闭包提供值的副本而不是装箱值。
其次,如果变量是非共享的——它不会被执行 f
创建的任何其他函数关闭,并且在创建 [=12] 之后它不会被 f
引用=] -- 变量可以简单地移动到 g
的闭包中。
实际上,在上述两种情况下,闭包本身都变成了盒子,但这具有不需要单独动态分配的优点。
证明这些优化在特定程序中的有效性需要良好的静态分析。第一个很简单,因为修改很容易在语法上检测到,但第二个需要流分析(至少)。
在上面,我对可能应用优化的情况使用了保守的描述,只需要简单的流程分析;检测其他可能的应用程序更复杂。