Merge pull request #2454 from tastywheattasteslikechicken/FixVtableAbort
[mono.git] / mono / mini / mini-runtime.c
index ad8b5bc1601a05f91b1553b4c0bdaf260d5376e5..136239a1211c7c217c32221e20bcd5faccc72aa4 100644 (file)
@@ -81,6 +81,7 @@
 #ifdef MONO_ARCH_LLVM_SUPPORTED
 #ifdef ENABLE_LLVM
 #include "mini-llvm-cpp.h"
+#include "llvm-jit.h"
 #endif
 #endif
 
@@ -631,10 +632,15 @@ mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
        wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_exc);
        g_free (name);
 
-       if (do_compile)
+       if (do_compile) {
                trampoline = mono_compile_method (wrapper);
-       else
-               trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper));
+       } else {
+               MonoError error;
+
+               trampoline = mono_create_jit_trampoline (domain, wrapper, &error);
+               mono_error_assert_ok (&error);
+               trampoline = mono_create_ftnptr (domain, (gpointer)trampoline);
+       }
 
        mono_loader_lock ();
        if (!callinfo->trampoline) {
@@ -1302,6 +1308,7 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_METHOD_JUMP:
        case MONO_PATCH_INFO_IMAGE:
        case MONO_PATCH_INFO_ICALL_ADDR:
+       case MONO_PATCH_INFO_ICALL_ADDR_CALL:
        case MONO_PATCH_INFO_FIELD:
        case MONO_PATCH_INFO_SFLDA:
        case MONO_PATCH_INFO_SEQ_POINT_INFO:
@@ -1480,7 +1487,9 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                break;
        }
        case MONO_PATCH_INFO_METHOD_JUMP:
-               target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE);
+               target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE, error);
+               if (!mono_error_ok (error))
+                       return NULL;
 #if defined(__native_client__) && defined(__native_client_codegen__)
 # if defined(TARGET_AMD64)
                /* This target is an absolute address, not relative to the */
@@ -1496,13 +1505,17 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                 * avoid trampoline, as we not yet know where we will
                 * be installed.
                 */
-               target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method);
+               target = mono_create_jit_trampoline (domain, patch_info->data.method, error);
+               if (!mono_error_ok (error))
+                       return NULL;
 #else
                if (patch_info->data.method == method) {
                        target = code;
                } else {
                        /* get the trampoline to the method from the domain */
-                       target = mono_create_jit_trampoline_in_domain (domain, patch_info->data.method);
+                       target = mono_create_jit_trampoline (domain, patch_info->data.method, error);
+                       if (!mono_error_ok (error))
+                               return NULL;
                }
 #endif
                break;
@@ -1617,8 +1630,11 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                        /* Done by the generated code */
                        ;
                else {
-                       if (run_cctors)
-                               mono_runtime_class_init (vtable);
+                       if (run_cctors) {
+                               if (!mono_runtime_class_init_full (vtable, error)) {
+                                       return NULL;
+                               }
+                       }
                }
                target = (char*)mono_vtable_get_static_field_data (vtable) + patch_info->data.field->offset;
                break;
@@ -1676,6 +1692,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = (mono_metadata_blob_heap (patch_info->data.token->image, patch_info->data.token->token) + 2);
                break;
        case MONO_PATCH_INFO_ICALL_ADDR:
+       case MONO_PATCH_INFO_ICALL_ADDR_CALL:
                /* run_cctors == 0 -> AOT */
                if (patch_info->data.method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
                        const char *exc_class;
@@ -1988,16 +2005,18 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er
                /* We can't use a domain specific method in another domain */
                if (! ((domain != target_domain) && !info->domain_neutral)) {
                        MonoVTable *vtable;
-                       MonoException *tmpEx;
 
                        mono_jit_stats.methods_lookups++;
-                       vtable = mono_class_vtable (domain, method->klass);
-                       g_assert (vtable);
-                       tmpEx = mono_runtime_class_init_full (vtable, FALSE);
-                       if (tmpEx) {
-                               mono_error_set_exception_instance (error, tmpEx);
+
+                       vtable = mono_class_vtable_full (domain, method->klass, ex == NULL);
+                       if (ex && method->klass->exception_type) {
+                               *ex = mono_class_get_exception_for_failure (method->klass);
                                return NULL;
                        }
+
+                       g_assert (vtable);
+                       if (!mono_runtime_class_init_full (vtable, error))
+                               return NULL;
                        return mono_create_ftnptr (target_domain, info->code_start);
                }
        }
@@ -2019,7 +2038,8 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er
                        if (!mono_llvm_only) {
                                vtable = mono_class_vtable (domain, method->klass);
                                g_assert (vtable);
-                               mono_runtime_class_init (vtable);
+                               if (!mono_runtime_class_init_full (vtable, error))
+                                       return NULL;
                        }
                }
        }
@@ -2150,7 +2170,6 @@ mono_jit_free_method (MonoDomain *domain, MonoMethod *method)
                }
                g_slist_free (remove);
        }
-
        mono_domain_unlock (domain);
 
 #ifdef MONO_ARCH_HAVE_INVALIDATE_METHOD
@@ -2296,7 +2315,9 @@ create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer com
        info->sig = mono_method_signature (method);
 
        invoke = mono_marshal_get_runtime_invoke (method, FALSE);
-       info->vtable = mono_class_vtable_full (domain, method->klass, TRUE);
+       info->vtable = mono_class_vtable_full (domain, method->klass, error);
+       if (!mono_error_ok (error))
+               return NULL;
        g_assert (info->vtable);
 
        MonoMethodSignature *sig = mono_method_signature (method);
@@ -2598,15 +2619,10 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
         * We need this here because mono_marshal_get_runtime_invoke can place
         * the helper method in System.Object and not the target class.
         */
-       if (exc)
-       {
-               *exc = (MonoObject*)mono_runtime_class_init_full (info->vtable, FALSE);
-               if (*exc) {
-                       mono_error_set_exception_instance (error, (MonoException*) *exc);
-                       return NULL;
-               }
-       } else {
-               mono_runtime_class_init (info->vtable);
+       if (!mono_runtime_class_init_full (info->vtable, error)) {
+               if (exc)
+                       *exc = (MonoObject*) mono_error_convert_to_exception (error);
+               return NULL;
        }
 
        /* If coop is enabled, and the caller didn't ask for the exception to be caught separately,
@@ -3300,6 +3316,8 @@ mini_parse_debug_option (const char *option)
                mono_align_small_structs = TRUE;
        else if (!strcmp (option, "native-debugger-break"))
                debug_options.native_debugger_break = TRUE;
+       else if (!strcmp (option, "disable_omit_fp"))
+               debug_options.disable_omit_fp = TRUE;
        else
                return FALSE;
 
@@ -3412,8 +3430,8 @@ register_jit_stats (void)
        mono_counters_register ("JIT/linear_scan (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_linear_scan);
        mono_counters_register ("JIT/arch_allocate_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_arch_allocate_vars);
        mono_counters_register ("JIT/spill_global_vars (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_spill_global_vars);
-       mono_counters_register ("JIT/jit_local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
-       mono_counters_register ("JIT/jit_local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
+       mono_counters_register ("JIT/local_cprop3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_cprop3);
+       mono_counters_register ("JIT/local_deadce3 (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_local_deadce3);
        mono_counters_register ("JIT/codegen (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_codegen);
        mono_counters_register ("JIT/create_jit_info (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_create_jit_info);
        mono_counters_register ("JIT/gc_create_gc_map (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_gc_create_gc_map);
@@ -3508,6 +3526,12 @@ runtime_invoke_info_free (gpointer value)
        g_free (info);
 }
 
+static void
+free_jit_callee_list (gpointer key, gpointer value, gpointer user_data)
+{
+       g_slist_free (value);
+}
+
 static void
 mini_free_jit_domain_info (MonoDomain *domain)
 {
@@ -3538,6 +3562,10 @@ mini_free_jit_domain_info (MonoDomain *domain)
                mono_debugger_agent_free_domain_info (domain);
        if (info->gsharedvt_arg_tramp_hash)
                g_hash_table_destroy (info->gsharedvt_arg_tramp_hash);
+       if (info->llvm_jit_callees) {
+               g_hash_table_foreach (info->llvm_jit_callees, free_jit_callee_list, NULL);
+               g_hash_table_destroy (info->llvm_jit_callees);
+       }
 #ifdef ENABLE_LLVM
        mono_llvm_free_domain_info (domain);
 #endif
@@ -3652,6 +3680,8 @@ mini_init (const char *filename, const char *runtime_version)
 #define JIT_TRAMPOLINES_WORK
 #ifdef JIT_TRAMPOLINES_WORK
        callbacks.compile_method = mono_jit_compile_method;
+       callbacks.create_jump_trampoline = mono_create_jump_trampoline;
+       callbacks.create_jit_trampoline = mono_create_jit_trampoline;
 #endif
 
        mono_install_callbacks (&callbacks);
@@ -3724,8 +3754,6 @@ mini_init (const char *filename, const char *runtime_version)
 
 #ifdef JIT_TRAMPOLINES_WORK
        mono_install_free_method (mono_jit_free_method);
-       mono_install_trampoline (mono_create_jit_trampoline);
-       mono_install_jump_trampoline (mono_create_jump_trampoline);
 #ifndef DISABLE_REMOTING
        mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline);
 #endif
@@ -4026,7 +4054,7 @@ register_icalls (void)
        register_icall (ves_icall_object_new_specific, "ves_icall_object_new_specific", "object ptr", FALSE);
        register_icall (mono_array_new, "mono_array_new", "object ptr ptr int32", FALSE);
        register_icall (ves_icall_array_new_specific, "ves_icall_array_new_specific", "object ptr int32", FALSE);
-       register_icall (mono_runtime_class_init, "mono_runtime_class_init", "void ptr", FALSE);
+       register_icall (ves_icall_runtime_class_init, "ves_icall_runtime_class_init", "void ptr", FALSE);
        register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
        register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE);
        register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE);