Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
168 changes: 70 additions & 98 deletions src/mono/mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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;

Expand All @@ -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;
}
Expand Down