Merge pull request #4380 from alexanderkyte/conflicting_attrs
[mono.git] / mono / mini / method-to-ir.c
index 2193d5f327281f402c52f295c118840fe1026541..09bab4683ef57335c2209792745f8b4ea6546db0 100644 (file)
@@ -60,7 +60,6 @@
 #include <mono/metadata/profiler.h>
 #include <mono/metadata/monitor.h>
 #include <mono/metadata/debug-mono-symfile.h>
-#include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-memory-model.h>
 #include <mono/utils/mono-error-internals.h>
 #include <mono/metadata/mono-basic-block.h>
@@ -164,8 +163,8 @@ static MonoMethodSignature *helper_sig_get_tls_tramp;
 static MonoMethodSignature *helper_sig_set_tls_tramp;
 
 /* type loading helpers */
-static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, System.Runtime.CompilerServices, RuntimeHelpers)
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (debuggable_attribute, System.Diagnostics, DebuggableAttribute)
+static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, "System.Runtime.CompilerServices", "RuntimeHelpers")
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (debuggable_attribute, "System.Diagnostics", "DebuggableAttribute")
 
 /*
  * Instruction metadata
@@ -208,12 +207,6 @@ const gint8 ins_sreg_counts[] = {
 #undef MINI_OP
 #undef MINI_OP3
 
-#define MONO_INIT_VARINFO(vi,id) do { \
-       (vi)->range.first_use.pos.bid = 0xffff; \
-       (vi)->reg = -1; \
-       (vi)->idx = (id); \
-} while (0)
-
 guint32
 mono_alloc_ireg (MonoCompile *cfg)
 {
@@ -4457,7 +4450,7 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
         * pack the arguments into an array, and do the rest of the work in in an icall.
         */
        if (((cmethod->klass == mono_defaults.object_class) || mono_class_is_interface (cmethod->klass) || (!cmethod->klass->valuetype && cmethod->klass->image != mono_defaults.corlib)) &&
-               (MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mini_is_gsharedvt_type (fsig->ret)) &&
+               (MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mono_class_is_enum (mono_class_from_mono_type (fsig->ret)) || mini_is_gsharedvt_type (fsig->ret)) &&
                (fsig->param_count == 0 || (!fsig->hasthis && fsig->param_count == 1) || (fsig->param_count == 1 && (MONO_TYPE_IS_REFERENCE (fsig->params [0]) || fsig->params [0]->byref || mini_is_gsharedvt_type (fsig->params [0]))))) {
                MonoInst *args [16];
 
@@ -4509,7 +4502,7 @@ handle_constrained_gsharedvt_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMe
 
                if (mini_is_gsharedvt_type (fsig->ret)) {
                        ins = handle_unbox_gsharedvt (cfg, mono_class_from_mono_type (fsig->ret), ins);
-               } else if (MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret)) {
+               } else if (MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mono_class_is_enum (mono_class_from_mono_type (fsig->ret))) {
                        MonoInst *add;
 
                        /* Unbox */
@@ -6506,7 +6499,8 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig,
                 * Get rid of the begin and end bblocks if possible to aid local
                 * optimizations.
                 */
-               mono_merge_basic_blocks (cfg, prev_cbb, sbblock);
+               if (prev_cbb->out_count == 1)
+                       mono_merge_basic_blocks (cfg, prev_cbb, sbblock);
 
                if ((prev_cbb->out_count == 1) && (prev_cbb->out_bb [0]->in_count == 1) && (prev_cbb->out_bb [0] != ebblock))
                        mono_merge_basic_blocks (cfg, prev_cbb, prev_cbb->out_bb [0]);
@@ -7009,6 +7003,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
        gboolean variant_iface = FALSE;
        guint32 slot;
        int offset;
+       gboolean special_array_interface = cmethod->klass->is_array_special_interface;
 
        /*
         * In llvm-only mode, vtables contain function descriptors instead of
@@ -7067,7 +7062,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
                return emit_extra_arg_calli (cfg, fsig, sp, arg_reg, call_target);
        }
 
-       if (!fsig->generic_param_count && is_iface && !variant_iface && !is_gsharedvt) {
+       if (!fsig->generic_param_count && is_iface && !variant_iface && !is_gsharedvt && !special_array_interface) {
                /*
                 * A simple interface call
                 *
@@ -7106,7 +7101,7 @@ emit_llvmonly_virtual_call (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSig
                return emit_llvmonly_calli (cfg, fsig, sp, ftndesc_ins);
        }
 
-       if ((fsig->generic_param_count || variant_iface) && !is_gsharedvt) {
+       if ((fsig->generic_param_count || variant_iface || special_array_interface) && !is_gsharedvt) {
                /*
                 * This is similar to the interface case, the vtable slot points to an imt thunk which is
                 * dynamically extended as more instantiations are discovered.
@@ -7545,6 +7540,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        mono_bitset_set_fast (seq_point_locs, sps [i].il_offset);
                        }
                        g_free (sps);
+
+                       MonoDebugMethodAsyncInfo* asyncMethod = mono_debug_lookup_method_async_debug_info (method);
+                       if (asyncMethod) {
+                               for (i = 0; asyncMethod != NULL && i < asyncMethod->num_awaits; i++)
+                               {
+                                       mono_bitset_set_fast (seq_point_locs, asyncMethod->resume_offsets[i]);
+                                       mono_bitset_set_fast (seq_point_locs, asyncMethod->yield_offsets[i]);
+                               }
+                               mono_debug_free_method_async_debug_info (asyncMethod);
+                       }
                } else if (!method->wrapper_type && !method->dynamic && mono_debug_image_has_debug_info (method->klass->image)) {
                        /* Methods without line number info like auto-generated property accessors */
                        seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
@@ -8580,6 +8585,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                CHECK_CFG_ERROR;
                                        }
                                }
+
+                               if (constrained_class->enumtype && !strcmp (cmethod->name, "GetHashCode")) {
+                                       /* Use the corresponding method from the base type to avoid boxing */
+                                       MonoType *base_type = mono_class_enum_basetype (constrained_class);
+                                       g_assert (base_type);
+                                       constrained_class = mono_class_from_mono_type (base_type);
+                                       cmethod = mono_class_get_method_from_name (constrained_class, cmethod->name, 0);
+                                       g_assert (cmethod);
+                               }
                        }
                                        
                        if (!dont_verify && !cfg->skip_visibility) {
@@ -8870,7 +8884,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                 * request a generic sharing context.
                                 */
                                if (context_used &&
-                                               ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype))
+                                               ((cfg->method->flags & METHOD_ATTRIBUTE_STATIC) || cfg->method->klass->valuetype))
                                        mono_get_vtable_var (cfg);
                        }
 
@@ -10862,7 +10876,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                guint32 offset;
                                int idx, static_data_reg, array_reg, dreg;
 
-                               GSHAREDVT_FAILURE (op);
+                               if (context_used && cfg->gsharedvt && mini_is_gsharedvt_klass (klass))
+                                       GSHAREDVT_FAILURE (op);
 
                                static_data_reg = alloc_ireg (cfg);
                                MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, MONO_STRUCT_OFFSET (MonoInternalThread, static_data));
@@ -13800,7 +13815,7 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
        int orig_next_vreg;
        guint32 *vreg_to_lvreg;
        guint32 *lvregs;
-       guint32 i, lvregs_len;
+       guint32 i, lvregs_len, lvregs_size;
        gboolean dest_has_lvreg = FALSE;
        MonoStackType stacktypes [128];
        MonoInst **live_range_start, **live_range_end;
@@ -13873,7 +13888,8 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
         */
        orig_next_vreg = cfg->next_vreg;
        vreg_to_lvreg = (guint32 *)mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * cfg->next_vreg);
-       lvregs = (guint32 *)mono_mempool_alloc (cfg->mempool, sizeof (guint32) * 1024);
+       lvregs_size = 1024;
+       lvregs = (guint32 *)mono_mempool_alloc (cfg->mempool, sizeof (guint32) * lvregs_size);
        lvregs_len = 0;
 
        /* 
@@ -14256,7 +14272,12 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
                                                                }
                                                                g_assert (sreg != -1);
                                                                vreg_to_lvreg [var->dreg] = sreg;
-                                                               g_assert (lvregs_len < 1024);
+                                                               if (lvregs_len >= lvregs_size) {
+                                                                       guint32 *new_lvregs = mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * lvregs_size * 2);
+                                                                       memcpy (new_lvregs, lvregs, sizeof (guint32) * lvregs_size);
+                                                                       lvregs = new_lvregs;
+                                                                       lvregs_size *= 2;
+                                                               }
                                                                lvregs [lvregs_len ++] = var->dreg;
                                                        }
                                                }
@@ -14303,7 +14324,12 @@ mono_spill_global_vars (MonoCompile *cfg, gboolean *need_local_opts)
                        if (dest_has_lvreg) {
                                g_assert (ins->dreg != -1);
                                vreg_to_lvreg [prev_dreg] = ins->dreg;
-                               g_assert (lvregs_len < 1024);
+                               if (lvregs_len >= lvregs_size) {
+                                       guint32 *new_lvregs = mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * lvregs_size * 2);
+                                       memcpy (new_lvregs, lvregs, sizeof (guint32) * lvregs_size);
+                                       lvregs = new_lvregs;
+                                       lvregs_size *= 2;
+                               }
                                lvregs [lvregs_len ++] = prev_dreg;
                                dest_has_lvreg = FALSE;
                        }