Skip to content

Commit

Permalink
[wasm] Migrate from catch_all to catch in the jiterpreter and destroy…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
kg committed Oct 5, 2023
1 parent 49a42cb commit 4bdd490
Show file tree
Hide file tree
Showing 18 changed files with 150 additions and 239 deletions.
11 changes: 10 additions & 1 deletion src/mono/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -655,7 +655,12 @@ if(LLVM_PREFIX)

# llvm-config --cflags
set(llvm_cflags "-I${LLVM_PREFIX}/include -D__STDC_CONSTANT_MACROS -D__STD_FORMAT_MACROS -D__STDC_LIMIT_MACROS")
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")

if (HOST_BROWSER)
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")
else()
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")
endif()
set(llvm_includedir "${LLVM_PREFIX}/include")

if(HOST_LINUX)
Expand Down Expand Up @@ -694,6 +699,10 @@ if(LLVM_PREFIX)
string(REPLACE "/EHs-c-" "" llvm_cxxflags "${llvm_cxxflags}")
# /GR- already enabled and inherited from LLVM flags. Corresponds to -fno-rtti.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${llvm_cxxflags}")
elseif(HOST_BROWSER)
# emscripten's handling of the different exception modes is complex, so having multiple flags
# passed during a single compile is undesirable. we need to set them elsewhere.
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${llvm_cxxflags} -fno-rtti")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${llvm_cxxflags} -fexceptions -fno-rtti")
endif()
Expand Down
8 changes: 3 additions & 5 deletions src/mono/mono.proj
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@
<ActualWasiSdkVersion>%(_ActualVersionLines.Identity)</ActualWasiSdkVersion>
<ExpectedWasiSdkVersion>%(_ExpectedVersionLines.Identity)</ExpectedWasiSdkVersion>
</PropertyGroup>
<Error Text="Expected and actual version of WASI SDK does not match. Please delete $(WASI_SDK_PATH) folder to provision a new version."
<Error Text="Expected and actual version of WASI SDK does not match. Please delete $(WASI_SDK_PATH) folder to provision a new version."
Condition="'$(ActualWasiSdkVersion)' != '$(ExpectedWasiSdkVersion)'" />
</Target>

Expand Down Expand Up @@ -417,10 +417,8 @@
<_MonoCMakeArgs Include="-DENABLE_ICALL_EXPORT=1"/>
<_MonoCMakeArgs Include="-DENABLE_LAZY_GC_THREAD_CREATION=1"/>
<_MonoCMakeArgs Include="-DENABLE_WEBCIL=1"/>
<_MonoCFLAGS Include="-fexceptions"/>
<_MonoCFLAGS Condition="'$(MonoWasmThreads)' == 'true'" Include="-pthread"/>
<_MonoCFLAGS Condition="'$(MonoWasmThreads)' == 'true'" Include="-D_GNU_SOURCE=1" />
<_MonoCXXFLAGS Include="-fexceptions"/>
<_MonoCXXFLAGS Condition="'$(MonoWasmThreads)' == 'true'" Include="-pthread"/>
<_MonoCXXFLAGS Condition="'$(MonoWasmThreads)' == 'true'" Include="-D_GNU_SOURCE=1" />
</ItemGroup>
Expand All @@ -434,8 +432,8 @@
</ItemGroup>
<!-- WASI specific options -->
<ItemGroup Condition="'$(TargetsWasi)' == 'true'">
<!-- TODOWASI
use $(CrossToolchainFile) and eng/common/cross/toolchain.cmake ?
<!-- TODOWASI
use $(CrossToolchainFile) and eng/common/cross/toolchain.cmake ?
sockets,eventpipe, DENABLE_LLVM_RUNTIME
-->
<_MonoCFLAGS Include="$(EscapedQuoteW)-I$([MSBuild]::NormalizePath('$(MonoProjectRoot)', 'wasi', 'include').Replace('\','/'))$(EscapedQuoteW)"/>
Expand Down
4 changes: 4 additions & 0 deletions src/mono/mono/mini/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -503,10 +503,14 @@ if(HOST_BROWSER)
# This is the only source file which contains a c++ throw or catch
add_library(mono-wasm-eh-js STATIC llvm-runtime.cpp)
target_link_libraries (mono-wasm-eh-js PRIVATE monoapi eglib_api)
set_target_properties(mono-wasm-eh-js PROPERTIES COMPILE_FLAGS "-fexceptions")
set_target_properties(mono-wasm-eh-js PROPERTIES LINK_FLAGS "-fexceptions -s EXPORT_EXCEPTION_HANDLING_HELPERS=1")
install(TARGETS mono-wasm-eh-js LIBRARY)

add_library(mono-wasm-eh-wasm STATIC llvm-runtime.cpp)
target_link_libraries (mono-wasm-eh-wasm PRIVATE monoapi eglib_api)
set_target_properties(mono-wasm-eh-wasm PROPERTIES COMPILE_FLAGS "-fwasm-exceptions")
set_target_properties(mono-wasm-eh-wasm PROPERTIES LINK_FLAGS "-fwasm-exceptions -s EXPORT_EXCEPTION_HANDLING_HELPERS=1")
install(TARGETS mono-wasm-eh-wasm LIBRARY)
endif()

Expand Down
13 changes: 0 additions & 13 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -2707,21 +2707,8 @@ do_jit_call (ThreadContext *context, stackval *ret_sp, stackval *sp, InterpFrame
interp_push_lmf (&ext, frame);

if (mono_aot_mode == MONO_AOT_MODE_LLVMONLY_INTERP) {
#if JITERPRETER_ENABLE_SPECIALIZED_JIT_CALL
/*
* invoke jit_call_cb via a single indirect function call that dispatches to
* either a specialized JS implementation or a specialized WASM EH version
* see jiterpreter-jit-call.ts and do-jit-call.wat
* NOTE: the first argument must ALWAYS be jit_call_cb for the specialization.
* the actual implementation cannot verify this at runtime, so get it right
* this is faster than mono_llvm_cpp_catch_exception by avoiding the use of
* emscripten invoke_vi to find and invoke jit_call_cb indirectly
*/
jiterpreter_do_jit_call (jit_call_cb, &cb_data, &thrown);
#else
/* Catch the exception thrown by the native code using a try-catch */
mono_llvm_cpp_catch_exception (jit_call_cb, &cb_data, &thrown);
#endif
} else {
jit_call_cb (&cb_data);
}
Expand Down
18 changes: 0 additions & 18 deletions src/mono/mono/mini/interp/jiterpreter.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,6 @@ void jiterp_preserve_module (void);
static gint32 jiterpreter_abort_counts[MINT_LASTOP + 1] = { 0 };
static int64_t jiterp_trace_bailout_counts[256] = { 0 };

// This function pointer is used by interp.c to invoke jit_call_cb for exception handling purposes
// See jiterpreter-jit-call.ts mono_jiterp_do_jit_call_indirect
WasmDoJitCall jiterpreter_do_jit_call = mono_jiterp_do_jit_call_indirect;

// We disable this diagnostic because EMSCRIPTEN_KEEPALIVE makes it a false alarm, the keepalive
// functions are being used externally. Having a bunch of prototypes is pointless since these
// functions are not consumed by C anywhere else
Expand Down Expand Up @@ -1021,20 +1017,6 @@ mono_jiterp_get_options_as_json ()
return mono_options_get_as_json ();
}

EMSCRIPTEN_KEEPALIVE void
mono_jiterp_update_jit_call_dispatcher (WasmDoJitCall dispatcher)
{
// If we received a 0 dispatcher that means the TS side failed to compile
// any kind of dispatcher - this likely indicates that content security policy
// blocked the use of Module.addFunction
if (!dispatcher)
dispatcher = (WasmDoJitCall)mono_llvm_cpp_catch_exception;
else if (((int)(void*)dispatcher)==-1)
dispatcher = mono_jiterp_do_jit_call_indirect;

jiterpreter_do_jit_call = dispatcher;
}

EMSCRIPTEN_KEEPALIVE int
mono_jiterp_object_has_component_size (MonoObject ** ppObj)
{
Expand Down
16 changes: 2 additions & 14 deletions src/mono/mono/mini/interp/jiterpreter.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,8 @@

#ifdef DISABLE_THREADS
#define JITERPRETER_ENABLE_JIT_CALL_TRAMPOLINES 1
// enables specialized mono_llvm_cpp_catch_exception replacement (see jiterpreter-jit-call.ts)
// works even if the jiterpreter is otherwise disabled.
#define JITERPRETER_ENABLE_SPECIALIZED_JIT_CALL 1
#else
#define JITERPRETER_ENABLE_JIT_CALL_TRAMPOLINES 0
#define JITERPRETER_ENABLE_SPECIALIZED_JIT_CALL 0
#endif // DISABLE_THREADS

// mono_interp_tier_prepare_jiterpreter will return these special values if it doesn't
Expand Down Expand Up @@ -49,9 +45,8 @@ __attribute__ ((__packed__, __aligned__(2)))
// Keep in sync with JiterpreterTable in jiterpreter-enums.ts
enum {
JITERPRETER_TABLE_TRACE = 0,
JITERPRETER_TABLE_DO_JIT_CALL = 1,
JITERPRETER_TABLE_JIT_CALL = 2,
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_0 = 3,
JITERPRETER_TABLE_JIT_CALL = 1,
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_0 = 2,
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_1,
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_2,
JITERPRETER_TABLE_INTERP_ENTRY_STATIC_3,
Expand Down Expand Up @@ -165,11 +160,6 @@ mono_interp_invoke_wasm_jit_call_trampoline (
void *ftndesc, gboolean *thrown
);

extern void
mono_jiterp_do_jit_call_indirect (
gpointer cb, gpointer arg, gboolean *out_thrown
);

#ifdef __MONO_MINI_INTERPRETER_INTERNALS_H__

extern void
Expand Down Expand Up @@ -247,8 +237,6 @@ mono_jiterp_tlqueue_purge_all (gpointer item);

#endif // __MONO_MINI_INTERPRETER_INTERNALS_H__

extern WasmDoJitCall jiterpreter_do_jit_call;

#endif // HOST_BROWSER

#endif // __MONO_MINI_JITERPRETER_H__
18 changes: 18 additions & 0 deletions src/mono/mono/mini/llvm-runtime.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,22 @@ mono_llvm_cpp_catch_exception (MonoLLVMInvokeCallback cb, gpointer arg, gboolean
}
}

#ifdef HOST_WASM

// https://itanium-cxx-abi.github.io/cxx-abi/abi-eh.html
void *__cxa_begin_catch (void *exceptionObject);
void __cxa_end_catch (void);

EMSCRIPTEN_KEEPALIVE void
mono_jiterp_begin_catch (void *exception_object) {
__cxa_begin_catch (exception_object);
}

EMSCRIPTEN_KEEPALIVE void
mono_jiterp_end_catch (void) {
return __cxa_end_catch ();
}

#endif

}
3 changes: 3 additions & 0 deletions src/mono/wasm/build/WasmApp.Native.targets
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
_ReadEmccProps
</_BeforeWasmBuildAppDependsOn>

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

<_DriverCDependencies Include="$(_WasmPInvokeHPath);$(_WasmICallTablePath)" />
<_DriverCDependencies Include="$(_DriverGenCPath)" Condition="'$(_DriverGenCNeeded)' == 'true'" />
Expand Down
6 changes: 4 additions & 2 deletions src/mono/wasm/runtime/cwraps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,6 @@ const fn_signatures: SigLine[] = [
[true, "mono_jiterp_adjust_abort_count", "number", ["number", "number"]],
[true, "mono_jiterp_register_jit_call_thunk", "void", ["number", "number"]],
[true, "mono_jiterp_type_get_raw_value_size", "number", ["number"]],
[true, "mono_jiterp_update_jit_call_dispatcher", "void", ["number"]],
[true, "mono_jiterp_get_signature_has_this", "number", ["number"]],
[true, "mono_jiterp_get_signature_return_type", "number", ["number"]],
[true, "mono_jiterp_get_signature_param_count", "number", ["number"]],
Expand Down Expand Up @@ -147,6 +146,8 @@ const fn_signatures: SigLine[] = [
[true, "mono_jiterp_tlqueue_next", "number", ["number"]],
[true, "mono_jiterp_tlqueue_add", "number", ["number", "number"]],
[true, "mono_jiterp_tlqueue_clear", "void", ["number"]],
[true, "mono_jiterp_begin_catch", "void", ["number"]],
[true, "mono_jiterp_end_catch", "void", []],

...diagnostics_cwraps,
...legacy_interop_cwraps
Expand Down Expand Up @@ -259,7 +260,6 @@ export interface t_Cwraps {
mono_jiterp_get_options_version(): number;
mono_jiterp_adjust_abort_count(opcode: number, delta: number): number;
mono_jiterp_register_jit_call_thunk(cinfo: number, func: number): void;
mono_jiterp_update_jit_call_dispatcher(fn: number): void;
mono_jiterp_get_signature_has_this(sig: VoidPtr): number;
mono_jiterp_get_signature_return_type(sig: VoidPtr): MonoType;
mono_jiterp_get_signature_param_count(sig: VoidPtr): number;
Expand Down Expand Up @@ -291,6 +291,8 @@ export interface t_Cwraps {
// returns new size of queue after add
mono_jiterp_tlqueue_add(queue: number, value: VoidPtr): number;
mono_jiterp_tlqueue_clear(queue: number): void;
mono_jiterp_begin_catch(ptr: number): void;
mono_jiterp_end_catch(): void;
}

const wrapped_c_functions: t_Cwraps = <any>{};
Expand Down
3 changes: 1 addition & 2 deletions src/mono/wasm/runtime/exports-binding.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { mono_wasm_bind_cs_function } from "./invoke-cs";
import { mono_wasm_bind_js_function, mono_wasm_invoke_bound_function, mono_wasm_invoke_import } from "./invoke-js";
import { mono_interp_tier_prepare_jiterpreter, mono_jiterp_free_method_data_js } from "./jiterpreter";
import { mono_interp_jit_wasm_entry_trampoline, mono_interp_record_interp_entry } from "./jiterpreter-interp-entry";
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";
import { mono_interp_jit_wasm_jit_call_trampoline, mono_interp_invoke_wasm_jit_call_trampoline, mono_interp_flush_jitcall_queue } from "./jiterpreter-jit-call";
import { mono_wasm_marshal_promise } from "./marshal-to-js";
import { mono_wasm_eventloop_has_unsettled_interop_promises } from "./pthreads/shared/eventloop";
import { mono_wasm_pthread_on_pthread_attached, mono_wasm_pthread_on_pthread_detached } from "./pthreads/worker";
Expand Down Expand Up @@ -88,7 +88,6 @@ export const mono_wasm_imports = [
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,
mono_jiterp_free_method_data_js,

mono_wasm_profiler_enter,
Expand Down
7 changes: 3 additions & 4 deletions src/mono/wasm/runtime/jiterpreter-enums.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,9 @@ export const enum JiterpNumberMode {

// keep in sync with jiterpreter.h
export const enum JiterpreterTable {
Trace,
DoJitCall,
JitCall,
InterpEntryStatic0,
Trace = 0,
JitCall = 1,
InterpEntryStatic0 = 2,
InterpEntryStatic1,
InterpEntryStatic2,
InterpEntryStatic3,
Expand Down
66 changes: 0 additions & 66 deletions src/mono/wasm/runtime/jiterpreter-feature-detect.ts

This file was deleted.

Loading

0 comments on commit 4bdd490

Please sign in to comment.