Skip to content

Commit 4bdd490

Browse files
authored
[wasm] Migrate from catch_all to catch in the jiterpreter and destroy exceptions (#91364)
* Expose the cxa catch functions to jiterp * Import the exception tag type from dotnet.wasm when generating jiterpreter modules * Properly free C++ exceptions in do_jit_call_indirect_js and don't trap non-C++ exceptions * Properly clean up exceptions in the fallback trampoline invoke routine (though this shouldn't be necessary) * Call begin_catch/end_catch in generated jitcall trampolines * Remove the jiterpreter_do_jit_call machinery, it is no longer useful * Reuse loader feature detection for SIMD and EH
1 parent 49a42cb commit 4bdd490

18 files changed

+150
-239
lines changed

src/mono/CMakeLists.txt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,12 @@ if(LLVM_PREFIX)
655655

656656
# llvm-config --cflags
657657
set(llvm_cflags "-I${LLVM_PREFIX}/include -D__STDC_CONSTANT_MACROS -D__STD_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
658-
set(llvm_cxxflags "-I${LLVM_PREFIX}/include ${MONO_cxx_include} ${MONO_cxx_std_version} ${MONO_stdlib} -fno-exceptions -fno-rtti -D__STDC_CONSTANT_MACROS -D__STD_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
658+
659+
if (HOST_BROWSER)
660+
set(llvm_cxxflags "-I${LLVM_PREFIX}/include ${MONO_cxx_include} ${MONO_cxx_std_version} ${MONO_stdlib} -fno-rtti -D__STDC_CONSTANT_MACROS -D__STD_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
661+
else()
662+
set(llvm_cxxflags "-I${LLVM_PREFIX}/include ${MONO_cxx_include} ${MONO_cxx_std_version} ${MONO_stdlib} -fno-exceptions -fno-rtti -D__STDC_CONSTANT_MACROS -D__STD_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
663+
endif()
659664
set(llvm_includedir "${LLVM_PREFIX}/include")
660665

661666
if(HOST_LINUX)
@@ -694,6 +699,10 @@ if(LLVM_PREFIX)
694699
string(REPLACE "/EHs-c-" "" llvm_cxxflags "${llvm_cxxflags}")
695700
# /GR- already enabled and inherited from LLVM flags. Corresponds to -fno-rtti.
696701
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${llvm_cxxflags}")
702+
elseif(HOST_BROWSER)
703+
# emscripten's handling of the different exception modes is complex, so having multiple flags
704+
# passed during a single compile is undesirable. we need to set them elsewhere.
705+
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${llvm_cxxflags} -fno-rtti")
697706
else()
698707
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${llvm_cxxflags} -fexceptions -fno-rtti")
699708
endif()

src/mono/mono.proj

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@
207207
<ActualWasiSdkVersion>%(_ActualVersionLines.Identity)</ActualWasiSdkVersion>
208208
<ExpectedWasiSdkVersion>%(_ExpectedVersionLines.Identity)</ExpectedWasiSdkVersion>
209209
</PropertyGroup>
210-
<Error Text="Expected and actual version of WASI SDK does not match. Please delete $(WASI_SDK_PATH) folder to provision a new version."
210+
<Error Text="Expected and actual version of WASI SDK does not match. Please delete $(WASI_SDK_PATH) folder to provision a new version."
211211
Condition="'$(ActualWasiSdkVersion)' != '$(ExpectedWasiSdkVersion)'" />
212212
</Target>
213213

@@ -417,10 +417,8 @@
417417
<_MonoCMakeArgs Include="-DENABLE_ICALL_EXPORT=1"/>
418418
<_MonoCMakeArgs Include="-DENABLE_LAZY_GC_THREAD_CREATION=1"/>
419419
<_MonoCMakeArgs Include="-DENABLE_WEBCIL=1"/>
420-
<_MonoCFLAGS Include="-fexceptions"/>
421420
<_MonoCFLAGS Condition="'$(MonoWasmThreads)' == 'true'" Include="-pthread"/>
422421
<_MonoCFLAGS Condition="'$(MonoWasmThreads)' == 'true'" Include="-D_GNU_SOURCE=1" />
423-
<_MonoCXXFLAGS Include="-fexceptions"/>
424422
<_MonoCXXFLAGS Condition="'$(MonoWasmThreads)' == 'true'" Include="-pthread"/>
425423
<_MonoCXXFLAGS Condition="'$(MonoWasmThreads)' == 'true'" Include="-D_GNU_SOURCE=1" />
426424
</ItemGroup>
@@ -434,8 +432,8 @@
434432
</ItemGroup>
435433
<!-- WASI specific options -->
436434
<ItemGroup Condition="'$(TargetsWasi)' == 'true'">
437-
<!-- TODOWASI
438-
use $(CrossToolchainFile) and eng/common/cross/toolchain.cmake ?
435+
<!-- TODOWASI
436+
use $(CrossToolchainFile) and eng/common/cross/toolchain.cmake ?
439437
sockets,eventpipe, DENABLE_LLVM_RUNTIME
440438
-->
441439
<_MonoCFLAGS Include="$(EscapedQuoteW)-I$([MSBuild]::NormalizePath('$(MonoProjectRoot)', 'wasi', 'include').Replace('\','/'))$(EscapedQuoteW)"/>

src/mono/mono/mini/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -503,10 +503,14 @@ if(HOST_BROWSER)
503503
# This is the only source file which contains a c++ throw or catch
504504
add_library(mono-wasm-eh-js STATIC llvm-runtime.cpp)
505505
target_link_libraries (mono-wasm-eh-js PRIVATE monoapi eglib_api)
506+
set_target_properties(mono-wasm-eh-js PROPERTIES COMPILE_FLAGS "-fexceptions")
507+
set_target_properties(mono-wasm-eh-js PROPERTIES LINK_FLAGS "-fexceptions -s EXPORT_EXCEPTION_HANDLING_HELPERS=1")
506508
install(TARGETS mono-wasm-eh-js LIBRARY)
509+
507510
add_library(mono-wasm-eh-wasm STATIC llvm-runtime.cpp)
508511
target_link_libraries (mono-wasm-eh-wasm PRIVATE monoapi eglib_api)
509512
set_target_properties(mono-wasm-eh-wasm PROPERTIES COMPILE_FLAGS "-fwasm-exceptions")
513+
set_target_properties(mono-wasm-eh-wasm PROPERTIES LINK_FLAGS "-fwasm-exceptions -s EXPORT_EXCEPTION_HANDLING_HELPERS=1")
510514
install(TARGETS mono-wasm-eh-wasm LIBRARY)
511515
endif()
512516

src/mono/mono/mini/interp/interp.c

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2707,21 +2707,8 @@ do_jit_call (ThreadContext *context, stackval *ret_sp, stackval *sp, InterpFrame
27072707
interp_push_lmf (&ext, frame);
27082708

27092709
if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY_INTERP) {
2710-
#if JITERPRETER_ENABLE_SPECIALIZED_JIT_CALL
2711-
/*
2712-
* invoke jit_call_cb via a single indirect function call that dispatches to
2713-
* either a specialized JS implementation or a specialized WASM EH version
2714-
* see jiterpreter-jit-call.ts and do-jit-call.wat
2715-
* NOTE: the first argument must ALWAYS be jit_call_cb for the specialization.
2716-
* the actual implementation cannot verify this at runtime, so get it right
2717-
* this is faster than mono_llvm_cpp_catch_exception by avoiding the use of
2718-
* emscripten invoke_vi to find and invoke jit_call_cb indirectly
2719-
*/
2720-
jiterpreter_do_jit_call (jit_call_cb, &cb_data, &thrown);
2721-
#else
27222710
/* Catch the exception thrown by the native code using a try-catch */
27232711
mono_llvm_cpp_catch_exception (jit_call_cb, &cb_data, &thrown);
2724-
#endif
27252712
} else {
27262713
jit_call_cb (&cb_data);
27272714
}

src/mono/mono/mini/interp/jiterpreter.c

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,6 @@ void jiterp_preserve_module (void);
6060
static gint32 jiterpreter_abort_counts[MINT_LASTOP + 1] = { 0 };
6161
static int64_t jiterp_trace_bailout_counts[256] = { 0 };
6262

63-
// This function pointer is used by interp.c to invoke jit_call_cb for exception handling purposes
64-
// See jiterpreter-jit-call.ts mono_jiterp_do_jit_call_indirect
65-
WasmDoJitCall jiterpreter_do_jit_call = mono_jiterp_do_jit_call_indirect;
66-
6763
// We disable this diagnostic because EMSCRIPTEN_KEEPALIVE makes it a false alarm, the keepalive
6864
// functions are being used externally. Having a bunch of prototypes is pointless since these
6965
// functions are not consumed by C anywhere else
@@ -1021,20 +1017,6 @@ mono_jiterp_get_options_as_json ()
10211017
return mono_options_get_as_json ();
10221018
}
10231019

1024-
EMSCRIPTEN_KEEPALIVE void
1025-
mono_jiterp_update_jit_call_dispatcher (WasmDoJitCall dispatcher)
1026-
{
1027-
// If we received a 0 dispatcher that means the TS side failed to compile
1028-
// any kind of dispatcher - this likely indicates that content security policy
1029-
// blocked the use of Module.addFunction
1030-
if (!dispatcher)
1031-
dispatcher = (WasmDoJitCall)mono_llvm_cpp_catch_exception;
1032-
else if (((int)(void*)dispatcher)==-1)
1033-
dispatcher = mono_jiterp_do_jit_call_indirect;
1034-
1035-
jiterpreter_do_jit_call = dispatcher;
1036-
}
1037-
10381020
EMSCRIPTEN_KEEPALIVE int
10391021
mono_jiterp_object_has_component_size (MonoObject ** ppObj)
10401022
{

src/mono/mono/mini/interp/jiterpreter.h

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,8 @@
55

66
#ifdef DISABLE_THREADS
77
#define JITERPRETER_ENABLE_JIT_CALL_TRAMPOLINES 1
8-
// enables specialized mono_llvm_cpp_catch_exception replacement (see jiterpreter-jit-call.ts)
9-
// works even if the jiterpreter is otherwise disabled.
10-
#define JITERPRETER_ENABLE_SPECIALIZED_JIT_CALL 1
118
#else
129
#define JITERPRETER_ENABLE_JIT_CALL_TRAMPOLINES 0
13-
#define JITERPRETER_ENABLE_SPECIALIZED_JIT_CALL 0
1410
#endif // DISABLE_THREADS
1511

1612
// mono_interp_tier_prepare_jiterpreter will return these special values if it doesn't
@@ -49,9 +45,8 @@ __attribute__ ((__packed__, __aligned__(2)))
4945
// Keep in sync with JiterpreterTable in jiterpreter-enums.ts
5046
enum {
5147
JITERPRETER_TABLE_TRACE = 0,
52-
JITERPRETER_TABLE_DO_JIT_CALL = 1,
53-
JITERPRETER_TABLE_JIT_CALL = 2,
54-
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_0 = 3,
48+
JITERPRETER_TABLE_JIT_CALL = 1,
49+
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_0 = 2,
5550
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_1,
5651
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_2,
5752
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_3,
@@ -165,11 +160,6 @@ mono_interp_invoke_wasm_jit_call_trampoline (
165160
void *ftndesc, gboolean *thrown
166161
);
167162

168-
extern void
169-
mono_jiterp_do_jit_call_indirect (
170-
gpointer cb, gpointer arg, gboolean *out_thrown
171-
);
172-
173163
#ifdef __MONO_MINI_INTERPRETER_INTERNALS_H__
174164

175165
extern void
@@ -247,8 +237,6 @@ mono_jiterp_tlqueue_purge_all (gpointer item);
247237

248238
#endif // __MONO_MINI_INTERPRETER_INTERNALS_H__
249239

250-
extern WasmDoJitCall jiterpreter_do_jit_call;
251-
252240
#endif // HOST_BROWSER
253241

254242
#endif // __MONO_MINI_JITERPRETER_H__

src/mono/mono/mini/llvm-runtime.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,4 +47,22 @@ mono_llvm_cpp_catch_exception (MonoLLVMInvokeCallback cb, gpointer arg, gboolean
4747
}
4848
}
4949

50+
#ifdef HOST_WASM
51+
52+
// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
53+
void *__cxa_begin_catch (void *exceptionObject);
54+
void __cxa_end_catch (void);
55+
56+
EMSCRIPTEN_KEEPALIVE void
57+
mono_jiterp_begin_catch (void *exception_object) {
58+
__cxa_begin_catch (exception_object);
59+
}
60+
61+
EMSCRIPTEN_KEEPALIVE void
62+
mono_jiterp_end_catch (void) {
63+
return __cxa_end_catch ();
64+
}
65+
66+
#endif
67+
5068
}

src/mono/wasm/build/WasmApp.Native.targets

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
_ReadEmccProps
2727
</_BeforeWasmBuildAppDependsOn>
2828

29+
<_EmccDefaultFlags Condition="'$(WasmEnableExceptionHandling)' == 'false'">-fexceptions</_EmccDefaultFlags>
30+
<_EmccDefaultFlags Condition="'$(WasmEnableExceptionHandling)' != 'false'">-fwasm-exceptions</_EmccDefaultFlags>
2931
<_EmccDefaultFlags Condition="'$(WasmEnableSIMD)' == 'true'">-msimd128</_EmccDefaultFlags>
3032
<_ExeExt Condition="$([MSBuild]::IsOSPlatform('WINDOWS'))">.exe</_ExeExt>
3133
<WasmUseEMSDK_PATH Condition="'$(WasmUseEMSDK_PATH)' == '' and '$(EMSDK_PATH)' != '' and Exists('$(MSBuildThisFileDirectory)WasmApp.InTree.targets')">true</WasmUseEMSDK_PATH>
@@ -254,6 +256,7 @@
254256
<_EmccLDFlags Include="$(EmccLinkOptimizationFlag)" />
255257
<_EmccLDFlags Include="@(_EmccCommonFlags)" />
256258
<_EmccLDFlags Include="-s EXPORT_ES6=1" />
259+
<_EmccLDFlags Condition="'$(WasmEnableExceptionHandling)' != 'false'" Include="-s EXPORT_EXCEPTION_HANDLING_HELPERS=1" />
257260

258261
<_DriverCDependencies Include="$(_WasmPInvokeHPath);$(_WasmICallTablePath)" />
259262
<_DriverCDependencies Include="$(_DriverGenCPath)" Condition="'$(_DriverGenCNeeded)' == 'true'" />

src/mono/wasm/runtime/cwraps.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,6 @@ const fn_signatures: SigLine[] = [
118118
[true, "mono_jiterp_adjust_abort_count", "number", ["number", "number"]],
119119
[true, "mono_jiterp_register_jit_call_thunk", "void", ["number", "number"]],
120120
[true, "mono_jiterp_type_get_raw_value_size", "number", ["number"]],
121-
[true, "mono_jiterp_update_jit_call_dispatcher", "void", ["number"]],
122121
[true, "mono_jiterp_get_signature_has_this", "number", ["number"]],
123122
[true, "mono_jiterp_get_signature_return_type", "number", ["number"]],
124123
[true, "mono_jiterp_get_signature_param_count", "number", ["number"]],
@@ -147,6 +146,8 @@ const fn_signatures: SigLine[] = [
147146
[true, "mono_jiterp_tlqueue_next", "number", ["number"]],
148147
[true, "mono_jiterp_tlqueue_add", "number", ["number", "number"]],
149148
[true, "mono_jiterp_tlqueue_clear", "void", ["number"]],
149+
[true, "mono_jiterp_begin_catch", "void", ["number"]],
150+
[true, "mono_jiterp_end_catch", "void", []],
150151

151152
...diagnostics_cwraps,
152153
...legacy_interop_cwraps
@@ -259,7 +260,6 @@ export interface t_Cwraps {
259260
mono_jiterp_get_options_version(): number;
260261
mono_jiterp_adjust_abort_count(opcode: number, delta: number): number;
261262
mono_jiterp_register_jit_call_thunk(cinfo: number, func: number): void;
262-
mono_jiterp_update_jit_call_dispatcher(fn: number): void;
263263
mono_jiterp_get_signature_has_this(sig: VoidPtr): number;
264264
mono_jiterp_get_signature_return_type(sig: VoidPtr): MonoType;
265265
mono_jiterp_get_signature_param_count(sig: VoidPtr): number;
@@ -291,6 +291,8 @@ export interface t_Cwraps {
291291
// returns new size of queue after add
292292
mono_jiterp_tlqueue_add(queue: number, value: VoidPtr): number;
293293
mono_jiterp_tlqueue_clear(queue: number): void;
294+
mono_jiterp_begin_catch(ptr: number): void;
295+
mono_jiterp_end_catch(): void;
294296
}
295297

296298
const wrapped_c_functions: t_Cwraps = <any>{};

src/mono/wasm/runtime/exports-binding.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import { mono_wasm_bind_cs_function } from "./invoke-cs";
1010
import { mono_wasm_bind_js_function, mono_wasm_invoke_bound_function, mono_wasm_invoke_import } from "./invoke-js";
1111
import { mono_interp_tier_prepare_jiterpreter, mono_jiterp_free_method_data_js } from "./jiterpreter";
1212
import { mono_interp_jit_wasm_entry_trampoline, mono_interp_record_interp_entry } from "./jiterpreter-interp-entry";
13-
import { mono_interp_jit_wasm_jit_call_trampoline, mono_interp_invoke_wasm_jit_call_trampoline, mono_interp_flush_jitcall_queue, mono_jiterp_do_jit_call_indirect } from "./jiterpreter-jit-call";
13+
import { mono_interp_jit_wasm_jit_call_trampoline, mono_interp_invoke_wasm_jit_call_trampoline, mono_interp_flush_jitcall_queue } from "./jiterpreter-jit-call";
1414
import { mono_wasm_marshal_promise } from "./marshal-to-js";
1515
import { mono_wasm_eventloop_has_unsettled_interop_promises } from "./pthreads/shared/eventloop";
1616
import { mono_wasm_pthread_on_pthread_attached, mono_wasm_pthread_on_pthread_detached } from "./pthreads/worker";
@@ -88,7 +88,6 @@ export const mono_wasm_imports = [
8888
mono_interp_jit_wasm_jit_call_trampoline,
8989
mono_interp_invoke_wasm_jit_call_trampoline,
9090
mono_interp_flush_jitcall_queue,
91-
mono_jiterp_do_jit_call_indirect,
9291
mono_jiterp_free_method_data_js,
9392

9493
mono_wasm_profiler_enter,

0 commit comments

Comments
 (0)