Tue Oct 4 20:23:25 CEST 2005 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / mini / mini.c
index 407b52b9c00f0600015c97e91ee232e017d9a84a..1e0dfc46dedcc1314e1e522d3baff3251ea016d8 100644 (file)
@@ -49,6 +49,7 @@
 #include <mono/metadata/monitor.h>
 #include <mono/metadata/security-manager.h>
 #include <mono/metadata/threads-types.h>
+#include <mono/metadata/rawbuffer.h>
 #include <mono/utils/mono-math.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/os/gc_wrapper.h>
@@ -102,6 +103,8 @@ gboolean mono_use_security_manager = FALSE;
 
 static int mini_verbose = 0;
 
+#define mono_jit_lock() EnterCriticalSection (&jit_mutex)
+#define mono_jit_unlock() LeaveCriticalSection (&jit_mutex)
 static CRITICAL_SECTION jit_mutex;
 
 static GHashTable *class_init_hash_addr = NULL;
@@ -255,9 +258,9 @@ void *mono_global_codeman_reserve (int size)
                return mono_code_manager_reserve (global_codeman, size);
        }
        else {
-               EnterCriticalSection (&jit_mutex);
+               mono_jit_lock ();
                ptr = mono_code_manager_reserve (global_codeman, size);
-               LeaveCriticalSection (&jit_mutex);
+               mono_jit_unlock ();
                return ptr;
        }
 }
@@ -849,7 +852,7 @@ df_visit (MonoBasicBlock *start, int *dfn, MonoBasicBlock **array)
        int i;
 
        array [*dfn] = start;
-       /*g_print ("visit %d at %p\n", *dfn, start->cil_code);*/
+       /*g_print ("visit %d at %p (BB%ld)\n", *dfn, start->cil_code, start->block_num);*/
        for (i = 0; i < start->out_count; ++i) {
                if (start->out_bb [i]->dfn)
                        continue;
@@ -1799,6 +1802,9 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
                found = FALSE;
                for (i = 0; i < bb->out_count; ++i) {
                        outb = bb->out_bb [i];
+                       /* exception handlers are linked, but they should not be considered for stack args */
+                       if (outb->flags & BB_EXCEPTION_HANDLER)
+                               continue;
                        //g_print (" %d", outb->block_num);
                        if (outb->in_stack) {
                                found = TRUE;
@@ -1832,8 +1838,14 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
 
        for (i = 0; i < bb->out_count; ++i) {
                outb = bb->out_bb [i];
-               if (outb->in_scount)
+               /* exception handlers are linked, but they should not be considered for stack args */
+               if (outb->flags & BB_EXCEPTION_HANDLER)
+                       continue;
+               if (outb->in_scount) {
+                       if (outb->in_scount != bb->out_scount)
+                               G_BREAKPOINT ();
                        continue; /* check they are the same locals */
+               }
                outb->in_scount = count;
                outb->in_stack = bb->out_stack;
        }
@@ -1866,6 +1878,11 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
                found = FALSE;
                while (bindex < bb->out_count) {
                        outb = bb->out_bb [bindex];
+                       /* exception handlers are linked, but they should not be considered for stack args */
+                       if (outb->flags & BB_EXCEPTION_HANDLER) {
+                               bindex++;
+                               continue;
+                       }
                        if (outb->in_stack != locals) {
                                /* 
                                 * Instead of storing sp [i] to locals [i], we need to store
@@ -2338,7 +2355,7 @@ mono_get_element_address_signature (int arity)
        MonoMethodSignature *res;
        int i;
 
-       EnterCriticalSection (&jit_mutex);
+       mono_jit_lock ();
        if (!sighash) {
                sighash = g_hash_table_new (NULL, NULL);
        }
@@ -2362,7 +2379,7 @@ mono_get_element_address_signature (int arity)
        res->ret = &mono_defaults.int_class->byval_arg;
 
        g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
-       LeaveCriticalSection (&jit_mutex);
+       mono_jit_unlock ();
 
        return res;
 }
@@ -2374,12 +2391,12 @@ mono_get_array_new_va_signature (int arity)
        MonoMethodSignature *res;
        int i;
 
-       EnterCriticalSection (&jit_mutex);
+       mono_jit_lock ();
        if (!sighash) {
                sighash = g_hash_table_new (NULL, NULL);
        }
        else if ((res = g_hash_table_lookup (sighash, GINT_TO_POINTER (arity)))) {
-               LeaveCriticalSection (&jit_mutex);
+               mono_jit_unlock ();
                return res;
        }
 
@@ -2398,7 +2415,7 @@ mono_get_array_new_va_signature (int arity)
        res->ret = &mono_defaults.int_class->byval_arg;
 
        g_hash_table_insert (sighash, GINT_TO_POINTER (arity), res);
-       LeaveCriticalSection (&jit_mutex);
+       mono_jit_unlock ();
 
        return res;
 }
@@ -2590,9 +2607,9 @@ handle_array_new (MonoCompile *cfg, MonoBasicBlock *bblock, int rank, MonoInst *
                name = g_strdup (icall_name);
                info = mono_register_jit_icall (mono_array_new_va, name, esig, FALSE);
 
-               EnterCriticalSection (&jit_mutex);
+               mono_jit_lock ();
                g_hash_table_insert (jit_icall_name_hash, name, name);
-               LeaveCriticalSection (&jit_mutex);
+               mono_jit_unlock ();
        }
 
        cfg->flags |= MONO_CFG_HAS_VARARGS;
@@ -2778,9 +2795,9 @@ mini_get_ldelema_ins (MonoCompile *cfg, MonoBasicBlock *bblock, MonoMethod *cmet
                name = g_strdup (icall_name);
                info = mono_register_jit_icall (ves_array_element_address, name, esig, FALSE);
 
-               EnterCriticalSection (&jit_mutex);
+               mono_jit_lock ();
                g_hash_table_insert (jit_icall_name_hash, name, name);
-               LeaveCriticalSection (&jit_mutex);
+               mono_jit_unlock ();
        }
 
        temp = mono_emit_native_call (cfg, bblock, mono_icall_get_wrapper (info), info->sig, sp, ip, FALSE, FALSE);
@@ -3327,19 +3344,30 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                }
                /* handle exception clauses */
                for (i = 0; i < header->num_clauses; ++i) {
-                       //unsigned char *p = ip;
+                       MonoBasicBlock *try_bb;
                        MonoExceptionClause *clause = &header->clauses [i];
-                       GET_BBLOCK (cfg, bbhash, tblock, ip + clause->try_offset);
-                       tblock->real_offset = clause->try_offset;
+                       GET_BBLOCK (cfg, bbhash, try_bb, ip + clause->try_offset);
+                       try_bb->real_offset = clause->try_offset;
                        GET_BBLOCK (cfg, bbhash, tblock, ip + clause->handler_offset);
                        tblock->real_offset = clause->handler_offset;
+                       tblock->flags |= BB_EXCEPTION_HANDLER;
+
+                       link_bblock (cfg, try_bb, tblock);
+
+                       if (*(ip + clause->handler_offset) == CEE_POP)
+                               tblock->flags |= BB_EXCEPTION_DEAD_OBJ;
 
                        if (clause->flags == MONO_EXCEPTION_CLAUSE_FINALLY ||
                            clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
                                MONO_INST_NEW (cfg, ins, OP_START_HANDLER);
                                MONO_ADD_INS (tblock, ins);
+
+                               /* todo: is a fault block unsafe to optimize? */
+                               if (clause->flags == MONO_EXCEPTION_CLAUSE_FAULT)
+                                       tblock->flags |= BB_EXCEPTION_UNSAFE;
                        }
 
+
                        /*g_print ("clause try IL_%04x to IL_%04x handler %d at IL_%04x to IL_%04x\n", clause->try_offset, clause->try_offset + clause->try_len, clause->flags, clause->handler_offset, clause->handler_offset + clause->handler_len);
                          while (p < end) {
                          g_print ("%s", mono_disasm_code_one (NULL, method, p, &p));
@@ -5138,6 +5166,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->cil_code = ip - 1;
                        MONO_ADD_INS (bblock, ins);
                        sp = stack_start;
+                       
                        link_bblock (cfg, bblock, end_bblock);
                        start_new_bblock = 1;
                        mono_get_got_var (cfg);
@@ -6543,6 +6572,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                handler_offset = clause->handler_offset;
                                }
 
+                               bblock->flags |= BB_EXCEPTION_UNSAFE;
+
                                g_assert (handler_offset != -1);
 
                                NEW_TEMPLOAD (cfg, load, mono_find_exvar_for_offset (cfg, handler_offset)->inst_c0);
@@ -6953,11 +6984,11 @@ mono_create_class_init_trampoline (MonoVTable *vtable)
                                                          vtable, ptr);
        mono_domain_unlock (vtable->domain);
 
-       EnterCriticalSection (&jit_mutex);
+       mono_jit_lock ();
        if (!class_init_hash_addr)
                class_init_hash_addr = g_hash_table_new (NULL, NULL);
        g_hash_table_insert (class_init_hash_addr, ptr, vtable);
-       LeaveCriticalSection (&jit_mutex);
+       mono_jit_unlock ();
 
        return ptr;
 }
@@ -7111,12 +7142,12 @@ mono_find_class_init_trampoline_by_addr (gconstpointer addr)
 {
        MonoVTable *res;
 
-       EnterCriticalSection (&jit_mutex);
+       mono_jit_lock ();
        if (class_init_hash_addr)
                res = g_hash_table_lookup (class_init_hash_addr, addr);
        else
                res = NULL;
-       LeaveCriticalSection (&jit_mutex);
+       mono_jit_unlock ();
        return res;
 }
 
@@ -7660,13 +7691,13 @@ mini_thread_cleanup (MonoThread *thread)
 
        if (jit_tls) {
                mono_arch_free_jit_tls_data (jit_tls);
-               g_free (jit_tls->first_lmf);
-               g_free (jit_tls);
-               thread->jit_data = NULL;
 
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
                mono_free_altstack (jit_tls);
 #endif
+               g_free (jit_tls->first_lmf);
+               g_free (jit_tls);
+               thread->jit_data = NULL;
        }
 }
 
@@ -9472,7 +9503,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain)
        method = mono_get_inflated_method (method);
 
 #ifdef MONO_USE_AOT_COMPILER
-       if (!mono_compile_aot && (opt & MONO_OPT_AOT)) {
+       if (!mono_compile_aot && (opt & MONO_OPT_AOT) && !(mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)) {
                MonoJitInfo *info;
                MonoDomain *domain = mono_domain_get ();
 
@@ -9820,6 +9851,19 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
 #endif
        GET_CONTEXT
 
+#ifdef MONO_ARCH_USE_SIGACTION
+       if (debug_options.collect_pagefault_stats) {
+               if (mono_raw_buffer_is_pagefault (info->si_addr)) {
+                       mono_raw_buffer_handle_pagefault (info->si_addr);
+                       return;
+               }
+               if (mono_aot_is_pagefault (info->si_addr)) {
+                       mono_aot_handle_pagefault (info->si_addr);
+                       return;
+               }
+       }
+#endif
+
 #ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK
        /* Can't allocate memory using Boehm GC on altstack */
        if (jit_tls->stack_size && 
@@ -10098,9 +10142,11 @@ mini_parse_debug_options (void)
                        debug_options.keep_delegates = TRUE;
                else if (!strcmp (arg, "abort-on-sigsegv"))
                        debug_options.abort_on_sigsegv = TRUE;
+               else if (!strcmp (arg, "collect-pagefault-stats"))
+                       debug_options.collect_pagefault_stats = TRUE;
                else {
                        fprintf (stderr, "Invalid option for the MONO_DEBUG env variable: %s\n", arg);
-                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'abort-on-sigsegv'\n");
+                       fprintf (stderr, "Available options: 'handle-sigint', 'keep-delegates', 'abort-on-sigsegv', 'collect-pagefault-stats'\n");
                        exit (1);
                }
        }
@@ -10169,6 +10215,11 @@ mini_init (const char *filename)
        mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
        mono_install_jit_info_find_in_aot (mono_aot_find_jit_info);
 
+       if (debug_options.collect_pagefault_stats) {
+               mono_raw_buffer_set_make_unreadable (TRUE);
+               mono_aot_set_make_unreadable (TRUE);
+       }
+
        domain = mono_init_from_assembly (filename, filename);
        mono_icall_init ();
 
@@ -10356,6 +10407,10 @@ print_jit_stats (void)
                        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);
                }
+               if (debug_options.collect_pagefault_stats) {
+                       g_print ("Metadata pagefaults   : %d\n", mono_raw_buffer_get_n_pagefaults ());
+                       g_print ("AOT pagefaults        : %d\n", mono_aot_get_n_pagefaults ());
+               }
        }
 }