}
return 0;
}
+
+ public class MyException : Exception {
+ public int marker = 0;
+ public string res = "";
+
+ public MyException (String res) {
+ this.res = res;
+ }
+
+ public bool FilterWithoutState () {
+ return this.marker == 0x666;
+ }
+
+ public bool FilterWithState () {
+ bool ret = this.marker == 0x566;
+ this.marker += 0x100;
+ return ret;
+ }
+
+ public bool FilterWithStringState () {
+ bool ret = this.marker == 0x777;
+ this.res = "fromFilter_" + this.res;
+ return ret;
+ }
+ }
+
+ public static int test_1_basic_filter_catch () {
+ try {
+ MyException e = new MyException ("");
+ e.marker = 0x1337;
+ throw e;
+ } catch (MyException ex) when (ex.marker == 0x1337) {
+ return 1;
+ }
+ return 0;
+ }
+
+ public static int test_1234_complicated_filter_catch () {
+ string res = "init";
+ try {
+ MyException e = new MyException (res);
+ e.marker = 0x566;
+ try {
+ try {
+ throw e;
+ } catch (MyException ex) when (ex.FilterWithoutState ()) {
+ res = "WRONG_" + res;
+ } finally {
+ e.marker = 0x777;
+ res = "innerFinally_" + res;
+ }
+ } catch (MyException ex) when (ex.FilterWithState ()) {
+ res = "2ndcatch_" + res;
+ }
+ // "2ndcatch_innerFinally_init"
+ // Console.WriteLine ("res1: " + res);
+ e.res = res;
+ throw e;
+ } catch (MyException ex) when (ex.FilterWithStringState ()) {
+ res = "fwos_" + ex.res;
+ } finally {
+ res = "outerFinally_" + res;
+ }
+ // Console.WriteLine ("res2: " + res);
+ return "outerFinally_fwos_fromFilter_2ndcatch_innerFinally_init" == res ? 1234 : 0;
+ }
}
#if !__MOBILE__
#define MINT_IN_DEFAULT default:
#endif
+static void
+ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context);
+
static void
-ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
+ves_exec_method_with_context_with_ip (MonoInvocation *frame, ThreadContext *context, unsigned short *start_with_ip, MonoException *filter_exception)
{
MonoInvocation child_frame;
GSList *finally_ips = NULL;
}
rtm = frame->runtime_method;
- frame->args = alloca (rtm->alloca_size);
- memset (frame->args, 0, rtm->alloca_size);
-
- sp = frame->stack = (stackval *)((char *)frame->args + rtm->args_size);
- memset (sp, 0, rtm->stack_size);
+ if (!start_with_ip ) {
+ frame->args = alloca (rtm->alloca_size);
+ memset (frame->args, 0, rtm->alloca_size);
+ ip = rtm->code;
+ } else {
+ ip = start_with_ip;
+ }
+ sp = frame->stack = (stackval *) ((char *) frame->args + rtm->args_size);
vt_sp = (unsigned char *) sp + rtm->stack_size;
- memset (vt_sp, 0, rtm->vt_stack_size);
#if DEBUG_INTERP
vtalloc = vt_sp;
#endif
-
locals = (unsigned char *) vt_sp + rtm->vt_stack_size;
- memset (vt_sp, 0, rtm->locals_size);
-
child_frame.parent = frame;
- /* ready to go */
- ip = rtm->code;
+ if (filter_exception) {
+ sp->data.p = filter_exception;
+ sp++;
+ }
/*
* using while (ip < end) may result in a 15% performance drop,
++ip;
MINT_IN_BREAK;
}
-#if 0
- MINT_IN_CASE(MINT_ENDFILTER) ves_abort(); MINT_IN_BREAK;
-#endif
+ MINT_IN_CASE(MINT_ENDFILTER)
+ /* top of stack is result of filter */
+ frame->retval = &sp [-1];
+ goto exit_frame;
MINT_IN_CASE(MINT_INITOBJ)
--sp;
memset (sp->data.vt, 0, READ32(ip + 1));
inv->ex_handler = NULL; /* clear this in case we are trhowing an exception while handling one - this one wins */
for (i = 0; i < inv->runtime_method->num_clauses; ++i) {
clause = &inv->runtime_method->clauses [i];
- if (clause->flags <= 1 && MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
- if (!clause->flags) {
- MonoObject *isinst_obj = mono_object_isinst_checked ((MonoObject*)frame->ex, clause->data.catch_class, &error);
- mono_error_cleanup (&error); /* FIXME: don't swallow the error */
- if (isinst_obj) {
- /*
- * OK, we found an handler, now we need to execute the finally
- * and fault blocks before branching to the handler code.
- */
- inv->ex_handler = clause;
#if DEBUG_INTERP
- if (tracing)
- g_print ("* Found handler at '%s'\n", method->name);
+ g_print ("* clause [%d]: %p\n", i, clause);
+#endif
+ if (!MONO_OFFSET_IN_CLAUSE (clause, ip_offset)) {
+ continue;
+ }
+ if (clause->flags == MONO_EXCEPTION_CLAUSE_FILTER) {
+#if DEBUG_INTERP
+ if (tracing)
+ g_print ("* Filter found at '%s'\n", method->name);
+#endif
+ MonoInvocation dup_frame;
+ stackval retval;
+ memcpy (&dup_frame, inv, sizeof (MonoInvocation));
+ dup_frame.retval = &retval;
+ ves_exec_method_with_context_with_ip (&dup_frame, context, inv->runtime_method->code + clause->data.filter_offset, frame->ex);
+ if (dup_frame.retval->data.i) {
+#if DEBUG_INTERP
+ if (tracing)
+ g_print ("* Matched Filter at '%s'\n", method->name);
+#endif
+ inv->ex_handler = clause;
+ goto handle_finally;
+ }
+ } else if (clause->flags == MONO_EXCEPTION_CLAUSE_NONE) {
+ MonoObject *isinst_obj = mono_object_isinst_checked ((MonoObject*)frame->ex, clause->data.catch_class, &error);
+ mono_error_cleanup (&error); /* FIXME: don't swallow the error */
+ if (isinst_obj) {
+ /*
+ * OK, we found an handler, now we need to execute the finally
+ * and fault blocks before branching to the handler code.
+ */
+#if DEBUG_INTERP
+ if (tracing)
+ g_print ("* Found handler at '%s'\n", method->name);
#endif
- goto handle_finally;
- }
- } else {
- g_error ("FIXME: handle filter clause");
+ inv->ex_handler = clause;
+ goto handle_finally;
}
}
}
DEBUG_LEAVE ();
}
+static void
+ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
+{
+ ves_exec_method_with_context_with_ip (frame, context, NULL, NULL);
+}
+
void
ves_exec_method (MonoInvocation *frame)
{
td.stack_state [c->handler_offset] = g_malloc0(sizeof(StackInfo));
td.stack_state [c->handler_offset][0].type = STACK_TYPE_O;
td.stack_state [c->handler_offset][0].klass = NULL; /*FIX*/
+
+ if (c->flags & MONO_EXCEPTION_CLAUSE_FILTER) {
+ td.stack_height [c->data.filter_offset] = 0;
+ td.vt_stack_size [c->data.filter_offset] = 0;
+ td.is_bb_start [c->data.filter_offset] = 1;
+
+ td.stack_height [c->data.filter_offset] = 1;
+ td.stack_state [c->data.filter_offset] = g_malloc0(sizeof(StackInfo));
+ td.stack_state [c->data.filter_offset][0].type = STACK_TYPE_O;
+ td.stack_state [c->data.filter_offset][0].klass = NULL; /*FIX*/
+ }
}
td.ip = header->code;
break;
#if 0
case CEE_UNUSED57: ves_abort(); break;
- case CEE_ENDFILTER: ves_abort(); break;
#endif
+ case CEE_ENDFILTER:
+ ADD_CODE (&td, MINT_ENDFILTER);
+ ++td.ip;
+ break;
case CEE_UNALIGNED_:
++td.ip;
/* FIX: should do something? */;
end_off = c->handler_offset + c->handler_len;
c->handler_offset = td.in_offsets [c->handler_offset];
c->handler_len = td.in_offsets [end_off] - c->handler_offset;
+ if (c->flags & MONO_EXCEPTION_CLAUSE_FILTER)
+ c->data.filter_offset = td.in_offsets [c->data.filter_offset];
}
rtm->vt_stack_size = td.max_vt_sp;
rtm->alloca_size = rtm->locals_size + rtm->args_size + rtm->vt_stack_size + rtm->stack_size;