setjmp-longjmpサポートは、Emscriptenでデフォルトで有効になっています。これは、次の値を取ることができるSUPPORT_LONGJMP
設定によって制御されます。
emscripten
: JavaScriptベースのサポート
wasm
: WebAssembly例外処理ベースのサポート
0:サポートなし
1:例外モードに応じてデフォルトのサポート。-fwasm-exception
が使用されている場合はwasm
、それ以外の場合はemscripten
。
ネイティブWasm例外が使用されている場合、SUPPORT_LONGJMP
はデフォルトでwasm
になり、JavaScriptベースの例外が使用されている場合、または例外サポートが使用されていない場合は、デフォルトでemscripten
になります。
setjmp
は呼び出し環境に関する情報をバッファに保存し、longjmp
はバッファを使用してsetjmp
が呼び出された時点に制御を戻します。longjmp
の呼び出しスタックには、setjmp
が呼び出された関数が含まれている必要があります。
Emscriptenのサポートには、setjmp
への間接呼び出しはサポートされないという制限があります。たとえば、以下は機能しません。
jmp_buf env;
int (*fp)(jmp_buf) = setjmp;
fp(env); // Doesn't work
このモードでは、EmscriptenはJavaScriptを使用してsetjmp-longjmpをエミュレートします。このオプションは、コマンドラインに-sSUPPORT_LONGJMP=emscripten
を追加することで設定されますが、現在、これはデフォルトで有効になっています。
このオプションは、コードサイズに関して比較的高いオーバーヘッドが発生する可能性があることに注意してください。ただし、新しいWebAssembly例外処理提案をまだサポートしていない場合でも、WebAssemblyをサポートするすべてのJavaScriptエンジンで動作します。
または、WebAssembly例外処理提案を使用して、新しいサポートをオプトインできます。これを有効にするには、コンパイル時とリンク時の両方で-sSUPPORT_LONGJMP=wasm
を渡します。
このオプションは、例外をスローおよびキャッチするための組み込み命令をWebAssemblyに導入する新機能を利用します。その結果、JavaScriptベースの実装と比較して、コードサイズとパフォーマンスのオーバーヘッドを削減できます。このオプションは現在、いくつかの主要なWebブラウザーでサポートされていますが、まだすべてのWebAssemblyエンジンでサポートされていない可能性があります。
また、例外処理サポートには、JavaScriptベースのサポートと新しいWebAssembly EHベースのサポートの2種類があります。setjmp-longjmpサポートは同じメカニズムを使用します。そのため、例外とsetjmp-longjmpを一緒に使用する場合は、同じ種類のEHとsetjmp-longjmpサポートを使用する必要があります。
たとえば、JavaScriptベースのEHとsetjmp-longjmpサポートを一緒に使用するには
em++ -fexceptions test.cpp -o test.js
例外モードに応じて、デフォルトでemscripten
またはwasm
になる-sSUPPORT_LONGJMP
はデフォルトで有効になっているため、明示的に渡す必要はありません。
WebAssembly EHとsetjmp-longjmpサポートを一緒に使用するには
em++ -fwasm-exceptions -sSUPPORT_LONGJMP=wasm test.cpp -o test.js
例外とsetjmp-longjmpにWebAssembly EHベースのサポートを同時に使用する場合、1つの特定の制限があります。C++のcatch
句内でsetjmp
を呼び出すことはできません。たとえば、以下はコンパイル時にエラーになります。
try {
...
catch (int n) {
setjmp(buf); // Doesn't work
}
try
句内でsetjmp
を呼び出すのは問題ありません。catch
句内でsetjmp
を呼び出す別のユーザー関数を呼び出すのも問題ありません。
try {
setjmp(buf); // Works
catch (int n) {
...
}
try {
...
} catch (int n) {
function_that_calls_setjmp(); // Works
}