* CodeGenerationOptions.cs: Made the class internal for the 1.1 profile.
[mono.git] / mono / mini / mini.c
index 1bd4147526d9359fd7bf5c65b5109305ebe8661d..db0a95711d547cb53fd0f810cc2982f144ed572c 100644 (file)
@@ -1607,23 +1607,24 @@ mono_compile_get_interface_var (MonoCompile *cfg, int slot, MonoInst *ins)
  */
 static int
 handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int count) {
-       int i;
+       int i, bindex;
        MonoBasicBlock *outb;
        MonoInst *inst, **locals;
+       gboolean found;
 
        if (!count)
                return 0;
        if (cfg->verbose_level > 3)
                g_print ("%d item(s) on exit from B%d\n", count, bb->block_num);
        if (!bb->out_scount) {
-               int found = 0;
                bb->out_scount = count;
                //g_print ("bblock %d has out:", bb->block_num);
+               found = FALSE;
                for (i = 0; i < bb->out_count; ++i) {
                        outb = bb->out_bb [i];
                        //g_print (" %d", outb->block_num);
                        if (outb->in_stack) {
-                               found = 1;
+                               found = TRUE;
                                bb->out_stack = outb->in_stack;
                                break;
                        }
@@ -1632,19 +1633,34 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
                if (!found) {
                        bb->out_stack = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * count);
                        for (i = 0; i < count; ++i) {
-/* see bug#58863, but removing this code causes regressions in gtk-sharp build 
- * (SEGV running Method::Initialize() in gapi_codegen.exe) 
- */
-#if 1
-                               /* try to reuse temps already allocated for this purpouse, if they occupy the same 
-                                * stack slot and if they are of the same type. */
-                               bb->out_stack [i] = mono_compile_get_interface_var (cfg, i, sp [i]);
-#else
-                               bb->out_stack [i] = mono_compile_create_var (cfg, type_from_stack_type (sp [i]), OP_LOCAL);
-#endif
+                               /* 
+                                * try to reuse temps already allocated for this purpouse, if they occupy the same
+                                * stack slot and if they are of the same type.
+                                * This won't cause conflicts since if 'local' is used to 
+                                * store one of the values in the in_stack of a bblock, then
+                                * the same variable will be used for the same outgoing stack 
+                                * slot as well. 
+                                * This doesn't work when inlining methods, since the bblocks
+                                * in the inlined methods do not inherit their in_stack from
+                                * the bblock they are inlined to. See bug #58863 for an
+                                * example.
+                                */
+                               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]);
                        }
                }
        }
+
+       for (i = 0; i < bb->out_count; ++i) {
+               outb = bb->out_bb [i];
+               if (outb->in_scount)
+                       continue; /* check they are the same locals */
+               outb->in_scount = count;
+               outb->in_stack = bb->out_stack;
+       }
+
        locals = bb->out_stack;
        for (i = 0; i < count; ++i) {
                /* add store ops at the end of the bb, before the branch */
@@ -1659,14 +1675,36 @@ handle_stack_args (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst **sp, int coun
                if (cfg->verbose_level > 3)
                        g_print ("storing %d to temp %d\n", i, locals [i]->inst_c0);
        }
-       
-       for (i = 0; i < bb->out_count; ++i) {
-               outb = bb->out_bb [i];
-               if (outb->in_scount)
-                       continue; /* check they are the same locals */
-               outb->in_scount = count;
-               outb->in_stack = locals;
+
+       /*
+        * It is possible that the out bblocks already have in_stack assigned, and
+        * the in_stacks differ. In this case, we will store to all the different 
+        * in_stacks.
+        */
+
+       found = TRUE;
+       bindex = 0;
+       while (found) {
+               /* Find a bblock which has a different in_stack */
+               found = FALSE;
+               while (bindex < bb->out_count) {
+                       outb = bb->out_bb [bindex];
+                       if (outb->in_stack != locals) {
+                               /* 
+                                * Instead of storing sp [i] to locals [i], we need to store
+                                * locals [i] to <new locals>[i], since the sp [i] tree can't
+                                * be shared between trees.
+                                */
+                               for (i = 0; i < count; ++i)
+                                       mono_add_varcopy_to_end (cfg, bb, locals [i]->inst_c0, outb->in_stack [i]->inst_c0);
+                               locals = outb->in_stack;
+                               found = TRUE;
+                               break;
+                       }
+                       bindex ++;
+               }
        }
+       
        return 0;
 }
 
@@ -3242,12 +3280,19 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 * We have the `constrained.' prefix opcode.
                                 */
                                if (constrained_call->valuetype && !cmethod->klass->valuetype) {
+                                       MonoInst *load;
                                        /*
                                         * The type parameter is instantiated as a valuetype,
                                         * but that type doesn't override the method we're
                                         * calling, so we need to box `this'.
+                                        * sp [0] is a pointer to the data: we need the value
+                                        * in handle_box (), so load it here.
                                         */
-                                       sp [0] = handle_box (cfg, bblock, sp [0], ip, constrained_call);
+                                       MONO_INST_NEW (cfg, load, mono_type_to_ldind (&constrained_call->byval_arg));
+                                       type_to_eval_stack_type (&constrained_call->byval_arg, load);
+                                       load->cil_code = ip;
+                                       load->inst_left = sp [0];
+                                       sp [0] = handle_box (cfg, bblock, load, ip, constrained_call);
                                } else if (!constrained_call->valuetype) {
                                        MonoInst *ins;
 
@@ -4791,14 +4836,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        klass = mono_class_get_full (image, token, generic_context);
                        mono_class_init (klass);
                        if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) {
+                               MonoMethod* helper = mono_marshal_get_stelemref ();
                                MonoInst *iargs [3];
                                handle_loaded_temps (cfg, bblock, stack_start, sp);
 
                                iargs [2] = sp [2];
                                iargs [1] = sp [1];
                                iargs [0] = sp [0];
-                       
-                               mono_emit_jit_icall (cfg, bblock, helper_stelem_ref, iargs, ip);
+                               
+                               mono_emit_method_call_spilled (cfg, bblock, helper, helper->signature, iargs, ip, NULL);
                        } else {
                                NEW_LDELEMA (cfg, load, sp, klass);
                                load->cil_code = ip;
@@ -4821,6 +4867,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                }
                case CEE_STELEM_REF: {
                        MonoInst *iargs [3];
+                       MonoMethod* helper = mono_marshal_get_stelemref ();
 
                        CHECK_STACK (3);
                        sp -= 3;
@@ -4831,7 +4878,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        iargs [1] = sp [1];
                        iargs [0] = sp [0];
                        
-                       mono_emit_jit_icall (cfg, bblock, helper_stelem_ref, iargs, ip);
+                       mono_emit_method_call_spilled (cfg, bblock, helper, helper->signature, iargs, ip, NULL);
 
                        /*
                        MonoInst *group;
@@ -6200,7 +6247,7 @@ print_dfn (MonoCompile *cfg) {
 
        for (i = 0; i < cfg->num_bblocks; ++i) {
                bb = cfg->bblocks [i];
-               if (bb->cil_code) {
+               /*if (bb->cil_code) {
                        char* code1, *code2;
                        code1 = mono_disasm_code_one (NULL, cfg->method, bb->cil_code, NULL);
                        if (bb->last_ins->cil_code)
@@ -6212,7 +6259,7 @@ print_dfn (MonoCompile *cfg) {
                        code = g_strdup_printf ("%s -> %s", code1, code2);
                        g_free (code1);
                        g_free (code2);
-               } else
+               } else*/
                        code = g_strdup ("\n");
                g_print ("\nBB%d DFN%d (len: %d): %s", bb->block_num, i, bb->cil_length, code);
                if (bb->code) {