Merge pull request #2799 from BrzVlad/fix-conc-card-clean
[mono.git] / mono / mini / mini.c
index f52124d4ffe70a5380ffeb2439e97567568555fc..046572a332925011fdfb5b9d33a0f3ec30c14f7a 100644 (file)
@@ -855,7 +855,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
        inst->backend.is_pinvoke = 0;
        inst->dreg = vreg;
 
-       if (inst->klass->exception_type)
+       if (mono_class_has_failure (inst->klass))
                mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
 
        if (cfg->compute_gc_maps) {
@@ -1261,7 +1261,7 @@ mini_method_verify (MonoCompile *cfg, MonoMethod *method, gboolean fail_compile)
 
                                        if (info->exception_type == MONO_EXCEPTION_METHOD_ACCESS)
                                                mono_error_set_generic_error (&cfg->error, "System", "MethodAccessException", "%s", msg);
-                                       else if (info->exception_type == info->exception_type == MONO_EXCEPTION_FIELD_ACCESS)
+                                       else if (info->exception_type == MONO_EXCEPTION_FIELD_ACCESS)
                                                mono_error_set_generic_error (&cfg->error, "System", "FieldAccessException", "%s", msg);
                                        else if (info->exception_type == MONO_EXCEPTION_UNVERIFIABLE_IL)
                                                mono_error_set_generic_error (&cfg->error, "System.Security", "VerificationException", msg);
@@ -1715,7 +1715,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s
                        size = mini_type_stack_size (t, &ialign);
                        align = ialign;
 
-                       if (mono_class_from_mono_type (t)->exception_type)
+                       if (mono_class_has_failure (mono_class_from_mono_type (t)))
                                mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD);
 
                        if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (t)))
@@ -2669,7 +2669,11 @@ mono_codegen (MonoCompile *cfg)
                        if (ji->type == MONO_PATCH_INFO_NONE)
                                continue;
 
-                       target = mono_resolve_patch_target (cfg->method, cfg->domain, cfg->native_code, ji, cfg->run_cctors);
+                       target = mono_resolve_patch_target (cfg->method, cfg->domain, cfg->native_code, ji, cfg->run_cctors, &cfg->error);
+                       if (!mono_error_ok (&cfg->error)) {
+                               mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
+                               return;
+                       }
                        mono_arch_patch_code_new (cfg, cfg->domain, cfg->native_code, ji, target);
                }
        }
@@ -3004,7 +3008,12 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                                 */
                                ei->try_start = (guint8*)ei->try_start - cfg->backend->monitor_enter_adjustment;
                        }
-                       tblock = cfg->cil_offset_to_bb [ec->try_offset + ec->try_len];
+                       if (ec->try_offset + ec->try_len < header->code_size)
+                               tblock = cfg->cil_offset_to_bb [ec->try_offset + ec->try_len];
+                       else
+                               tblock = cfg->bb_exit;
+                       if (G_UNLIKELY (cfg->verbose_level >= 4))
+                               printf ("looking for end of try [%d, %d] -> %p (code size %d)\n", ec->try_offset, ec->try_len, tblock, header->code_size);
                        g_assert (tblock);
                        if (!tblock->native_offset) {
                                int j, end;
@@ -3461,7 +3470,6 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
        cfg = g_new0 (MonoCompile, 1);
        cfg->method = method_to_compile;
-       cfg->header = mono_method_get_header (cfg->method);
        cfg->mempool = mono_mempool_new ();
        cfg->opt = opts;
        cfg->prof_options = mono_profiler_get_events ();
@@ -3470,6 +3478,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        cfg->verbose_level = mini_verbose;
        cfg->compile_aot = compile_aot;
        cfg->full_aot = full_aot;
+       cfg->disable_omit_fp = debug_options.disable_omit_fp;
        cfg->skip_visibility = method->skip_visibility;
        cfg->orig_method = method;
        cfg->gen_seq_points = debug_options.gen_seq_points_compact_data || debug_options.gen_sdb_seq_points;
@@ -3566,14 +3575,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                return cfg;
        }
 
-       header = cfg->header;
+       header = cfg->header = mono_method_get_header_checked (cfg->method, &cfg->error);
        if (!header) {
-               if (mono_loader_get_last_error ()) {
-                       mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
-                       mono_error_set_from_loader_error (&cfg->error);
-               } else {
-                       mono_cfg_set_exception_invalid_program (cfg, g_strdup_printf ("Missing or incorrect header for method %s", cfg->method->name));
-               }
+               mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR);
                if (MONO_METHOD_COMPILE_END_ENABLED ())
                        MONO_PROBE_METHOD_COMPILE_END (method, FALSE);
                return cfg;
@@ -3729,7 +3733,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
         */
        mono_compile_create_vars (cfg);
 
-       i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, NULL, NULL, 0, FALSE);
+       MONO_TIME_TRACK (mono_jit_stats.jit_method_to_ir, i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, NULL, NULL, 0, FALSE));
 
        if (i < 0) {
                if (try_generic_shared && cfg->exception_type == MONO_EXCEPTION_GENERIC_SHARING_FAILED) {
@@ -3790,40 +3794,43 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
         * This also allows SSA to be run on methods containing exception clauses, since
         * SSA will ignore variables marked VOLATILE.
         */
-       mono_liveness_handle_exception_clauses (cfg);
+       MONO_TIME_TRACK (mono_jit_stats.jit_liveness_handle_exception_clauses, mono_liveness_handle_exception_clauses (cfg));
 
-       mono_handle_out_of_line_bblock (cfg);
+       MONO_TIME_TRACK (mono_jit_stats.jit_handle_out_of_line_bblock, mono_handle_out_of_line_bblock (cfg));
 
        /*g_print ("numblocks = %d\n", cfg->num_bblocks);*/
 
-       if (!COMPILE_LLVM (cfg))
-               mono_decompose_long_opts (cfg);
+       if (!COMPILE_LLVM (cfg)) {
+               MONO_TIME_TRACK (mono_jit_stats.jit_decompose_long_opts, mono_decompose_long_opts (cfg));
+       }
 
        /* Should be done before branch opts */
        if (cfg->opt & (MONO_OPT_CONSPROP | MONO_OPT_COPYPROP))
-               mono_local_cprop (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_local_cprop, mono_local_cprop (cfg));
+
        /*
         * Should be done after cprop which can do strength reduction on
         * some of these ops, after propagating immediates.
         */
        if (cfg->has_emulated_ops)
-               mono_local_emulate_ops (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_local_emulate_ops, mono_local_emulate_ops (cfg));
+
        if (cfg->opt & MONO_OPT_BRANCH)
-               mono_optimize_branches (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_optimize_branches, mono_optimize_branches (cfg));
 
        /* This must be done _before_ global reg alloc and _after_ decompose */
-       mono_handle_global_vregs (cfg);
+       MONO_TIME_TRACK (mono_jit_stats.jit_handle_global_vregs, mono_handle_global_vregs (cfg));
        if (cfg->opt & MONO_OPT_DEADCE)
-               mono_local_deadce (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_local_deadce, mono_local_deadce (cfg));
        if (cfg->opt & MONO_OPT_ALIAS_ANALYSIS)
-               mono_local_alias_analysis (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_local_alias_analysis, mono_local_alias_analysis (cfg));
        /* Disable this for LLVM to make the IR easier to handle */
        if (!COMPILE_LLVM (cfg))
-               mono_if_conversion (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_if_conversion, mono_if_conversion (cfg));
 
        mono_threads_safepoint ();
 
-       mono_bb_ordering (cfg);
+       MONO_TIME_TRACK (mono_jit_stats.jit_bb_ordering, mono_bb_ordering (cfg));
 
        if (((cfg->num_varinfo > 2000) || (cfg->num_bblocks > 1000)) && !cfg->compile_aot) {
                /* 
@@ -3836,11 +3843,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        }
 
        if (cfg->opt & MONO_OPT_LOOP) {
-               mono_compile_dominator_info (cfg, MONO_COMP_DOM | MONO_COMP_IDOM);
-               mono_compute_natural_loops (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_compile_dominator_info, mono_compile_dominator_info (cfg, MONO_COMP_DOM | MONO_COMP_IDOM));
+               MONO_TIME_TRACK (mono_jit_stats.jit_compute_natural_loops, mono_compute_natural_loops (cfg));
        }
 
-       mono_insert_safepoints (cfg);
+       MONO_TIME_TRACK (mono_jit_stats.jit_insert_safepoints, mono_insert_safepoints (cfg));
 
        /* after method_to_ir */
        if (parts == 1) {
@@ -3869,7 +3876,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        if (cfg->opt & MONO_OPT_SSA) {
                if (!(cfg->comp_done & MONO_COMP_SSA) && !cfg->disable_ssa) {
 #ifndef DISABLE_SSA
-                       mono_ssa_compute (cfg);
+                       MONO_TIME_TRACK (mono_jit_stats.jit_ssa_compute, mono_ssa_compute (cfg));
 #endif
 
                        if (cfg->verbose_level >= 2) {
@@ -3889,7 +3896,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        if ((cfg->opt & MONO_OPT_CONSPROP) || (cfg->opt & MONO_OPT_COPYPROP)) {
                if (cfg->comp_done & MONO_COMP_SSA && !COMPILE_LLVM (cfg)) {
 #ifndef DISABLE_SSA
-                       mono_ssa_cprop (cfg);
+                       MONO_TIME_TRACK (mono_jit_stats.jit_ssa_cprop, mono_ssa_cprop (cfg));
 #endif
                }
        }
@@ -3899,19 +3906,19 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                //mono_ssa_strength_reduction (cfg);
 
                if (cfg->opt & MONO_OPT_DEADCE)
-                       mono_ssa_deadce (cfg);
+                       MONO_TIME_TRACK (mono_jit_stats.jit_ssa_deadce, mono_ssa_deadce (cfg));
 
                if ((cfg->flags & (MONO_CFG_HAS_LDELEMA|MONO_CFG_HAS_CHECK_THIS)) && (cfg->opt & MONO_OPT_ABCREM))
-                       mono_perform_abc_removal (cfg);
+                       MONO_TIME_TRACK (mono_jit_stats.jit_perform_abc_removal, mono_perform_abc_removal (cfg));
 
-               mono_ssa_remove (cfg);
-               mono_local_cprop (cfg);
-               mono_handle_global_vregs (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_ssa_remove, mono_ssa_remove (cfg));
+               MONO_TIME_TRACK (mono_jit_stats.jit_local_cprop2, mono_local_cprop (cfg));
+               MONO_TIME_TRACK (mono_jit_stats.jit_handle_global_vregs2, mono_handle_global_vregs (cfg));
                if (cfg->opt & MONO_OPT_DEADCE)
-                       mono_local_deadce (cfg);
+                       MONO_TIME_TRACK (mono_jit_stats.jit_local_deadce2, mono_local_deadce (cfg));
 
                if (cfg->opt & MONO_OPT_BRANCH)
-                       mono_optimize_branches (cfg);
+                       MONO_TIME_TRACK (mono_jit_stats.jit_optimize_branches2, mono_optimize_branches (cfg));
        }
 #endif
 
@@ -3936,9 +3943,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        if (COMPILE_SOFT_FLOAT (cfg))
                mono_decompose_soft_float (cfg);
 #endif
-       mono_decompose_vtype_opts (cfg);
+       MONO_TIME_TRACK (mono_jit_stats.jit_decompose_vtype_opts, mono_decompose_vtype_opts (cfg));
        if (cfg->flags & MONO_CFG_HAS_ARRAY_ACCESS)
-               mono_decompose_array_access_opts (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_decompose_array_access_opts, mono_decompose_array_access_opts (cfg));
 
        if (cfg->got_var) {
 #ifndef MONO_ARCH_GOT_REG
@@ -3971,7 +3978,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        /*
         * Have to call this again to process variables added since the first call.
         */
-       mono_liveness_handle_exception_clauses (cfg);
+       MONO_TIME_TRACK(mono_jit_stats.jit_liveness_handle_exception_clauses2, mono_liveness_handle_exception_clauses (cfg));
 
        if (cfg->opt & MONO_OPT_LINEARS) {
                GList *vars, *regs, *l;
@@ -3979,7 +3986,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                /* fixme: maybe we can avoid to compute livenesss here if already computed ? */
                cfg->comp_done &= ~MONO_COMP_LIVENESS;
                if (!(cfg->comp_done & MONO_COMP_LIVENESS))
-                       mono_analyze_liveness (cfg);
+                       MONO_TIME_TRACK (mono_jit_stats.jit_analyze_liveness, mono_analyze_liveness (cfg));
 
                if ((vars = mono_arch_get_allocatable_int_vars (cfg))) {
                        regs = mono_arch_get_global_int_regs (cfg);
@@ -3992,7 +3999,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                                        }
                                }
                        }
-                       mono_linear_scan (cfg, vars, regs, &cfg->used_int_regs);
+                       MONO_TIME_TRACK (mono_jit_stats.jit_linear_scan, mono_linear_scan (cfg, vars, regs, &cfg->used_int_regs));
                }
        }
 
@@ -4002,7 +4009,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        
        /* variables are allocated after decompose, since decompose could create temps */
        if (!COMPILE_LLVM (cfg)) {
-               mono_arch_allocate_vars (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_arch_allocate_vars, mono_arch_allocate_vars (cfg));
                if (cfg->exception_type)
                        return cfg;
        }
@@ -4012,13 +4019,13 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
        if (!COMPILE_LLVM (cfg)) {
                gboolean need_local_opts;
-               mono_spill_global_vars (cfg, &need_local_opts);
+               MONO_TIME_TRACK (mono_jit_stats.jit_spill_global_vars, mono_spill_global_vars (cfg, &need_local_opts));
 
                if (need_local_opts || cfg->compile_aot) {
                        /* To optimize code created by spill_global_vars */
-                       mono_local_cprop (cfg);
+                       MONO_TIME_TRACK (mono_jit_stats.jit_local_cprop3, mono_local_cprop (cfg));
                        if (cfg->opt & MONO_OPT_DEADCE)
-                               mono_local_deadce (cfg);
+                               MONO_TIME_TRACK (mono_jit_stats.jit_local_deadce3, mono_local_deadce (cfg));
                }
        }
 
@@ -4063,7 +4070,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                }
 #endif
        } else {
-               mono_codegen (cfg);
+               MONO_TIME_TRACK (mono_jit_stats.jit_codegen, mono_codegen (cfg));
+               if (cfg->exception_type)
+                       return cfg;
        }
 
        if (COMPILE_LLVM (cfg))
@@ -4071,7 +4080,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        else
                InterlockedIncrement (&mono_jit_stats.methods_without_llvm);
 
-       cfg->jit_info = create_jit_info (cfg, method_to_compile);
+       MONO_TIME_TRACK (mono_jit_stats.jit_create_jit_info, cfg->jit_info = create_jit_info (cfg, method_to_compile));
 
 #ifdef MONO_ARCH_HAVE_LIVERANGE_OPS
        if (cfg->extend_live_ranges) {
@@ -4084,9 +4093,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        if (!cfg->compile_aot)
                mono_save_xdebug_info (cfg);
 
-       mini_gc_create_gc_map (cfg);
+       MONO_TIME_TRACK (mono_jit_stats.jit_gc_create_gc_map, mini_gc_create_gc_map (cfg));
  
-       mono_save_seq_point_info (cfg);
+       MONO_TIME_TRACK (mono_jit_stats.jit_save_seq_point_info, mono_save_seq_point_info (cfg));
 
        if (cfg->verbose_level >= 2) {
                char *id =  mono_method_full_name (cfg->method, FALSE);
@@ -4467,7 +4476,9 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
 #endif
 #ifdef MONO_ARCH_HAVE_PATCH_CODE_NEW
                        for (tmp = jlist->list; tmp; tmp = tmp->next) {
-                               gpointer target = mono_resolve_patch_target (NULL, target_domain, (guint8 *)tmp->data, &patch_info, TRUE);
+                               gpointer target = mono_resolve_patch_target (NULL, target_domain, (guint8 *)tmp->data, &patch_info, TRUE, error);
+                               if (!mono_error_ok (error))
+                                       break;
                                mono_arch_patch_code_new (NULL, target_domain, (guint8 *)tmp->data, &patch_info, target);
                        }
 #else
@@ -4480,10 +4491,25 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                }
        }
 
+       /* Update llvm callees */
+       if (domain_jit_info (target_domain)->llvm_jit_callees) {
+               GSList *callees = g_hash_table_lookup (domain_jit_info (target_domain)->llvm_jit_callees, method);
+               GSList *l;
+
+               for (l = callees; l; l = l->next) {
+                       gpointer *addr = (gpointer*)l->data;
+
+                       *addr = code;
+               }
+       }
+
        mono_emit_jit_map (jinfo);
 #endif
        mono_domain_unlock (target_domain);
 
+       if (!mono_error_ok (error))
+               return NULL;
+
        vtable = mono_class_vtable (target_domain, method->klass);
        if (!vtable) {
                ex = mono_class_get_exception_for_failure (method->klass);
@@ -4506,11 +4532,8 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
                }
        }
 
-       ex = mono_runtime_class_init_full (vtable, FALSE);
-       if (ex) {
-               mono_error_set_exception_instance (error, ex);
+       if (!mono_runtime_class_init_full (vtable, error))
                return NULL;
-       }
        return code;
 }