2017-07-17 75 views
0

当编译器使用SSA形式表示代码时,对局部变量的更新成为新变量。但是,当变量处于封闭范围内时,这并不总是有效的,例如, (使用JavaScript语法说明,可以在许多语言中出现的情况):在封闭范围内更新变量的SSA表示

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

什么是代表这个通常的方法是什么?

回答

2

封闭中使用的可变自由变量(在您的示例中为x)需要隐式“装箱”。

有两个问题需要考虑。首先,生命期:变量可能超过它创建的范围。 (f可能会返回g,或将其存储在持久性容器中。)其次,共享:可通过fg或由f创建的任何其他函数修改该变量。

最简单的解决方案是将变量更改为“框”(一个对象的容器,它是变量的值)。盒子本身是不可变的(也就是说,这个名字总是指向相同的盒子)。修改和引用变量的值成为容器setter和getter方法。当然,该值的存储必须在不再需要时动态分配和回收(与任何容器一样)。

在某些情况下可以优化 - 甚至可能是大多数情况。首先,如果变量永远不会被修改,则可能为每个闭包赋予一个值的副本,而不是装箱该值。

其次,如果变量是不共享 - 这是不是通过的f执行创建的任何其他功能创造g后关闭,它不被引用的f - 变量可以简单地转移到g“关闭。

实际上,在上述两种情况下,闭包本身都变成了盒子,但这具有不需要单独动态分配的优点。

证明这些优化在特定程序中的有效性需要良好的静态分析。第一个很简单,因为修改很容易检测句法,但第二个需要流程分析(至少)。

在上面,我对可能应用优化的情况进行了保守的描述,只需要简单的流量分析;检测其他可能的应用程序更为复杂。