diff --git a/src/mono/mono/mini/interp/interp.c b/src/mono/mono/mini/interp/interp.c index d48451ff1bede8..30a2c205f4df69 100644 --- a/src/mono/mono/mini/interp/interp.c +++ b/src/mono/mono/mini/interp/interp.c @@ -1160,15 +1160,6 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con } \ } while (0) -#define EXCEPTION_CHECKPOINT_IN_HELPER_FUNCTION \ - do { \ - if (mono_thread_interruption_request_flag && !mono_threads_is_critical_method (frame->imethod->method)) { \ - MonoException *exc = mono_thread_interruption_checkpoint (); \ - if (exc) \ - return exc; \ - } \ - } while (0) - static MonoObject* ves_array_create (MonoDomain *domain, MonoClass *klass, int param_count, stackval *values, MonoError *error) { @@ -3215,88 +3206,6 @@ mono_interp_leave (InterpFrame* child_frame) return (MonoException*)tmp_sp.data.p; } -static MONO_NEVER_INLINE MonoException* -mono_interp_newobj ( - // Parameters are sorted by name and parameter list is minimized - // to reduce stack use in caller, on e.g. NT/AMD64 (up to 4 parameters - // use no stack in caller). - InterpFrame* child_frame, - ThreadContext* context, - MonoError* error, - guchar* vt_sp) -{ - InterpFrame* const frame = child_frame->parent; - InterpMethod* const imethod = frame->imethod; - stackval* const sp = child_frame->stack_args; - - MonoObject* o = NULL; // See the comment about GC safety. - stackval valuetype_this; - stackval retval; - - MonoClass * const newobj_class = child_frame->imethod->method->klass; - /*if (profiling_classes) { - guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class)); - count++; - g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count)); - }*/ - - /* - * First arg is the object. - */ - if (m_class_is_valuetype (newobj_class)) { - MonoType *t = m_class_get_byval_arg (newobj_class); - memset (&valuetype_this, 0, sizeof (stackval)); - if (!m_class_is_enumtype (newobj_class) && (t->type == MONO_TYPE_VALUETYPE || (t->type == MONO_TYPE_GENERICINST && mono_type_generic_inst_is_valuetype (t)))) { - sp->data.p = vt_sp; - valuetype_this.data.p = vt_sp; - } else { - sp->data.p = &valuetype_this; - } - } else { - if (newobj_class != mono_defaults.string_class) { - MonoVTable *vtable = mono_class_vtable_checked (imethod->domain, newobj_class, error); - if (!is_ok (error) || !mono_runtime_class_init_full (vtable, error)) { - MonoException* const exc = mono_error_convert_to_exception (error); - g_assert (exc); - return exc; - } - ERROR_DECL (error); - OBJREF (o) = mono_object_new_checked (imethod->domain, newobj_class, error); - mono_error_cleanup (error); // FIXME: do not swallow the error - EXCEPTION_CHECKPOINT_IN_HELPER_FUNCTION; - sp->data.o = o; -#ifndef DISABLE_REMOTING - if (mono_object_is_transparent_proxy (o)) { - MonoMethod *remoting_invoke_method = mono_marshal_get_remoting_invoke_with_check (child_frame->imethod->method, error); - mono_error_assert_ok (error); - child_frame->imethod = mono_interp_get_imethod (imethod->domain, remoting_invoke_method, error); - mono_error_assert_ok (error); - } -#endif - } else { - sp->data.p = NULL; - child_frame->retval = &retval; - } - } - - interp_exec_method (child_frame, context, error); - - CHECK_RESUME_STATE (context); - - /* - * a constructor returns void, but we need to return the object we created - */ - if (m_class_is_valuetype (newobj_class) && !m_class_is_enumtype (newobj_class)) { - *sp = valuetype_this; - } else if (newobj_class == mono_defaults.string_class) { - *sp = retval; - } else { - sp->data.o = o; - } -resume: - return NULL; -} - static MONO_NEVER_INLINE void mono_interp_enum_hasflag (stackval* sp, MonoClass* klass) { @@ -5087,9 +4996,8 @@ call:; MINT_IN_CASE(MINT_NEWOBJ) { int dummy; - // This is split up to: - // - conserve stack - // - keep exception handling and resume mostly in the main function + + // FIXME: Clean this up and make it not recursive. frame->ip = ip; @@ -5107,11 +5015,75 @@ call:; child_frame->stack_args = sp; - // FIXME remove recursion - MonoException* const exc = mono_interp_newobj (child_frame, context, error, vt_sp); - if (exc) - THROW_EX (exc, ip); + MonoException *exc = NULL; + + InterpMethod* const imethod = frame->imethod; + + MonoObject* o = NULL; // See the comment about GC safety. + stackval valuetype_this; + stackval retval; + + MonoClass * const newobj_class = child_frame->imethod->method->klass; + /*if (profiling_classes) { + guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class)); + count++; + g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count)); + }*/ + + /* + * First arg is the object. + */ + if (m_class_is_valuetype (newobj_class)) { + MonoType *t = m_class_get_byval_arg (newobj_class); + memset (&valuetype_this, 0, sizeof (stackval)); + if (!m_class_is_enumtype (newobj_class) && (t->type == MONO_TYPE_VALUETYPE || (t->type == MONO_TYPE_GENERICINST && mono_type_generic_inst_is_valuetype (t)))) { + sp->data.p = vt_sp; + valuetype_this.data.p = vt_sp; + } else { + sp->data.p = &valuetype_this; + } + } else { + if (newobj_class != mono_defaults.string_class) { + MonoVTable *vtable = mono_class_vtable_checked (imethod->domain, newobj_class, error); + if (!is_ok (error) || !mono_runtime_class_init_full (vtable, error)) { + exc = mono_error_convert_to_exception (error); + g_assert (exc); + THROW_EX (exc, ip); + } + ERROR_DECL (error); + OBJREF (o) = mono_object_new_checked (imethod->domain, newobj_class, error); + mono_error_cleanup (error); // FIXME: do not swallow the error + EXCEPTION_CHECKPOINT; + sp->data.o = o; +#ifndef DISABLE_REMOTING + if (mono_object_is_transparent_proxy (o)) { + MonoMethod *remoting_invoke_method = mono_marshal_get_remoting_invoke_with_check (child_frame->imethod->method, error); + mono_error_assert_ok (error); + child_frame->imethod = mono_interp_get_imethod (imethod->domain, remoting_invoke_method, error); + mono_error_assert_ok (error); + } +#endif + } else { + sp->data.p = NULL; + child_frame->retval = &retval; + } + } + + interp_exec_method (child_frame, context, error); + CHECK_RESUME_STATE (context); + + /* + * a constructor returns void, but we need to return the object we created + */ + if (m_class_is_valuetype (newobj_class) && !m_class_is_enumtype (newobj_class)) { + *sp = valuetype_this; + } else if (newobj_class == mono_defaults.string_class) { + *sp = retval; + } else { + sp->data.o = o; + } + ++sp; MINT_IN_BREAK; }