虎書ML版裡面關於garbage collector的問題?

虎書裡面第288頁有這麼一段:

Stack上的那些變數的map怎麼implement我懂。問題是這個temp-map:

這裡temp是指在register color之前的unbounded number of temporaries,著色之後temp都會變成真的machine register的。

問題在於,就算我這個map做出來了。垃圾回收的時候collector得去看這個map裡面有哪幾個register存著pointer。比如說我們假設EBX跟EDX裡面存了root pointer,但是collector查看map這個本身的過程當中,collector被編譯之後(假設不是用彙編寫collector)的代碼就有可能會需要用到register,而且如果用到了EBX跟EDX那麼register裡面存的root pointer就會被覆蓋掉。

這個問題應該怎麼解決?多謝!


哈哈哈會問這個問題說明真的在做東西,很好。

補充點背景知識給對這個話題不了解的同學:

找出棧上的指針/引用 &<- stack map相關

現代JVM中的Safe Region和Safe Point到底是如何定義和劃分的? - RednaxelaFX 的回答 &<- safepoint相關

其實這個問題很好解決。取決於compiled code如何與collector交互。

拋開虎書的描述,抽象看這個問題:

最簡單的懶漢做法:

讓編譯器的CodeGenerator不要在任何可能進入GC的地方允許寄存器里存有託管指針。這樣所有託管指針最多只會在棧上,好辦。

要做到這點很簡單:首先不要在callee-save寄存器里分配託管指針,其次的的話:

  • 最偷懶當然是完全不要把具名的局部變數分配到寄存器里,全放棧上;然後臨時變數可以分配到寄存器里,但不要讓它們能活過一個GC發生點。
  • 略為少偷懶一點的話,可以在GC發生點的前把含有託管指針的活寄存器spill到棧上,過了GC發生點之後再restore回來。別說,LLVM以前的gcroot機制就是這麼乾的,很懶。這樣的壞處是,一個可能發生GC的位置前後會無條件多了一堆spill-restore代碼,但那個位置當前可能不需要進入GC,所以就浪費了功夫。隔壁組的同事最近給LLVM添加的statepoint機制就是要解決gcroot的弊病而做的。

不偷懶的做法:

如果compiled code是同步調用GC,那可以讓這種對GC的調用先經過一個帶有特殊calling convention的stub,進入的時候先把所有寄存器都保存到該stub的stack frame上,每個寄存器對應一個特定的offset,然後再真的調用runtime里GC的入口。在GC過程中,如果有需要對compiled frame的「寄存器狀態」讀寫,其實它們的值都在那個stub的stack frame里,直接對那裡操作即可,例如說找指針、修正指針,其實都是對stack frame上的版本操作。然後等GC結束後返回到那個stub,在stub臨返回前把保存的值restore到實際寄存器里。

這比前面的懶人辦法好很多——只有真的要進入GC的時候才spill和restore,平時不用付出這開銷。

如果compiled code是非同步「陷入」GC,例如說使用trap-based polling來做safepoint polling,那在trap進signal handler的時候可以得到一個ucontext,寄存器的值都在裡面。接下來GC該幹嘛幹嘛,需要操作compiled frame的「寄存器狀態」時對那個ucontext操作即可。然後GC結束後,把ucontext恢復給實際寄存器就好。

當然上面的做法很蠢——signal handler里不能待太久,更重要的是不能再干繁瑣的操作。所以也有另一種辦法,正統解法:在signal handler里找出能調用GC的stub的入口,把這個入口設到ucontext的PC欄位里,像這樣:

// uc = (ucontext_t) ...
uc-&>uc_mcontext.gregs[REG_PC] = (greg_t)stub

然後趕緊返回,離開signal handler。離開signal handler之後,控制會來到stub的入口,然後就跟前面說的同步調用的做法一樣搞就好了。HotSpot VM就是這麼做的嗯。


推薦閱讀:

如何評價 RAII 特性在 C++ 中的大範圍運用?
明明很多編程語言從對象數組中取數據比用SQL從表中取數據方便,為什麼資料庫還是使用SQL?
為什麼Python程序不怎麼佔用CPU資源?
假如DNA是一種編程語言,那麼誰能保證人類對DNA的修改沒有bug?
CPU空操作的原理是什麼?

TAG:編程語言 | 編譯原理 | GC垃圾回收計算機科學 |