2007-04-11 Martin Baulig <martin@ximian.com>
[mono.git] / mono / mini / mini.c
index 41dada575e8f4a39c585c48009fd0e52eed73c8b..3db26016be6916051fc83df8484df66823b41208 100644 (file)
 #include <pthread.h>
 #endif
 
+#ifdef PLATFORM_WIN32
+#define _WIN32_WINNT 0x0500
+#endif
+
 #ifdef HAVE_VALGRIND_MEMCHECK_H
 #include <valgrind/memcheck.h>
 #endif
@@ -1411,8 +1415,12 @@ type_from_op (MonoInst *ins) {
                ins->type = STACK_PTR;
                switch (ins->inst_i0->type) {
                case STACK_I4:
+                       break;
                case STACK_PTR:
                case STACK_MP:
+#if SIZEOF_VOID_P == 8
+                       ins->opcode = OP_LCONV_TO_U;
+#endif
                        break;
                case STACK_I8:
                        ins->opcode = OP_LCONV_TO_U;
@@ -1628,7 +1636,8 @@ mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
        MONO_INIT_VARINFO (cfg->vars [num], num);
 
        cfg->num_varinfo++;
-       //g_print ("created temp %d of type %s\n", num, mono_type_get_name (type));
+       if (cfg->verbose_level > 2)
+               g_print ("created temp %d of type %s\n", num, mono_type_get_name (type));
        return inst;
 }
 
@@ -1681,7 +1690,14 @@ type_from_stack_type (MonoInst *ins) {
                        return &ins->klass->this_arg;
                else
                        return &mono_defaults.object_class->this_arg;
-       case STACK_OBJ: return &mono_defaults.object_class->byval_arg;
+       case STACK_OBJ:
+               /* ins->klass may not be set for ldnull.
+                * Also, if we have a boxed valuetype, we want an object lass,
+                * not the valuetype class
+                */
+               if (ins->klass && !ins->klass->valuetype)
+                       return &ins->klass->byval_arg;
+               return &mono_defaults.object_class->byval_arg;
        case STACK_VTYPE: return &ins->klass->byval_arg;
        default:
                g_error ("stack type %d to montype not handled\n", ins->type);
@@ -1695,7 +1711,7 @@ mono_type_from_stack_type (MonoInst *ins) {
 }
 
 static MonoClass*
-array_access_to_klass (int opcode)
+array_access_to_klass (int opcode, MonoInst *array_obj)
 {
        switch (opcode) {
        case CEE_LDELEM_U1:
@@ -1726,8 +1742,13 @@ array_access_to_klass (int opcode)
        case CEE_STELEM_R8:
                return mono_defaults.double_class;
        case CEE_LDELEM_REF:
-       case CEE_STELEM_REF:
+       case CEE_STELEM_REF: {
+               MonoClass *klass = array_obj->klass;
+               /* FIXME: add assert */
+               if (klass && klass->rank)
+                       return klass->element_class;
                return mono_defaults.object_class;
+       }
        default:
                g_assert_not_reached ();
        }
@@ -1987,11 +2008,16 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
                                 * in the inlined methods do not inherit their in_stack from
                                 * the bblock they are inlined to. See bug #58863 for an
                                 * example.
+                                * This hack is disabled since it also prevents proper tracking of types.
                                 */
+#if 1
+                               bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
+#else
                                if (cfg->inlined_method)
                                        bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
                                else
                                        bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]);
+#endif
                        }
                }
        }
@@ -2219,9 +2245,20 @@ target_type_is_incompatible (MonoCompile *cfg, MonoType *target, MonoInst *arg)
                if (arg->type != STACK_I4 && arg->type != STACK_PTR)
                        return 1;
                return 0;
-       case MONO_TYPE_CLASS:
-       case MONO_TYPE_STRING:
        case MONO_TYPE_OBJECT:
+               if (arg->type != STACK_OBJ)
+                       return 1;
+               return 0;
+       case MONO_TYPE_STRING:
+               if (arg->type != STACK_OBJ)
+                       return 1;
+               /* ldnull has arg->klass unset */
+               /*if (arg->klass && arg->klass != mono_defaults.string_class) {
+                       G_BREAKPOINT ();
+                       return 1;
+               }*/
+               return 0;
+       case MONO_TYPE_CLASS:
        case MONO_TYPE_SZARRAY:
        case MONO_TYPE_ARRAY:    
                if (arg->type != STACK_OBJ)
@@ -3278,6 +3315,15 @@ mini_get_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSigna
                        MONO_INST_NEW (cfg, ins, CEE_BREAK);
                        return ins;
                }
+               if (cmethod->name [0] == 'g' && strcmp (cmethod->name, "get_IsRunningOnWindows") == 0
+                               && strcmp (cmethod->klass->name, "Environment") == 0) {
+#ifdef PLATFORM_WIN32
+                       NEW_ICONST (cfg, ins, 1);
+#else
+                       NEW_ICONST (cfg, ins, 0);
+#endif
+                       return ins;
+               }
        }
 
        return mono_arch_get_inst_for_method (cfg, cmethod, fsig, args);
@@ -3714,6 +3760,13 @@ can_access_internals (MonoAssembly *accessing, MonoAssembly* accessed)
 static gboolean
 can_access_member (MonoClass *access_klass, MonoClass *member_klass, int access_level)
 {
+       if (access_klass->generic_class && member_klass->generic_class &&
+           access_klass->generic_class->container_class && member_klass->generic_class->container_class) {
+               if (can_access_member (access_klass->generic_class->container_class,
+                                      member_klass->generic_class->container_class, access_level))
+                       return TRUE;
+       }
+
        /* Partition I 8.5.3.2 */
        /* the access level values are the same for fields and methods */
        switch (access_level) {
@@ -3721,12 +3774,10 @@ can_access_member (MonoClass *access_klass, MonoClass *member_klass, int access_
                /* same compilation unit */
                return access_klass->image == member_klass->image;
        case FIELD_ATTRIBUTE_PRIVATE:
-               if (access_klass->generic_class && member_klass->generic_class && member_klass->generic_class->container_class)
-                       return member_klass->generic_class->container_class == access_klass->generic_class->container_class;
                return access_klass == member_klass;
        case FIELD_ATTRIBUTE_FAM_AND_ASSEM:
                if (mono_class_has_parent (access_klass, member_klass) &&
-                               can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
+                   can_access_internals (access_klass->image->assembly, member_klass->image->assembly))
                        return TRUE;
                return FALSE;
        case FIELD_ATTRIBUTE_ASSEMBLY:
@@ -4574,6 +4625,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } else if (constrained_call) {
                                        cmethod = mono_get_method_constrained (image, token, constrained_call, generic_context, &cil_method);
                                        cmethod = mono_get_inflated_method (cmethod);
+                                       cil_method = cmethod;
                                } else {
                                        cmethod = mini_get_method (method, token, NULL, generic_context);
                                        cil_method = cmethod;
@@ -5499,6 +5551,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        n = read32 (ip + 1);
 
                        if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
+                               /* FIXME: moving GC */
                                NEW_PCONST (cfg, ins, mono_method_get_wrapper_data (method, n));
                                ins->cil_code = ip;
                                ins->type = STACK_OBJ;
@@ -6401,6 +6454,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                link_bblock (cfg, bblock, tblock);
                                CHECK_BBLOCK (target, ip, tblock);
                                ins->inst_target_bb = tblock;
+                               GET_BBLOCK (cfg, bbhash, tblock, ip);
+                               link_bblock (cfg, bblock, tblock);
                                if (sp != stack_start) {
                                        handle_stack_args (cfg, bblock, stack_start, sp - stack_start);
                                        sp = stack_start;
@@ -6438,7 +6493,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        ins->inst_newa_class = klass;
                        ins->inst_newa_len = *sp;
                        ins->type = STACK_OBJ;
-                       ins->klass = klass;
+                       ins->klass = mono_array_class_get (klass, 1);
                        ip += 5;
                        *sp++ = ins;
                        /* 
@@ -6574,7 +6629,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        sp -= 2;
                        if (sp [0]->type != STACK_OBJ)
                                UNVERIFIED;
-                       klass = array_access_to_klass (*ip);
+                       klass = array_access_to_klass (*ip, sp [0]);
                        NEW_LDELEMA (cfg, load, sp, klass);
                        load->cil_code = ip;
 #ifdef MONO_ARCH_SOFT_FLOAT
@@ -6613,7 +6668,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        sp -= 3;
                        if (sp [0]->type != STACK_OBJ)
                                UNVERIFIED;
-                       klass = array_access_to_klass (*ip);
+                       klass = array_access_to_klass (*ip, sp [0]);
                        NEW_LDELEMA (cfg, load, sp, klass);
                        load->cil_code = ip;
 #ifdef MONO_ARCH_SOFT_FLOAT
@@ -10506,6 +10561,15 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool
                g_list_free (regs);
        }
 
+       /* todo: remove code when we have verified that the liveness for try/catch blocks
+        * works perfectly 
+        */
+       /* 
+        * Currently, this can't be commented out since exception blocks are not
+        * processed during liveness analysis.
+        */
+       mono_liveness_handle_exception_clauses (cfg);
+
        if (cfg->opt & MONO_OPT_LINEARS) {
                GList *vars, *regs;
                
@@ -11110,6 +11174,8 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler)
        mono_arch_handle_exception (ctx, exc, FALSE);
 }
 
+#ifndef PLATFORM_WIN32
+
 static void
 SIG_HANDLER_SIGNATURE (sigabrt_signal_handler)
 {
@@ -11179,6 +11245,16 @@ SIG_HANDLER_SIGNATURE (sigquit_signal_handler)
        mono_print_thread_dump (ctx);
 }
 
+static void
+SIG_HANDLER_SIGNATURE (sigusr2_signal_handler)
+{
+       gboolean enabled = mono_trace_is_enabled ();
+
+       mono_trace_enable (!enabled);
+}
+
+#endif
+
 static void
 SIG_HANDLER_SIGNATURE (sigint_signal_handler)
 {
@@ -11190,14 +11266,6 @@ SIG_HANDLER_SIGNATURE (sigint_signal_handler)
        mono_arch_handle_exception (ctx, exc, FALSE);
 }
 
-static void
-SIG_HANDLER_SIGNATURE (sigusr2_signal_handler)
-{
-       gboolean enabled = mono_trace_is_enabled ();
-
-       mono_trace_enable (!enabled);
-}
-
 #ifdef PLATFORM_MACOSX
 
 /*
@@ -11451,6 +11519,26 @@ enable_rtc_timer (gboolean enable)
 }
 #endif
 
+#ifdef PLATFORM_WIN32
+static HANDLE win32_main_thread;
+static MMRESULT win32_timer;
+
+static void CALLBACK
+win32_time_proc (UINT uID, UINT uMsg, DWORD dwUser, DWORD dw1, DWORD dw2)
+{
+       CONTEXT context;
+
+       context.ContextFlags = CONTEXT_CONTROL;
+       if (GetThreadContext (win32_main_thread, &context)) {
+#ifdef _WIN64
+               mono_profiler_stat_hit ((guchar *) context.Rip, &context);
+#else
+               mono_profiler_stat_hit ((guchar *) context.Eip, &context);
+#endif
+       }
+}
+#endif
+
 static void
 setup_stat_profiler (void)
 {
@@ -11503,6 +11591,27 @@ setup_stat_profiler (void)
                return;
        inited = 1;
        add_signal_handler (SIGPROF, sigprof_signal_handler);
+#elif defined (PLATFORM_WIN32)
+       static int inited = 0;
+       TIMECAPS timecaps;
+
+       if (inited)
+               return;
+
+       inited = 1;
+       if (timeGetDevCaps (&timecaps, sizeof (timecaps)) != TIMERR_NOERROR)
+               return;
+
+       if ((win32_main_thread = OpenThread (READ_CONTROL | THREAD_GET_CONTEXT, FALSE, GetCurrentThreadId ())) == NULL)
+               return;
+
+       if (timeBeginPeriod (1) != TIMERR_NOERROR)
+               return;
+
+       if ((win32_timer = timeSetEvent (1, 0, win32_time_proc, 0, TIME_PERIODIC)) == 0) {
+               timeEndPeriod (1);
+               return;
+       }
 #endif
 }