Moved sequence point logic to seq-points.h and seq-points.c
authorMarcos Henrich <marcos.henrich@xamarin.com>
Tue, 28 Oct 2014 22:06:07 +0000 (22:06 +0000)
committerMarcos Henrich <marcos.henrich@xamarin.com>
Fri, 14 Nov 2014 19:44:07 +0000 (03:44 +0800)
mono/mini/Makefile.am.in
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/debugger-agent.c
mono/mini/debugger-agent.h
mono/mini/method-to-ir.c
mono/mini/mini.c
mono/mini/mini.h
mono/mini/seq-points.c [new file with mode: 0644]
mono/mini/seq-points.h [new file with mode: 0644]

index d43605ce620c8c9e472e83debd2a1451ae4b5356..04ac59db62041e7e50868241a50d0ed18b4e8cf9 100755 (executable)
@@ -289,6 +289,7 @@ endif
 
 genmdesc_SOURCES = \
        mini.h          \
+       seq-points.h    \
        genmdesc.c      \
        helpers.c       \
        ../metadata/opcodes.c
@@ -375,6 +376,8 @@ endif
 
 common_sources = \
        mini.c                  \
+       seq-points.c    \
+       seq-points.h    \
        ir-emit.h               \
        method-to-ir.c          \
        decompose.c             \
index 44812084153173ded322f433b649682b9cae6fe0..c3c1251b80b73aac624f0ea0d7b68225e81eb184 100644 (file)
@@ -52,6 +52,7 @@
 #include <mono/utils/mono-mmap.h>
 
 #include "mini.h"
+#include "seq-points.h"
 #include "image-writer.h"
 #include "dwarfwriter.h"
 #include "mini-gc.h"
index 97d22706db0440ac1d2d695d1bdcd26a93a57f43..b1a80a0f0c62b3a5debf7466e9b43153cd8c6ba4 100644 (file)
@@ -58,6 +58,7 @@
 #include <mono/utils/mono-digest.h>
 
 #include "mini.h"
+#include "seq-points.h"
 #include "version.h"
 
 #ifndef DISABLE_AOT
index 1599f6aba13bf4f0c5b2fb803e49a7c02c871176..8969fa09aa00e578c7ee8523b64c6583dd433a3b 100644 (file)
@@ -84,6 +84,7 @@ int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
 #include <mono/utils/mono-threads.h>
 #include "debugger-agent.h"
 #include "mini.h"
+#include "seq-points.h"
 
 /*
 On iOS we can't use System.Environment.Exit () as it will do the wrong
@@ -3135,24 +3136,6 @@ is_suspended (void)
        return count_threads_to_wait_for () == 0;
 }
 
-static MonoSeqPointInfo*
-get_seq_points (MonoDomain *domain, MonoMethod *method)
-{
-       MonoSeqPointInfo *seq_points;
-
-       mono_domain_lock (domain);
-       seq_points = 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));
-               if (!seq_points)
-                       seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, mini_get_shared_method (method));
-       }
-       mono_domain_unlock (domain);
-
-       return seq_points;
-}
-
 static void
 no_seq_points_found (MonoMethod *method)
 {
@@ -3162,87 +3145,6 @@ no_seq_points_found (MonoMethod *method)
        printf ("Unable to find seq points for method '%s'.\n", mono_method_full_name (method, TRUE));
 }
 
-/*
- * find_next_seq_point_for_native_offset:
- *
- *   Find the first sequence point after NATIVE_OFFSET.
- */
-static SeqPoint*
-find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info)
-{
-       MonoSeqPointInfo *seq_points;
-       int i;
-
-       seq_points = get_seq_points (domain, method);
-       if (!seq_points) {
-               if (info)
-                       *info = NULL;
-               return NULL;
-       }
-       g_assert (seq_points);
-       if (info)
-               *info = seq_points;
-
-       for (i = 0; i < seq_points->len; ++i) {
-               if (seq_points->seq_points [i].native_offset >= native_offset)
-                       return &seq_points->seq_points [i];
-       }
-
-       return NULL;
-}
-
-/*
- * find_prev_seq_point_for_native_offset:
- *
- *   Find the first sequence point before NATIVE_OFFSET.
- */
-static SeqPoint*
-find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info)
-{
-       MonoSeqPointInfo *seq_points;
-       int i;
-
-       seq_points = get_seq_points (domain, method);
-       if (info)
-               *info = seq_points;
-       if (!seq_points)
-               return NULL;
-
-       for (i = seq_points->len - 1; i >= 0; --i) {
-               if (seq_points->seq_points [i].native_offset <= native_offset)
-                       return &seq_points->seq_points [i];
-       }
-
-       return NULL;
-}
-
-/*
- * find_seq_point:
- *
- *   Find the sequence point corresponding to the IL offset IL_OFFSET, which
- * should be the location of a sequence point.
- */
-static G_GNUC_UNUSED SeqPoint*
-find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSeqPointInfo **info)
-{
-       MonoSeqPointInfo *seq_points;
-       int i;
-
-       *info = NULL;
-
-       seq_points = get_seq_points (domain, method);
-       if (!seq_points)
-               return NULL;
-       *info = seq_points;
-
-       for (i = 0; i < seq_points->len; ++i) {
-               if (seq_points->seq_points [i].il_offset == il_offset)
-                       return &seq_points->seq_points [i];
-       }
-
-       return NULL;
-}
-
 typedef struct {
        DebuggerTlsData *tls;
        GSList *frames;
index 02853d0856b9bfe6f8e2b2ef3981272db236535c..63129c264831da75319e36aa3a13de46000d20ff 100644 (file)
@@ -3,13 +3,6 @@
 
 #include "mini.h"
 
-/* IL offsets used to mark the sequence points belonging to method entry/exit events */
-#define METHOD_ENTRY_IL_OFFSET -1
-#define METHOD_EXIT_IL_OFFSET 0xffffff
-
-/* Native offset used to mark seq points in dead code */
-#define SEQ_POINT_NATIVE_OFFSET_DEAD_CODE -1
-
 void
 mono_debugger_agent_parse_options (char *options) MONO_INTERNAL;
 
index de016eff717b3c54fb51a6be1276a383f4849e75..328b62b208b3af0644efd08bc140c133f4c83664 100755 (executable)
@@ -68,6 +68,7 @@
 #include "jit-icalls.h"
 #include "jit.h"
 #include "debugger-agent.h"
+#include "seq-points.h"
 
 #define BRANCH_COST 10
 #define INLINE_LENGTH_LIMIT 20
index b4f04231f574ca812ee94b1ca2e02de8114d20f8..8107ae22247454a36b910b1d7208978b716ebd19 100755 (executable)
@@ -63,6 +63,7 @@
 #include <mono/utils/mono-threads.h>
 
 #include "mini.h"
+#include "seq-points.h"
 #include "mini-llvm.h"
 #include "tasklets.h"
 #include <string.h>
@@ -75,6 +76,7 @@
 
 #include "mini-gc.h"
 #include "debugger-agent.h"
+#include "seq-points.h"
 
 static gpointer mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, MonoException **ex);
 
@@ -3919,159 +3921,6 @@ mono_postprocess_patches (MonoCompile *cfg)
        }
 }
 
-static void
-collect_pred_seq_points (MonoBasicBlock *bb, MonoInst *ins, GSList **next, int depth)
-{
-       int i;
-       MonoBasicBlock *in_bb;
-       GSList *l;
-
-       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);
-               }
-       }
-}
-
-static void
-mono_save_seq_point_info (MonoCompile *cfg)
-{
-       MonoBasicBlock *bb;
-       GSList *bb_seq_points, *l;
-       MonoInst *last;
-       MonoDomain *domain = cfg->domain;
-       int i;
-       MonoSeqPointInfo *info;
-       GSList **next;
-
-       if (!cfg->seq_points)
-               return;
-
-       info = g_malloc0 (sizeof (MonoSeqPointInfo) + (cfg->seq_points->len * sizeof (SeqPoint)));
-       info->len = cfg->seq_points->len;
-       for (i = 0; i < cfg->seq_points->len; ++i) {
-               SeqPoint *sp = &info->seq_points [i];
-               MonoInst *ins = g_ptr_array_index (cfg->seq_points, i);
-
-               sp->il_offset = ins->inst_imm;
-               sp->native_offset = ins->inst_offset;
-               if (ins->flags & MONO_INST_NONEMPTY_STACK)
-                       sp->flags |= MONO_SEQ_POINT_FLAG_NONEMPTY_STACK;
-
-               /* Used below */
-               ins->backend.size = i;
-       }
-
-       /*
-        * For each sequence point, compute the list of sequence points immediately
-        * following it, this is needed to implement 'step over' in the debugger agent.
-        */ 
-       next = g_new0 (GSList*, cfg->seq_points->len);
-       for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
-               bb_seq_points = g_slist_reverse (bb->seq_points);
-               last = NULL;
-               for (l = bb_seq_points; l; l = l->next) {
-                       MonoInst *ins = l->data;
-
-                       if (ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET)
-                               /* Used to implement method entry/exit events */
-                               continue;
-                       if (ins->inst_offset == SEQ_POINT_NATIVE_OFFSET_DEAD_CODE)
-                               continue;
-
-                       if (last != NULL) {
-                               /* Link with the previous seq point in the same bb */
-                               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);
-                       }
-
-                       last = ins;
-               }
-
-               if (bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY && bb->seq_points) {
-                       MonoBasicBlock *bb2;
-                       MonoInst *endfinally_seq_point = NULL;
-
-                       /*
-                        * The ENDFINALLY branches are not represented in the cfg, so link it with all seq points starting bbs.
-                        */
-                       l = g_slist_last (bb->seq_points);
-                       if (l) {
-                               endfinally_seq_point = 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;
-
-                                               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));
-                                       }
-                               }
-                       }
-               }
-       }
-
-       if (cfg->verbose_level > 2) {
-               printf ("\nSEQ POINT MAP: \n");
-       }
-
-       for (i = 0; i < cfg->seq_points->len; ++i) {
-               SeqPoint *sp = &info->seq_points [i];
-               GSList *l;
-               int j, next_index;
-
-               sp->next_len = g_slist_length (next [i]);
-               sp->next = g_new (int, sp->next_len);
-               j = 0;
-               if (cfg->verbose_level > 2 && next [i]) {
-                       printf ("\tIL0x%x ->", sp->il_offset);
-                       for (l = next [i]; l; l = l->next) {
-                               next_index = GPOINTER_TO_UINT (l->data);
-                               printf (" IL0x%x", info->seq_points [next_index].il_offset);
-                       }
-                       printf ("\n");
-               }
-               for (l = next [i]; l; l = l->next) {
-                       next_index = GPOINTER_TO_UINT (l->data);
-                       sp->next [j ++] = next_index;
-               }
-               g_slist_free (next [i]);
-       }
-       g_free (next);
-
-       cfg->seq_point_info = info;
-
-       // FIXME: dynamic methods
-       if (!cfg->compile_aot) {
-               mono_domain_lock (domain);
-               // FIXME: How can the lookup succeed ?
-               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, info);
-               mono_domain_unlock (domain);
-       }
-
-       g_ptr_array_free (cfg->seq_points, TRUE);
-       cfg->seq_points = NULL;
-}
-
 void
 mono_codegen (MonoCompile *cfg)
 {
index 6c2bf9b65dca7268ecf269dfcb378a191f43524f..5d5c86c1427b73ba052701cdd45db6080be8bf6c 100755 (executable)
@@ -333,21 +333,6 @@ typedef struct {
  */
 typedef MonoStackFrameInfo StackFrameInfo;
 
-#define MONO_SEQ_POINT_FLAG_NONEMPTY_STACK 1
-
-typedef struct {
-       int il_offset, native_offset, flags;
-       /* Indexes of successor sequence points */
-       int *next;
-       /* Number of entries in next */
-       int next_len;
-} SeqPoint;
-
-typedef struct {
-       int len;
-       SeqPoint seq_points [MONO_ZERO_LEN_ARRAY];
-} MonoSeqPointInfo;
-
 #if 0
 #define mono_bitset_foreach_bit(set,b,n) \
        for (b = 0; b < n; b++)\
@@ -1597,7 +1582,7 @@ typedef struct {
        GPtrArray *seq_points;
 
        /* The encoded sequence point info */
-       MonoSeqPointInfo *seq_point_info;
+       struct MonoSeqPointInfo *seq_point_info;
 
        /* Method headers which need to be freed after compilation */
        GSList *headers_to_free;
diff --git a/mono/mini/seq-points.c b/mono/mini/seq-points.c
new file mode 100644 (file)
index 0000000..c89dcf2
--- /dev/null
@@ -0,0 +1,263 @@
+/*
+ * seq-points.c: Sequence Points functions
+ *
+ * Authors:
+ *   Marcos Henrich (marcos.henrich@xamarin.com)
+ *
+ * Copyright 2014 Xamarin, Inc (http://www.xamarin.com)
+ */
+
+#include "mini.h"
+#include "seq-points.h"
+
+static void
+collect_pred_seq_points (MonoBasicBlock *bb, MonoInst *ins, GSList **next, int depth)
+{
+       int i;
+       MonoBasicBlock *in_bb;
+       GSList *l;
+
+       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);
+               }
+       }
+}
+
+void
+mono_save_seq_point_info (MonoCompile *cfg)
+{
+       MonoBasicBlock *bb;
+       GSList *bb_seq_points, *l;
+       MonoInst *last;
+       MonoDomain *domain = cfg->domain;
+       int i;
+       MonoSeqPointInfo *info;
+       GSList **next;
+
+       if (!cfg->seq_points)
+               return;
+
+       info = g_malloc0 (sizeof (MonoSeqPointInfo) + (cfg->seq_points->len * sizeof (SeqPoint)));
+       info->len = cfg->seq_points->len;
+       for (i = 0; i < cfg->seq_points->len; ++i) {
+               SeqPoint *sp = &info->seq_points [i];
+               MonoInst *ins = g_ptr_array_index (cfg->seq_points, i);
+
+               sp->il_offset = ins->inst_imm;
+               sp->native_offset = ins->inst_offset;
+               if (ins->flags & MONO_INST_NONEMPTY_STACK)
+                       sp->flags |= MONO_SEQ_POINT_FLAG_NONEMPTY_STACK;
+
+               /* Used below */
+               ins->backend.size = i;
+       }
+
+       /*
+        * For each sequence point, compute the list of sequence points immediately
+        * following it, this is needed to implement 'step over' in the debugger agent.
+        */
+       next = g_new0 (GSList*, cfg->seq_points->len);
+       for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
+               bb_seq_points = g_slist_reverse (bb->seq_points);
+               last = NULL;
+               for (l = bb_seq_points; l; l = l->next) {
+                       MonoInst *ins = l->data;
+
+                       if (ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET)
+                       /* Used to implement method entry/exit events */
+                               continue;
+                       if (ins->inst_offset == SEQ_POINT_NATIVE_OFFSET_DEAD_CODE)
+                               continue;
+
+                       if (last != NULL) {
+                               /* Link with the previous seq point in the same bb */
+                               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);
+                       }
+
+                       last = ins;
+               }
+
+               if (bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY && bb->seq_points) {
+                       MonoBasicBlock *bb2;
+                       MonoInst *endfinally_seq_point = NULL;
+
+                       /*
+                        * The ENDFINALLY branches are not represented in the cfg, so link it with all seq points starting bbs.
+                        */
+                       l = g_slist_last (bb->seq_points);
+                       if (l) {
+                               endfinally_seq_point = 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;
+
+                                               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));
+                                       }
+                               }
+                       }
+               }
+       }
+
+       if (cfg->verbose_level > 2) {
+               printf ("\nSEQ POINT MAP: \n");
+       }
+
+       for (i = 0; i < cfg->seq_points->len; ++i) {
+               SeqPoint *sp = &info->seq_points [i];
+               GSList *l;
+               int j, next_index;
+
+               sp->next_len = g_slist_length (next [i]);
+               sp->next = g_new (int, sp->next_len);
+               j = 0;
+               if (cfg->verbose_level > 2 && next [i]) {
+                       printf ("\tIL0x%x ->", sp->il_offset);
+                       for (l = next [i]; l; l = l->next) {
+                               next_index = GPOINTER_TO_UINT (l->data);
+                               printf (" IL0x%x", info->seq_points [next_index].il_offset);
+                       }
+                       printf ("\n");
+               }
+               for (l = next [i]; l; l = l->next) {
+                       next_index = GPOINTER_TO_UINT (l->data);
+                       sp->next [j ++] = next_index;
+               }
+               g_slist_free (next [i]);
+       }
+       g_free (next);
+
+       cfg->seq_point_info = info;
+
+       // FIXME: dynamic methods
+       if (!cfg->compile_aot) {
+               mono_domain_lock (domain);
+               // FIXME: How can the lookup succeed ?
+               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, info);
+               mono_domain_unlock (domain);
+       }
+
+       g_ptr_array_free (cfg->seq_points, TRUE);
+       cfg->seq_points = NULL;
+}
+
+MonoSeqPointInfo*
+get_seq_points (MonoDomain *domain, MonoMethod *method)
+{
+       MonoSeqPointInfo *seq_points;
+
+       mono_domain_lock (domain);
+       seq_points = 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));
+               if (!seq_points)
+                       seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, mini_get_shared_method (method));
+       }
+       mono_domain_unlock (domain);
+
+       return seq_points;
+}
+
+/*
+ * find_next_seq_point_for_native_offset:
+ *
+ *   Find the first sequence point after NATIVE_OFFSET.
+ */
+SeqPoint*
+find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info)
+{
+       MonoSeqPointInfo *seq_points;
+       int i;
+
+       seq_points = get_seq_points (domain, method);
+       if (!seq_points) {
+               if (info)
+                       *info = NULL;
+               return NULL;
+       }
+       g_assert (seq_points);
+       if (info)
+               *info = seq_points;
+
+       for (i = 0; i < seq_points->len; ++i) {
+               if (seq_points->seq_points [i].native_offset >= native_offset)
+                       return &seq_points->seq_points [i];
+       }
+
+       return NULL;
+}
+
+/*
+ * find_prev_seq_point_for_native_offset:
+ *
+ *   Find the first sequence point before NATIVE_OFFSET.
+ */
+SeqPoint*
+find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info)
+{
+       MonoSeqPointInfo *seq_points;
+       int i;
+
+       seq_points = get_seq_points (domain, method);
+       if (info)
+               *info = seq_points;
+       if (!seq_points)
+               return NULL;
+
+       for (i = seq_points->len - 1; i >= 0; --i) {
+               if (seq_points->seq_points [i].native_offset <= native_offset)
+                       return &seq_points->seq_points [i];
+       }
+
+       return NULL;
+}
+
+/*
+ * find_seq_point:
+ *
+ *   Find the sequence point corresponding to the IL offset IL_OFFSET, which
+ * should be the location of a sequence point.
+ */
+G_GNUC_UNUSED SeqPoint*
+find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSeqPointInfo **info)
+{
+       MonoSeqPointInfo *seq_points;
+       int i;
+
+       *info = NULL;
+
+       seq_points = get_seq_points (domain, method);
+       if (!seq_points)
+               return NULL;
+       *info = seq_points;
+
+       for (i = 0; i < seq_points->len; ++i) {
+               if (seq_points->seq_points [i].il_offset == il_offset)
+                       return &seq_points->seq_points [i];
+       }
+
+       return NULL;
+}
\ No newline at end of file
diff --git a/mono/mini/seq-points.h b/mono/mini/seq-points.h
new file mode 100644 (file)
index 0000000..cce4b12
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2014 Xamarin Inc
+ */
+#ifndef __MONO_SEQ_POINTS_H__
+#define __MONO_SEQ_POINTS_H__
+
+#define MONO_SEQ_POINT_FLAG_NONEMPTY_STACK 1
+
+/* IL offsets used to mark the sequence points belonging to method entry/exit events */
+#define METHOD_ENTRY_IL_OFFSET -1
+#define METHOD_EXIT_IL_OFFSET 0xffffff
+
+/* Native offset used to mark seq points in dead code */
+#define SEQ_POINT_NATIVE_OFFSET_DEAD_CODE -1
+
+typedef struct {
+       int il_offset, native_offset, flags;
+       /* Indexes of successor sequence points */
+       int *next;
+       /* Number of entries in next */
+       int next_len;
+} SeqPoint;
+
+typedef struct MonoSeqPointInfo {
+       int len;
+       SeqPoint seq_points [MONO_ZERO_LEN_ARRAY];
+} MonoSeqPointInfo;
+
+void
+mono_save_seq_point_info (MonoCompile *cfg);
+
+MonoSeqPointInfo*
+get_seq_points (MonoDomain *domain, MonoMethod *method);
+
+SeqPoint*
+find_next_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info);
+
+SeqPoint*
+find_prev_seq_point_for_native_offset (MonoDomain *domain, MonoMethod *method, gint32 native_offset, MonoSeqPointInfo **info);
+
+G_GNUC_UNUSED SeqPoint*
+find_seq_point (MonoDomain *domain, MonoMethod *method, gint32 il_offset, MonoSeqPointInfo **info);
+
+#endif /* __MONO_SEQ_POINTS_H__ */
\ No newline at end of file