From: monojenkins Date: Mon, 24 Feb 2020 09:31:31 +0000 (-0500) Subject: [interp] Use alloca for InterpFrame (#32720) X-Git-Tag: submit/tizen/20210909.063632~9539 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=c415fe33ac14ec47431a70e8936982295f67032a;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [interp] Use alloca for InterpFrame (#32720) This is like https://github.com/mono/mono/pull/19002 but next_free is initialized upon allocation instead of `pop_frame` which is a slight optimization, if it works. Co-authored-by: Jay Krell --- diff --git a/src/mono/mono/eglib/glib.h b/src/mono/mono/eglib/glib.h index 2026f09..073edfc6 100644 --- a/src/mono/mono/eglib/glib.h +++ b/src/mono/mono/eglib/glib.h @@ -291,6 +291,7 @@ gpointer g_try_realloc (gpointer obj, gsize size); #define g_new(type,size) ((type *) g_malloc (sizeof (type) * (size))) #define g_new0(type,size) ((type *) g_malloc0 (sizeof (type)* (size))) #define g_newa(type,size) ((type *) alloca (sizeof (type) * (size))) +#define g_newa0(type,size) ((type *) memset (alloca (sizeof (type) * (size)), 0, sizeof (type) * (size))) #define g_memmove(dest,src,len) memmove (dest, src, len) #define g_renew(struct_type, mem, n_structs) ((struct_type*)g_realloc (mem, sizeof (struct_type) * n_structs)) diff --git a/src/mono/mono/mini/ee.h b/src/mono/mono/mini/ee.h index 1b1bd5a..55efe53 100644 --- a/src/mono/mono/mini/ee.h +++ b/src/mono/mono/mini/ee.h @@ -15,7 +15,7 @@ #ifndef __MONO_EE_H__ #define __MONO_EE_H__ -#define MONO_EE_API_VERSION 0xe +#define MONO_EE_API_VERSION 0xf typedef struct _MonoInterpStackIter MonoInterpStackIter; @@ -51,7 +51,6 @@ typedef gpointer MonoInterpFrameHandle; MONO_EE_CALLBACK (gpointer, frame_get_local, (MonoInterpFrameHandle frame, int pos)) \ MONO_EE_CALLBACK (gpointer, frame_get_this, (MonoInterpFrameHandle frame)) \ MONO_EE_CALLBACK (gpointer, frame_get_res, (MonoInterpFrameHandle frame)) \ - MONO_EE_CALLBACK (gpointer, frame_get_native_stack_addr, (MonoInterpFrameHandle frame)) \ MONO_EE_CALLBACK (void, frame_arg_to_data, (MonoInterpFrameHandle frame, MonoMethodSignature *sig, int index, gpointer data)) \ MONO_EE_CALLBACK (void, data_to_frame_arg, (MonoInterpFrameHandle frame, MonoMethodSignature *sig, int index, gconstpointer data)) \ MONO_EE_CALLBACK (gpointer, frame_arg_to_storage, (MonoInterpFrameHandle frame, MonoMethodSignature *sig, int index)) \ diff --git a/src/mono/mono/mini/interp-stubs.c b/src/mono/mono/mini/interp-stubs.c index 233dda1..3a3db0e 100644 --- a/src/mono/mono/mini/interp-stubs.c +++ b/src/mono/mono/mini/interp-stubs.c @@ -71,13 +71,6 @@ stub_frame_get_res (MonoInterpFrameHandle frame) return NULL; } -static gpointer -stub_frame_get_native_stack_addr (MonoInterpFrameHandle frame) -{ - g_assert_not_reached (); - return NULL; -} - static void stub_start_single_stepping (void) { diff --git a/src/mono/mono/mini/interp/interp-internals.h b/src/mono/mono/mini/interp/interp-internals.h index 93b1290..1396dd7 100644 --- a/src/mono/mono/mini/interp/interp-internals.h +++ b/src/mono/mono/mini/interp/interp-internals.h @@ -114,7 +114,7 @@ typedef struct { } data; } stackval; -typedef struct _InterpFrame InterpFrame; +typedef struct InterpFrame InterpFrame; typedef void (*MonoFuncV) (void); typedef void (*MonoPIFunc) (void *callme, void *margs); @@ -199,16 +199,15 @@ typedef struct { gboolean is_void : 1; } InterpState; -struct _InterpFrame { +struct InterpFrame { InterpFrame *parent; /* parent */ InterpMethod *imethod; /* parent */ - stackval *retval; /* parent */ stackval *stack_args; /* parent */ + stackval *retval; /* parent */ stackval *stack; - /* An address on the native stack associated with the frame, used during EH */ - gpointer native_stack_addr; + InterpFrame *next_free; /* Stack fragments this frame was allocated from */ - StackFragment *iframe_frag, *data_frag; + StackFragment *data_frag; /* exception info */ const unsigned short *ip; /* State saved before calls */ @@ -229,8 +228,6 @@ typedef struct { MonoJitExceptionInfo *handler_ei; /* Exception that is being thrown. Set with rest of resume state */ guint32 exc_gchandle; - /* Stack of InterpFrames */ - FrameStack iframe_stack; /* Stack of frame data */ FrameStack data_stack; } ThreadContext; diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index bb0df2d..874abbe 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -220,30 +220,20 @@ frame_stack_free (FrameStack *stack) } /* - * alloc_frame: + * reinit_frame: * - * Allocate a new frame from the frame stack. + * Reinitialize a frame. */ -static InterpFrame* -alloc_frame (ThreadContext *ctx, gpointer native_stack_addr, InterpFrame *parent, InterpMethod *imethod, stackval *stack_args, stackval *retval) +static void +reinit_frame (InterpFrame *frame, InterpFrame *parent, InterpMethod *imethod, stackval *stack_args, stackval *retval) { - StackFragment *frag; - InterpFrame *frame; - - // FIXME: Add stack overflow checks - frame = (InterpFrame*)frame_stack_alloc (&ctx->iframe_stack, sizeof (InterpFrame), &frag); - - frame->iframe_frag = frag; frame->parent = parent; - frame->native_stack_addr = native_stack_addr; frame->imethod = imethod; frame->stack_args = stack_args; frame->retval = retval; frame->stack = NULL; frame->ip = NULL; frame->state.ip = NULL; - - return frame; } /* @@ -255,9 +245,7 @@ static MONO_ALWAYS_INLINE void alloc_stack_data (ThreadContext *ctx, InterpFrame *frame, int size) { StackFragment *frag; - gpointer res; - - res = frame_stack_alloc (&ctx->data_stack, size, &frag); + gpointer res = frame_stack_alloc (&ctx->data_stack, size, &frag); frame->stack = (stackval*)res; frame->data_frag = frag; @@ -282,11 +270,8 @@ pop_frame (ThreadContext *context, InterpFrame *frame) { if (frame->stack) frame_stack_pop (&context->data_stack, frame->data_frag, frame->stack); - frame_stack_pop (&context->iframe_stack, frame->iframe_frag, frame); } -#define interp_exec_method(frame, context, error) interp_exec_method_full ((frame), (context), NULL, error) - /* * List of classes whose methods will be executed by transitioning to JITted code. * Used for testing. @@ -299,7 +284,8 @@ static gboolean ss_enabled; static gboolean interp_init_done = FALSE; -static void interp_exec_method_full (InterpFrame *frame, ThreadContext *context, FrameClauseArgs *clause_args, MonoError *error); +static void +interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs *clause_args, MonoError *error); static InterpMethod* lookup_method_pointer (gpointer addr); @@ -453,10 +439,12 @@ get_context (void) if (context == NULL) { context = g_new0 (ThreadContext, 1); /* - * Use two stacks, one for InterpFrame structures, one for data. - * This is useful because InterpFrame structures don't need to be GC tracked. + * Initialize data stack. + * There are multiple advantages to this being separate from the frame stack. + * Frame stack can be alloca. + * Frame stack can be perfectly fit (if heap). + * Frame stack can skip GC tracking. */ - frame_stack_init (&context->iframe_stack, 8192); frame_stack_init (&context->data_stack, 8192); set_context (context); } @@ -468,7 +456,6 @@ interp_free_context (gpointer ctx) { ThreadContext *context = (ThreadContext*)ctx; - frame_stack_free (&context->iframe_stack); frame_stack_free (&context->data_stack); g_free (context); } @@ -1108,7 +1095,7 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con MonoContext ctx; memset (&ctx, 0, sizeof (MonoContext)); - MONO_CONTEXT_SET_SP (&ctx, frame->native_stack_addr); + MONO_CONTEXT_SET_SP (&ctx, frame); /* * Call the JIT EH code. The EH code will call back to us using: @@ -1527,17 +1514,26 @@ interp_to_native_trampoline (gpointer addr, gpointer ccontext) get_interp_to_native_trampoline () (addr, ccontext); } -/* MONO_NO_OPTIMIATION is needed due to usage of INTERP_PUSH_LMF_WITH_CTX. */ +/* MONO_NO_OPTIMIZATION is needed due to usage of INTERP_PUSH_LMF_WITH_CTX. */ #ifdef _MSC_VER #pragma optimize ("", off) #endif static MONO_NO_OPTIMIZATION MONO_NEVER_INLINE void -ves_pinvoke_method (InterpFrame *frame, MonoMethodSignature *sig, MonoFuncV addr, ThreadContext *context, gboolean save_last_error) +ves_pinvoke_method ( + MonoMethodSignature *sig, + MonoFuncV addr, + ThreadContext *context, + InterpFrame *parent_frame, + stackval *retval, + gboolean save_last_error, + stackval *sp) { + InterpFrame frame = {parent_frame, NULL, sp, retval}; + MonoLMFExt ext; gpointer args; - g_assert (!frame->imethod); + g_assert (!frame.imethod); static MonoPIFunc entry_func = NULL; if (!entry_func) { @@ -1560,15 +1556,15 @@ ves_pinvoke_method (InterpFrame *frame, MonoMethodSignature *sig, MonoFuncV addr #ifdef MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP CallContext ccontext; MONO_ENTER_GC_UNSAFE; - mono_arch_set_native_call_context_args (&ccontext, frame, sig); + mono_arch_set_native_call_context_args (&ccontext, &frame, sig); MONO_EXIT_GC_UNSAFE; args = &ccontext; #else - InterpMethodArguments *margs = build_args_from_sig (sig, frame); + InterpMethodArguments *margs = build_args_from_sig (sig, &frame); args = margs; #endif - INTERP_PUSH_LMF_WITH_CTX (frame, ext, exit_pinvoke); + INTERP_PUSH_LMF_WITH_CTX (&frame, ext, exit_pinvoke); entry_func ((gpointer) addr, args); if (save_last_error) mono_marshal_set_last_error (); @@ -1577,15 +1573,14 @@ ves_pinvoke_method (InterpFrame *frame, MonoMethodSignature *sig, MonoFuncV addr #ifdef MONO_ARCH_HAVE_INTERP_PINVOKE_TRAMP if (!context->has_resume_state) { MONO_ENTER_GC_UNSAFE; - mono_arch_get_native_call_context_ret (&ccontext, frame, sig); + mono_arch_get_native_call_context_ret (&ccontext, &frame, sig); MONO_EXIT_GC_UNSAFE; } - if (ccontext.stack != NULL) - g_free (ccontext.stack); + g_free (ccontext.stack); #else if (!context->has_resume_state && !MONO_TYPE_ISSTRUCT (sig->ret)) - stackval_from_data (sig->ret, frame->retval, (char*)&frame->retval->data.p, sig->pinvoke); + stackval_from_data (sig->ret, frame.retval, (char*)&frame.retval->data.p, sig->pinvoke); g_free (margs->iargs); g_free (margs->fargs); @@ -1876,10 +1871,10 @@ dump_args (InterpFrame *inv) #define CHECK_MUL_OVERFLOW_NAT_UN(a,b) CHECK_MUL_OVERFLOW64_UN(a,b) #endif -static MonoObject* +// Do not inline in case order of frame addresses matters. +static MONO_NEVER_INLINE MonoObject* interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject **exc, MonoError *error) { - InterpFrame *frame; ThreadContext *context = get_context (); MonoMethodSignature *sig = mono_method_signature_internal (method); MonoClass *klass = mono_class_from_mono_type_internal (sig->ret); @@ -1911,9 +1906,10 @@ interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObject InterpMethod *imethod = mono_interp_get_imethod (domain, invoke_wrapper, error); mono_error_assert_ok (error); - frame = alloc_frame (context, &result, NULL, imethod, args, &result); - interp_exec_method (frame, context, error); + InterpFrame frame = {NULL, imethod, args, &result}; + + interp_exec_method (&frame, context, NULL, error); if (context->has_resume_state) { // This can happen on wasm !? @@ -1936,10 +1932,10 @@ typedef struct { } InterpEntryData; /* Main function for entering the interpreter from compiled code */ -static void +// Do not inline in case order of frame addresses matters. +static MONO_NEVER_INLINE void interp_entry (InterpEntryData *data) { - InterpFrame *frame; InterpMethod *rmethod; ThreadContext *context; stackval result; @@ -2002,7 +1998,8 @@ interp_entry (InterpEntryData *data) } memset (&result, 0, sizeof (result)); - frame = alloc_frame (context, &result, NULL, data->rmethod, args, &result); + + InterpFrame frame = {NULL, data->rmethod, args, &result}; type = rmethod->rtype; switch (type->type) { @@ -2018,7 +2015,7 @@ interp_entry (InterpEntryData *data) } ERROR_DECL (error); - interp_exec_method (frame, context, error); + interp_exec_method (&frame, context, NULL, error); g_assert (!context->has_resume_state); @@ -2175,10 +2172,11 @@ do_icall (MonoMethodSignature *sig, int op, stackval *sp, gpointer ptr, gboolean return sp; } -/* MONO_NO_OPTIMIATION is needed due to usage of INTERP_PUSH_LMF_WITH_CTX. */ +/* MONO_NO_OPTIMIZATION is needed due to usage of INTERP_PUSH_LMF_WITH_CTX. */ #ifdef _MSC_VER #pragma optimize ("", off) #endif +// Do not inline in case order of frame addresses matters, and maybe other reasons. static MONO_NO_OPTIMIZATION MONO_NEVER_INLINE stackval * do_icall_wrapper (InterpFrame *frame, MonoMethodSignature *sig, int op, stackval *sp, gpointer ptr, gboolean save_last_error) { @@ -2704,10 +2702,10 @@ interp_entry_general (gpointer this_arg, gpointer res, gpointer *args, gpointer } \ } while (0) -static void +// Do not inline in case order of frame addresses matters. +static MONO_NEVER_INLINE void interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untyped) { - InterpFrame *frame; ThreadContext *context; stackval result; stackval *args; @@ -2734,22 +2732,22 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype args = (stackval*)alloca (sizeof (stackval) * (sig->param_count + (sig->hasthis ? 1 : 0))); - frame = alloc_frame (context, &result, NULL, rmethod, args, &result); - /* Allocate storage for value types */ for (i = 0; i < sig->param_count; i++) { MonoType *type = sig->params [i]; - alloc_storage_for_stackval (&frame->stack_args [i + sig->hasthis], type, sig->pinvoke); + alloc_storage_for_stackval (&args [i + sig->hasthis], type, sig->pinvoke); } if (sig->ret->type != MONO_TYPE_VOID) - alloc_storage_for_stackval (frame->retval, sig->ret, sig->pinvoke); + alloc_storage_for_stackval (&result, sig->ret, sig->pinvoke); + + InterpFrame frame = {NULL, rmethod, args, &result}; /* Copy the args saved in the trampoline to the frame stack */ - mono_arch_get_native_call_context_args (ccontext, frame, sig); + mono_arch_get_native_call_context_args (ccontext, &frame, sig); ERROR_DECL (error); - interp_exec_method (frame, context, error); + interp_exec_method (&frame, context, NULL, error); g_assert (!context->has_resume_state); @@ -2758,7 +2756,7 @@ interp_entry_from_trampoline (gpointer ccontext_untyped, gpointer rmethod_untype /* Write back the return value */ /* 'frame' is still valid */ - mono_arch_set_native_call_context_ret (ccontext, frame, sig); + mono_arch_set_native_call_context_ret (ccontext, &frame, sig); } #else @@ -3144,23 +3142,27 @@ mono_interp_isinst (MonoObject* object, MonoClass* klass) } // Do not inline use of alloca. +// Do not inline in case order of frame addresses matters. static MONO_NEVER_INLINE void mono_interp_calli_nat_dynamic_pinvoke ( // Parameters are sorted by name. - InterpFrame* child_frame, guchar* code, ThreadContext* context, MonoMethodSignature* csignature, - MonoError* error) + MonoError* error, + InterpFrame *parent_frame, + stackval *retval, + stackval *sp) { + InterpFrame frame = {parent_frame, NULL, sp, retval}; + // Recompute to limit parameters, which can also contribute to caller stack. - InterpMethod* const imethod = child_frame->parent->imethod; + InterpMethod* const imethod = parent_frame->imethod; g_assert (imethod->method->dynamic && csignature->pinvoke); /* Pinvoke call is missing the wrapper. See mono_get_native_calli_wrapper */ - MonoMarshalSpec** mspecs = g_newa (MonoMarshalSpec*, csignature->param_count + 1); - memset (mspecs, 0, sizeof (MonoMarshalSpec*) * (csignature->param_count + 1)); + MonoMarshalSpec** mspecs = g_newa0 (MonoMarshalSpec*, csignature->param_count + 1); MonoMethodPInvoke iinfo; memset (&iinfo, 0, sizeof (iinfo)); @@ -3173,23 +3175,26 @@ mono_interp_calli_nat_dynamic_pinvoke ( { ERROR_DECL (error); - child_frame->imethod = mono_interp_get_imethod (imethod->domain, m, error); + frame.imethod = mono_interp_get_imethod (imethod->domain, m, error); mono_error_cleanup (error); /* FIXME: don't swallow the error */ } - interp_exec_method (child_frame, context, error); + interp_exec_method (&frame, context, NULL, error); } -static MonoException* -mono_interp_leave (InterpFrame* child_frame) +// Do not inline in case order of frame addresses matters. +static MONO_NEVER_INLINE MonoException* +mono_interp_leave (InterpFrame* parent_frame) { + InterpFrame frame = {parent_frame}; + stackval tmp_sp; /* * We need for mono_thread_get_undeniable_exception to be able to unwind - * to check the abort threshold. For this to work we use child_frame as a + * to check the abort threshold. For this to work we use frame as a * dummy frame that is stored in the lmf and serves as the transition frame */ - do_icall_wrapper (child_frame, NULL, MINT_ICALL_V_P, &tmp_sp, (gpointer)mono_thread_get_undeniable_exception, FALSE); + do_icall_wrapper (&frame, NULL, MINT_ICALL_V_P, &tmp_sp, (gpointer)mono_thread_get_undeniable_exception, FALSE); return (MonoException*)tmp_sp.data.p; } @@ -3377,7 +3382,7 @@ method_entry (ThreadContext *context, InterpFrame *frame, * FRAME is only valid until the next call to alloc_frame (). */ static MONO_NEVER_INLINE void -interp_exec_method_full (InterpFrame *frame, ThreadContext *context, FrameClauseArgs *clause_args, MonoError *error) +interp_exec_method (InterpFrame *frame, ThreadContext *context, FrameClauseArgs *clause_args, MonoError *error) { InterpMethod *cmethod; MonoException *ex; @@ -3682,17 +3687,13 @@ main_loop: if (csignature->hasthis) --sp; - InterpFrame* const child_frame = alloc_frame (context, &retval, frame, NULL, sp, retval); - if (frame->imethod->method->dynamic && csignature->pinvoke) { - mono_interp_calli_nat_dynamic_pinvoke (child_frame, code, context, csignature, error); + mono_interp_calli_nat_dynamic_pinvoke (code, context, csignature, error, frame, retval, sp); } else { const gboolean save_last_error = ip [-3 + 2]; - ves_pinvoke_method (child_frame, csignature, (MonoFuncV) code, context, save_last_error); + ves_pinvoke_method (csignature, (MonoFuncV)code, context, frame, retval, save_last_error, sp); } - pop_frame (context, child_frame); - CHECK_RESUME_STATE (context); if (csignature->ret->type != MONO_TYPE_VOID) { @@ -3825,17 +3826,24 @@ main_loop: ip += 3; #endif call:; - // FIXME This assumes a grow-down stack. - gpointer native_stack_addr = frame->native_stack_addr ? (gpointer)((guint8*)frame->native_stack_addr - 1) : (gpointer)&retval; - /* * Make a non-recursive call by loading the new interpreter state based on child frame, * and going back to the main loop. */ SAVE_INTERP_STATE (frame); - frame = alloc_frame (context, native_stack_addr, frame, cmethod, sp, retval); - + // Allocate child frame. + // FIXME: Add stack overflow checks + { + InterpFrame *child_frame = frame->next_free; + if (!child_frame) { + child_frame = g_newa0 (InterpFrame, 1); + // Not free currently, but will be when allocation attempted. + frame->next_free = child_frame; + } + reinit_frame (child_frame, frame, cmethod, sp, retval); + frame = child_frame; + } #if DEBUG_INTERP int tracing; #endif @@ -6274,9 +6282,6 @@ call_newobj: MINT_IN_CASE(MINT_LEAVE_S) MINT_IN_CASE(MINT_LEAVE_CHECK) MINT_IN_CASE(MINT_LEAVE_S_CHECK) { - int dummy; - // Leave is split into pieces in order to consume less stack, - // but not have to change how exception handling macros access labels and locals. g_assert (sp >= frame->stack); sp = frame->stack; /* spec says stack should be empty at endfinally so it should be at the start too */ @@ -6287,9 +6292,7 @@ call_newobj: gboolean const check = opcode == MINT_LEAVE_CHECK || opcode == MINT_LEAVE_S_CHECK; if (check && frame->imethod->method->wrapper_type != MONO_WRAPPER_RUNTIME_INVOKE) { - InterpFrame* const child_frame = alloc_frame (context, &dummy, frame, NULL, NULL, NULL); - MonoException *abort_exc = mono_interp_leave (child_frame); - pop_frame (context, child_frame); + MonoException *abort_exc = mono_interp_leave (frame); if (abort_exc) THROW_EX (abort_exc, frame->ip); } @@ -6393,7 +6396,7 @@ call_newobj: ++ip; MINT_IN_BREAK; MINT_IN_CASE(MINT_MONO_GET_SP) - sp->data.p = &frame; + sp->data.p = frame; ++sp; ++ip; MINT_IN_BREAK; @@ -7135,19 +7138,24 @@ interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip ThreadContext *context = get_context (); const unsigned short *old_ip = iframe->ip; FrameClauseArgs clause_args; - const guint16 *saved_ip; + const guint16 *state_ip; memset (&clause_args, 0, sizeof (FrameClauseArgs)); clause_args.start_with_ip = (const guint16*)handler_ip; clause_args.end_at_ip = (const guint16*)handler_ip_end; clause_args.exit_clause = clause_index; - saved_ip = iframe->state.ip; + state_ip = iframe->state.ip; iframe->state.ip = NULL; + InterpFrame* const next_free = iframe->next_free; + iframe->next_free = NULL; + ERROR_DECL (error); - interp_exec_method_full (iframe, context, &clause_args, error); - iframe->state.ip = saved_ip; + interp_exec_method (iframe, context, &clause_args, error); + + iframe->next_free = next_free; + iframe->state.ip = state_ip; iframe->state.clause_args = NULL; if (context->has_resume_state) { return TRUE; @@ -7163,12 +7171,12 @@ interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip * Run the filter clause identified by CLAUSE_INDEX in the intepreter frame given by * frame->interp_frame. */ -static gboolean +// Do not inline in case order of frame addresses matters. +static MONO_NEVER_INLINE gboolean interp_run_filter (StackFrameInfo *frame, MonoException *ex, int clause_index, gpointer handler_ip, gpointer handler_ip_end) { InterpFrame *iframe = (InterpFrame*)frame->interp_frame; ThreadContext *context = get_context (); - InterpFrame *child_frame; stackval retval; FrameClauseArgs clause_args; @@ -7176,7 +7184,7 @@ interp_run_filter (StackFrameInfo *frame, MonoException *ex, int clause_index, g * Have to run the clause in a new frame which is a copy of IFRAME, since * during debugging, there are two copies of the frame on the stack. */ - child_frame = alloc_frame (context, &retval, iframe, iframe->imethod, iframe->stack_args, &retval); + InterpFrame child_frame = {iframe, iframe->imethod, iframe->stack_args, &retval}; memset (&clause_args, 0, sizeof (FrameClauseArgs)); clause_args.start_with_ip = (const guint16*)handler_ip; @@ -7185,7 +7193,8 @@ interp_run_filter (StackFrameInfo *frame, MonoException *ex, int clause_index, g clause_args.base_frame = iframe; ERROR_DECL (error); - interp_exec_method_full (child_frame, context, &clause_args, error); + interp_exec_method (&child_frame, context, &clause_args, error); + /* ENDFILTER stores the result into child_frame->retval */ return retval.data.i ? TRUE : FALSE; } @@ -7241,7 +7250,7 @@ interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame) frame->managed = TRUE; } frame->ji = iframe->imethod->jinfo; - frame->frame_addr = iframe->native_stack_addr; + frame->frame_addr = iframe; stack_iter->current = iframe->parent; @@ -7348,14 +7357,6 @@ interp_frame_get_res (MonoInterpFrameHandle frame) return stackval_to_data_addr (sig->ret, iframe->retval); } -static gpointer -interp_frame_get_native_stack_addr (MonoInterpFrameHandle frame) -{ - InterpFrame *iframe = (InterpFrame*)frame; - - return iframe->native_stack_addr; -} - static void interp_start_single_stepping (void) { diff --git a/src/mono/mono/mini/mini-exceptions.c b/src/mono/mono/mini/mini-exceptions.c index 993fe25..3bcebae 100644 --- a/src/mono/mono/mini/mini-exceptions.c +++ b/src/mono/mono/mini/mini-exceptions.c @@ -741,7 +741,6 @@ unwinder_unwind_frame (Unwinder *unwinder, host_mgreg_t **save_locations, StackFrameInfo *frame) { - gpointer parent; if (unwinder->in_interp) { memcpy (new_ctx, ctx, sizeof (MonoContext)); @@ -760,12 +759,10 @@ unwinder_unwind_frame (Unwinder *unwinder, unwinder->in_interp = mini_get_interp_callbacks ()->frame_iter_next (&unwinder->interp_iter, frame); if (frame->type == FRAME_TYPE_INTERP) { - parent = mini_get_interp_callbacks ()->frame_get_parent (frame->interp_frame); - if (parent) - unwinder->last_frame_addr = mini_get_interp_callbacks ()->frame_get_native_stack_addr (parent); - else - unwinder->last_frame_addr = NULL; + const gpointer parent = mini_get_interp_callbacks ()->frame_get_parent (frame->interp_frame); + unwinder->last_frame_addr = parent; } + if (!unwinder->in_interp) return unwinder_unwind_frame (unwinder, domain, jit_tls, prev_ji, ctx, new_ctx, trace, lmf, save_locations, frame); return TRUE;