Merge pull request #3381 from krytarowski/netbsd-support-20
[mono.git] / mono / mini / seq-points.c
index 26ac63986a36f6ee51ed94a7fa82a611b3d6ffe8..8ff2e1e3ec6ca95145828a077e03d8a48cb8d709 100644 (file)
@@ -5,37 +5,95 @@
  *   Marcos Henrich (marcos.henrich@xamarin.com)
  *
  * Copyright 2014 Xamarin, Inc (http://www.xamarin.com)
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #include "mini.h"
 #include "seq-points.h"
 
 static void
-collect_pred_seq_points (MonoBasicBlock *bb, MonoInst *ins, GSList **next, int depth)
+insert_pred_seq_point (MonoInst *last_seq_ins, MonoInst *ins, GSList **next)
 {
-       int i;
-       MonoBasicBlock *in_bb;
        GSList *l;
+       int src_index = last_seq_ins->backend.size;
+       int dst_index = ins->backend.size;
+
+       /* bb->in_bb might contain duplicates */
+       for (l = next [src_index]; l; l = l->next)
+               if (GPOINTER_TO_UINT (l->data) == dst_index)
+                       break;
+       if (!l)
+               next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index));
+}
+
+static void
+recursively_make_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb)
+{
+       const gpointer MONO_SEQ_SEEN_LOOP = GINT_TO_POINTER(-1);
+
+       GArray *predecessors = g_array_new (FALSE, TRUE, sizeof (gpointer));
+       GHashTable *seen = g_hash_table_new_full (g_direct_hash, NULL, NULL, NULL);
+
+       // Insert/remove sentinel into the memoize table to detect loops containing bb
+       bb->pred_seq_points = MONO_SEQ_SEEN_LOOP;
+
+       for (int i = 0; i < bb->in_count; ++i) {
+               MonoBasicBlock *in_bb = bb->in_bb [i];
+               
+               // This bb has the last seq point, append it and continue
+               if (in_bb->last_seq_point != NULL) {
+                       predecessors = g_array_append_val (predecessors, in_bb->last_seq_point);
+                       continue;
+               }
+
+               // We've looped or handled this before, exit early.
+               // No last sequence points to find.
+               if (in_bb->pred_seq_points == MONO_SEQ_SEEN_LOOP)
+                       continue;
+
+               // Take sequence points from incoming basic blocks
+       
+               if (in_bb == cfg->bb_entry)
+                       continue;
+
+               if (in_bb->pred_seq_points == NULL)
+                       recursively_make_pred_seq_points (cfg, in_bb);
 
-       for (i = 0; i < bb->in_count; ++i) {
-               in_bb = bb->in_bb [i];
-
-               if (in_bb->last_seq_point) {
-                       int src_index = in_bb->last_seq_point->backend.size;
-                       int dst_index = ins->backend.size;
-
-                       /* bb->in_bb might contain duplicates */
-                       for (l = next [src_index]; l; l = l->next)
-                               if (GPOINTER_TO_UINT (l->data) == dst_index)
-                                       break;
-                       if (!l)
-                               next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index));
-               } else {
-                       /* Have to look at its predecessors */
-                       if (depth < 5)
-                               collect_pred_seq_points (in_bb, ins, next, depth + 1);
+               // Union sequence points with incoming bb's
+               for (int i=0; i < in_bb->num_pred_seq_points; i++) {
+                       if (!g_hash_table_lookup (seen, in_bb->pred_seq_points [i])) {
+                               g_array_append_val (predecessors, in_bb->pred_seq_points [i]);
+                               g_hash_table_insert (seen, in_bb->pred_seq_points [i], (gpointer)&MONO_SEQ_SEEN_LOOP);
+                       }
                }
+               // predecessors = g_array_append_vals (predecessors, in_bb->pred_seq_points, in_bb->num_pred_seq_points);
        }
+
+       g_hash_table_destroy (seen);
+
+       if (predecessors->len != 0) {
+               bb->pred_seq_points = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst *) * predecessors->len);
+               bb->num_pred_seq_points = predecessors->len;
+
+               for (int newer = 0; newer < bb->num_pred_seq_points; newer++) {
+                       bb->pred_seq_points [newer] = g_array_index(predecessors, gpointer, newer);
+               }
+       } 
+
+       g_free (predecessors);
+}
+
+static void
+collect_pred_seq_points (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins, GSList **next)
+{
+       // Doesn't have a last sequence point, must find from incoming basic blocks
+       if (bb->pred_seq_points == NULL && bb != cfg->bb_entry)
+               recursively_make_pred_seq_points (cfg, bb);
+
+       for (int i = 0; i < bb->num_pred_seq_points; i++)
+               insert_pred_seq_point (bb->pred_seq_points [i], ins, next);
+
+       return;
 }
 
 void
@@ -49,7 +107,7 @@ mono_save_seq_point_info (MonoCompile *cfg)
        GSList **next = NULL;
        SeqPoint* seq_points;
        GByteArray* array;
-       gboolean has_debug_data = cfg->gen_seq_points_debug_data;
+       gboolean has_debug_data = cfg->gen_sdb_seq_points;
 
        if (!cfg->seq_points)
                return;
@@ -58,7 +116,7 @@ mono_save_seq_point_info (MonoCompile *cfg)
 
        for (i = 0; i < cfg->seq_points->len; ++i) {
                SeqPoint *sp = &seq_points [i];
-               MonoInst *ins = g_ptr_array_index (cfg->seq_points, i);
+               MonoInst *ins = (MonoInst *)g_ptr_array_index (cfg->seq_points, i);
 
                sp->il_offset = ins->inst_imm;
                sp->native_offset = ins->inst_offset;
@@ -79,7 +137,7 @@ mono_save_seq_point_info (MonoCompile *cfg)
                        bb_seq_points = g_slist_reverse (bb->seq_points);
                        last = NULL;
                        for (l = bb_seq_points; l; l = l->next) {
-                               MonoInst *ins = l->data;
+                               MonoInst *ins = (MonoInst *)l->data;
 
                                if (ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET)
                                /* Used to implement method entry/exit events */
@@ -92,13 +150,14 @@ mono_save_seq_point_info (MonoCompile *cfg)
                                        next [last->backend.size] = g_slist_append (next [last->backend.size], GUINT_TO_POINTER (ins->backend.size));
                                } else {
                                        /* Link with the last bb in the previous bblocks */
-                                       collect_pred_seq_points (bb, ins, next, 0);
+                                       collect_pred_seq_points (cfg, bb, ins, next);
                                }
 
                                last = ins;
                        }
 
-                       if (bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY && bb->seq_points) {
+                       /* The second case handles endfinally opcodes which are in a separate bb by themselves */
+                       if ((bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY && bb->seq_points) || (bb->out_count == 1 && bb->out_bb [0]->code && bb->out_bb [0]->code->opcode == OP_ENDFINALLY)) {
                                MonoBasicBlock *bb2;
                                MonoInst *endfinally_seq_point = NULL;
 
@@ -107,13 +166,13 @@ mono_save_seq_point_info (MonoCompile *cfg)
                                 */
                                l = g_slist_last (bb->seq_points);
                                if (l) {
-                                       endfinally_seq_point = l->data;
+                                       endfinally_seq_point = (MonoInst *)l->data;
 
                                        for (bb2 = cfg->bb_entry; bb2; bb2 = bb2->next_bb) {
                                                GSList *l = g_slist_last (bb2->seq_points);
 
                                                if (l) {
-                                                       MonoInst *ins = l->data;
+                                                       MonoInst *ins = (MonoInst *)l->data;
 
                                                        if (!(ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET) && ins != endfinally_seq_point)
                                                                next [endfinally_seq_point->backend.size] = g_slist_append (next [endfinally_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size));
@@ -156,7 +215,7 @@ mono_save_seq_point_info (MonoCompile *cfg)
                        if (has_debug_data)
                                next_list = next[i];
 
-                       if (seq_point_info_add_seq_point (array, sp, last_seq_point, next_list, has_debug_data))
+                       if (mono_seq_point_info_add_seq_point (array, sp, last_seq_point, next_list, has_debug_data))
                                last_seq_point = sp;
 
                        if (has_debug_data)
@@ -167,7 +226,7 @@ mono_save_seq_point_info (MonoCompile *cfg)
        if (has_debug_data)
                g_free (next);
 
-       cfg->seq_point_info = seq_point_info_new (array->len, TRUE, array->data, has_debug_data, &seq_info_size);
+       cfg->seq_point_info = mono_seq_point_info_new (array->len, TRUE, array->data, has_debug_data, &seq_info_size);
        mono_jit_stats.allocated_seq_points_size += seq_info_size;
 
        g_byte_array_free (array, TRUE);
@@ -186,34 +245,40 @@ mono_save_seq_point_info (MonoCompile *cfg)
 }
 
 MonoSeqPointInfo*
-get_seq_points (MonoDomain *domain, MonoMethod *method)
+mono_get_seq_points (MonoDomain *domain, MonoMethod *method)
 {
        MonoSeqPointInfo *seq_points;
+       MonoMethod *declaring_generic_method = NULL, *shared_method = NULL;
+
+       if (method->is_inflated) {
+               declaring_generic_method = mono_method_get_declaring_generic_method (method);
+               shared_method = mini_get_shared_method (method);
+       }
 
-       mono_domain_lock (domain);
-       seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
+       mono_loader_lock ();
+       seq_points = (MonoSeqPointInfo *)g_hash_table_lookup (domain_jit_info (domain)->seq_points, method);
        if (!seq_points && method->is_inflated) {
                /* generic sharing + aot */
-               seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, mono_method_get_declaring_generic_method (method));
+               seq_points = (MonoSeqPointInfo *)g_hash_table_lookup (domain_jit_info (domain)->seq_points, declaring_generic_method);
                if (!seq_points)
-                       seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, mini_get_shared_method (method));
+                       seq_points = (MonoSeqPointInfo *)g_hash_table_lookup (domain_jit_info (domain)->seq_points, shared_method);
        }
-       mono_domain_unlock (domain);
+       mono_loader_unlock ();
 
        return seq_points;
 }
 
 /*
- * find_next_seq_point_for_native_offset:
+ * mono_find_next_seq_point_for_native_offset:
  *
  *   Find the first sequence point after NATIVE_OFFSET.
  */
 gboolean
-find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info, SeqPoint* seq_point)
+mono_find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info, SeqPoint* seq_point)
 {
        MonoSeqPointInfo *seq_points;
 
-       seq_points = get_seq_points (domain, method);
+       seq_points = mono_get_seq_points (domain, method);
        if (!seq_points) {
                if (info)
                        *info = NULL;
@@ -222,20 +287,20 @@ find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, g
        if (info)
                *info = seq_points;
 
-       return seq_point_find_next_by_native_offset (seq_points, native_offset, seq_point);
+       return mono_seq_point_find_next_by_native_offset (seq_points, native_offset, seq_point);
 }
 
 /*
- * find_prev_seq_point_for_native_offset:
+ * mono_find_prev_seq_point_for_native_offset:
  *
  *   Find the first sequence point before NATIVE_OFFSET.
  */
 gboolean
-find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info, SeqPoint* seq_point)
+mono_find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info, SeqPoint* seq_point)
 {
        MonoSeqPointInfo *seq_points;
 
-       seq_points = get_seq_points (domain, method);
+       seq_points = mono_get_seq_points (domain, method);
        if (!seq_points) {
                if (info)
                        *info = NULL;
@@ -244,21 +309,21 @@ find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, g
        if (info)
                *info = seq_points;
 
-       return seq_point_find_prev_by_native_offset (seq_points, native_offset, seq_point);
+       return mono_seq_point_find_prev_by_native_offset (seq_points, native_offset, seq_point);
 }
 
 /*
- * find_seq_point:
+ * mono_find_seq_point:
  *
  *   Find the sequence point corresponding to the IL offset IL_OFFSET, which
  * should be the location of a sequence point.
  */
 gboolean
-find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSeqPointInfo **info, SeqPoint *seq_point)
+mono_find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSeqPointInfo **info, SeqPoint *seq_point)
 {
        MonoSeqPointInfo *seq_points;
 
-       seq_points = get_seq_points (domain, method);
+       seq_points = mono_get_seq_points (domain, method);
        if (!seq_points) {
                if (info)
                        *info = NULL;
@@ -267,11 +332,11 @@ find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSe
        if (info)
                *info = seq_points;
 
-       return seq_point_find_by_il_offset (seq_points, il_offset, seq_point);
+       return mono_seq_point_find_by_il_offset (seq_points, il_offset, seq_point);
 }
 
 void
-bb_deduplicate_op_il_seq_points (MonoCompile *cfg, MonoBasicBlock *bb)
+mono_bb_deduplicate_op_il_seq_points (MonoCompile *cfg, MonoBasicBlock *bb)
 {
        MonoInst *ins, *n, *prev;
 
@@ -287,11 +352,3 @@ bb_deduplicate_op_il_seq_points (MonoCompile *cfg, MonoBasicBlock *bb)
                MONO_REMOVE_INS (bb, prev);
        };
 }
-
-void
-mono_image_get_aot_seq_point_path (MonoImage *image, char **str)
-{
-       int size = strlen (image->name) + strlen (SEQ_POINT_AOT_EXT) + 1;
-       *str = g_malloc (size);
-       g_sprintf (*str, "%s%s", image->name, SEQ_POINT_AOT_EXT);
-}