Merge pull request #1857 from slluis/fix-assembly-resolver
[mono.git] / mono / mini / mini-runtime.c
old mode 100755 (executable)
new mode 100644 (file)
index 9b48dcd..615d56b
@@ -86,8 +86,8 @@ MONO_FAST_TLS_DECLARE(mono_jit_tls);
 gboolean mono_compile_aot = FALSE;
 /* If this is set, no code is generated dynamically, everything is taken from AOT files */
 gboolean mono_aot_only = FALSE;
-/* Whenever to use IMT */
-gboolean mono_use_imt = TRUE;
+MonoAotMode mono_aot_mode = MONO_AOT_MODE_NONE;
+
 const char *mono_build_date;
 gboolean mono_do_signal_chaining;
 gboolean mono_do_crash_chaining;
@@ -227,29 +227,28 @@ mono_print_method_from_ip (void *ip)
        FindTrampUserData user_data;
        MonoGenericSharingContext*gsctx;
        const char *shared_type;
-       GSList *l;
 
-       ji = mini_jit_info_table_find (domain, ip, &target_domain);
+       ji = mini_jit_info_table_find_ext (domain, ip, TRUE, &target_domain);
+       if (ji && ji->is_trampoline) {
+               MonoTrampInfo *tinfo = ji->d.tramp_info;
+
+               printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name);
+               return;
+       }
+
        if (!ji) {
                user_data.ip = ip;
                user_data.method = NULL;
                mono_domain_lock (domain);
                g_hash_table_foreach (domain_jit_info (domain)->jit_trampoline_hash, find_tramp, &user_data);
                mono_domain_unlock (domain);
+
                if (user_data.method) {
                        char *mname = mono_method_full_name (user_data.method, TRUE);
                        printf ("IP %p is a JIT trampoline for %s\n", ip, mname);
                        g_free (mname);
                        return;
                }
-               for (l = tramp_infos; l; l = l->next) {
-                       MonoTrampInfo *tinfo = l->data;
-
-                       if ((guint8*)ip >= tinfo->code && (guint8*)ip <= tinfo->code + tinfo->code_size) {
-                               printf ("IP %p is at offset 0x%x of trampoline '%s'.\n", ip, (int)((guint8*)ip - tinfo->code), tinfo->name);
-                               return;
-                       }
-               }
 
                g_print ("No method at %p\n", ip);
                fflush (stdout);
@@ -472,6 +471,20 @@ mono_tramp_info_free (MonoTrampInfo *info)
        g_free (info);
 }
 
+static void
+register_trampoline_jit_info (MonoDomain *domain, MonoTrampInfo *info)
+{
+       MonoJitInfo *ji;
+
+       ji = mono_domain_alloc0 (domain, mono_jit_info_size (0, 0, 0));
+       mono_jit_info_init (ji, NULL, info->code, info->code_size, 0, 0, 0);
+       ji->d.tramp_info = info;
+       ji->is_trampoline = TRUE;
+       // FIXME: Unwind info
+
+       mono_jit_info_table_add (domain, ji);
+}
+
 /*
  * mono_tramp_info_register:
  *
@@ -498,6 +511,9 @@ mono_tramp_info_register (MonoTrampInfo *info)
 
        mono_save_trampoline_xdebug_info (info);
 
+       if (mono_get_root_domain ())
+               register_trampoline_jit_info (mono_get_root_domain (), copy);
+
        if (mono_jit_map_is_enabled ())
                mono_emit_jit_tramp (info->code, info->code_size, info->name);
 
@@ -517,6 +533,19 @@ mono_tramp_info_cleanup (void)
        g_slist_free (tramp_infos);
 }
 
+/* Register trampolines created before the root domain was created in the jit info tables */
+static void
+register_trampolines (MonoDomain *domain)
+{
+       GSList *l;
+
+       for (l = tramp_infos; l; l = l->next) {
+               MonoTrampInfo *info = l->data;
+
+               register_trampoline_jit_info (domain, info);
+       }
+}
+
 G_GNUC_UNUSED static void
 break_count (void)
 {
@@ -630,11 +659,11 @@ register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpo
 /*
  * For JIT icalls implemented in C.
  * NAME should be the same as the name of the C function whose address is FUNC.
- * If SAVE is TRUE, no wrapper is generated. This is for perf critical icalls which
+ * If @avoid_wrapper is TRUE, no wrapper is generated. This is for perf critical icalls which
  * can't throw exceptions.
  */
 static void
-register_icall (gpointer func, const char *name, const char *sigstr, gboolean save)
+register_icall (gpointer func, const char *name, const char *sigstr, gboolean avoid_wrapper)
 {
        MonoMethodSignature *sig;
 
@@ -643,7 +672,7 @@ register_icall (gpointer func, const char *name, const char *sigstr, gboolean sa
        else
                sig = NULL;
 
-       mono_register_jit_icall_full (func, name, sig, save, FALSE, save ? name : NULL);
+       mono_register_jit_icall_full (func, name, sig, avoid_wrapper, FALSE, avoid_wrapper ? name : NULL);
 }
 
 static void
@@ -1145,12 +1174,10 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_IID:
        case MONO_PATCH_INFO_ADJUSTED_IID:
        case MONO_PATCH_INFO_CLASS_INIT:
-       case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
        case MONO_PATCH_INFO_METHODCONST:
        case MONO_PATCH_INFO_METHOD:
        case MONO_PATCH_INFO_METHOD_JUMP:
        case MONO_PATCH_INFO_IMAGE:
-       case MONO_PATCH_INFO_JIT_ICALL_ADDR:
        case MONO_PATCH_INFO_ICALL_ADDR:
        case MONO_PATCH_INFO_FIELD:
        case MONO_PATCH_INFO_SFLDA:
@@ -1176,6 +1203,7 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_MONITOR_ENTER_V4:
        case MONO_PATCH_INFO_MONITOR_EXIT:
        case MONO_PATCH_INFO_GOT_OFFSET:
+       case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
                return (ji->type << 8);
        case MONO_PATCH_INFO_CASTCLASS_CACHE:
                return (ji->type << 8) | (ji->data.index);
@@ -1195,6 +1223,8 @@ mono_patch_info_hash (gconstpointer data)
 
                return (ji->type << 8) | (gssize)info->klass | (gssize)info->method;
        }
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+               return (ji->type << 8) | g_str_hash (ji->data.target);
        default:
                printf ("info type: %d\n", ji->type);
                mono_print_ji (ji); printf ("\n");
@@ -1254,6 +1284,10 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
                return ji1->data.index == ji2->data.index;
        case MONO_PATCH_INFO_VIRT_METHOD:
                return ji1->data.virt_method->klass == ji2->data.virt_method->klass && ji1->data.virt_method->method == ji2->data.virt_method->method;
+       case MONO_PATCH_INFO_JIT_ICALL_ADDR:
+               if (ji1->data.target == ji2->data.target)
+                       return 1;
+               return strcmp (ji1->data.target, ji2->data.target) == 0 ? 1 : 0;
        default:
                if (ji1->data.target != ji2->data.target)
                        return 0;
@@ -1356,6 +1390,15 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = code_slot;
                break;
        }
+       case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG:
+#if defined(__native_client_codegen__)
+               target = (gpointer)&__nacl_thread_suspension_needed;
+#elif defined (USE_COOP_GC)
+               target = (gpointer)&mono_polling_required;
+#else
+               g_error ("Unsuported patch target");
+#endif
+               break;
        case MONO_PATCH_INFO_SWITCH: {
                gpointer *jump_table;
                int i;
@@ -1608,9 +1651,6 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                target = mono_create_rgctx_lazy_fetch_trampoline (slot);
                break;
        }
-       case MONO_PATCH_INFO_GENERIC_CLASS_INIT:
-               target = mono_create_generic_class_init_trampoline ();
-               break;
        case MONO_PATCH_INFO_MONITOR_ENTER:
                target = mono_create_monitor_enter_trampoline ();
                break;
@@ -1691,12 +1731,6 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
        return (gpointer)target;
 }
 
-static gboolean
-is_gsharedvt_type (MonoType *t)
-{
-       return (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) && t->data.generic_param->gshared_constraint == MONO_TYPE_VALUETYPE;
-}
-
 void
 mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *context, MonoGenericSharingContext *gsctx)
 {
@@ -1717,7 +1751,7 @@ mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *contex
                for (i = 0; i < inst->type_argc; ++i) {
                        MonoType *type = inst->type_argv [i];
 
-                       if (is_gsharedvt_type (type))
+                       if (mini_is_gsharedvt_gparam (type))
                                gsctx->var_is_vt [i] = TRUE;
                }
        }
@@ -1733,7 +1767,7 @@ mini_init_gsctx (MonoDomain *domain, MonoMemPool *mp, MonoGenericContext *contex
                for (i = 0; i < inst->type_argc; ++i) {
                        MonoType *type = inst->type_argv [i];
 
-                       if (is_gsharedvt_type (type))
+                       if (mini_is_gsharedvt_gparam (type))
                                gsctx->mvar_is_vt [i] = TRUE;
                }
        }
@@ -2234,7 +2268,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
                        for (i = 0; i < sig->param_count; ++i) {
                                MonoType *t = sig->params [i];
 
-                               if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
+                               if (t->byref && t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
                                        supported = FALSE;
                        }
 
@@ -2703,9 +2737,13 @@ mini_parse_debug_options (void)
                        debug_options.check_pinvoke_callconv = TRUE;
                else if (!strcmp (arg, "debug-domain-unload"))
                        mono_enable_debug_domain_unload (TRUE);
+               else if (!strcmp (arg, "partial-sharing"))
+                       mono_set_partial_sharing_supported (TRUE);
+               else if (!strcmp (arg, "align-small-structs"))
+                       mono_align_small_structs = TRUE;
                else {
                        fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
-                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks', 'check-pinvoke-callconv', 'debug-domain-unload'\n");
+                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'reverse-pinvoke-exceptions', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv', 'suspend-on-exception', 'suspend-on-unhandled', 'dyn-runtime-invoke', 'gdb', 'explicit-null-checks', 'init-stacks', 'check-pinvoke-callconv', 'debug-domain-unload', 'partial-sharing', 'align-small-structs'\n");
                        exit (1);
                }
        }
@@ -2814,7 +2852,7 @@ mini_create_jit_domain_info (MonoDomain *domain)
        info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
        info->llvm_vcall_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->runtime_invoke_hash = mono_conc_hashtable_new_full (&domain->lock, mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
-       info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, seq_point_info_free);
+       info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
        info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
        info->jump_target_hash = g_hash_table_new (NULL, NULL);
 
@@ -2984,10 +3022,8 @@ mini_init (const char *filename, const char *runtime_version)
        callbacks.debug_log_is_enabled = mono_debugger_agent_debug_log_is_enabled;
        callbacks.tls_key_supported = mini_tls_key_supported;
 
-       if (mono_use_imt) {
-               callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
-               callbacks.get_imt_trampoline = mini_get_imt_trampoline;
-       }
+       callbacks.get_vtable_trampoline = mini_get_vtable_trampoline;
+       callbacks.get_imt_trampoline = mini_get_imt_trampoline;
 
        mono_install_callbacks (&callbacks);
 
@@ -3096,12 +3132,10 @@ mini_init (const char *filename, const char *runtime_version)
                mono_marshal_use_aot_wrappers (TRUE);
        }
 
-       if (mono_use_imt) {
-               if (mono_aot_only)
-                       mono_install_imt_thunk_builder (mono_aot_get_imt_thunk);
-               else
-                       mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
-       }
+       if (mono_aot_only)
+               mono_install_imt_thunk_builder (mono_aot_get_imt_thunk);
+       else
+               mono_install_imt_thunk_builder (mono_arch_build_imt_thunk);
 
        /*Init arch tls information only after the metadata side is inited to make sure we see dynamic appdomain tls keys*/
        mono_arch_finish_init ();
@@ -3140,6 +3174,8 @@ mini_init (const char *filename, const char *runtime_version)
        mono_tasklets_init ();
 #endif
 
+       register_trampolines (domain);
+
        if (mono_compile_aot)
                /*
                 * Avoid running managed code when AOT compiling, since the platform
@@ -3170,10 +3206,6 @@ register_icalls (void)
                                ves_icall_get_trace);
        mono_add_internal_call ("System.Exception::get_trace",
                                ves_icall_System_Exception_get_trace);
-       mono_add_internal_call ("System.Security.SecurityFrame::_GetSecurityFrame",
-                               ves_icall_System_Security_SecurityFrame_GetSecurityFrame);
-       mono_add_internal_call ("System.Security.SecurityFrame::_GetSecurityStack",
-                               ves_icall_System_Security_SecurityFrame_GetSecurityStack);
        mono_add_internal_call ("Mono.Runtime::mono_runtime_install_handlers",
                                mono_runtime_install_handlers);
 
@@ -3212,8 +3244,12 @@ register_icalls (void)
 #endif
 
 #if defined(__native_client__) || defined(__native_client_codegen__)
-       register_icall (mono_nacl_gc, "mono_nacl_gc", "void", TRUE);
+       register_icall (mono_nacl_gc, "mono_nacl_gc", "void", FALSE);
+#endif
+#if defined(USE_COOP_GC)
+       register_icall (mono_threads_state_poll, "mono_threads_state_poll", "void", FALSE);
 #endif
+
 #ifndef MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
        register_opcode_emulation (OP_LMUL, "__emul_lmul", "long long long", mono_llmult, "mono_llmult", TRUE);
        register_opcode_emulation (OP_LDIV, "__emul_ldiv", "long long long", mono_lldiv, "mono_lldiv", FALSE);
@@ -3280,6 +3316,7 @@ register_icalls (void)
 #ifdef MONO_ARCH_EMULATE_FREM
 #if defined(__default_codegen__)
        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__)
        register_opcode_emulation (OP_FREM, "__emul_frem", "double double double", mono_fmod, "mono_fmod", FALSE);
 #endif
@@ -3379,8 +3416,11 @@ register_icalls (void)
 
        register_icall (mono_object_castclass_with_cache, "mono_object_castclass_with_cache", "object object ptr ptr", FALSE);
        register_icall (mono_object_isinst_with_cache, "mono_object_isinst_with_cache", "object object ptr ptr", FALSE);
+       register_icall (mono_generic_class_init, "mono_generic_class_init", "void ptr", FALSE);
 
        register_icall (mono_debugger_agent_user_break, "mono_debugger_agent_user_break", "void", FALSE);
+       register_dyn_icall (mono_create_specific_trampoline (NULL, MONO_TRAMPOLINE_GENERIC_CLASS_INIT, mono_get_root_domain (), NULL),
+                                               "specific_trampoline_generic_class_init", "void", TRUE);
 
 #ifdef TARGET_IOS
        register_icall (pthread_getspecific, "pthread_getspecific", "ptr ptr", TRUE);
@@ -3430,15 +3470,6 @@ print_jit_stats (void)
                g_print ("JIT info table removes: %ld\n", mono_stats.jit_info_table_remove_count);
                g_print ("JIT info table lookups: %ld\n", mono_stats.jit_info_table_lookup_count);
 
-               if (mono_security_cas_enabled ()) {
-                       g_print ("\nDecl security check   : %ld\n", mono_jit_stats.cas_declsec_check);
-                       g_print ("LinkDemand (user)     : %ld\n", mono_jit_stats.cas_linkdemand);
-                       g_print ("LinkDemand (icall)    : %ld\n", mono_jit_stats.cas_linkdemand_icall);
-                       g_print ("LinkDemand (pinvoke)  : %ld\n", mono_jit_stats.cas_linkdemand_pinvoke);
-                       g_print ("LinkDemand (aptc)     : %ld\n", mono_jit_stats.cas_linkdemand_aptc);
-                       g_print ("Demand (code gen)     : %ld\n", mono_jit_stats.cas_demand_generation);
-               }
-
                g_free (mono_jit_stats.max_ratio_method);
                mono_jit_stats.max_ratio_method = NULL;
                g_free (mono_jit_stats.biggest_method);