Merge pull request #1412 from esdrubal/stackframe
[mono.git] / mono / mini / mini.c
index b489216a885814fb4df537f7a1fa869a67072dd4..f876ce3ea5c5e30c9eff8506e15d0c87eca36806 100755 (executable)
@@ -53,6 +53,7 @@
 #include <mono/utils/mono-math.h>
 #include <mono/utils/mono-compiler.h>
 #include <mono/utils/mono-counters.h>
+#include <mono/utils/mono-error-internals.h>
 #include <mono/utils/mono-logger-internal.h>
 #include <mono/utils/mono-mmap.h>
 #include <mono/utils/mono-path.h>
@@ -63,6 +64,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 +77,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);
 
@@ -710,18 +713,24 @@ G_GNUC_UNUSED gboolean
 mono_debug_count (void)
 {
        static int count = 0;
+       static gboolean inited;
+       static const char *value;
+
        count ++;
 
-       if (!g_getenv ("COUNT"))
+       if (!inited) {
+               value = g_getenv ("COUNT");
+               inited = TRUE;
+       }
+
+       if (!value)
                return TRUE;
 
-       if (count == atoi (g_getenv ("COUNT"))) {
+       if (count == atoi (value))
                break_count ();
-       }
 
-       if (count > atoi (g_getenv ("COUNT"))) {
+       if (count > atoi (value))
                return FALSE;
-       }
 
        return TRUE;
 }
@@ -1241,7 +1250,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode,
 
        if ((num + 1) >= cfg->varinfo_count) {
                int orig_count = cfg->varinfo_count;
-               cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 64;
+               cfg->varinfo_count = cfg->varinfo_count ? (cfg->varinfo_count * 2) : 32;
                cfg->varinfo = (MonoInst **)g_realloc (cfg->varinfo, sizeof (MonoInst*) * cfg->varinfo_count);
                cfg->vars = (MonoMethodVar *)g_realloc (cfg->vars, sizeof (MonoMethodVar) * cfg->varinfo_count);
                memset (&cfg->vars [orig_count], 0, (cfg->varinfo_count - orig_count) * sizeof (MonoMethodVar));
@@ -3239,9 +3248,10 @@ mono_patch_info_hash (gconstpointer data)
        case MONO_PATCH_INFO_JIT_TLS_ID:
        case MONO_PATCH_INFO_MONITOR_ENTER:
        case MONO_PATCH_INFO_MONITOR_EXIT:
-       case MONO_PATCH_INFO_CASTCLASS_CACHE:
        case MONO_PATCH_INFO_GOT_OFFSET:
                return (ji->type << 8);
+       case MONO_PATCH_INFO_CASTCLASS_CACHE:
+               return (ji->type << 8) | (ji->data.index);
        case MONO_PATCH_INFO_SWITCH:
                return (ji->type << 8) | ji->data.table->table_size;
        case MONO_PATCH_INFO_GSHAREDVT_METHOD:
@@ -3306,6 +3316,8 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb)
                return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method;
        case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
                return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method && ji1->data.del_tramp->virtual == ji2->data.del_tramp->virtual;
+       case MONO_PATCH_INFO_CASTCLASS_CACHE:
+               return ji1->data.index == ji2->data.index;
        default:
                if (ji1->data.target != ji2->data.target)
                        return 0;
@@ -3911,159 +3923,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)
 {
@@ -4115,6 +3974,8 @@ mono_codegen (MonoCompile *cfg)
 
        cfg->code_len = code - cfg->native_code;
        cfg->prolog_end = cfg->code_len;
+       cfg->cfa_reg = cfg->cur_cfa_reg;
+       cfg->cfa_offset = cfg->cur_cfa_offset;
 
        mono_debug_open_method (cfg);
 
@@ -4129,6 +3990,7 @@ mono_codegen (MonoCompile *cfg)
                if (bb == cfg->bb_exit) {
                        cfg->epilog_begin = cfg->code_len;
                        mono_arch_emit_epilog (cfg);
+                       cfg->epilog_end = cfg->code_len;
                }
        }
 
@@ -4326,18 +4188,15 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
        GSList *tmp;
        MonoMethodHeader *header;
        MonoJitInfo *jinfo;
-       int num_clauses;
-       int generic_info_size, arch_eh_info_size = 0;
-       int holes_size = 0, num_holes = 0, cas_size = 0;
+       MonoJitInfoFlags flags = JIT_INFO_NONE;
+       int num_clauses, num_holes = 0;
        guint32 stack_size = 0;
 
        g_assert (method_to_compile == cfg->method);
        header = cfg->header;
 
        if (cfg->generic_sharing_context)
-               generic_info_size = sizeof (MonoGenericJitInfo);
-       else
-               generic_info_size = 0;
+               flags |= JIT_INFO_HAS_GENERIC_JIT_INFO;
 
        if (cfg->arch_eh_jit_info) {
                MonoJitArgumentInfo *arg_info;
@@ -4351,11 +4210,11 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                stack_size = mono_arch_get_argument_info (cfg->generic_sharing_context, sig, sig->param_count, arg_info);
 
                if (stack_size)
-                       arch_eh_info_size = sizeof (MonoArchEHJitInfo);
+                       flags |= JIT_INFO_HAS_ARCH_EH_INFO;
        }
 
-       if (cfg->has_unwind_info_for_epilog && !arch_eh_info_size)
-               arch_eh_info_size = sizeof (MonoArchEHJitInfo);
+       if (cfg->has_unwind_info_for_epilog && !(flags & JIT_INFO_HAS_ARCH_EH_INFO))
+               flags |= JIT_INFO_HAS_ARCH_EH_INFO;
                
        if (cfg->try_block_holes) {
                for (tmp = cfg->try_block_holes; tmp; tmp = tmp->next) {
@@ -4370,34 +4229,25 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                                ++num_holes;
                }
                if (num_holes)
-                       holes_size = sizeof (MonoTryBlockHoleTableJitInfo) + num_holes * sizeof (MonoTryBlockHoleJitInfo);
+                       flags |= JIT_INFO_HAS_TRY_BLOCK_HOLES;
                if (G_UNLIKELY (cfg->verbose_level >= 4))
                        printf ("Number of try block holes %d\n", num_holes);
        }
 
-       if (mono_security_method_has_declsec (cfg->method_to_register)) {
-               cas_size = sizeof (MonoMethodCasInfo);
-       }
+       if (mono_security_method_has_declsec (cfg->method_to_register))
+               flags |= JIT_INFO_HAS_ARCH_EH_INFO;
 
        if (COMPILE_LLVM (cfg))
                num_clauses = cfg->llvm_ex_info_len;
        else
                num_clauses = header->num_clauses;
 
-       if (cfg->method->dynamic) {
-               jinfo = g_malloc0 (MONO_SIZEOF_JIT_INFO + (num_clauses * sizeof (MonoJitExceptionInfo)) +
-                               generic_info_size + holes_size + arch_eh_info_size + cas_size);
-       } else {
-               jinfo = mono_domain_alloc0 (cfg->domain, MONO_SIZEOF_JIT_INFO +
-                               (num_clauses * sizeof (MonoJitExceptionInfo)) +
-                               generic_info_size + holes_size + arch_eh_info_size + cas_size);
-       }
-
-       jinfo->d.method = cfg->method_to_register;
-       jinfo->code_start = cfg->native_code;
-       jinfo->code_size = cfg->code_len;
+       if (cfg->method->dynamic)
+               jinfo = g_malloc0 (mono_jit_info_size (flags, num_clauses, num_holes));
+       else
+               jinfo = mono_domain_alloc0 (cfg->domain, mono_jit_info_size (flags, num_clauses, num_holes));
+       mono_jit_info_init (jinfo, cfg->method_to_register, cfg->native_code, cfg->code_len, flags, num_clauses, num_holes);
        jinfo->domain_neutral = (cfg->opt & MONO_OPT_SHARED) != 0;
-       jinfo->num_clauses = num_clauses;
 
        if (COMPILE_LLVM (cfg))
                jinfo->from_llvm = TRUE;
@@ -4407,8 +4257,6 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                MonoGenericJitInfo *gi;
                GSList *loclist = NULL;
 
-               jinfo->has_generic_jit_info = 1;
-
                gi = mono_jit_info_get_generic_jit_info (jinfo);
                g_assert (gi);
 
@@ -4482,7 +4330,6 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                MonoTryBlockHoleTableJitInfo *table;
                int i;
 
-               jinfo->has_try_block_holes = 1;
                table = mono_jit_info_get_try_block_hole_table_info (jinfo);
                table->num_holes = (guint16)num_holes;
                i = 0;
@@ -4511,19 +4358,14 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
                g_assert (i == num_holes);
        }
 
-       if (arch_eh_info_size) {
+       if (jinfo->has_arch_eh_info) {
                MonoArchEHJitInfo *info;
 
-               jinfo->has_arch_eh_info = 1;
                info = mono_jit_info_get_arch_eh_info (jinfo);
 
                info->stack_size = stack_size;
        }
 
-       if (cas_size) {
-               jinfo->has_cas_info = 1;
-       }
-
        if (COMPILE_LLVM (cfg)) {
                if (num_clauses)
                        memcpy (&jinfo->clauses [0], &cfg->llvm_ex_info [0], num_clauses * sizeof (MonoJitExceptionInfo));
@@ -4657,7 +4499,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile)
 
                        info = mono_jit_info_get_arch_eh_info (jinfo);
                        g_assert (info);
-                       info->epilog_size = cfg->code_size - cfg->epilog_begin;
+                       info->epilog_size = cfg->code_len - cfg->epilog_begin;
                }
                jinfo->unwind_info = unwind_desc;
                g_free (unwind_info);
@@ -4934,7 +4776,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        gboolean run_cctors = (flags & JIT_FLAG_RUN_CCTORS) ? 1 : 0;
        gboolean compile_aot = (flags & JIT_FLAG_AOT) ? 1 : 0;
        gboolean full_aot = (flags & JIT_FLAG_FULL_AOT) ? 1 : 0;
+#ifdef ENABLE_LLVM
        gboolean llvm = (flags & JIT_FLAG_LLVM) ? 1 : 0;
+#endif
+       static gboolean verbose_method_inited;
+       static const char *verbose_method_name;
 
        InterlockedIncrement (&mono_jit_stats.methods_compiled);
        if (mono_profiler_get_events () & MONO_PROFILE_JIT_COMPILATION)
@@ -5004,7 +4850,9 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        cfg->full_aot = full_aot;
        cfg->skip_visibility = method->skip_visibility;
        cfg->orig_method = method;
-       cfg->gen_seq_points = debug_options.gen_seq_points;
+       cfg->gen_seq_points = TRUE;
+       cfg->gen_seq_points_debug_data = debug_options.gen_seq_points_debug_data;
+
        cfg->explicit_null_checks = debug_options.explicit_null_checks;
        cfg->soft_breakpoints = debug_options.soft_breakpoints;
        cfg->check_pinvoke_callconv = debug_options.check_pinvoke_callconv;
@@ -5015,6 +4863,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
        if (cfg->gen_seq_points)
                cfg->seq_points = g_ptr_array_new ();
+       mono_error_init (&cfg->error);
 
        if (cfg->compile_aot && !try_generic_shared && (method->is_generic || method->klass->generic_container || method_is_gshared)) {
                cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED;
@@ -5048,6 +4897,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
 
        if (cfg->generic_sharing_context) {
                method_to_register = method_to_compile;
+               cfg->gshared = TRUE;
        } else {
                g_assert (method == method_to_compile);
                method_to_register = method;
@@ -5084,9 +4934,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        {
                static gboolean inited;
 
-               if (!inited) {
+               if (!inited)
                        inited = TRUE;
-               }
 
                /* 
                 * Check for methods which cannot be compiled by LLVM early, to avoid
@@ -5162,8 +5011,12 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                cfg->opt |= MONO_OPT_ABCREM;
        }
 
-       if (g_getenv ("MONO_VERBOSE_METHOD")) {
-               const char *name = g_getenv ("MONO_VERBOSE_METHOD");
+       if (!verbose_method_inited) {
+               verbose_method_name = g_getenv ("MONO_VERBOSE_METHOD");
+               verbose_method_inited = TRUE;
+       }
+       if (verbose_method_name) {
+               const char *name = verbose_method_name;
 
                if ((strchr (name, '.') > name) || strchr (name, ':')) {
                        MonoMethodDesc *desc;
@@ -5174,7 +5027,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
                        }
                        mono_method_desc_free (desc);
                } else {
-                       if (strcmp (cfg->method->name, g_getenv ("MONO_VERBOSE_METHOD")) == 0)
+                       if (strcmp (cfg->method->name, name) == 0)
                                cfg->verbose_level = 4;
                }
        }
@@ -5281,7 +5134,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        /* SSAPRE is not supported on linear IR */
        cfg->opt &= ~MONO_OPT_SSAPRE;
 
-       i = mono_method_to_ir (cfg, method_to_compile, NULL, NULL, NULL, NULL, NULL, 0, FALSE);
+       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) {
@@ -5432,7 +5285,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl
        */
 
 //#define DEBUGSSA "logic_run"
-#define DEBUGSSA_CLASS "Tests"
+//#define DEBUGSSA_CLASS "Tests"
 #ifdef DEBUGSSA
 
        if (!cfg->disable_ssa) {
@@ -6101,6 +5954,10 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in
        case MONO_EXCEPTION_OUT_OF_MEMORY:
                ex = mono_domain_get ()->out_of_memory_ex;
                break;
+       case MONO_EXCEPTION_MONO_ERROR:
+               g_assert (!mono_error_ok (&cfg->error));
+               ex = mono_error_convert_to_exception (&cfg->error);
+               break;
        default:
                g_assert_not_reached ();
        }
@@ -6738,14 +6595,12 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
        return runtime_invoke (obj, params, exc, info->compiled_method);
 }
 
-SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
 {
        MonoException *exc = NULL;
        MonoJitInfo *ji;
-#if !(defined(MONO_ARCH_USE_SIGACTION) || defined(HOST_WIN32))
-       void *info = NULL;
-#endif
-       GET_CONTEXT;
+       void *info = MONO_SIG_HANDLER_GET_INFO ();
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        ji = mono_jit_info_table_find (mono_domain_get (), mono_arch_ip_from_context (ctx));
 
@@ -6763,12 +6618,12 @@ SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
 #endif
 
        if (!ji) {
-               if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
 
                mono_handle_native_sigsegv (SIGSEGV, ctx);
                if (mono_do_crash_chaining) {
-                       mono_chain_signal (SIG_HANDLER_PARAMS);
+                       mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
                        return;
                }
        }
@@ -6776,10 +6631,10 @@ SIG_HANDLER_FUNC (, mono_sigfpe_signal_handler)
        mono_arch_handle_exception (ctx, exc);
 }
 
-SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
 {
        MonoException *exc;
-       GET_CONTEXT;
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        exc = mono_get_exception_execution_engine ("SIGILL");
        
@@ -6790,13 +6645,15 @@ SIG_HANDLER_FUNC (, mono_sigill_signal_handler)
 #define HAVE_SIG_INFO
 #endif
 
-SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 {
        MonoJitInfo *ji;
        MonoJitTlsData *jit_tls = mono_native_tls_get_value (mono_jit_tls_id);
        gpointer fault_addr = NULL;
-
-       GET_CONTEXT;
+#ifdef HAVE_SIG_INFO
+       MONO_SIG_HANDLER_INFO_TYPE *info = MONO_SIG_HANDLER_GET_INFO ();
+#endif
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
 #if defined(MONO_ARCH_SOFT_DEBUG_SUPPORTED) && defined(HAVE_SIG_INFO)
        if (mono_arch_is_single_step_event (info, ctx)) {
@@ -6818,11 +6675,11 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 
        /* The thread might no be registered with the runtime */
        if (!mono_domain_get () || !jit_tls) {
-               if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
                mono_handle_native_sigsegv (SIGSEGV, ctx);
                if (mono_do_crash_chaining) {
-                       mono_chain_signal (SIG_HANDLER_PARAMS);
+                       mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
                        return;
                }
        }
@@ -6839,7 +6696,7 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
        if (fault_addr == NULL) {
                MonoContext mctx;
 
-               mono_arch_sigctx_to_monoctx (ctx, &mctx);
+               mono_sigctx_to_monoctx (ctx, &mctx);
 
                fault_addr = MONO_CONTEXT_GET_SP (&mctx);
        }
@@ -6855,7 +6712,7 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
                g_assert_not_reached ();
        } else {
                /* The original handler might not like that it is executed on an altstack... */
-               if (!ji && mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!ji && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
 
                mono_arch_handle_altstack_exception (ctx, info->si_addr, FALSE);
@@ -6863,13 +6720,13 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 #else
 
        if (!ji) {
-               if (!mono_do_crash_chaining && mono_chain_signal (SIG_HANDLER_PARAMS))
+               if (!mono_do_crash_chaining && mono_chain_signal (MONO_SIG_HANDLER_PARAMS))
                        return;
 
                mono_handle_native_sigsegv (SIGSEGV, ctx);
 
                if (mono_do_crash_chaining) {
-                       mono_chain_signal (SIG_HANDLER_PARAMS);
+                       mono_chain_signal (MONO_SIG_HANDLER_PARAMS);
                        return;
                }
        }
@@ -6878,10 +6735,10 @@ SIG_HANDLER_FUNC (, mono_sigsegv_signal_handler)
 #endif
 }
 
-SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
+MONO_SIG_HANDLER_FUNC (, mono_sigint_signal_handler)
 {
        MonoException *exc;
-       GET_CONTEXT;
+       MONO_SIG_HANDLER_GET_CONTEXT;
 
        exc = mono_get_exception_execution_engine ("Interrupted (SIGINT).");
        
@@ -7058,7 +6915,7 @@ mini_parse_debug_options (void)
                else if (!strcmp (arg, "explicit-null-checks"))
                        debug_options.explicit_null_checks = TRUE;
                else if (!strcmp (arg, "gen-seq-points"))
-                       debug_options.gen_seq_points = TRUE;
+                       debug_options.gen_seq_points_debug_data = TRUE;
                else if (!strcmp (arg, "init-stacks"))
                        debug_options.init_stacks = TRUE;
                else if (!strcmp (arg, "casts"))
@@ -7088,10 +6945,9 @@ mini_get_debug_options (void)
 static gpointer
 mini_create_ftnptr (MonoDomain *domain, gpointer addr)
 {
-#if !defined(__ia64__) && !defined(__ppc64__) && !defined(__powerpc64__)
+#if !defined(__ia64__) && (!defined(__ppc64__) && !defined(__powerpc64__) || _CALL_ELF == 2)
        return addr;
 #else
-
        gpointer* desc = NULL;
 
        if ((desc = g_hash_table_lookup (domain->ftnptrs_hash, addr)))
@@ -7117,7 +6973,7 @@ mini_create_ftnptr (MonoDomain *domain, gpointer addr)
 static gpointer
 mini_get_addr_from_ftnptr (gpointer descr)
 {
-#if defined(__ia64__) || defined(__ppc64__) || defined(__powerpc64__)
+#if defined(__ia64__) || ((defined(__ppc64__) || defined(__powerpc64__)) && _CALL_ELF != 2)
        return *(gpointer*)descr;
 #else
        return descr;
@@ -7137,6 +6993,7 @@ register_jit_stats (void)
        mono_counters_register ("Allocated vars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocate_var);
        mono_counters_register ("Code reallocs", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.code_reallocs);
        mono_counters_register ("Allocated code size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_code_size);
+       mono_counters_register ("Allocated seq points size", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.allocated_seq_points_size);
        mono_counters_register ("Inlineable methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlineable_methods);
        mono_counters_register ("Inlined methods", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.inlined_methods);
        mono_counters_register ("Regvars", MONO_COUNTER_JIT | MONO_COUNTER_INT, &mono_jit_stats.regvars);
@@ -7151,7 +7008,6 @@ register_jit_stats (void)
 }
 
 static void runtime_invoke_info_free (gpointer value);
-static void seq_point_info_free (gpointer value);
 
 static gint
 class_method_pair_equal (gconstpointer ka, gconstpointer kb)
@@ -7222,19 +7078,6 @@ runtime_invoke_info_free (gpointer value)
        g_free (info);
 }
 
-static void seq_point_info_free (gpointer value)
-{
-       int i = 0;
-       MonoSeqPointInfo* info = (MonoSeqPointInfo*)value;
-       
-       for (i = 0; i < info->len; ++i) {
-               SeqPoint *sp = &info->seq_points [i];
-               g_free (sp->next);
-       }
-
-       g_free (info);
-}
-
 static void
 mini_free_jit_domain_info (MonoDomain *domain)
 {
@@ -7274,6 +7117,43 @@ mini_free_jit_domain_info (MonoDomain *domain)
        domain->runtime_info = NULL;
 }
 
+#ifdef ENABLE_LLVM
+static gboolean
+llvm_init_inner (void)
+{
+       if (!mono_llvm_load (NULL))
+               return FALSE;
+
+       mono_llvm_init ();
+       return TRUE;
+}
+#endif
+
+/*
+ * mini_llvm_init:
+ *
+ *   Load and initialize LLVM support.
+ * Return TRUE on success.
+ */
+gboolean
+mini_llvm_init (void)
+{
+#ifdef ENABLE_LLVM
+       static gboolean llvm_inited;
+       static gboolean init_result;
+
+       mono_loader_lock_if_inited ();
+       if (!llvm_inited) {
+               init_result = llvm_init_inner ();
+               llvm_inited = TRUE;
+       }
+       mono_loader_unlock_if_inited ();
+       return init_result;
+#else
+       return FALSE;
+#endif
+}
+
 MonoDomain *
 mini_init (const char *filename, const char *runtime_version)
 {
@@ -7394,13 +7274,8 @@ mini_init (const char *filename, const char *runtime_version)
        mono_threads_install_cleanup (mini_thread_cleanup);
 
 #ifdef MONO_ARCH_HAVE_NOTIFY_PENDING_EXC
-       // This is experimental code so provide an env var to switch it off
-       if (g_getenv ("MONO_DISABLE_PENDING_EXCEPTIONS")) {
-               printf ("MONO_DISABLE_PENDING_EXCEPTIONS env var set.\n");
-       } else {
-               check_for_pending_exc = FALSE;
-               mono_threads_install_notify_pending_exc (mono_arch_notify_pending_exc);
-       }
+       check_for_pending_exc = FALSE;
+       mono_threads_install_notify_pending_exc ((MonoThreadNotifyPendingExcFunc)mono_arch_notify_pending_exc);
 #endif
 
 #define JIT_TRAMPOLINES_WORK
@@ -7937,6 +7812,8 @@ mono_precompile_assembly (MonoAssembly *ass, void *user_data)
                method = mono_get_method (image, MONO_TOKEN_METHOD_DEF | (i + 1), NULL);
                if (method->flags & METHOD_ATTRIBUTE_ABSTRACT)
                        continue;
+               if (method->is_generic || method->klass->generic_container)
+                       continue;
 
                count++;
                if (mini_verbose > 1) {