[WebKit] JavaScriptCore解析--高階篇(三) Register Allocation & Trampoline
Register Allocation
對於一個JIT而言,暫存器分配對系統的消耗通常是一個瓶徑。之前有Graph Coloring Allocators, Chaitin style等分配方式,現在要介紹的是DFG JIT使用的Linear Scan演算法。其基本工作方式是將佔用暫存器的變數根據生命週期長短排列出來,在使用時檢視可以回收哪些暫存器加以利用。
先看一些定義:
•Live interval:是某個變數可以存活的一個指令序列,也可以稱為了連續性。這個也依賴於演算法使用的是深度優先還是廣度優先。如下圖,B1~B4代表的是四個Basic Blocks,w/r代表的是讀和寫.
•Spilling:當變數儲存到堆疊時就稱為溢位。
•Interference: 當兩個活動區間共同存在於一個程式中時,稱他們之間會有干擾。
演算法的執行過程簡述如下:
1. 計算變數的live interval.
2. 遍歷:
2.1 如果live interval已經過期就扔掉。
2.2 分配新的live interval和暫存器。
2.3 如果無法分配(所需的interval過長等),則spill出去,再選擇較低成本的變數。
複雜度:O(V logR) (V是變數數,R暫存器數)
下面是示意圖:
Trampoline
再介紹一下JIT中應用的Trampoline,蹦床或者彈簧技術,可以達到延遲編譯的效果(其它領域的效果不同,比如編譯器裡的
在JSC中,相關程式碼檢視JITStubs.cpp中的實現,如ctiTrampoline等。下面是一個呼叫堆疊:
然後再跳轉到具體的操作(可能會調回到LLInt對應的slow path進行處理):
參考:
Massimilliano Poletto, Linear Scan Register Allocation
CS 380C Lecture 14, Register Allocation
系列索引: