2014-01-29 49 views
5

在模塊級別聲明的函數永遠不會有閉包,並通過LOAD_GLOBAL訪問非局部變量。全局變量與解除引用變量的實現

聲明的功能而不是在模塊級別可能有閉包並通過LOAD_DEREF訪問非本地變量,如果這些變量不是全局變量的話。所以基本上我們有三種存儲和加載變量的方法:GLOBAL(全局),FAST(本地)和DEREF(非本地,封閉,覆蓋)。

爲什麼GLOBAL?如果讓所有函數都關閉,那麼FASTDEREF就足夠了嗎?非局部變量和全局變量之間是否存在一些重要區別?這可能是由於性能問題,因爲也許全局變量(如模塊級定義的所有函數和類(包括它們的方法)加上內建函數)通常比非局部變量更常見?

回答

5

在編譯期間枚舉本地名稱和封閉名稱。在運行時,它們存儲在C數組中並使用整數/索引訪問。 LOAD_FASTLOAD_DEREF取一個C整數並執行C數組查找。

全局名稱無法在編譯時枚舉,它們可以在運行期間通過任何代碼在整個過程中添加和刪除。這與對象屬性類似 - 因爲全局變量本質上是模塊對象的屬性。因此,它們存儲在字典中,並且實現的訪問方式與本地名稱和封閉名稱的訪問方式截然不同。 LOAD_GLOBAL需要一個字符串(常量)並執行字典查找。

+0

然後我猜在編譯期間的枚舉過程中,編譯器還會判斷一個變量是否(可能)從一個封閉範圍內訪問,並且在這些情況下使用'STORE_DEREF'而不是'STORE_FAST'。這是正確的嗎? – Hyperboreus

+0

@Hyperboreus是的,它只是搜索作業和非本地聲明。 – delnan

+0

這是否也意味着我需要兩次掃描來編譯一個塊(範圍,幀,我不知道正確的術語)?我的意思是,我需要所有*封閉*塊的信息以便在「STORE_FAST」和「STORE_DEREF」之間做出決定。同時,我需要關於所有*封閉*塊的信息,以便在「LOAD_DEREF」和「LOAD_GLOBAL」之間做出決定。因此編譯一個孩子取決於父母,反之亦然。還是我得到這個錯誤? – Hyperboreus