Merge pull request #2989 from lambdageek/dev/monoerror-message
[mono.git] / mono / mini / mini-runtime.c
index 795bab9e41d319ebb23ec690c14ee6cf6c288980..fee574471bd5834ab34ff99bcd5b436a548df072 100644 (file)
@@ -163,7 +163,8 @@ G_GNUC_UNUSED static char*
 get_method_from_ip (void *ip)
 {
        MonoJitInfo *ji;
-       char *method;
+       MonoMethod *method;
+       char *method_name;
        char *res;
        MonoDomain *domain = mono_domain_get ();
        MonoDebugSourceLocation *location;
@@ -192,14 +193,15 @@ get_method_from_ip (void *ip)
                return res;
        }
 
-       method = mono_method_full_name (jinfo_get_method (ji), TRUE);
+       method = jinfo_get_method (ji);
+       method_name = mono_method_full_name (method, TRUE);
        /* FIXME: unused ? */
-       location = mono_debug_lookup_source_location (jinfo_get_method (ji), (guint32)((guint8*)ip - (guint8*)ji->code_start), domain);
+       location = mono_debug_lookup_source_location (method, (guint32)((guint8*)ip - (guint8*)ji->code_start), domain);
 
-       res = g_strdup_printf (" %s + 0x%x (%p %p) [%p - %s]", method, (int)((char*)ip - (char*)ji->code_start), ji->code_start, (char*)ji->code_start + ji->code_size, domain, domain->friendly_name);
+       res = g_strdup_printf (" %s {%p} + 0x%x (%p %p) [%p - %s]", method_name, method, (int)((char*)ip - (char*)ji->code_start), ji->code_start, (char*)ji->code_start + ji->code_size, domain, domain->friendly_name);
 
        mono_debug_free_source_location (location);
-       g_free (method);
+       g_free (method_name);
 
        return res;
 }
@@ -360,65 +362,6 @@ mono_nacl_gc()
        __nacl_suspend_thread_if_needed();
 #endif
 }
-
-/* Given the temporary buffer (allocated by mono_global_codeman_reserve) into
- * which we are generating code, return a pointer to the destination in the
- * dynamic code segment into which the code will be copied when
- * mono_global_codeman_commit is called.
- * LOCKING: Acquires the jit lock.
- */
-void*
-nacl_global_codeman_get_dest (void *data)
-{
-       void *dest;
-       mono_jit_lock ();
-       dest = nacl_code_manager_get_code_dest (global_codeman, data);
-       mono_jit_unlock ();
-       return dest;
-}
-
-void
-mono_global_codeman_commit (void *data, int size, int newsize)
-{
-       mono_jit_lock ();
-       mono_code_manager_commit (global_codeman, data, size, newsize);
-       mono_jit_unlock ();
-}
-
-/*
- * Convenience function which calls mono_global_codeman_commit to validate and
- * copy the code. The caller sets *buf_base and *buf_size to the start and size
- * of the buffer (allocated by mono_global_codeman_reserve), and *code_end to
- * the byte after the last instruction byte. On return, *buf_base will point to
- * the start of the copied in the code segment, and *code_end will point after
- * the end of the copied code.
- */
-void
-nacl_global_codeman_validate (guint8 **buf_base, int buf_size, guint8 **code_end)
-{
-       guint8 *tmp = nacl_global_codeman_get_dest (*buf_base);
-       mono_global_codeman_commit (*buf_base, buf_size, *code_end - *buf_base);
-       *code_end = tmp + (*code_end - *buf_base);
-       *buf_base = tmp;
-}
-#else
-/* no-op versions of Native Client functions */
-void*
-nacl_global_codeman_get_dest (void *data)
-{
-       return data;
-}
-
-void
-mono_global_codeman_commit (void *data, int size, int newsize)
-{
-}
-
-void
-nacl_global_codeman_validate (guint8 **buf_base, int buf_size, guint8 **code_end)
-{
-}
-
 #endif /* __native_client__ */
 
 /**
@@ -614,6 +557,7 @@ mono_debug_count (void)
 gconstpointer
 mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
 {
+       MonoError error;
        char *name;
        MonoMethod *wrapper;
        gconstpointer trampoline;
@@ -635,9 +579,9 @@ mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
        g_free (name);
 
        if (do_compile) {
-               trampoline = mono_compile_method (wrapper);
+               trampoline = mono_compile_method_checked (wrapper, &error);
+               mono_error_assert_ok (&error);
        } else {
-               MonoError error;
 
                trampoline = mono_create_jit_trampoline (domain, wrapper, &error);
                mono_error_assert_ok (&error);
@@ -901,7 +845,7 @@ mono_set_lmf_addr (gpointer lmf_addr)
  *
  * In coop mode:
  *  - @dummy: contains the original domain
- *  - @return: a cookie containing current MonoThreadInfo* if it was in BLOCKING mode, NULL otherwise
+ *  - @return: a cookie containing current MonoThreadInfo*.
  */
 gpointer
 mono_jit_thread_attach (MonoDomain *domain, gpointer *dummy)
@@ -915,7 +859,18 @@ mono_jit_thread_attach (MonoDomain *domain, gpointer *dummy)
 
        g_assert (domain);
 
-       if (!mono_threads_is_coop_enabled ()) {
+       /* On coop, when we detached, we moved the thread from  RUNNING->BLOCKING.  If we try to
+        * reattach we do a BLOCKING->RUNNING transition.  If the thread is fresh,
+        * mono_thread_attach() will do a STARTING->RUNNING transition so we're only responsible
+        * for making the cookie. */
+       gboolean fresh_thread = FALSE;
+       {
+               MonoThreadInfo *info;
+
+               info = mono_thread_info_current_unchecked ();
+               fresh_thread = !info || !mono_thread_info_is_live (info);
+       }
+       {
                gboolean attached;
 
 #ifdef MONO_HAVE_FAST_TLS
@@ -935,35 +890,19 @@ mono_jit_thread_attach (MonoDomain *domain, gpointer *dummy)
                if (orig != domain)
                        mono_domain_set (domain, TRUE);
 
+       }
+       if (!mono_threads_is_coop_enabled ()) {
                return orig != domain ? orig : NULL;
        } else {
-               MonoThreadInfo *info;
-
-               info = mono_thread_info_current_unchecked ();
-               if (!info || !mono_thread_info_is_live (info)) {
-                       /* thread state STARTING -> RUNNING */
-                       mono_thread_attach (domain);
-
-                       // #678164
-                       mono_thread_set_state (mono_thread_internal_current (), ThreadState_Background);
-
+               if (fresh_thread) {
                        *dummy = NULL;
-
-                       /* mono_threads_reset_blocking_start returns the current MonoThreadInfo
-                        * if we were in BLOCKING mode */
-                       return mono_thread_info_current ();
+                       /* mono_thread_attach put the thread in RUNNING mode from STARTING, but we need to
+                        * return the right cookie. */
+                       return mono_threads_enter_gc_unsafe_region_cookie (mono_thread_info_current ());
                } else {
-                       orig = mono_domain_get ();
-
-                       /* orig might be null if we did an attach -> detach -> attach sequence */
-
-                       if (orig != domain)
-                               mono_domain_set (domain, TRUE);
-
                        *dummy = orig;
-
                        /* thread state (BLOCKING|RUNNING) -> RUNNING */
-                       return mono_threads_reset_blocking_start (dummy);
+                       return mono_threads_enter_gc_unsafe_region (dummy);
                }
        }
 }
@@ -997,7 +936,7 @@ mono_jit_thread_detach (gpointer cookie, gpointer *dummy)
 
                /* it won't do anything if cookie is NULL
                 * thread state RUNNING -> (RUNNING|BLOCKING) */
-               mono_threads_reset_blocking_end (cookie, dummy);
+               mono_threads_exit_gc_unsafe_region (cookie, dummy);
 
                if (orig != domain) {
                        if (!orig)
@@ -1112,8 +1051,6 @@ mono_thread_attach_cb (intptr_t tid, gpointer stack_start)
        thread = mono_thread_info_current_unchecked ();
        if (thread)
                thread->jit_data = jit_tls;
-       if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
-               mono_runtime_setup_stat_profiler ();
 
        mono_arch_cpu_init ();
 }
@@ -1459,13 +1396,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = patch_info->data.inst->inst_c0 + code;
                break;
        case MONO_PATCH_INFO_IP:
-#if defined(__native_client__) && defined(__native_client_codegen__)
-               /* Need to transform to the destination address, it's */
-               /* emitted as an immediate in the code. */
-               target = nacl_inverse_modify_patch_target(ip);
-#else
                target = ip;
-#endif
                break;
        case MONO_PATCH_INFO_METHOD_REL:
                target = code + patch_info->data.offset;
@@ -1492,25 +1423,8 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                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 */
-               /* current code being emitted on AMD64. */
-               target = nacl_inverse_modify_patch_target(target);
-# endif
-#endif
                break;
        case MONO_PATCH_INFO_METHOD:
-#if defined(__native_client_codegen__) && defined(USE_JUMP_TABLES)
-               /*
-                * If we use jumptables, for recursive calls we cannot
-                * avoid trampoline, as we not yet know where we will
-                * be installed.
-                */
-               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 {
@@ -1519,7 +1433,6 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                        if (!mono_error_ok (error))
                                return NULL;
                }
-#endif
                break;
        case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
                gpointer code_slot;
@@ -1564,24 +1477,10 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
 #endif
 
                for (i = 0; i < patch_info->data.table->table_size; i++) {
-#if defined(__native_client__) && defined(__native_client_codegen__)
-                       /* 'code' is relative to the current code blob, we */
-                       /* need to do this transform on it to make the     */
-                       /* pointers in this table absolute                 */
-                       jump_table [i] = nacl_inverse_modify_patch_target (code) + GPOINTER_TO_INT (patch_info->data.table->table [i]);
-#else
                        jump_table [i] = code + GPOINTER_TO_INT (patch_info->data.table->table [i]);
-#endif
                }
 
-#if defined(__native_client__) && defined(__native_client_codegen__)
-               /* jump_table is in the data section, we need to transform */
-               /* it here so when it gets modified in amd64_patch it will */
-               /* then point back to the absolute data address            */
-               target = nacl_inverse_modify_patch_target (jump_table);
-#else
                target = jump_table;
-#endif
                break;
        }
        case MONO_PATCH_INFO_METHODCONST:
@@ -1658,8 +1557,8 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                break;
        case MONO_PATCH_INFO_LDSTR:
                target =
-                       mono_ldstr (domain, patch_info->data.token->image,
-                                               mono_metadata_token_index (patch_info->data.token->token));
+                       mono_ldstr_checked (domain, patch_info->data.token->image,
+                                           mono_metadata_token_index (patch_info->data.token->token), error);
                break;
        case MONO_PATCH_INFO_TYPE_FROM_HANDLE: {
                gpointer handle;
@@ -2025,7 +1924,7 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er
 
                mono_class_init (method->klass);
 
-               if ((code = mono_aot_get_method (domain, method))) {
+               if ((code = mono_aot_get_method_checked (domain, method, error))) {
                        MonoVTable *vtable;
 
                        /*
@@ -2040,6 +1939,8 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoError *er
                                        return NULL;
                        }
                }
+               if (!is_ok (error))
+                       return NULL;
        }
 #endif
 
@@ -3045,6 +2946,7 @@ MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
 static gpointer
 mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, MonoRemotingTarget target)
 {
+       MonoError error;
        MonoMethod *nm;
        guint8 *addr = NULL;
 
@@ -3056,10 +2958,12 @@ mono_jit_create_remoting_trampoline (MonoDomain *domain, MonoMethod *method, Mon
        if ((method->flags & METHOD_ATTRIBUTE_ABSTRACT) ||
            (mono_method_signature (method)->hasthis && (mono_class_is_marshalbyref (method->klass) || method->klass == mono_defaults.object_class))) {
                nm = mono_marshal_get_remoting_invoke_for_target (method, target);
-               addr = (guint8 *)mono_compile_method (nm);
+               addr = (guint8 *)mono_compile_method_checked (nm, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
        } else
        {
-               addr = (guint8 *)mono_compile_method (method);
+               addr = (guint8 *)mono_compile_method_checked (method, &error);
+               mono_error_raise_exception (&error); /* FIXME don't raise here */
        }
        return mono_get_addr_from_ftnptr (addr);
 }
@@ -3397,7 +3301,7 @@ register_jit_stats (void)
        mono_counters_register ("Methods from AOT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_aot);
        mono_counters_register ("Methods JITted using mono JIT", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_without_llvm);
        mono_counters_register ("Methods JITted using LLVM", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.methods_with_llvm);
-       mono_counters_register ("JIT/method-to-IR (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_method_to_ir);
+       mono_counters_register ("JIT/method_to_ir (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_method_to_ir);
        mono_counters_register ("JIT/liveness_handle_exception_clauses (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_liveness_handle_exception_clauses);
        mono_counters_register ("JIT/handle_out_of_line_bblock (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_handle_out_of_line_bblock);
        mono_counters_register ("JIT/decompose_long_opts (sec)", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &mono_jit_stats.jit_decompose_long_opts);
@@ -3840,6 +3744,9 @@ mini_init (const char *filename, const char *runtime_version)
        mono_thread_attach (domain);
 #endif
 
+       if (mono_profiler_get_events () & MONO_PROFILE_STATISTICAL)
+               mono_runtime_setup_stat_profiler ();
+
        mono_profiler_runtime_initialized ();
 
        MONO_VES_INIT_END ();
@@ -3900,8 +3807,8 @@ register_icalls (void)
        register_icall (mono_thread_interruption_checkpoint, "mono_thread_interruption_checkpoint", "object", FALSE);
        register_icall (mono_thread_force_interruption_checkpoint_noraise, "mono_thread_force_interruption_checkpoint_noraise", "object", FALSE);
 #ifndef DISABLE_REMOTING
-       register_icall (mono_load_remote_field_new, "mono_load_remote_field_new", "object object ptr ptr", FALSE);
-       register_icall (mono_store_remote_field_new, "mono_store_remote_field_new", "void object ptr ptr object", FALSE);
+       register_icall (mono_load_remote_field_new_icall, "mono_load_remote_field_new_icall", "object object ptr ptr", FALSE);
+       register_icall (mono_store_remote_field_new_icall, "mono_store_remote_field_new_icall", "void object ptr ptr object", FALSE);
 #endif
 
 #if defined(__native_client__) || defined(__native_client_codegen__)
@@ -3976,10 +3883,10 @@ register_icalls (void)
        register_opcode_emulation (OP_LCONV_TO_R_UN, "__emul_lconv_to_r8_un", "double long", mono_lconv_to_r8_un, "mono_lconv_to_r8_un", FALSE);
 #endif
 #ifdef MONO_ARCH_EMULATE_FREM
-#if defined(__default_codegen__)
+#if !defined(__native_client__)
        register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", fmod, "fmod", FALSE);
        register_opcode_emulation (OP_RREM, "__emul_rrem", "float float float", fmodf, "fmodf", FALSE);
-#elif defined(__native_client_codegen__)
+#else
        register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, "mono_fmod", FALSE);
 #endif
 #endif
@@ -4039,18 +3946,18 @@ register_icalls (void)
 #endif
 
        /* other jit icalls */
-       register_icall (mono_delegate_ctor, "mono_delegate_ctor", "void object object ptr", FALSE);
+       register_icall (ves_icall_mono_delegate_ctor, "ves_icall_mono_delegate_ctor", "void object object ptr", FALSE);
        register_icall (mono_class_static_field_address , "mono_class_static_field_address",
                                 "ptr ptr ptr", FALSE);
        register_icall (mono_ldtoken_wrapper, "mono_ldtoken_wrapper", "ptr ptr ptr ptr", FALSE);
        register_icall (mono_ldtoken_wrapper_generic_shared, "mono_ldtoken_wrapper_generic_shared",
                "ptr ptr ptr ptr", FALSE);
        register_icall (mono_get_special_static_data, "mono_get_special_static_data", "ptr int", FALSE);
-       register_icall (mono_ldstr, "mono_ldstr", "object ptr ptr int32", FALSE);
+       register_icall (ves_icall_mono_ldstr, "ves_icall_mono_ldstr", "object ptr ptr int32", FALSE);
        register_icall (mono_helper_stelem_ref_check, "mono_helper_stelem_ref_check", "void object object", FALSE);
        register_icall (ves_icall_object_new, "ves_icall_object_new", "object ptr ptr", FALSE);
        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, "ves_icall_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 (ves_icall_runtime_class_init, "ves_icall_runtime_class_init", "void ptr", FALSE);
        register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE);
@@ -4234,10 +4141,6 @@ mini_cleanup (MonoDomain *domain)
        mono_os_mutex_destroy (&jit_mutex);
 
        mono_code_manager_cleanup ();
-
-#ifdef USE_JUMP_TABLES
-       mono_jumptable_cleanup ();
-#endif
 }
 
 void
@@ -4323,15 +4226,21 @@ mono_precompile_assembly (MonoAssembly *ass, void *user_data)
                        g_print ("Compiling %d %s\n", count, desc);
                        g_free (desc);
                }
-               mono_compile_method (method);
+               mono_compile_method_checked (method, &error);
+               if (!is_ok (&error)) {
+                       mono_error_cleanup (&error); /* FIXME don't swallow the error */
+                       continue;
+               }
                if (strcmp (method->name, "Finalize") == 0) {
                        invoke = mono_marshal_get_runtime_invoke (method, FALSE);
-                       mono_compile_method (invoke);
+                       mono_compile_method_checked (invoke, &error);
+                       mono_error_assert_ok (&error);
                }
 #ifndef DISABLE_REMOTING
                if (mono_class_is_marshalbyref (method->klass) && mono_method_signature (method)->hasthis) {
                        invoke = mono_marshal_get_remoting_invoke_with_check (method);
-                       mono_compile_method (invoke);
+                       mono_compile_method_checked (invoke, &error);
+                       mono_error_assert_ok (&error);
                }
 #endif
        }
@@ -4363,98 +4272,3 @@ mono_personality (void)
        /* Not used */
        g_assert_not_reached ();
 }
-
-#ifdef USE_JUMP_TABLES
-#define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128
-
-typedef struct MonoJumpTableChunk {
-       guint32 total;
-       guint32 active;
-       struct MonoJumpTableChunk *previous;
-       /* gpointer entries[total]; */
-} MonoJumpTableChunk;
-
-static MonoJumpTableChunk* g_jumptable;
-#define mono_jumptable_lock() mono_os_mutex_lock (&jumptable_mutex)
-#define mono_jumptable_unlock() mono_os_mutex_unlock (&jumptable_mutex)
-static mono_mutex_t jumptable_mutex;
-
-static  MonoJumpTableChunk*
-mono_create_jumptable_chunk (guint32 max_entries)
-{
-       guint32 size = sizeof (MonoJumpTableChunk) + max_entries * sizeof(gpointer);
-       MonoJumpTableChunk *chunk = (MonoJumpTableChunk*) g_new0 (guchar, size);
-       chunk->total = max_entries;
-       return chunk;
-}
-
-void
-mono_jumptable_init (void)
-{
-       if (g_jumptable == NULL) {
-               mono_os_mutex_init_recursive (&jumptable_mutex);
-               g_jumptable = mono_create_jumptable_chunk (DEFAULT_JUMPTABLE_CHUNK_ELEMENTS);
-       }
-}
-
-gpointer*
-mono_jumptable_add_entry (void)
-{
-       return mono_jumptable_add_entries (1);
-}
-
-gpointer*
-mono_jumptable_add_entries (guint32 entries)
-{
-       guint32 index;
-       gpointer *result;
-
-       mono_jumptable_init ();
-       mono_jumptable_lock ();
-       index = g_jumptable->active;
-       if (index + entries >= g_jumptable->total) {
-               /*
-                * Grow jumptable, by adding one more chunk.
-                * We cannot realloc jumptable, as there could be pointers
-                * to existing jump table entries in the code, so instead
-                * we just add one more chunk.
-                */
-               guint32 max_entries = entries;
-               MonoJumpTableChunk *new_chunk;
-
-               if (max_entries < DEFAULT_JUMPTABLE_CHUNK_ELEMENTS)
-                       max_entries = DEFAULT_JUMPTABLE_CHUNK_ELEMENTS;
-               new_chunk = mono_create_jumptable_chunk (max_entries);
-               /* Link old jumptable, so that we could free it up later. */
-               new_chunk->previous = g_jumptable;
-               g_jumptable = new_chunk;
-               index = 0;
-       }
-       g_jumptable->active = index + entries;
-       result = (gpointer*)((guchar*)g_jumptable + sizeof(MonoJumpTableChunk)) + index;
-       mono_jumptable_unlock();
-
-       return result;
-}
-
-void
-mono_jumptable_cleanup (void)
-{
-       if (g_jumptable) {
-               MonoJumpTableChunk *current = g_jumptable, *prev;
-               while (current != NULL) {
-                       prev = current->previous;
-                       g_free (current);
-                       current = prev;
-               }
-               g_jumptable = NULL;
-               mono_os_mutex_destroy (&jumptable_mutex);
-       }
-}
-
-gpointer*
-mono_jumptable_get_entry (guint8 *code_ptr)
-{
-       return mono_arch_jumptable_entry_from_code (code_ptr);
-}
-#endif