2009-03-02 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / mini.c
index 95f57525bc6ceef09a973d310e0314dc74f5d6bb..ddb9f6929b1854b87cd7c7625fd5685132271e81 100644 (file)
@@ -101,6 +101,7 @@ MonoMethodDesc *mono_break_at_bb_method = NULL;
 int mono_break_at_bb_bb_num;
 gboolean mono_do_x86_stack_align = TRUE;
 const char *mono_build_date;
+gboolean mono_do_signal_chaining;
 
 static int mini_verbose = 0;
 
@@ -551,7 +552,7 @@ handle_enum:
                return OP_STORER8_MEMBASE_REG;
        case MONO_TYPE_VALUETYPE:
                if (type->data.klass->enumtype) {
-                       type = type->data.klass->enum_basetype;
+                       type = mono_class_enum_basetype (type->data.klass);
                        goto handle_enum;
                }
                if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (type)))
@@ -844,6 +845,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
        cfg->varinfo [num] = inst;
 
        MONO_INIT_VARINFO (&cfg->vars [num], num);
+       MONO_VARINFO (cfg, num)->vreg = vreg;
 
        if (vreg != -1)
                set_vreg_to_inst (cfg, vreg, inst);
@@ -1245,10 +1247,12 @@ mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
         * We use the lock on the root domain instead of the JIT lock to protect 
         * callinfo->trampoline, since we do a lot of stuff inside the critical section.
         */
+       mono_loader_lock (); /*FIXME mono_compile_method requires the loader lock, by large.*/
        mono_domain_lock (domain);
 
        if (callinfo->trampoline) {
                mono_domain_unlock (domain);
+               mono_loader_unlock ();
                return callinfo->trampoline;
        }
 
@@ -1265,6 +1269,7 @@ mono_icall_get_wrapper_full (MonoJitICallInfo* callinfo, gboolean do_compile)
        callinfo->trampoline = trampoline;
 
        mono_domain_unlock (domain);
+       mono_loader_unlock ();
        
        return callinfo->trampoline;
 }
@@ -1804,12 +1809,6 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
        return offsets;
 }
 
-gint32*
-mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_align)
-{
-       return mono_allocate_stack_slots_full (m, TRUE, stack_size, stack_align);
-}
-
 #else
 
 gint32*
@@ -1821,6 +1820,12 @@ mono_allocate_stack_slots_full (MonoCompile *cfg, gboolean backward, guint32 *st
 
 #endif /* DISABLE_JIT */
 
+gint32*
+mono_allocate_stack_slots (MonoCompile *m, guint32 *stack_size, guint32 *stack_align)
+{
+       return mono_allocate_stack_slots_full (m, TRUE, stack_size, stack_align);
+}
+
 void
 mono_register_opcode_emulation (int opcode, const char *name, const char *sigstr, gpointer func, gboolean no_throw)
 {
@@ -2490,12 +2495,11 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code,
                if (method && method->dynamic) {
                        jump_table = mono_code_manager_reserve (mono_dynamic_code_hash_lookup (domain, method)->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
                } else {
-                       mono_domain_lock (domain);
-                       if (mono_aot_only)
+                       if (mono_aot_only) {
                                jump_table = mono_domain_alloc (domain, sizeof (gpointer) * patch_info->data.table->table_size);
-                       else
-                               jump_table = mono_code_manager_reserve (domain->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
-                       mono_domain_unlock (domain);
+                       } else {
+                               jump_table = mono_domain_code_reserve (domain, sizeof (gpointer) * patch_info->data.table->table_size);
+                       }
                }
 
                for (i = 0; i < patch_info->data.table->table_size; i++)
@@ -2737,48 +2741,6 @@ mono_print_code (MonoCompile *cfg, const char* msg)
                mono_print_bb (bb, msg);
 }
 
-static MonoGenericInst*
-get_object_generic_inst (int type_argc)
-{
-       MonoType **type_argv;
-       int i;
-
-       type_argv = alloca (sizeof (MonoType*) * type_argc);
-
-       for (i = 0; i < type_argc; ++i)
-               type_argv [i] = &mono_defaults.object_class->byval_arg;
-
-       return mono_metadata_get_generic_inst (type_argc, type_argv);
-}
-
-static MonoGenericContext
-construct_object_context_for_method (MonoMethod *method)
-{
-       MonoGenericContext object_context;
-
-       g_assert (method->wrapper_type == MONO_WRAPPER_NONE);
-       g_assert (!method->klass->generic_class);
-       if (method->klass->generic_container) {
-               int type_argc = method->klass->generic_container->type_argc;
-
-               object_context.class_inst = get_object_generic_inst (type_argc);
-       } else {
-               object_context.class_inst = NULL;
-       }
-
-       if (mini_method_get_context (method)->method_inst) {
-               int type_argc = mini_method_get_context (method)->method_inst->type_argc;
-
-               object_context.method_inst = get_object_generic_inst (type_argc);
-       } else {
-               object_context.method_inst = NULL;
-       }
-
-       g_assert (object_context.class_inst || object_context.method_inst);
-
-       return object_context;
-}
-
 #ifndef DISABLE_JIT
 
 void
@@ -2867,9 +2829,7 @@ mono_codegen (MonoCompile *cfg)
 #ifdef MONO_ARCH_HAVE_UNWIND_TABLE
                unwindlen = mono_arch_unwindinfo_get_size (cfg->arch.unwindinfo);
 #endif
-               mono_domain_lock (cfg->domain);
-               code = mono_code_manager_reserve (cfg->domain->code_mp, cfg->code_size + unwindlen);
-               mono_domain_unlock (cfg->domain);
+               code = mono_domain_code_reserve (cfg->domain, cfg->code_size + unwindlen);
        }
 
        memcpy (code, cfg->native_code, cfg->code_len);
@@ -2930,9 +2890,7 @@ mono_codegen (MonoCompile *cfg)
                        if (cfg->method->dynamic) {
                                table = mono_code_manager_reserve (cfg->dynamic_info->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
                        } else {
-                               mono_domain_lock (cfg->domain);
-                               table = mono_code_manager_reserve (cfg->domain->code_mp, sizeof (gpointer) * patch_info->data.table->table_size);
-                               mono_domain_unlock (cfg->domain);
+                               table = mono_domain_code_reserve (cfg->domain, sizeof (gpointer) * patch_info->data.table->table_size);
                        }
 
                        for (i = 0; i < patch_info->data.table->table_size; i++) {
@@ -3004,9 +2962,7 @@ if (valgrind_register){
        if (cfg->method->dynamic) {
                mono_code_manager_commit (cfg->dynamic_info->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
        } else {
-               mono_domain_lock (cfg->domain);
-               mono_code_manager_commit (cfg->domain->code_mp, cfg->native_code, cfg->code_size, cfg->code_len);
-               mono_domain_unlock (cfg->domain);
+               mono_domain_code_commit (cfg->domain, cfg->native_code, cfg->code_size, cfg->code_len);
        }
        
        mono_arch_flush_icache (cfg->native_code, cfg->code_len);
@@ -3582,16 +3538,13 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                jinfo = g_malloc0 (sizeof (MonoJitInfo) + (header->num_clauses * sizeof (MonoJitExceptionInfo)) +
                                generic_info_size);
        } else {
-               /* we access cfg->domain->mp */
-               mono_domain_lock (cfg->domain);
                jinfo = mono_domain_alloc0 (cfg->domain, sizeof (MonoJitInfo) +
                                (header->num_clauses * sizeof (MonoJitExceptionInfo)) +
                                generic_info_size);
-               mono_domain_unlock (cfg->domain);
        }
 
        if (cfg->generic_sharing_context) {
-               MonoGenericContext object_context = construct_object_context_for_method (method_to_compile);
+               MonoGenericContext object_context = mono_method_construct_object_context (method_to_compile);
 
                method_to_register = mono_class_inflate_generic_method (method_to_compile, &object_context);
        } else {
@@ -3699,6 +3652,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                }
        }
 
+       /* 
+        * Its possible to generate dwarf unwind info for xdebug etc, but not actually
+        * using it during runtime, hence the define.
+        */
+#ifdef MONO_ARCH_HAVE_XP_UNWIND
        if (cfg->unwind_ops) {
                guint32 info_len;
                guint8 *unwind_info = mono_unwind_ops_encode (cfg->unwind_ops, &info_len);
@@ -3706,13 +3664,14 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                jinfo->used_regs = mono_cache_unwind_info (unwind_info, info_len);
                g_free (unwind_info);
        }
+#endif
 
        cfg->jit_info = jinfo;
 #if defined(__arm__)
        mono_arch_fixup_jinfo (cfg);
 #endif
 
-       mono_save_xdebug_info (method_to_register, jinfo->code_start, jinfo->code_size, cfg->args, cfg->locals, cfg->unwind_ops);
+       mono_save_xdebug_info (cfg);
 
        if (!cfg->compile_aot) {
                mono_domain_lock (cfg->domain);
@@ -3760,37 +3719,6 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
 
 #endif /* DISABLE_JIT */
 
-MonoJitInfo*
-mono_domain_lookup_shared_generic (MonoDomain *domain, MonoMethod *open_method)
-{
-       static gboolean inited = FALSE;
-       static int lookups = 0;
-       static int failed_lookups = 0;
-
-       MonoGenericContext object_context;
-       MonoMethod *object_method;
-       MonoJitInfo *ji;
-
-       object_context = construct_object_context_for_method (open_method);
-       object_method = mono_class_inflate_generic_method (open_method, &object_context);
-
-       ji = mono_internal_hash_table_lookup (&domain->jit_code_hash, object_method);
-       if (ji && !ji->has_generic_jit_info)
-               ji = NULL;
-
-       if (!inited) {
-               mono_counters_register ("Shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &lookups);
-               mono_counters_register ("Failed shared generic lookups", MONO_COUNTER_INT|MONO_COUNTER_GENERICS, &failed_lookups);
-               inited = TRUE;
-       }
-
-       ++lookups;
-       if (!ji)
-               ++failed_lookups;
-
-       return ji;
-}
-
 static MonoJitInfo*
 lookup_generic_method (MonoDomain *domain, MonoMethod *method)
 {
@@ -3823,9 +3751,11 @@ lookup_method (MonoDomain *domain, MonoMethod *method)
 {
        MonoJitInfo *info;
 
+       mono_loader_lock (); /*FIXME lookup_method_inner acquired it*/
        mono_domain_jit_code_hash_lock (domain);
        info = lookup_method_inner (domain, method);
        mono_domain_jit_code_hash_unlock (domain);
+       mono_loader_unlock ();
 
        return info;
 }
@@ -4003,6 +3933,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                g_assert_not_reached ();
        }
 
+       mono_loader_lock (); /*FIXME lookup_method_inner requires the loader lock*/
        mono_domain_lock (target_domain);
 
        /* Check if some other thread already did the job. In this case, we can
@@ -4049,6 +3980,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        }
 
        mono_domain_unlock (target_domain);
+       mono_loader_unlock ();
 
        vtable = mono_class_vtable (target_domain, method->klass);
        if (!vtable) {
@@ -4302,8 +4234,11 @@ SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler)
        GET_CONTEXT;
 
        /* The thread might no be registered with the runtime */
-       if (!mono_domain_get () || !jit_tls)
+       if (!mono_domain_get () || !jit_tls) {
+               if (mono_chain_signal (SIG_HANDLER_PARAMS))
+                       return;
                mono_handle_native_sigsegv (SIGSEGV, ctx);
+       }
 
        ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
 
@@ -4326,11 +4261,18 @@ SIG_HANDLER_SIGNATURE (mono_sigsegv_signal_handler)
                fprintf (stderr, "At %s\n", method);
                _exit (1);
        } else {
+               /* The original handler might not like that it is executed on an altstack... */
+               if (!ji && mono_chain_signal (SIG_HANDLER_PARAMS))
+                       return;
+
                mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
        }
 #else
 
        if (!ji) {
+               if (mono_chain_signal (SIG_HANDLER_PARAMS))
+                       return;
+
                mono_handle_native_sigsegv (SIGSEGV, ctx);
        }
                        
@@ -4424,11 +4366,13 @@ mini_parse_debug_options (void)
                        debug_options.break_on_unverified = TRUE;
                else if (!strcmp (arg, "no-gdb-backtrace"))
                        debug_options.no_gdb_backtrace = TRUE;
+               else if (!strcmp (arg, "suspend-on-sigsegv"))
+                       debug_options.suspend_on_sigsegv = TRUE;
                else if (!strcmp (arg, "dont-free-domains"))
                        mono_dont_free_domains = TRUE;
                else {
                        fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
-                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains'\n");
+                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'collect-pagefault-stats', 'break-on-unverified', 'no-gdb-backtrace', 'dont-free-domains', 'suspend-on-sigsegv'\n");
                        exit (1);
                }
        }
@@ -4686,13 +4630,17 @@ mini_init (const char *filename, const char *runtime_version)
 #endif
 
 #ifdef MONO_ARCH_EMULATE_MUL_DIV
-       mono_register_opcode_emulation (CEE_MUL_OVF, "__emul_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE);
-       mono_register_opcode_emulation (CEE_MUL_OVF_UN, "__emul_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE);
        mono_register_opcode_emulation (CEE_MUL, "__emul_imul", "int32 int32 int32", mono_imul, TRUE);
        mono_register_opcode_emulation (OP_IMUL, "__emul_op_imul", "int32 int32 int32", mono_imul, TRUE);
+#endif
+
+#if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_EMULATE_MUL_OVF)
+       mono_register_opcode_emulation (CEE_MUL_OVF, "__emul_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE);
+       mono_register_opcode_emulation (CEE_MUL_OVF_UN, "__emul_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE);
        mono_register_opcode_emulation (OP_IMUL_OVF, "__emul_op_imul_ovf", "int32 int32 int32", mono_imul_ovf, FALSE);
        mono_register_opcode_emulation (OP_IMUL_OVF_UN, "__emul_op_imul_ovf_un", "int32 int32 int32", mono_imul_ovf_un, FALSE);
 #endif
+
 #if defined(MONO_ARCH_EMULATE_MUL_DIV) || defined(MONO_ARCH_SOFT_FLOAT)
        mono_register_opcode_emulation (OP_FDIV, "__emul_fdiv", "double double double", mono_fdiv, FALSE);
 #endif
@@ -4737,6 +4685,9 @@ mini_init (const char *filename, const char *runtime_version)
        mono_register_opcode_emulation (OP_FCONV_TO_I4, "__emul_fconv_to_i4", "int32 double", mono_fconv_i4, FALSE);
        mono_register_opcode_emulation (OP_FCONV_TO_U1, "__emul_fconv_to_u1", "uint8 double", mono_fconv_u1, FALSE);
        mono_register_opcode_emulation (OP_FCONV_TO_U2, "__emul_fconv_to_u2", "uint16 double", mono_fconv_u2, FALSE);
+#if SIZEOF_VOID_P == 4
+       mono_register_opcode_emulation (OP_FCONV_TO_I, "__emul_fconv_to_i", "int32 double", mono_fconv_i4, FALSE);
+#endif
 
        mono_register_opcode_emulation (OP_FBEQ, "__emul_fcmp_eq", "uint32 double double", mono_fcmp_eq, FALSE);
        mono_register_opcode_emulation (OP_FBLT, "__emul_fcmp_lt", "uint32 double double", mono_fcmp_lt, FALSE);
@@ -4758,6 +4709,7 @@ mini_init (const char *filename, const char *runtime_version)
        register_icall (mono_fload_r4, "mono_fload_r4", "double ptr", FALSE);
        register_icall (mono_fstore_r4, "mono_fstore_r4", "void double ptr", FALSE);
        register_icall (mono_fload_r4_arg, "mono_fload_r4_arg", "uint32 double", FALSE);
+       register_icall (mono_isfinite, "mono_isfinite", "uint32 double", FALSE);
 #endif
 
 #if SIZEOF_REGISTER == 4
@@ -4860,12 +4812,8 @@ print_jit_stats (void)
                g_print ("VTable data size:       %ld\n", mono_stats.class_vtable_size);
                g_print ("Mscorlib mempool size:  %d\n", mono_mempool_get_allocated (mono_defaults.corlib->mempool));
 
-               g_print ("\nGeneric instances:      %ld\n", mono_stats.generic_instance_count);
-               g_print ("Initialized classes:    %ld\n", mono_stats.generic_class_count);
-               g_print ("Inflated methods:       %ld / %ld\n", mono_stats.inflated_method_count_2,
-                        mono_stats.inflated_method_count);
+               g_print ("\nInitialized classes:    %ld\n", mono_stats.generic_class_count);
                g_print ("Inflated types:         %ld\n", mono_stats.inflated_type_count);
-               g_print ("Generics metadata size: %ld\n", mono_stats.generics_metadata_size);
                g_print ("Generics virtual invokes: %ld\n", mono_jit_stats.generic_virtual_invocations);
 
                g_print ("Sharable generic methods: %ld\n", mono_stats.generics_sharable_methods);