2011-06-16 29 views
0

假設我有時也想編寫該語言生成C代碼的編譯器:實現在生成的C代碼析構函數

  • 已經完全引用計數GC,
  • 可以讓你回到一個點多幀(竊取Common Lisp的(return-from)表單),
  • ,並允許您爲每個數據類型定義一個析構函數(在數據結構的內存被釋放之前立即調用)。

你將如何去執行這個?你可以用C的setjmp()longjmp()來做到這一點,還有一個全局列表,可以在退棧的時候返回來進行清理。

另一種可能性是生成C++代碼。

回答

1

我首先考慮幾種方法。

一個類似於異常幀。創建每個線程鏈接的結構列表。在調用函數之前,在堆棧上創建一個結構並將其添加到列表的末尾。該結構包含一個jmp_buf。撥打電話setjmp,如果返回0,則繼續使用此功能,否則(以某種方式)檢查您是否是return-from的目標 - 如果是,則繼續使用該功能,否則清理您的當地人和longjmp前一幀。我認爲這可能是矯枉過正,這取決於這個return-from需要多麼靈活。是否只需要從周圍詞法範圍中的函數返回,或者我們是否實際上正在搜索調用堆棧以獲取可能甚至可能不存在的命名函數?如果前者,我懷疑我們需要這個。

另一種可能性是讓所有引用計數類型實現一個通用接口(在語言實現的內部,這是 - 它不需要用戶可見)。然後,您可以創建一堆需要清理的(指向)對象,以及在該堆棧中創建與調用堆棧級別對應的索引點的功能。在函數退出時,只需通過循環遍歷每個變量的列表來清除低於您要返回的堆棧級別的所有變量,而不需要跳轉到調用堆棧上方例程中的清理代碼段。然後你可以直接到達目標,或者你可以想出一個「調用約定」,其中的語言返回值實際上存儲在由指針參數(out-param)確定的位置,而關於C的返回值則表示您要返回到堆棧上的哪個位置。因此,呼叫者檢查返回值是否與自己的級別相匹配,如果不立即返回,則不需要longjmplongjmp的效率可能更高也可能更低,具體取決於您跳過的堆棧級別,以及重複檢查和返回的次數。

該方案有點像Symbian/C++中的清理堆棧。事實上,這要進一步 - 它不是要清理的資源必須實現通用接口,堆棧上的內容是一個TCleanupItem,它包含一個知道如何釋放資源的函數,以及一些要提供給該功能。