2017-07-17 72 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「關閉。

實際上,在上述兩種情況下,閉包本身都變成了盒子,但這具有不需要單獨動態分配的優點。

證明這些優化在特定程序中的有效性需要良好的靜態分析。第一個很簡單,因爲修改很容易檢測句法,但第二個需要流程分析(至少)。

在上面,我對可能應用優化的情況進行了保守的描述,只需要簡單的流量分析;檢測其他可能的應用程序更爲複雜。