-/*
- * seq-points.c: Sequence Points functions
+/**
+ * \file
+ * Sequence Points functions
*
* Authors:
* 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
-insert_pred_seq_point (MonoBasicBlock *in_bb, MonoInst *ins, GSList **next)
+insert_pred_seq_point (MonoInst *last_seq_ins, MonoInst *ins, GSList **next)
{
GSList *l;
- int src_index = in_bb->last_seq_point->backend.size;
+ int src_index = last_seq_ins->backend.size;
int dst_index = ins->backend.size;
/* bb->in_bb might contain duplicates */
}
static void
-collect_pred_seq_points (MonoBasicBlock *bb, MonoInst *ins, GSList **next, GHashTable *memoize)
+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];
- gpointer result = g_hash_table_lookup (memoize, in_bb);
+
+ // 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;
- if (result == MONO_SEQ_SEEN_LOOP) {
- // We've looped or handled this before, exit early.
- // No last sequence points to find.
+ // Take sequence points from incoming basic blocks
+
+ if (in_bb == cfg->bb_entry)
continue;
- } else if (in_bb->last_seq_point) {
- // if last seq point, insert into next
- insert_pred_seq_point (in_bb, ins, next);
- } else {
- // Compute predecessors of in_bb
-
- // Insert/remove sentinel into the memoize table to detect loops containing in_bb
- // This works to ensure that we only have a basic block on the stack once
- // at any given time
- g_hash_table_insert (memoize, in_bb, MONO_SEQ_SEEN_LOOP);
- collect_pred_seq_points (in_bb, ins, next, memoize);
- g_hash_table_remove (memoize, in_bb);
+
+ if (in_bb->pred_seq_points == NULL)
+ recursively_make_pred_seq_points (cfg, in_bb);
+
+ // 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_array_free (predecessors, TRUE);
+}
+
+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
* following it, this is needed to implement 'step over' in the debugger agent.
*/
next = g_new0 (GSList*, cfg->seq_points->len);
- GHashTable *memoize = g_hash_table_new (NULL, NULL);
for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
bb_seq_points = g_slist_reverse (bb->seq_points);
last = NULL;
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, memoize);
+ collect_pred_seq_points (cfg, bb, ins, next);
}
last = ins;
if (l) {
endfinally_seq_point = (MonoInst *)l->data;
- for (bb2 = cfg->bb_entry; bb2; bb2 = bb2->next_bb) {
+ for (bb2 = bb->next_bb; bb2; bb2 = bb2->next_bb) {
GSList *l = g_slist_last (bb2->seq_points);
if (l) {
}
}
}
- g_hash_table_destroy (memoize);
if (cfg->verbose_level > 2) {
printf ("\nSEQ POINT MAP: \n");
}
}
+ g_free (seq_points);
+
if (has_debug_data)
g_free (next);
// FIXME: dynamic methods
if (!cfg->compile_aot) {
mono_domain_lock (domain);
- // FIXME: How can the lookup succeed ?
+ // FIXME: The lookup can fail if the method is JITted recursively though a type cctor
if (!g_hash_table_lookup (domain_jit_info (domain)->seq_points, cfg->method_to_register))
g_hash_table_insert (domain_jit_info (domain)->seq_points, cfg->method_to_register, cfg->seq_point_info);
+ else
+ mono_seq_point_info_free (cfg->seq_point_info);
mono_domain_unlock (domain);
}
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 = (char *)g_malloc (size);
- g_sprintf (*str, "%s%s", image->name, SEQ_POINT_AOT_EXT);
-}