Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac2
-rw-r--r--mcs/class/referencesource/mscorlib/system/exception.cs2
-rw-r--r--mono/cil/cil-opcodes.xml1
-rw-r--r--mono/cil/opcode.def1
-rw-r--r--mono/metadata/marshal-ilgen.c10
-rw-r--r--mono/metadata/mono-basic-block.c1
-rw-r--r--mono/metadata/object-internals.h1
-rw-r--r--mono/mini/aot-compiler.c4
-rw-r--r--mono/mini/aot-runtime.c4
-rw-r--r--mono/mini/exceptions-amd64.c37
-rw-r--r--mono/mini/exceptions-arm.c49
-rw-r--r--mono/mini/exceptions-arm64.c29
-rw-r--r--mono/mini/exceptions-mips.c36
-rw-r--r--mono/mini/exceptions-ppc.c32
-rw-r--r--mono/mini/exceptions-s390x.c44
-rw-r--r--mono/mini/exceptions-sparc.c31
-rw-r--r--mono/mini/exceptions-wasm.c14
-rw-r--r--mono/mini/exceptions-x86.c36
-rw-r--r--mono/mini/interp/interp.c17
-rw-r--r--mono/mini/interp/mintops.def1
-rw-r--r--mono/mini/interp/transform.c6
-rw-r--r--mono/mini/method-to-ir.c20
-rw-r--r--mono/mini/mini-amd64.h2
-rw-r--r--mono/mini/mini-arm.h2
-rw-r--r--mono/mini/mini-arm64.h2
-rw-r--r--mono/mini/mini-exceptions.c28
-rw-r--r--mono/mini/mini-ppc.h2
-rw-r--r--mono/mini/mini-runtime.c4
-rw-r--r--mono/mini/mini-x86.h2
-rw-r--r--mono/mini/mini.h3
-rw-r--r--mono/mini/tramp-amd64.c4
-rw-r--r--mono/mini/tramp-arm.c4
-rw-r--r--mono/mini/tramp-arm64.c4
-rw-r--r--mono/mini/tramp-ppc.c2
-rw-r--r--mono/mini/tramp-s390x.c4
-rw-r--r--mono/mini/tramp-x86.c4
-rwxr-xr-xmono/tests/Makefile.am1
-rw-r--r--mono/tests/exception-invokes.cs81
38 files changed, 441 insertions, 86 deletions
diff --git a/configure.ac b/configure.ac
index 2534325a4d3..e613781e48b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -46,7 +46,7 @@ MONO_VERSION_BUILD=`echo $VERSION | cut -d . -f 3`
# There is no ordering of corlib versions, no old or new,
# the runtime expects an exact match.
#
-MONO_CORLIB_VERSION=BEAF66F4-BA36-44C5-974E-83C6F627DF8C
+MONO_CORLIB_VERSION=E06DCE2D-7852-4BBA-AD9F-54D67EEF1FF9
#
# Put a quoted #define in config.h.
diff --git a/mcs/class/referencesource/mscorlib/system/exception.cs b/mcs/class/referencesource/mscorlib/system/exception.cs
index ba3e49e67b2..ac0d1fc6ba1 100644
--- a/mcs/class/referencesource/mscorlib/system/exception.cs
+++ b/mcs/class/referencesource/mscorlib/system/exception.cs
@@ -978,6 +978,8 @@ namespace System {
// Mono addition: Used on iPhone
IntPtr[] native_trace_ips;
+
+ int caught_in_unmanaged;
#endif
// See clr\src\vm\excep.h's EXCEPTION_COMPLUS definition:
diff --git a/mono/cil/cil-opcodes.xml b/mono/cil/cil-opcodes.xml
index c779880212d..f65b16d5c89 100644
--- a/mono/cil/cil-opcodes.xml
+++ b/mono/cil/cil-opcodes.xml
@@ -323,4 +323,5 @@
<opcode name="mono_get_rgctx_arg" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1C" flow="next" />
<opcode name="mono_ldptr_profiler_allocation_count" input="Pop0" output="PushI" args="InlineNone" o1="0xF0" o2="0x1D" flow="next" />
<opcode name="mono_ld_delegate_method_ptr" input="Pop1" output="PushI" args="InlineNone" o1="0xF0" o2="0x1E" flow="next" />
+<opcode name="mono_rethrow" input="PopRef" output="Push0" args="InlineNone" o1="0xF0" o2="0x1F" flow="throw" type="Objmodel" />
</opdesc>
diff --git a/mono/cil/opcode.def b/mono/cil/opcode.def
index b27d16e6217..99e7be8195a 100644
--- a/mono/cil/opcode.def
+++ b/mono/cil/opcode.def
@@ -323,6 +323,7 @@ OPDEF(CEE_MONO_GET_LAST_ERROR, "mono_get_last_error", Pop0, PushI, InlineNone, 0
OPDEF(CEE_MONO_GET_RGCTX_ARG, "mono_get_rgctx_arg", Pop0, PushI, InlineNone, 0, 2, 0xF0, 0x1C, NEXT)
OPDEF(CEE_MONO_LDPTR_PROFILER_ALLOCATION_COUNT, "mono_ldptr_profiler_allocation_count", Pop0, PushI, InlineNone, 0, 2, 0xF0, 0x1D, NEXT)
OPDEF(CEE_MONO_LD_DELEGATE_METHOD_PTR, "mono_ld_delegate_method_ptr", Pop1, PushI, InlineNone, 0, 2, 0xF0, 0x1E, NEXT)
+OPDEF(CEE_MONO_RETHROW, "mono_rethrow", PopRef, Push0, InlineNone, 0, 2, 0xF0, 0x1F, ERROR)
#ifndef OPALIAS
#define _MONO_CIL_OPALIAS_DEFINED_
#define OPALIAS(a,s,r)
diff --git a/mono/metadata/marshal-ilgen.c b/mono/metadata/marshal-ilgen.c
index 200f38d9c2e..7f475e26fd0 100644
--- a/mono/metadata/marshal-ilgen.c
+++ b/mono/metadata/marshal-ilgen.c
@@ -1172,7 +1172,15 @@ emit_thread_interrupt_checkpoint_call (MonoMethodBuilder *mb, gpointer checkpoin
/* Throw the exception returned by the checkpoint function, if any */
mono_mb_emit_byte (mb, CEE_DUP);
pos_noex = mono_mb_emit_branch (mb, CEE_BRFALSE);
- mono_mb_emit_byte (mb, CEE_THROW);
+
+ mono_mb_emit_byte (mb, CEE_DUP);
+ mono_mb_emit_ldflda (mb, MONO_STRUCT_OFFSET (MonoException, caught_in_unmanaged));
+ mono_mb_emit_byte (mb, CEE_LDC_I4_1);
+ mono_mb_emit_byte (mb, CEE_STIND_I4);
+
+ mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
+ mono_mb_emit_byte (mb, CEE_MONO_RETHROW);
+
mono_mb_patch_branch (mb, pos_noex);
mono_mb_emit_byte (mb, CEE_POP);
diff --git a/mono/metadata/mono-basic-block.c b/mono/metadata/mono-basic-block.c
index b74ccd1f036..a19d445fe84 100644
--- a/mono/metadata/mono-basic-block.c
+++ b/mono/metadata/mono-basic-block.c
@@ -324,6 +324,7 @@ mono_opcode_has_static_branch (int opcode)
case MONO_CEE_THROW:
case MONO_CEE_RETHROW:
case MONO_CEE_ENDFINALLY:
+ case MONO_CEE_MONO_RETHROW:
return TRUE;
}
return FALSE;
diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h
index c260a123eaf..13c7cf1d832 100644
--- a/mono/metadata/object-internals.h
+++ b/mono/metadata/object-internals.h
@@ -268,6 +268,7 @@ struct _MonoException {
MonoObject *serialization_manager;
MonoObject *captured_traces;
MonoArray *native_trace_ips;
+ gint32 caught_in_unmanaged;
};
typedef struct {
diff --git a/mono/mini/aot-compiler.c b/mono/mini/aot-compiler.c
index ff6b09de995..6ae89d652a1 100644
--- a/mono/mini/aot-compiler.c
+++ b/mono/mini/aot-compiler.c
@@ -7056,6 +7056,10 @@ emit_trampolines (MonoAotCompile *acfg)
emit_trampoline (acfg, acfg->got_offset, info);
mono_tramp_info_free (info);
+ mono_arch_get_rethrow_preserve_exception (&info, TRUE);
+ emit_trampoline (acfg, acfg->got_offset, info);
+ mono_tramp_info_free (info);
+
mono_arch_get_throw_corlib_exception (&info, TRUE);
emit_trampoline (acfg, acfg->got_offset, info);
mono_tramp_info_free (info);
diff --git a/mono/mini/aot-runtime.c b/mono/mini/aot-runtime.c
index 3c31eae4a2d..ad469fb69bb 100644
--- a/mono/mini/aot-runtime.c
+++ b/mono/mini/aot-runtime.c
@@ -5315,6 +5315,8 @@ load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **ou
target = (gpointer)mono_exception_from_token;
} else if (!strcmp (ji->data.name, "mono_throw_exception")) {
target = (gpointer)mono_get_throw_exception ();
+ } else if (!strcmp (ji->data.name, "mono_rethrow_preserve_exception")) {
+ target = (gpointer)mono_get_rethrow_preserve_exception ();
} else if (strstr (ji->data.name, "trampoline_func_") == ji->data.name) {
MonoTrampolineType tramp_type2 = (MonoTrampolineType)atoi (ji->data.name + strlen ("trampoline_func_"));
target = (gpointer)mono_get_trampoline_func (tramp_type2);
@@ -5333,6 +5335,8 @@ load_function_full (MonoAotModule *amodule, const char *name, MonoTrampInfo **ou
target = (gpointer)mini_get_dbg_callbacks ()->breakpoint_from_context;
} else if (!strcmp (ji->data.name, "throw_exception_addr")) {
target = mono_get_throw_exception_addr ();
+ } else if (!strcmp (ji->data.name, "rethrow_preserve_exception_addr")) {
+ target = mono_get_rethrow_preserve_exception_addr ();
} else if (strstr (ji->data.name, "generic_trampoline_")) {
target = mono_aot_get_trampoline (ji->data.name);
} else if (aot_jit_icall_hash && g_hash_table_lookup (aot_jit_icall_hash, ji->data.name)) {
diff --git a/mono/mini/exceptions-amd64.c b/mono/mini/exceptions-amd64.c
index 006dab03e21..1cefe97f180 100644
--- a/mono/mini/exceptions-amd64.c
+++ b/mono/mini/exceptions-amd64.c
@@ -378,7 +378,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
void
mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
guint64 dummy5, guint64 dummy6,
- MonoContext *mctx, MonoObject *exc, gboolean rethrow)
+ MonoContext *mctx, MonoObject *exc, gboolean rethrow, gboolean preserve_ips)
{
ERROR_DECL (error);
MonoContext ctx;
@@ -391,6 +391,8 @@ mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guin
if (!rethrow) {
mono_ex->stack_trace = NULL;
mono_ex->trace_ips = NULL;
+ } else if (preserve_ips) {
+ mono_ex->caught_in_unmanaged = TRUE;
}
}
mono_error_assert_ok (error);
@@ -418,7 +420,7 @@ mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy
/* Negate the ip adjustment done in mono_amd64_throw_exception () */
mctx->gregs [AMD64_RIP] += 1;
- mono_amd64_throw_exception (dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, mctx, (MonoObject*)ex, FALSE);
+ mono_amd64_throw_exception (dummy1, dummy2, dummy3, dummy4, dummy5, dummy6, mctx, (MonoObject*)ex, FALSE, FALSE);
}
void
@@ -443,7 +445,7 @@ mono_amd64_resume_unwind (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint6
* mono_amd64_throw_corlib_exception.
*/
static gpointer
-get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, const char *tramp_name, gboolean aot)
+get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, const char *tramp_name, gboolean aot, gboolean preserve_ips)
{
guint8* start;
guint8 *code;
@@ -486,6 +488,7 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
arg_offsets [0] = dummy_stack_space + 0;
arg_offsets [1] = dummy_stack_space + sizeof(mgreg_t);
arg_offsets [2] = dummy_stack_space + sizeof(mgreg_t) * 2;
+ arg_offsets [3] = dummy_stack_space + sizeof(mgreg_t) * 3;
ctx_offset = dummy_stack_space + sizeof(mgreg_t) * 4;
regs_offset = ctx_offset + MONO_STRUCT_OFFSET (MonoContext, gregs);
@@ -521,6 +524,9 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
amd64_mov_membase_reg (code, AMD64_RSP, arg_offsets [2], AMD64_ARG_REG2, sizeof(mgreg_t));
} else {
amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [2], rethrow, sizeof(mgreg_t));
+
+ /* Set arg4 == preserve_ips */
+ amd64_mov_membase_imm (code, AMD64_RSP, arg_offsets [3], preserve_ips, sizeof(mgreg_t));
}
if (aot) {
@@ -562,13 +568,19 @@ get_throw_trampoline (MonoTrampInfo **info, gboolean rethrow, gboolean corlib, g
gpointer
mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline (info, FALSE, FALSE, FALSE, FALSE, "throw_exception", aot);
+ return get_throw_trampoline (info, FALSE, FALSE, FALSE, FALSE, "throw_exception", aot, FALSE);
}
gpointer
mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline (info, TRUE, FALSE, FALSE, FALSE, "rethrow_exception", aot);
+ return get_throw_trampoline (info, TRUE, FALSE, FALSE, FALSE, "rethrow_exception", aot, FALSE);
+}
+
+gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ return get_throw_trampoline (info, TRUE, FALSE, FALSE, FALSE, "rethrow_preserve_exception", aot, TRUE);
}
/**
@@ -584,7 +596,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
gpointer
mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline (info, FALSE, TRUE, FALSE, FALSE, "throw_corlib_exception", aot);
+ return get_throw_trampoline (info, FALSE, TRUE, FALSE, FALSE, "throw_corlib_exception", aot, FALSE);
}
#endif /* !DISABLE_JIT */
@@ -911,13 +923,13 @@ mono_amd64_get_exception_trampolines (gboolean aot)
GSList *tramps = NULL;
/* LLVM needs different throw trampolines */
- get_throw_trampoline (&info, FALSE, TRUE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", aot);
+ get_throw_trampoline (&info, FALSE, TRUE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", aot, FALSE);
tramps = g_slist_prepend (tramps, info);
- get_throw_trampoline (&info, FALSE, TRUE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", aot);
+ get_throw_trampoline (&info, FALSE, TRUE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", aot, FALSE);
tramps = g_slist_prepend (tramps, info);
- get_throw_trampoline (&info, FALSE, TRUE, TRUE, TRUE, "llvm_resume_unwind_trampoline", aot);
+ get_throw_trampoline (&info, FALSE, TRUE, TRUE, TRUE, "llvm_resume_unwind_trampoline", aot, FALSE);
tramps = g_slist_prepend (tramps, info);
return tramps;
@@ -1953,6 +1965,13 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
}
gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ g_assert_not_reached ();
+ return NULL;
+}
+
+gpointer
mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
{
g_assert_not_reached ();
diff --git a/mono/mini/exceptions-arm.c b/mono/mini/exceptions-arm.c
index 94c6dfe3512..ed822d20608 100644
--- a/mono/mini/exceptions-arm.c
+++ b/mono/mini/exceptions-arm.c
@@ -144,7 +144,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
}
void
-mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs)
+mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs, gboolean preserve_ips)
{
ERROR_DECL (error);
MonoContext ctx;
@@ -167,6 +167,8 @@ mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_
if (!rethrow) {
mono_ex->stack_trace = NULL;
mono_ex->trace_ips = NULL;
+ } else if (preserve_ips) {
+ mono_ex->caught_in_unmanaged = TRUE;
}
}
mono_error_assert_ok (error);
@@ -182,7 +184,7 @@ mono_arm_throw_exception_by_token (guint32 ex_token_index, mgreg_t pc, mgreg_t s
/* Clear thumb bit */
pc &= ~1;
- mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs);
+ mono_arm_throw_exception ((MonoObject*)mono_exception_from_token (mono_defaults.corlib, ex_token), pc, sp, int_regs, fp_regs, FALSE);
}
void
@@ -212,7 +214,7 @@ mono_arm_resume_unwind (guint32 dummy1, mgreg_t pc, mgreg_t sp, mgreg_t *int_reg
*
*/
static gpointer
-get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot)
+get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot, gboolean preserve_ips)
{
guint8 *start;
guint8 *code;
@@ -241,8 +243,11 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
}
/* Param area */
- ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, 8);
- cfa_offset += 8;
+ int param_size = 8;
+ if (!resume_unwind && !corlib)
+ param_size += 4; // Extra arg
+ ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, param_size);
+ cfa_offset += param_size;
mono_add_unwind_op_def_cfa_offset (unwind_ops, code, start, cfa_offset);
/* call throw_exception (exc, ip, sp, int_regs, fp_regs) */
@@ -271,9 +276,19 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
}
/* int regs */
ARM_ADD_REG_IMM8 (code, ARMREG_R3, ARMREG_SP, (cfa_offset - (MONO_ARM_NUM_SAVED_REGS * sizeof (mgreg_t))));
- /* fp regs */
- ARM_ADD_REG_IMM8 (code, ARMREG_LR, ARMREG_SP, 8);
- ARM_STR_IMM (code, ARMREG_LR, ARMREG_SP, 0);
+ if (resume_unwind || corlib) {
+ /* fp regs */
+ ARM_ADD_REG_IMM8 (code, ARMREG_LR, ARMREG_SP, 8);
+ ARM_STR_IMM (code, ARMREG_LR, ARMREG_SP, 0);
+ } else {
+ /* preserve_ips */
+ ARM_MOV_REG_IMM8 (code, ARMREG_R5, preserve_ips);
+ ARM_STR_IMM (code, ARMREG_R5, ARMREG_SP, 4);
+
+ /* fp regs */
+ ARM_ADD_REG_IMM8 (code, ARMREG_LR, ARMREG_SP, 8);
+ ARM_STR_IMM (code, ARMREG_LR, ARMREG_SP, 0);
+ }
if (aot) {
const char *icall_name;
@@ -323,7 +338,7 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
gpointer
mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline (132, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot);
+ return get_throw_trampoline (132, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot, FALSE);
}
/**
@@ -337,7 +352,13 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
gpointer
mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline (132, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot);
+ return get_throw_trampoline (132, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot, FALSE);
+}
+
+gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ return get_throw_trampoline (132, FALSE, TRUE, FALSE, FALSE, "rethrow_preserve_exception", info, aot, TRUE);
}
/**
@@ -353,7 +374,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
gpointer
mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot);
+ return get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot, FALSE);
}
GSList*
@@ -363,13 +384,13 @@ mono_arm_get_exception_trampolines (gboolean aot)
GSList *tramps = NULL;
/* LLVM uses the normal trampolines, but with a different name */
- get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot);
+ get_throw_trampoline (168, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot, FALSE);
tramps = g_slist_prepend (tramps, info);
- get_throw_trampoline (168, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot);
+ get_throw_trampoline (168, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot, FALSE);
tramps = g_slist_prepend (tramps, info);
- get_throw_trampoline (168, FALSE, FALSE, FALSE, TRUE, "llvm_resume_unwind_trampoline", &info, aot);
+ get_throw_trampoline (168, FALSE, FALSE, FALSE, TRUE, "llvm_resume_unwind_trampoline", &info, aot, FALSE);
tramps = g_slist_prepend (tramps, info);
return tramps;
diff --git a/mono/mini/exceptions-arm64.c b/mono/mini/exceptions-arm64.c
index 04e301b030d..15ebd08283d 100644
--- a/mono/mini/exceptions-arm64.c
+++ b/mono/mini/exceptions-arm64.c
@@ -161,7 +161,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
}
static gpointer
-get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot)
+get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm, gboolean resume_unwind, const char *tramp_name, MonoTrampInfo **info, gboolean aot, gboolean preserve_ips)
{
guint8 *start, *code;
MonoJumpInfo *ji = NULL;
@@ -223,6 +223,11 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
arm_movzx (code, ARMREG_R4, corlib ? 1 : 0, 0);
/* Arg 6 = rethrow */
arm_movzx (code, ARMREG_R5, rethrow ? 1 : 0, 0);
+ if (!resume_unwind) {
+ /* Arg 7 = preserve_ips */
+ arm_movzx (code, ARMREG_R6, preserve_ips ? 1 : 0, 0);
+ }
+
/* Call the function */
if (aot) {
const char *icall_name;
@@ -260,19 +265,25 @@ get_throw_trampoline (int size, gboolean corlib, gboolean rethrow, gboolean llvm
gpointer
mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline (256, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot);
+ return get_throw_trampoline (256, FALSE, FALSE, FALSE, FALSE, "throw_exception", info, aot, FALSE);
}
gpointer
mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline (256, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot);
+ return get_throw_trampoline (256, FALSE, TRUE, FALSE, FALSE, "rethrow_exception", info, aot, FALSE);
+}
+
+gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ return get_throw_trampoline (256, FALSE, TRUE, FALSE, FALSE, "rethrow_preserve_exception", info, aot, TRUE);
}
gpointer
mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot);
+ return get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "throw_corlib_exception", info, aot, FALSE);
}
GSList*
@@ -282,13 +293,13 @@ mono_arm_get_exception_trampolines (gboolean aot)
GSList *tramps = NULL;
/* LLVM uses the normal trampolines, but with a different name */
- get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot);
+ get_throw_trampoline (256, TRUE, FALSE, FALSE, FALSE, "llvm_throw_corlib_exception_trampoline", &info, aot, FALSE);
tramps = g_slist_prepend (tramps, info);
- get_throw_trampoline (256, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot);
+ get_throw_trampoline (256, TRUE, FALSE, TRUE, FALSE, "llvm_throw_corlib_exception_abs_trampoline", &info, aot, FALSE);
tramps = g_slist_prepend (tramps, info);
- get_throw_trampoline (256, FALSE, FALSE, FALSE, TRUE, "llvm_resume_unwind_trampoline", &info, aot);
+ get_throw_trampoline (256, FALSE, FALSE, FALSE, TRUE, "llvm_resume_unwind_trampoline", &info, aot, FALSE);
tramps = g_slist_prepend (tramps, info);
return tramps;
@@ -372,7 +383,7 @@ mono_arch_exceptions_init (void)
* FP_REGS points to the 8 callee saved fp regs.
*/
void
-mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow)
+mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow, gboolean preserve_ips)
{
ERROR_DECL (error);
MonoContext ctx;
@@ -403,6 +414,8 @@ mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *
if (!rethrow) {
mono_ex->stack_trace = NULL;
mono_ex->trace_ips = NULL;
+ } else if (preserve_ips) {
+ mono_ex->caught_in_unmanaged = TRUE;
}
}
mono_error_assert_ok (error);
diff --git a/mono/mini/exceptions-mips.c b/mono/mini/exceptions-mips.c
index 9efa0894fb1..195d9b3e20d 100644
--- a/mono/mini/exceptions-mips.c
+++ b/mono/mini/exceptions-mips.c
@@ -177,7 +177,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
}
static void
-throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow)
+throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean rethrow, gboolean preserve_ips)
{
ERROR_DECL (error);
MonoContext ctx;
@@ -203,6 +203,8 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean
if (!rethrow) {
mono_ex->stack_trace = NULL;
mono_ex->trace_ips = NULL;
+ } if (preserve_ips) {
+ mono_ex->catch_in_unmanaged = TRUE;
}
}
mono_error_assert_ok (error);
@@ -227,7 +229,7 @@ throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, gboolean
*
*/
static gpointer
-mono_arch_get_throw_exception_generic (guint8 *start, int size, int corlib, gboolean rethrow)
+mono_arch_get_throw_exception_generic (guint8 *start, int size, int corlib, gboolean rethrow, gboolean preserve_ips)
{
guint8 *code;
int alloc_size, pos, i;
@@ -312,7 +314,31 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
if (inited)
return start;
- mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, TRUE);
+ mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, TRUE, FALSE);
+ inited = 1;
+ return start;
+}
+
+/**
+ * mono_arch_get_rethrow_preserve_exception:
+ * \returns a function pointer which can be used to rethrow
+ * exceptions while avoiding modification of saved trace_ips.
+ * The returned function has the following
+ * signature: void (*func) (MonoException *exc);
+ */
+gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ static guint8 start [GENERIC_EXCEPTION_SIZE];
+ static int inited = 0;
+
+ g_assert (!aot);
+ if (info)
+ *info = NULL;
+
+ if (inited)
+ return start;
+ mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, TRUE, TRUE);
inited = 1;
return start;
}
@@ -341,7 +367,7 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
if (inited)
return start;
- mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, FALSE);
+ mono_arch_get_throw_exception_generic (start, sizeof (start), FALSE, FALSE, FALSE);
inited = 1;
return start;
}
@@ -379,7 +405,7 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
if (inited)
return start;
- mono_arch_get_throw_exception_generic (start, sizeof (start), TRUE, FALSE);
+ mono_arch_get_throw_exception_generic (start, sizeof (start), TRUE, FALSE, FALSE);
inited = 1;
return start;
}
diff --git a/mono/mini/exceptions-ppc.c b/mono/mini/exceptions-ppc.c
index 3483ba835d8..89125df5d05 100644
--- a/mono/mini/exceptions-ppc.c
+++ b/mono/mini/exceptions-ppc.c
@@ -322,7 +322,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
}
void
-mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow)
+mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow, gboolean preserve_ips)
{
ERROR_DECL (error);
MonoContext ctx;
@@ -343,6 +343,8 @@ mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp,
if (!rethrow) {
mono_ex->stack_trace = NULL;
mono_ex->trace_ips = NULL;
+ } else if (preserve_ips) {
+ mono_ex->catch_in_unmanaged = TRUE
}
}
mono_error_assert_ok (error);
@@ -362,7 +364,7 @@ mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp,
*
*/
static gpointer
-mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corlib, gboolean rethrow, gboolean aot)
+mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corlib, gboolean rethrow, gboolean aot, gboolean preserve_ips)
{
guint8 *start, *code;
int alloc_size, pos;
@@ -424,6 +426,7 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corli
pos -= sizeof (gpointer) * MONO_MAX_IREGS;
ppc_addi (code, ppc_r6, ppc_sp, pos);
ppc_li (code, ppc_r8, rethrow);
+ ppc_li (code, ppc_r9, preserve_ips);
if (aot) {
// This can be called from runtime code, which can't guarantee that
@@ -449,12 +452,29 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corli
MONO_PROFILER_RAISE (jit_code_buffer, (start, code - start, MONO_PROFILER_CODE_BUFFER_EXCEPTION_HANDLING, NULL));
if (info)
- *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_exception" : "throw_exception"), start, code - start, ji, unwind_ops);
+ *info = mono_tramp_info_create (corlib ? "throw_corlib_exception" : (rethrow ? "rethrow_preserve_exception" : (rethrow ? "rethrow_exception" : "throw_exception"), start, code - start, ji, unwind_ops);
return start;
}
/**
+ * mono_arch_get_rethrow_preserve_exception:
+ * \returns a function pointer which can be used to rethrow
+ * exceptions and completely preserve trace_ips.
+ * The returned function has the following
+ * signature: void (*func) (MonoException *exc);
+ */
+gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ int size = MONO_PPC_32_64_CASE (132, 224) + PPC_FTNPTR_SIZE;
+
+ if (aot)
+ size += 64;
+ return mono_arch_get_throw_exception_generic (size, info, FALSE, TRUE, aot, TRUE);
+}
+
+/**
* mono_arch_get_rethrow_exception:
* \returns a function pointer which can be used to rethrow
* exceptions. The returned function has the following
@@ -467,7 +487,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
if (aot)
size += 64;
- return mono_arch_get_throw_exception_generic (size, info, FALSE, TRUE, aot);
+ return mono_arch_get_throw_exception_generic (size, info, FALSE, TRUE, aot, FALSE);
}
/**
@@ -489,7 +509,7 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
if (aot)
size += 64;
- return mono_arch_get_throw_exception_generic (size, info, FALSE, FALSE, aot);
+ return mono_arch_get_throw_exception_generic (size, info, FALSE, FALSE, aot, FALSE);
}
/**
@@ -506,7 +526,7 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
if (aot)
size += 64;
- return mono_arch_get_throw_exception_generic (size, info, TRUE, FALSE, aot);
+ return mono_arch_get_throw_exception_generic (size, info, TRUE, FALSE, aot, FALSE);
}
/*
diff --git a/mono/mini/exceptions-s390x.c b/mono/mini/exceptions-s390x.c
index 23fecb60d2e..38b30c792ec 100644
--- a/mono/mini/exceptions-s390x.c
+++ b/mono/mini/exceptions-s390x.c
@@ -27,7 +27,8 @@
#define S390_THROWSTACK_ACCPRM S390_MINIMAL_STACK_SIZE
#define S390_THROWSTACK_FPCPRM (S390_THROWSTACK_ACCPRM+sizeof(gpointer))
-#define S390_THROWSTACK_RETHROW (S390_THROWSTACK_FPCPRM+sizeof(gulong))
+#define S390_THROWSTACK_PRESERVE_IPS (S390_THROWSTACK_FPCPRM+sizeof(gulong))
+#define S390_THROWSTACK_RETHROW (S390_THROWSTACK_PRESERVE_IPS+sizeof(gboolean))
#define S390_THROWSTACK_INTREGS (S390_THROWSTACK_RETHROW+sizeof(gboolean))
#define S390_THROWSTACK_FLTREGS (S390_THROWSTACK_INTREGS+(16*sizeof(gulong)))
#define S390_THROWSTACK_ACCREGS (S390_THROWSTACK_FLTREGS+(16*sizeof(gdouble)))
@@ -72,7 +73,7 @@
static void throw_exception (MonoObject *, unsigned long, unsigned long,
gulong *, gdouble *, gint32 *, guint, gboolean);
static gpointer mono_arch_get_throw_exception_generic (int, MonoTrampInfo **,
- int, gboolean, gboolean);
+ int, gboolean, gboolean, gboolean);
static void handle_signal_exception (gpointer);
/*========================= End of Prototypes ======================*/
@@ -240,7 +241,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
static void
throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp,
gulong *int_regs, gdouble *fp_regs, gint32 *acc_regs,
- guint fpc, gboolean rethrow)
+ guint fpc, gboolean rethrow, gboolean preserve_ips)
{
ERROR_DECL (error);
MonoContext ctx;
@@ -269,6 +270,8 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp,
if (!rethrow) {
mono_ex->stack_trace = NULL;
mono_ex->trace_ips = NULL;
+ } else if (preserve_ips) {
+ mono_ex->catch_in_unmanaged = TRUE
}
}
mono_error_assert_ok (error);
@@ -295,7 +298,7 @@ throw_exception (MonoObject *exc, unsigned long ip, unsigned long sp,
static gpointer
mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info,
- int corlib, gboolean rethrow, gboolean aot)
+ int corlib, gboolean rethrow, gboolean aot, gboolean preserve_ips)
{
guint8 *code, *start;
int alloc_size, pos, i;
@@ -358,6 +361,8 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info,
S390_SET (code, s390_r1, (guint8 *)throw_exception);
s390_lghi (code, s390_r7, rethrow);
s390_stg (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_RETHROW);
+ s390_lghi (code, s390_r7, preserve_ips);
+ s390_stg (code, s390_r7, 0, STK_BASE, S390_THROWSTACK_PRESERVE_IPS);
s390_basr (code, s390_r14, s390_r1);
/* we should never reach this breakpoint */
s390_break (code);
@@ -369,6 +374,7 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info,
if (info)
*info = mono_tramp_info_create (corlib ? "throw_corlib_exception"
: (rethrow ? "rethrow_exception"
+ : (preserve_ips ? "rethrow_preserve_exception"
: "throw_exception"),
start, code - start, ji, unwind_ops);
@@ -396,7 +402,31 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
if (info)
*info = NULL;
- return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, FALSE, aot));
+ return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, FALSE, aot, FALSE));
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/* */
+/* Name - arch_get_rethrow_preserve_exception */
+/* */
+/* Function - Return a function pointer which can be used to */
+/* raise exceptions. This preserves the stored ips. */
+/* The returned function has the */
+/* following signature: */
+/* void (*func) (MonoException *exc); */
+/* */
+/*------------------------------------------------------------------*/
+
+gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ g_assert (!aot);
+ if (info)
+ *info = NULL;
+
+ return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, TRUE, aot, TRUE));
}
/*========================= End of Function ========================*/
@@ -419,7 +449,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
if (info)
*info = NULL;
- return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, TRUE, aot));
+ return (mono_arch_get_throw_exception_generic (SZ_THROW, info, FALSE, TRUE, aot, FALSE));
}
/*========================= End of Function ========================*/
@@ -442,7 +472,7 @@ mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
if (info)
*info = NULL;
- return (mono_arch_get_throw_exception_generic (SZ_THROW, info, TRUE, FALSE, aot));
+ return (mono_arch_get_throw_exception_generic (SZ_THROW, info, TRUE, FALSE, aot, FALSE));
}
/*========================= End of Function ========================*/
diff --git a/mono/mini/exceptions-sparc.c b/mono/mini/exceptions-sparc.c
index fbf7f73392f..4ce3906a648 100644
--- a/mono/mini/exceptions-sparc.c
+++ b/mono/mini/exceptions-sparc.c
@@ -167,7 +167,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
}
static void
-throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow)
+throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow, gboolean preserve_ips)
{
ERROR_DECL (error);
MonoContext ctx;
@@ -187,6 +187,8 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow)
if (!rethrow) {
mono_ex->stack_trace = NULL;
mono_ex->trace_ips = NULL;
+ } else (preserve_ips) {
+ mono_ex->catch_in_unmanaged = NULL;
}
}
mono_error_assert_ok (error);
@@ -197,7 +199,7 @@ throw_exception (MonoObject *exc, gpointer sp, gpointer ip, gboolean rethrow)
}
static gpointer
-get_throw_exception (gboolean rethrow)
+get_throw_exception (gboolean rethrow, gboolean preserve_ips)
{
guint32 *start, *code;
@@ -210,6 +212,7 @@ get_throw_exception (gboolean rethrow)
sparc_mov_reg_reg (code, sparc_fp, sparc_o1);
sparc_mov_reg_reg (code, sparc_i7, sparc_o2);
sparc_set (code, rethrow, sparc_o3);
+ sparc_set (code, preserve_ips, sparc_o3);
sparc_set (code, throw_exception, sparc_o7);
sparc_jmpl (code, sparc_o7, sparc_g0, sparc_callsite);
sparc_nop (code);
@@ -243,7 +246,7 @@ mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
inited = 1;
- start = get_throw_exception (FALSE);
+ start = get_throw_exception (FALSE, FALSE);
return start;
}
@@ -263,7 +266,27 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
inited = 1;
- start = get_throw_exception (TRUE);
+ start = get_throw_exception (TRUE, FALSE);
+
+ return start;
+}
+
+gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ static guint32* start;
+ static int inited = 0;
+
+ g_assert (!aot);
+ if (info)
+ *info = NULL;
+
+ if (inited)
+ return start;
+
+ inited = 1;
+
+ start = get_throw_exception (TRUE, TRUE);
return start;
}
diff --git a/mono/mini/exceptions-wasm.c b/mono/mini/exceptions-wasm.c
index 07abc7a10ee..c6d70a04e33 100644
--- a/mono/mini/exceptions-wasm.c
+++ b/mono/mini/exceptions-wasm.c
@@ -25,6 +25,12 @@ wasm_rethrow_exception (void)
}
static void
+wasm_rethrow_preserve_exception (void)
+{
+ g_error ("wasm_rethrow_preserve_exception");
+}
+
+static void
wasm_throw_corlib_exception (void)
{
g_error ("wasm_throw_corlib_exception");
@@ -81,6 +87,14 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
}
gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ if (info)
+ *info = mono_tramp_info_create ("rethrow_preserve_exception", (guint8*)wasm_rethrow_preserve_exception, 1, NULL, NULL);
+ return (gpointer)wasm_rethrow_exception;
+}
+
+gpointer
mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
{
if (info)
diff --git a/mono/mini/exceptions-x86.c b/mono/mini/exceptions-x86.c
index b2ffd3ff78d..4e2c88f2b12 100644
--- a/mono/mini/exceptions-x86.c
+++ b/mono/mini/exceptions-x86.c
@@ -453,7 +453,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot)
*/
void
mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc,
- mgreg_t eip, gboolean rethrow)
+ mgreg_t eip, gboolean rethrow, gboolean preserve_ips)
{
ERROR_DECL (error);
MonoContext ctx;
@@ -478,6 +478,8 @@ mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc,
if (!rethrow) {
mono_ex->stack_trace = NULL;
mono_ex->trace_ips = NULL;
+ } else if (preserve_ips) {
+ mono_ex->caught_in_unmanaged = TRUE;
}
}
mono_error_assert_ok (error);
@@ -506,7 +508,7 @@ mono_x86_throw_corlib_exception (mgreg_t *regs, guint32 ex_token_index,
/* Negate the ip adjustment done in mono_x86_throw_exception () */
eip += 1;
- mono_x86_throw_exception (regs, (MonoObject*)ex, eip, FALSE);
+ mono_x86_throw_exception (regs, (MonoObject*)ex, eip, FALSE, FALSE);
}
static void
@@ -537,7 +539,7 @@ mono_x86_resume_unwind (mgreg_t *regs, MonoObject *exc,
* which doesn't push the arguments.
*/
static guint8*
-get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, MonoTrampInfo **info, gboolean aot)
+get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolean corlib, gboolean llvm_abs, gboolean resume_unwind, MonoTrampInfo **info, gboolean aot, gboolean preserve_ips)
{
guint8 *start, *code, *labels [16];
int i, stack_size, stack_offset, arg_offsets [5], regs_offset;
@@ -575,7 +577,8 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
arg_offsets [1] = 4;
arg_offsets [2] = 8;
arg_offsets [3] = 12;
- regs_offset = 16;
+ arg_offsets [4] = 16;
+ regs_offset = 20;
/* Save registers */
for (i = 0; i < X86_NREG; ++i)
@@ -651,6 +654,9 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
x86_mov_membase_reg (code, X86_ESP, arg_offsets [3], X86_EAX, 4);
} else {
x86_mov_membase_imm (code, X86_ESP, arg_offsets [3], rethrow, 4);
+
+ /* Set arg4 == preserve_ips */
+ x86_mov_membase_imm (code, X86_ESP, arg_offsets [4], preserve_ips, 4);
}
/* Make the call */
if (aot) {
@@ -697,13 +703,19 @@ get_throw_trampoline (const char *name, gboolean rethrow, gboolean llvm, gboolea
gpointer
mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline ("throw_exception", FALSE, FALSE, FALSE, FALSE, FALSE, info, aot);
+ return get_throw_trampoline ("throw_exception", FALSE, FALSE, FALSE, FALSE, FALSE, info, aot, FALSE);
}
gpointer
mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline ("rethrow_exception", TRUE, FALSE, FALSE, FALSE, FALSE, info, aot);
+ return get_throw_trampoline ("rethrow_exception", TRUE, FALSE, FALSE, FALSE, FALSE, info, aot, FALSE);
+}
+
+gpointer
+mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot)
+{
+ return get_throw_trampoline ("rethrow_preserve_exception", TRUE, FALSE, FALSE, FALSE, FALSE, info, aot, TRUE);
}
/**
@@ -718,7 +730,7 @@ mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot)
gpointer
mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot)
{
- return get_throw_trampoline ("throw_corlib_exception", FALSE, FALSE, TRUE, FALSE, FALSE, info, aot);
+ return get_throw_trampoline ("throw_corlib_exception", FALSE, FALSE, TRUE, FALSE, FALSE, info, aot, FALSE);
}
void
@@ -755,23 +767,23 @@ mono_arch_exceptions_init (void)
}
/* LLVM needs different throw trampolines */
- tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE);
+ tramp = get_throw_trampoline ("llvm_throw_exception_trampoline", FALSE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE, FALSE);
mono_register_jit_icall (tramp, "llvm_throw_exception_trampoline", NULL, TRUE);
mono_tramp_info_register (tinfo, NULL);
- tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", TRUE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE);
+ tramp = get_throw_trampoline ("llvm_rethrow_exception_trampoline", TRUE, TRUE, FALSE, FALSE, FALSE, &tinfo, FALSE, FALSE);
mono_register_jit_icall (tramp, "llvm_rethrow_exception_trampoline", NULL, TRUE);
mono_tramp_info_register (tinfo, NULL);
- tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, &tinfo, FALSE);
+ tramp = get_throw_trampoline ("llvm_throw_corlib_exception_trampoline", FALSE, TRUE, TRUE, FALSE, FALSE, &tinfo, FALSE, FALSE);
mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_trampoline", NULL, TRUE);
mono_tramp_info_register (tinfo, NULL);
- tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, &tinfo, FALSE);
+ tramp = get_throw_trampoline ("llvm_throw_corlib_exception_abs_trampoline", FALSE, TRUE, TRUE, TRUE, FALSE, &tinfo, FALSE, FALSE);
mono_register_jit_icall (tramp, "llvm_throw_corlib_exception_abs_trampoline", NULL, TRUE);
mono_tramp_info_register (tinfo, NULL);
- tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, &tinfo, FALSE);
+ tramp = get_throw_trampoline ("llvm_resume_unwind_trampoline", FALSE, FALSE, FALSE, FALSE, TRUE, &tinfo, FALSE, FALSE);
mono_register_jit_icall (tramp, "llvm_resume_unwind_trampoline", NULL, TRUE);
mono_tramp_info_register (tinfo, NULL);
diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c
index e180f4ff6a9..a1b72cadb59 100644
--- a/mono/mini/interp/interp.c
+++ b/mono/mini/interp/interp.c
@@ -5548,6 +5548,23 @@ interp_exec_method_full (InterpFrame *frame, ThreadContext *context, guint16 *st
THROW_EX_GENERAL (*(MonoException**)(frame->locals + exvar_offset), ip - 1, TRUE);
MINT_IN_BREAK;
}
+ MINT_IN_CASE(MINT_MONO_RETHROW) {
+ /*
+ * need to clarify what this should actually do:
+ *
+ * Takes an exception from the stack and rethrows it.
+ * This is useful for wrappers that don't want to have to
+ * use CEE_THROW and lose the exception stacktrace.
+ */
+
+ --sp;
+ frame->ex_handler = NULL;
+ if (!sp->data.p)
+ sp->data.p = mono_get_exception_null_reference ();
+
+ THROW_EX_GENERAL ((MonoException *)sp->data.p, ip, TRUE);
+ MINT_IN_BREAK;
+ }
MINT_IN_CASE(MINT_LD_DELEGATE_METHOD_PTR) {
MonoDelegate *del;
diff --git a/mono/mini/interp/mintops.def b/mono/mini/interp/mintops.def
index 78f1c8563d0..556a3c4ca21 100644
--- a/mono/mini/interp/mintops.def
+++ b/mono/mini/interp/mintops.def
@@ -178,6 +178,7 @@ OPDEF(MINT_LEAVE_S_CHECK, "leave.s.check", 2, MintOpShortBranch)
OPDEF(MINT_THROW, "throw", 1, MintOpNoArgs)
OPDEF(MINT_RETHROW, "rethrow", 2, MintOpUShortInt)
OPDEF(MINT_ENDFINALLY, "endfinally", 2, MintOpNoArgs)
+OPDEF(MINT_MONO_RETHROW, "mono_rethrow", 1, MintOpNoArgs)
OPDEF(MINT_CHECKPOINT, "checkpoint", 1, MintOpNoArgs)
OPDEF(MINT_SAFEPOINT, "safepoint", 1, MintOpNoArgs)
diff --git a/mono/mini/interp/transform.c b/mono/mini/interp/transform.c
index 948dbfac1bf..1fbddf6838b 100644
--- a/mono/mini/interp/transform.c
+++ b/mono/mini/interp/transform.c
@@ -4312,6 +4312,12 @@ generate (MonoMethod *method, MonoMethodHeader *header, InterpMethod *rtm, unsig
case MONO_CUSTOM_PREFIX:
++td->ip;
switch (*td->ip) {
+ case CEE_MONO_RETHROW:
+ CHECK_STACK (td, 1);
+ SIMPLE_OP (td, MINT_MONO_RETHROW);
+ td->sp = td->stack;
+ break;
+
case CEE_MONO_LD_DELEGATE_METHOD_PTR:
--td->sp;
td->ip += 1;
diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c
index 9b3cdc54ab7..0b8734b4755 100644
--- a/mono/mini/method-to-ir.c
+++ b/mono/mini/method-to-ir.c
@@ -11739,6 +11739,26 @@ mono_ldptr:
start_new_bblock = 1;
break;
}
+ case MONO_CEE_MONO_RETHROW: {
+ if (sp [-1]->type != STACK_OBJ)
+ UNVERIFIED;
+
+ MONO_INST_NEW (cfg, ins, OP_RETHROW);
+ --sp;
+ ins->sreg1 = sp [0]->dreg;
+ cfg->cbb->out_of_line = TRUE;
+ MONO_ADD_INS (cfg->cbb, ins);
+ MONO_INST_NEW (cfg, ins, OP_NOT_REACHED);
+ MONO_ADD_INS (cfg->cbb, ins);
+ sp = stack_start;
+
+ link_bblock (cfg, cfg->cbb, end_bblock);
+ start_new_bblock = 1;
+ /* This can complicate code generation for llvm since the return value might not be defined */
+ if (COMPILE_LLVM (cfg))
+ INLINE_FAILURE ("mono_rethrow");
+ break;
+ }
case MONO_CEE_SIZEOF: {
guint32 val;
int ialign;
diff --git a/mono/mini/mini-amd64.h b/mono/mini/mini-amd64.h
index 42c9360a54e..71e276f6216 100644
--- a/mono/mini/mini-amd64.h
+++ b/mono/mini/mini-amd64.h
@@ -501,7 +501,7 @@ mono_amd64_patch (unsigned char* code, gpointer target);
void
mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
guint64 dummy5, guint64 dummy6,
- MonoContext *mctx, MonoObject *exc, gboolean rethrow);
+ MonoContext *mctx, MonoObject *exc, gboolean rethrow, gboolean preserve_ips);
void
mono_amd64_throw_corlib_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
diff --git a/mono/mini/mini-arm.h b/mono/mini/mini-arm.h
index 344659c43a2..e851d6d11b5 100644
--- a/mono/mini/mini-arm.h
+++ b/mono/mini/mini-arm.h
@@ -397,7 +397,7 @@ typedef struct MonoCompileArch {
#define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf)
void
-mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs);
+mono_arm_throw_exception (MonoObject *exc, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs, gboolean preserve_ips);
void
mono_arm_throw_exception_by_token (guint32 type_token, mgreg_t pc, mgreg_t sp, mgreg_t *int_regs, gdouble *fp_regs);
diff --git a/mono/mini/mini-arm64.h b/mono/mini/mini-arm64.h
index 36fba6467eb..f1c7c2e52a4 100644
--- a/mono/mini/mini-arm64.h
+++ b/mono/mini/mini-arm64.h
@@ -258,7 +258,7 @@ guint8* mono_arm_emit_aotconst (gpointer ji, guint8 *code, guint8 *code_start, i
void mono_arm_patch (guint8 *code, guint8 *target, int relocation);
-void mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow);
+void mono_arm_throw_exception (gpointer arg, mgreg_t pc, mgreg_t *int_regs, gdouble *fp_regs, gboolean corlib, gboolean rethrow, gboolean preserve_ips);
void mono_arm_gsharedvt_init (void);
diff --git a/mono/mini/mini-exceptions.c b/mono/mini/mini-exceptions.c
index 292cd06f0ff..8dc5816d792 100644
--- a/mono/mini/mini-exceptions.c
+++ b/mono/mini/mini-exceptions.c
@@ -114,7 +114,7 @@ typedef struct
#define TRACE_IP_ENTRY_SIZE (sizeof (ExceptionTraceIp) / sizeof (gpointer))
static gpointer restore_context_func, call_filter_func;
-static gpointer throw_exception_func, rethrow_exception_func;
+static gpointer throw_exception_func, rethrow_exception_func, rethrow_preserve_exception_func;
static gpointer throw_corlib_exception_func;
static MonoFtnPtrEHCallback ftnptr_eh_callback;
@@ -216,6 +216,7 @@ mono_exceptions_init (void)
call_filter_func = mono_aot_get_trampoline ("call_filter");
throw_exception_func = mono_aot_get_trampoline ("throw_exception");
rethrow_exception_func = mono_aot_get_trampoline ("rethrow_exception");
+ rethrow_preserve_exception_func = mono_aot_get_trampoline ("rethrow_preserve_exception");
} else {
MonoTrampInfo *info;
@@ -227,6 +228,8 @@ mono_exceptions_init (void)
mono_tramp_info_register (info, NULL);
rethrow_exception_func = mono_arch_get_rethrow_exception (&info, FALSE);
mono_tramp_info_register (info, NULL);
+ rethrow_preserve_exception_func = mono_arch_get_rethrow_preserve_exception (&info, FALSE);
+ mono_tramp_info_register (info, NULL);
}
mono_arch_exceptions_init ();
@@ -269,6 +272,13 @@ mono_get_rethrow_exception (void)
}
gpointer
+mono_get_rethrow_preserve_exception (void)
+{
+ g_assert (rethrow_preserve_exception_func);
+ return rethrow_preserve_exception_func;
+}
+
+gpointer
mono_get_call_filter (void)
{
g_assert (call_filter_func);
@@ -318,6 +328,12 @@ mono_get_throw_exception_addr (void)
return &throw_exception_func;
}
+gpointer
+mono_get_rethrow_preserve_exception_addr (void)
+{
+ return &rethrow_preserve_exception_func;
+}
+
static gboolean
is_address_protected (MonoJitInfo *ji, MonoJitExceptionInfo *ei, gpointer ip)
{
@@ -1917,7 +1933,11 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt
if (initial_trace_ips) {
int len = mono_array_length (initial_trace_ips) / TRACE_IP_ENTRY_SIZE;
- for (i = 0; i < (len - 1); i++) {
+ // If we catch in managed/non-wrapper, we don't save the catching frame
+ if (!mono_ex->caught_in_unmanaged)
+ len -= 1;
+
+ for (i = 0; i < len; i++) {
for (int j = 0; j < TRACE_IP_ENTRY_SIZE; ++j) {
gpointer p = mono_array_get (initial_trace_ips, gpointer, (i * TRACE_IP_ENTRY_SIZE) + j);
trace_ips = g_list_prepend (trace_ips, p);
@@ -1925,6 +1945,10 @@ handle_exception_first_pass (MonoContext *ctx, MonoObject *obj, gint32 *out_filt
}
}
+ // Reset the state because we're making it be caught somewhere
+ if (mono_ex->caught_in_unmanaged)
+ MONO_OBJECT_SETREF (mono_ex, caught_in_unmanaged, 0);
+
if (!mono_object_isinst_checked (obj, mono_defaults.exception_class, error)) {
mono_error_assert_ok (error);
mono_ex = NULL;
diff --git a/mono/mini/mini-ppc.h b/mono/mini/mini-ppc.h
index 8308387e8c9..47de3b525c8 100644
--- a/mono/mini/mini-ppc.h
+++ b/mono/mini/mini-ppc.h
@@ -384,7 +384,7 @@ void
mono_ppc_patch (guchar *code, const guchar *target);
void
-mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow);
+mono_ppc_throw_exception (MonoObject *exc, unsigned long eip, unsigned long esp, mgreg_t *int_regs, gdouble *fp_regs, gboolean rethrow, gboolean preserve_ips);
#ifdef __mono_ppc64__
#define MONO_PPC_32_64_CASE(c32,c64) c64
diff --git a/mono/mini/mini-runtime.c b/mono/mini/mini-runtime.c
index 07443a7601e..51b7dc1913a 100644
--- a/mono/mini/mini-runtime.c
+++ b/mono/mini/mini-runtime.c
@@ -3135,8 +3135,10 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
result = runtime_invoke ((MonoObject *)obj, params, exc, info->compiled_method);
}
- if (catchExcInMonoError && *exc != NULL)
+ if (catchExcInMonoError && *exc != NULL) {
+ ((MonoException *)(*exc))->caught_in_unmanaged = TRUE;
mono_error_set_exception_instance (error, (MonoException*) *exc);
+ }
return result;
}
diff --git a/mono/mini/mini-x86.h b/mono/mini/mini-x86.h
index 33e2528553f..23d20b0f1a5 100644
--- a/mono/mini/mini-x86.h
+++ b/mono/mini/mini-x86.h
@@ -330,7 +330,7 @@ mono_x86_get_this_arg_offset (MonoMethodSignature *sig);
void
mono_x86_throw_exception (mgreg_t *regs, MonoObject *exc,
- mgreg_t eip, gboolean rethrow);
+ mgreg_t eip, gboolean rethrow, gboolean preserve_ips);
void
mono_x86_throw_corlib_exception (mgreg_t *regs, guint32 ex_token_index,
diff --git a/mono/mini/mini.h b/mono/mini/mini.h
index c186c1f74f9..1b8f52f49fb 100644
--- a/mono/mini/mini.h
+++ b/mono/mini/mini.h
@@ -2350,6 +2350,7 @@ gpointer mono_arch_get_call_filter (MonoTrampInfo **info, gboolean
gpointer mono_arch_get_restore_context (MonoTrampInfo **info, gboolean aot);
gpointer mono_arch_get_throw_exception (MonoTrampInfo **info, gboolean aot);
gpointer mono_arch_get_rethrow_exception (MonoTrampInfo **info, gboolean aot);
+gpointer mono_arch_get_rethrow_preserve_exception (MonoTrampInfo **info, gboolean aot);
gpointer mono_arch_get_throw_corlib_exception (MonoTrampInfo **info, gboolean aot);
gpointer mono_arch_get_throw_pending_exception (MonoTrampInfo **info, gboolean aot);
gboolean mono_arch_handle_exception (void *sigctx, gpointer obj);
@@ -2461,11 +2462,13 @@ mono_find_jit_info_ext (MonoDomain *domain, MonoJitTlsData *jit_tls,
gpointer mono_get_throw_exception (void);
gpointer mono_get_rethrow_exception (void);
+gpointer mono_get_rethrow_preserve_exception (void);
gpointer mono_get_call_filter (void);
gpointer mono_get_restore_context (void);
gpointer mono_get_throw_exception_by_name (void);
gpointer mono_get_throw_corlib_exception (void);
gpointer mono_get_throw_exception_addr (void);
+gpointer mono_get_rethrow_preserve_exception_addr (void);
ICALL_EXPORT
MonoArray *ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info);
diff --git a/mono/mini/tramp-amd64.c b/mono/mini/tramp-amd64.c
index 49492754b44..002a4f7ed81 100644
--- a/mono/mini/tramp-amd64.c
+++ b/mono/mini/tramp-amd64.c
@@ -520,9 +520,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
*/
if (aot) {
/* Not really a jit icall */
- code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "throw_exception_addr");
+ code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_preserve_exception_addr");
} else {
- amd64_mov_reg_imm (code, AMD64_R11, (guint8*)mono_get_throw_exception_addr ());
+ amd64_mov_reg_imm (code, AMD64_R11, (guint8*)mono_get_rethrow_preserve_exception_addr ());
}
amd64_mov_reg_membase (code, AMD64_R11, AMD64_R11, 0, sizeof(gpointer));
amd64_mov_reg_reg (code, AMD64_ARG_REG1, AMD64_RAX, sizeof(mgreg_t));
diff --git a/mono/mini/tramp-arm.c b/mono/mini/tramp-arm.c
index 129f2d35a20..fa53a53a924 100644
--- a/mono/mini/tramp-arm.c
+++ b/mono/mini/tramp-arm.c
@@ -416,11 +416,11 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
*/
if (aot) {
/* Not really a jit icall */
- code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP, MONO_PATCH_INFO_JIT_ICALL_ADDR, "throw_exception_addr");
+ code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_preserve_exception_addr");
} else {
ARM_LDR_IMM (code, ARMREG_IP, ARMREG_PC, 0);
ARM_B (code, 0);
- *(gpointer*)code = mono_get_throw_exception_addr ();
+ *(gpointer*)code = mono_get_rethrow_preserve_exception_addr ();
code += 4;
}
ARM_LDR_IMM (code, ARMREG_IP, ARMREG_IP, 0);
diff --git a/mono/mini/tramp-arm64.c b/mono/mini/tramp-arm64.c
index 1456a09a428..d4c9606e9ad 100644
--- a/mono/mini/tramp-arm64.c
+++ b/mono/mini/tramp-arm64.c
@@ -303,9 +303,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
*/
if (aot) {
/* Not really a jit icall */
- code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "throw_exception_addr");
+ code = mono_arm_emit_aotconst (&ji, code, buf, ARMREG_IP0, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_preserve_exception_addr");
} else {
- code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)mono_get_throw_exception_addr ());
+ code = mono_arm_emit_imm64 (code, ARMREG_IP0, (guint64)mono_get_rethrow_preserve_exception_addr ());
}
arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, 0);
/* lr contains the return address, the trampoline will use it as the throw site */
diff --git a/mono/mini/tramp-ppc.c b/mono/mini/tramp-ppc.c
index 840ceaaf221..a12e04fc636 100644
--- a/mono/mini/tramp-ppc.c
+++ b/mono/mini/tramp-ppc.c
@@ -424,7 +424,7 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
if (aot) {
g_error ("Not implemented");
} else {
- ppc_load_func (code, PPC_CALL_REG, mono_get_throw_exception_addr ());
+ ppc_load_func (code, PPC_CALL_REG, mono_get_rethrow_preserve_exception_addr ());
ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG);
ppc_mtctr (code, PPC_CALL_REG);
}
diff --git a/mono/mini/tramp-s390x.c b/mono/mini/tramp-s390x.c
index 5e121dc2de0..166b63c1b65 100644
--- a/mono/mini/tramp-s390x.c
+++ b/mono/mini/tramp-s390x.c
@@ -328,9 +328,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
/*
* Exception case:
* We have an exception we want to throw in the caller's frame, so pop
- * the trampoline frame and throw from the caller.
+ * the trampoline frame and throw from the caller.
*/
- S390_SET (buf, s390_r1, (guint *)mono_get_throw_exception_addr ());
+ S390_SET (buf, s390_r1, (guint *)mono_get_rethrow_preserve_exception_addr ());
s390_aghi (buf, STK_BASE, sizeof(trampStack_t));
s390_lg (buf, s390_r1, 0, s390_r1, 0);
s390_lmg (buf, s390_r6, s390_r14, STK_BASE, S390_REG_SAVE_OFFSET);
diff --git a/mono/mini/tramp-x86.c b/mono/mini/tramp-x86.c
index 498a8f810e1..7a87ba67e31 100644
--- a/mono/mini/tramp-x86.c
+++ b/mono/mini/tramp-x86.c
@@ -343,9 +343,9 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf
*/
if (aot) {
/* Not really a jit icall */
- code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "throw_exception_addr");
+ code = mono_arch_emit_load_aotconst (buf, code, &ji, MONO_PATCH_INFO_JIT_ICALL_ADDR, "rethrow_preserve_exception_addr");
} else {
- x86_mov_reg_imm (code, X86_ECX, (guint8*)mono_get_throw_exception_addr ());
+ x86_mov_reg_imm (code, X86_ECX, (guint8*)mono_get_rethrow_preserve_exception_addr ());
}
x86_mov_reg_membase (code, X86_ECX, X86_ECX, 0, sizeof(target_mgreg_t));
x86_jump_reg (code, X86_ECX);
diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am
index 9f005e35490..a08ded3d2f3 100755
--- a/mono/tests/Makefile.am
+++ b/mono/tests/Makefile.am
@@ -307,6 +307,7 @@ TESTS_CS_SRC= \
exception16.cs \
exception17.cs \
exception18.cs \
+ exception-invokes.cs \
exception19.cs \
exception20.cs \
typeload-unaligned.cs \
diff --git a/mono/tests/exception-invokes.cs b/mono/tests/exception-invokes.cs
new file mode 100644
index 00000000000..5d7a6a59328
--- /dev/null
+++ b/mono/tests/exception-invokes.cs
@@ -0,0 +1,81 @@
+using System;
+using System.Linq;
+using System.Runtime.CompilerServices;
+using System.Reflection;
+
+class C
+{
+ const int StepSize = 5;
+ const int Iterations = 8;
+
+ public static void Main ()
+ {
+ AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(HandleException);
+ var args = new object[] {C.Iterations * C.StepSize};
+ typeof (C).GetMethod ("InvokeChain", BindingFlags.NonPublic | BindingFlags.Instance).Invoke (new C (), args);
+ }
+
+ public static void HandleException (object sender, UnhandledExceptionEventArgs e)
+ {
+ var ex = e.ExceptionObject as Exception;
+
+ int iterations = 0;
+ while (ex != null) {
+ string fullTrace = ex.StackTrace;
+
+ string[] frames = fullTrace.Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
+ // Console.WriteLine("Split into {0} lines", frames.Length);
+
+ int count = 0;
+ for (int i=0; i < frames.Length; i++)
+ {
+ var words = frames [i].Split((char []) null, StringSplitOptions.RemoveEmptyEntries);
+ if (words.Length > 1 && words [0] == "at" && words [1].StartsWith("C.InvokeChain"))
+ count++;
+ // Console.WriteLine("Line: {0} {1}", frames [i], words.Length);
+ }
+
+ if (count != 0)
+ {
+ if (count > 1 && count != C.StepSize)
+ {
+ Console.WriteLine("Fail step size");
+ Environment.Exit(1);
+ }
+ if (count == C.StepSize)
+ iterations += 1;
+ }
+
+ ex = ex.InnerException;
+ }
+
+ if (iterations != C.Iterations) {
+ Console.WriteLine ("{0} iterations", iterations);
+ Environment.Exit (1);
+ }
+
+ // Prevents the runtime from printing the exception
+ Environment.Exit (0);
+ }
+
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private void InvokeChain (int depth)
+ {
+ if (depth == 0) {
+ Base ();
+ } else if (depth % C.StepSize == 0) {
+ //Console.WriteLine ("InvokeChain {0} indirect", depth);
+ typeof (C).GetMethod ("InvokeChain", BindingFlags.NonPublic | BindingFlags.Instance).Invoke (this, new object[] {depth - 1});
+ } else {
+ //Console.WriteLine ("InvokeChain {0} direct", depth);
+ InvokeChain (depth - 1);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ private void Base ()
+ {
+ throw new NotImplementedException ();
+ }
+}