- MonoDomain *domain = mono_domain_get ();
- MonoJitInfo *ji, rji;
- static int (*call_filter) (MonoContext *, gpointer) = NULL;
- static void (*restore_context) (struct sigcontext *);
- MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id);
- MonoLMF *lmf = jit_tls->lmf;
- GList *trace_ips = NULL;
- MonoException *mono_ex;
- gboolean stack_overflow = FALSE;
- MonoContext initial_ctx;
- int frame_count = 0;
- gboolean gc_disabled = FALSE;
-
- /*
- * This function might execute on an alternate signal stack, and Boehm GC
- * can't handle that.
- * Also, since the altstack is small, stack space intensive operations like
- * JIT compilation should be avoided.
- */
- if (IS_ON_SIGALTSTACK (jit_tls)) {
- /*
- * FIXME: disabling/enabling GC while already on a signal stack might
- * not be safe either.
- */
- /* Have to reenable it later */
- gc_disabled = TRUE;
- mono_gc_disable ();
- }
-
- g_assert (ctx != NULL);
- if (!obj) {
- MonoException *ex = mono_get_exception_null_reference ();
- ex->message = mono_string_new (domain, "Object reference not set to an instance of an object");
- obj = (MonoObject *)ex;
- }
-
- if (mono_object_isinst (obj, mono_defaults.exception_class)) {
- mono_ex = (MonoException*)obj;
- mono_ex->stack_trace = NULL;
- } else {
- mono_ex = NULL;
- }
-
- if (obj == domain->stack_overflow_ex)
- stack_overflow = TRUE;
-
- if (!call_filter)
- call_filter = arch_get_call_filter ();
-
- if (!restore_context)
- restore_context = arch_get_restore_context ();
-
- g_assert (jit_tls->end_of_stack);
- g_assert (jit_tls->abort_func);
-
- if (!test_only) {
- MonoContext ctx_cp = *ctx;
- if (mono_jit_trace_calls != NULL)
- g_print ("EXCEPTION handling: %s\n", mono_object_class (obj)->name);
- if (!mono_arch_handle_exception (&ctx_cp, obj, TRUE)) {
- if (mono_break_on_exc)
- G_BREAKPOINT ();
- mono_unhandled_exception (obj);
- }
- }
-
- initial_ctx = *ctx;
- memset (&rji, 0, sizeof (rji));
-
- while (1) {
- MonoContext new_ctx;
- char *trace = NULL;
- gboolean need_trace = FALSE;
- guint32 free_stack;
-
- if (test_only && (frame_count < 1000))
- need_trace = TRUE;
-
- ji = mono_arch_find_jit_info (domain, jit_tls, &rji, &rji, ctx, &new_ctx,
- need_trace ? &trace : NULL, &lmf, NULL, NULL);
- if (!ji) {
- g_warning ("Exception inside function without unwind info");
- g_assert_not_reached ();
- }
-
- if (ji != (gpointer)-1) {
- frame_count ++;
- //printf ("M: %s %p %p %d.\n", mono_method_full_name (ji->method, TRUE), jit_tls->end_of_stack, ctx->ebp, count);
-
- if (test_only && ji->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE && mono_ex) {
- char *tmp, *strace;
-
- /* Avoid giant stack traces */
- if (frame_count < 1000) {
- trace_ips = g_list_append (trace_ips, MONO_CONTEXT_GET_IP (ctx));
-
- if (!mono_ex->stack_trace)
- strace = g_strdup ("");
- else
- strace = mono_string_to_utf8 (mono_ex->stack_trace);
-
- tmp = g_strdup_printf ("%s%s\n", strace, trace);
- g_free (strace);
-
- mono_ex->stack_trace = mono_string_new (domain, tmp);
-
- g_free (tmp);
- }
- }
-
- if (stack_overflow)
- free_stack = (guint8*)(MONO_CONTEXT_GET_BP (ctx)) - (guint8*)(MONO_CONTEXT_GET_BP (&initial_ctx));
- else
- free_stack = 0xffffff;
-
- /*
- * During stack overflow, wait till the unwinding frees some stack
- * space before running handlers/finalizers.
- */
- if ((free_stack > (64 * 1024)) && ji->num_clauses) {
- int i;
-
- g_assert (ji->clauses);
-
- for (i = 0; i < ji->num_clauses; i++) {
- MonoJitExceptionInfo *ei = &ji->clauses [i];
-
- if (ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
- MONO_CONTEXT_GET_IP (ctx) <= ei->try_end) {
- /* catch block */
-
- if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE) || (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER)) {
- /* store the exception object int cfg->excvar */
- g_assert (ji->exvar_offset);
- *((gpointer *)((char *)MONO_CONTEXT_GET_BP (ctx) + ji->exvar_offset)) = obj;
- }
-
- if ((ei->flags == MONO_EXCEPTION_CLAUSE_NONE &&
- mono_object_isinst (obj, mono_class_get (ji->method->klass->image, ei->data.token))) ||
- ((ei->flags == MONO_EXCEPTION_CLAUSE_FILTER &&
- call_filter (ctx, ei->data.filter)))) {
- if (test_only) {
- if (mono_ex)
- mono_ex->trace_ips = glist_to_array (trace_ips);
- g_list_free (trace_ips);
- g_free (trace);
-
- if (gc_disabled)
- mono_gc_enable ();
- return TRUE;
- }
- if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method))
- g_print ("EXCEPTION: catch found at clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
- MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
- jit_tls->lmf = lmf;
- g_free (trace);
-
- if (gc_disabled)
- mono_gc_enable ();
- return 0;
- }
- if (!test_only && ei->try_start <= MONO_CONTEXT_GET_IP (ctx) &&
- MONO_CONTEXT_GET_IP (ctx) < ei->try_end &&
- (ei->flags & MONO_EXCEPTION_CLAUSE_FINALLY)) {
- if (mono_jit_trace_calls != NULL && mono_trace_eval (ji->method))
- g_print ("EXCEPTION: finally clause %d of %s\n", i, mono_method_full_name (ji->method, TRUE));
- call_filter (ctx, ei->handler_start);
- }
-
- }
- }
- }
- }
-
- g_free (trace);
-
- *ctx = new_ctx;
-
- if ((ji == (gpointer)-1) || MONO_CONTEXT_GET_BP (ctx) >= jit_tls->end_of_stack) {
- if (gc_disabled)
- mono_gc_enable ();
-
- if (!test_only) {
- jit_tls->lmf = lmf;
-
- if (IS_ON_SIGALTSTACK (jit_tls)) {
- /* Switch back to normal stack */
- if (stack_overflow)
- /* Free up some stack space */
- initial_ctx.SC_ESP += (64 * 1024);
- initial_ctx.SC_EIP = (unsigned int)jit_tls->abort_func;
- restore_context (&initial_ctx);
- }
- else
- jit_tls->abort_func (obj);
- g_assert_not_reached ();
- } else {
- if (mono_ex)
- mono_ex->trace_ips = glist_to_array (trace_ips);
- g_list_free (trace_ips);
- return FALSE;
- }
- }
- }
-
- g_assert_not_reached ();