我剛剛開始看WebAssembly MVP,並注意到沒有訪問堆棧和堆棧指針,或者確實有任何結構化的異常處理支持(throw/catch)等。如何在WebAssembly中實現setjmp/longjmp?
鑑於它應該是一個C編譯目標,它肯定有可能實現setjmp
和longjmp
,但我無法理解這可以如何很好地完成。這個構造看起來如何呢?
我剛剛開始看WebAssembly MVP,並注意到沒有訪問堆棧和堆棧指針,或者確實有任何結構化的異常處理支持(throw/catch)等。如何在WebAssembly中實現setjmp/longjmp?
鑑於它應該是一個C編譯目標,它肯定有可能實現setjmp
和longjmp
,但我無法理解這可以如何很好地完成。這個構造看起來如何呢?
WebAssembly MVP不支持零成本異常處理。
C++異常處理和setjmp
/longjmp
目前實現通過由具有各try
或「調用」執行與延續的JavaScript調用WebAssembly的C++代碼Emscripten。然後拋出一個JavaScript異常,它將展開堆棧並處理展開代碼所在的「着陸板」(通常是析構函數調用和塊)。這意味着每個continuation都會收到一個布爾值:異常路徑或常規路徑。
這是超級貴!如果LLVM不能證明函數調用不能拋出,那麼它的IR包含一個invoke
指令,並且Emscripten依靠這個來插入異常處理代碼。 C++中的默認值是任何東西都可以拋出,所以如果你看看LLVM IR,當你編譯異常的時候,全是invoke
。
零成本exception handling is being worked on at the moment,所以這種情況應該最終解決。這將用於實現setjmp
/longjmp
。這可以啓用所有定義的行爲setjmp
/longjmp
,即在不調用C++析構函數的情況下展開堆棧。然而,它並不允許未定義的行爲跳轉到一個已經解開的堆棧,有時用於實現協程。
啊哈!難怪我無法弄清楚它!這遠非理想,但爲了公平,我認爲最大的收穫是目前所有主要的瀏覽器供應商都在船上並運送或即將發運MVP。 – mseddon