[wasm] Add some JIT helper functions to throw common corlib exceptions. (#87044)
authorZoltan Varga <vargaz@gmail.com>
Tue, 27 Jun 2023 18:06:54 +0000 (14:06 -0400)
committerGitHub <noreply@github.com>
Tue, 27 Jun 2023 18:06:54 +0000 (14:06 -0400)
src/mono/mono/metadata/jit-icall-reg.h
src/mono/mono/mini/aot-compiler.c
src/mono/mono/mini/llvmonly-runtime.c
src/mono/mono/mini/llvmonly-runtime.h
src/mono/mono/mini/mini-llvm.c
src/mono/mono/mini/mini-runtime.c

index 122d8dc..02e3042 100644 (file)
@@ -140,6 +140,8 @@ MONO_JIT_ICALL (mini_llvmonly_resolve_vcall_gsharedvt) \
 MONO_JIT_ICALL (mini_llvmonly_resolve_vcall_gsharedvt_fast) \
 MONO_JIT_ICALL (mini_llvmonly_throw_nullref_exception) \
 MONO_JIT_ICALL (mini_llvmonly_throw_aot_failed_exception) \
+MONO_JIT_ICALL (mini_llvmonly_throw_index_out_of_range_exception) \
+MONO_JIT_ICALL (mini_llvmonly_throw_invalid_cast_exception) \
 MONO_JIT_ICALL (mini_llvmonly_interp_entry_gsharedvt) \
 MONO_JIT_ICALL (mini_llvmonly_throw_exception) \
 MONO_JIT_ICALL (mini_llvmonly_rethrow_exception) \
index 6b86211..35d73cc 100644 (file)
@@ -14436,6 +14436,8 @@ static void aot_dump (MonoAotCompile *acfg)
 static const MonoJitICallId preinited_jit_icalls [] = {
        MONO_JIT_ICALL_mini_llvm_init_method,
        MONO_JIT_ICALL_mini_llvmonly_throw_nullref_exception,
+       MONO_JIT_ICALL_mini_llvmonly_throw_index_out_of_range_exception,
+       MONO_JIT_ICALL_mini_llvmonly_throw_invalid_cast_exception,
        MONO_JIT_ICALL_mini_llvmonly_throw_corlib_exception,
        MONO_JIT_ICALL_mono_threads_state_poll,
        MONO_JIT_ICALL_mini_llvmonly_init_vtable_slot,
index 4cf1908..2830b84 100644 (file)
@@ -953,6 +953,8 @@ mini_llvm_init_method (MonoAotFileInfo *info, gpointer aot_module, gpointer meth
 }
 
 static GENERATE_GET_CLASS_WITH_CACHE (nullref, "System", "NullReferenceException")
+static GENERATE_GET_CLASS_WITH_CACHE (index_out_of_range, "System", "IndexOutOfRangeException")
+static GENERATE_GET_CLASS_WITH_CACHE (invalid_cast, "System", "InvalidCastException")
 
 void
 mini_llvmonly_throw_nullref_exception (void)
@@ -974,6 +976,26 @@ mini_llvmonly_throw_aot_failed_exception (const char *name)
 }
 
 void
+mini_llvmonly_throw_index_out_of_range_exception (void)
+{
+       MonoClass *klass = mono_class_get_index_out_of_range_class ();
+
+       guint32 ex_token_index = m_class_get_type_token (klass) - MONO_TOKEN_TYPE_DEF;
+
+       mini_llvmonly_throw_corlib_exception (ex_token_index);
+}
+
+void
+mini_llvmonly_throw_invalid_cast_exception (void)
+{
+       MonoClass *klass = mono_class_get_invalid_cast_class ();
+
+       guint32 ex_token_index = m_class_get_type_token (klass) - MONO_TOKEN_TYPE_DEF;
+
+       mini_llvmonly_throw_corlib_exception (ex_token_index);
+}
+
+void
 mini_llvmonly_interp_entry_gsharedvt (gpointer imethod, gpointer res, gpointer *args)
 {
        mini_get_interp_callbacks ()->entry_llvmonly (res, args, imethod);
index 0c9cff5..4beee18 100644 (file)
@@ -32,6 +32,8 @@ G_EXTERN_C void mini_llvmonly_init_delegate (MonoDelegate *del, MonoDelegateTram
 G_EXTERN_C void mini_llvm_init_method (MonoAotFileInfo *info, gpointer aot_module, gpointer method_info, MonoVTable *vtable);
 
 G_EXTERN_C void mini_llvmonly_throw_nullref_exception (void);
+G_EXTERN_C void mini_llvmonly_throw_index_out_of_range_exception (void);
+G_EXTERN_C void mini_llvmonly_throw_invalid_cast_exception (void);
 
 G_EXTERN_C void mini_llvmonly_throw_aot_failed_exception (const char *name);
 
index 5f1b441..2c7e25a 100644 (file)
@@ -2591,13 +2591,29 @@ emit_cond_system_exception (EmitContext *ctx, MonoBasicBlock *bb, const char *ex
                ctx->builder = builder = create_builder (ctx);
                LLVMPositionBuilderAtEnd (ctx->builder, ex2_bb);
 
-               if (exc_id == MONO_EXC_NULL_REF) {
+               MonoJitICallId icall_id = (MonoJitICallId)0;
+               switch (exc_id) {
+               case MONO_EXC_NULL_REF:
+                       icall_id = MONO_JIT_ICALL_mini_llvmonly_throw_nullref_exception;
+                       break;
+               case MONO_EXC_INDEX_OUT_OF_RANGE:
+                       icall_id = MONO_JIT_ICALL_mini_llvmonly_throw_index_out_of_range_exception;
+                       break;
+               case MONO_EXC_INVALID_CAST:
+                       icall_id = MONO_JIT_ICALL_mini_llvmonly_throw_invalid_cast_exception;
+                       break;
+               default:
+                       break;
+               }
+
+               if ((int)icall_id != 0) {
                        static LLVMTypeRef sig;
 
+                       /* These calls are very common, so call a specialized version without an argument */
                        if (!sig)
                                sig = LLVMFunctionType0 (LLVMVoidType (), FALSE);
                        /* Can't cache this */
-                       callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, GUINT_TO_POINTER (MONO_JIT_ICALL_mini_llvmonly_throw_nullref_exception));
+                       callee = get_callee (ctx, sig, MONO_PATCH_INFO_JIT_ICALL_ADDR, GUINT_TO_POINTER (icall_id));
                        emit_call (ctx, bb, &builder, sig, callee, NULL, 0);
                } else {
                        static LLVMTypeRef sig;
index 0b99532..933b6f8 100644 (file)
@@ -5076,6 +5076,8 @@ register_icalls (void)
        register_icall (mini_llvmonly_init_vtable_slot, mono_icall_sig_ptr_ptr_int, FALSE);
        register_icall (mini_llvmonly_init_delegate, mono_icall_sig_void_object_ptr, TRUE);
        register_icall (mini_llvmonly_throw_nullref_exception, mono_icall_sig_void, TRUE);
+       register_icall (mini_llvmonly_throw_index_out_of_range_exception, mono_icall_sig_void, TRUE);
+       register_icall (mini_llvmonly_throw_invalid_cast_exception, mono_icall_sig_void, TRUE);
        register_icall (mini_llvmonly_throw_aot_failed_exception, mono_icall_sig_void_ptr, TRUE);
        register_icall (mini_llvmonly_interp_entry_gsharedvt, mono_icall_sig_void_ptr_ptr_ptr, TRUE);