楔子
在看GC垃圾回收plan_phase的時候,發現了一段特殊的代碼,仔細研究下得知,獲取當前數字bit位裏面爲1的個數。
通過這個bit位爲1的個數(count),來確定掛接當前二叉樹子節點的一個地方。
算法
size_t logcount (size_t word)
{
//counts the number of high bits in a 16 bit word.
assert (word < 0x10000);
size_t count;
count = (word & 0x5555) + ( (word >> 1 ) & 0x5555);
count = (count & 0x3333) + ( (count >> 2) & 0x3333);
count = (count & 0x0F0F) + ( (count >> 4) & 0x0F0F);
count = (count & 0x00FF) + ( (count >> 8) & 0x00FF);
return count;
}
counts the number of high bits in a 16 bit word.這一段英文註釋很有誤導性,它的意思翻一下大致是:獲取當前16位字裏面的高位bit數。
如果按照這個理解,基本上不知道這個logcount函數是幹嘛的。
但實際上它做的事情非常簡單。
舉個例子:
5的二進制:0101,那麼經過logcount函數計算之後,返回值爲2。因爲5的二進制裏面有兩個1。
以此類推,6返回2,7返回3,8返回1。
背景
GC垃圾回收的計劃階段,當plan_phase構建二叉樹的時候,需要區分根節點,左子節點,和右子節點。新加入的新節點作爲根節點,新節點的左子節點(G)就是上一個根節點(C)的右子節點。新節點本身又作爲上一個根節點(C)的右子節點。
圖:
上面這個算法的作用就是,把新加入的新節點掛接到二叉樹深度N(logcount返回值)的地方。
圖兩個二叉樹,分別深度爲2和3。logcount返回其參數bit位裏面爲1的個數,作爲二叉樹的深度。然後進行一個掛接。其行爲邏輯是二叉樹構建的核心。
整體
GC計劃階段(plan_phase)的二叉樹構建主要是爲後面的重定位,壓縮和清掃做準備。
二叉樹是其關鍵一步。
大致爲:
1.區分固定對象和非固定對象,如果非固定對象後面跟着非固定對象就會形成一個堆段,如果後面繼續有非固定對象,則繼續加入這個小堆段。如果後面跟着固定對象則到小堆段到此爲止。然後判斷固定對象後面是否跟着固定對象,如果是則把這兩個固定對象形成一個小堆段。後面繼續判斷,如果還是固定對象則加入到小堆段。如沒有,則此小堆段到此爲止。其邏輯跟非固定對象一樣。如此一直遍歷完這個堆,這樣的話堆裏面形成了一個個小堆段。
2.這些小堆段,會被plan_phase當成一個個的節點,然後把這些節點通過相關的邏輯構建成一顆二叉樹。
3.如果二叉樹過於龐大,則無論是在時間還是在空間上的複雜度都很高。爲了避免性能問題,於是引入了brick_table來分割這顆龐大的二叉樹
結尾
理解其行爲,則需聯繫上下文,查看其整體構建,然後逐步推導。