Skip to content

Commit 1afcda6

Browse files
[interp] Inline newobj. (#32480)
The real goal is to make it not recursive. This is just a step along the way. Note that the actual not-recursive change has *not* yet been developed, so this *might* amount to nothing useful. Co-authored-by: Jay Krell <[email protected]>
1 parent c4ab2a7 commit 1afcda6

File tree

1 file changed

+70
-98
lines changed

1 file changed

+70
-98
lines changed

src/mono/mono/mini/interp/interp.c

Lines changed: 70 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,15 +1160,6 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, con
11601160
} \
11611161
} while (0)
11621162

1163-
#define EXCEPTION_CHECKPOINT_IN_HELPER_FUNCTION \
1164-
do { \
1165-
if (mono_thread_interruption_request_flag && !mono_threads_is_critical_method (frame->imethod->method)) { \
1166-
MonoException *exc = mono_thread_interruption_checkpoint (); \
1167-
if (exc) \
1168-
return exc; \
1169-
} \
1170-
} while (0)
1171-
11721163
static MonoObject*
11731164
ves_array_create (MonoDomain *domain, MonoClass *klass, int param_count, stackval *values, MonoError *error)
11741165
{
@@ -3215,88 +3206,6 @@ mono_interp_leave (InterpFrame* child_frame)
32153206
return (MonoException*)tmp_sp.data.p;
32163207
}
32173208

3218-
static MONO_NEVER_INLINE MonoException*
3219-
mono_interp_newobj (
3220-
// Parameters are sorted by name and parameter list is minimized
3221-
// to reduce stack use in caller, on e.g. NT/AMD64 (up to 4 parameters
3222-
// use no stack in caller).
3223-
InterpFrame* child_frame,
3224-
ThreadContext* context,
3225-
MonoError* error,
3226-
guchar* vt_sp)
3227-
{
3228-
InterpFrame* const frame = child_frame->parent;
3229-
InterpMethod* const imethod = frame->imethod;
3230-
stackval* const sp = child_frame->stack_args;
3231-
3232-
MonoObject* o = NULL; // See the comment about GC safety.
3233-
stackval valuetype_this;
3234-
stackval retval;
3235-
3236-
MonoClass * const newobj_class = child_frame->imethod->method->klass;
3237-
/*if (profiling_classes) {
3238-
guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
3239-
count++;
3240-
g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
3241-
}*/
3242-
3243-
/*
3244-
* First arg is the object.
3245-
*/
3246-
if (m_class_is_valuetype (newobj_class)) {
3247-
MonoType *t = m_class_get_byval_arg (newobj_class);
3248-
memset (&valuetype_this, 0, sizeof (stackval));
3249-
if (!m_class_is_enumtype (newobj_class) && (t->type == MONO_TYPE_VALUETYPE || (t->type == MONO_TYPE_GENERICINST && mono_type_generic_inst_is_valuetype (t)))) {
3250-
sp->data.p = vt_sp;
3251-
valuetype_this.data.p = vt_sp;
3252-
} else {
3253-
sp->data.p = &valuetype_this;
3254-
}
3255-
} else {
3256-
if (newobj_class != mono_defaults.string_class) {
3257-
MonoVTable *vtable = mono_class_vtable_checked (imethod->domain, newobj_class, error);
3258-
if (!is_ok (error) || !mono_runtime_class_init_full (vtable, error)) {
3259-
MonoException* const exc = mono_error_convert_to_exception (error);
3260-
g_assert (exc);
3261-
return exc;
3262-
}
3263-
ERROR_DECL (error);
3264-
OBJREF (o) = mono_object_new_checked (imethod->domain, newobj_class, error);
3265-
mono_error_cleanup (error); // FIXME: do not swallow the error
3266-
EXCEPTION_CHECKPOINT_IN_HELPER_FUNCTION;
3267-
sp->data.o = o;
3268-
#ifndef DISABLE_REMOTING
3269-
if (mono_object_is_transparent_proxy (o)) {
3270-
MonoMethod *remoting_invoke_method = mono_marshal_get_remoting_invoke_with_check (child_frame->imethod->method, error);
3271-
mono_error_assert_ok (error);
3272-
child_frame->imethod = mono_interp_get_imethod (imethod->domain, remoting_invoke_method, error);
3273-
mono_error_assert_ok (error);
3274-
}
3275-
#endif
3276-
} else {
3277-
sp->data.p = NULL;
3278-
child_frame->retval = &retval;
3279-
}
3280-
}
3281-
3282-
interp_exec_method (child_frame, context, error);
3283-
3284-
CHECK_RESUME_STATE (context);
3285-
3286-
/*
3287-
* a constructor returns void, but we need to return the object we created
3288-
*/
3289-
if (m_class_is_valuetype (newobj_class) && !m_class_is_enumtype (newobj_class)) {
3290-
*sp = valuetype_this;
3291-
} else if (newobj_class == mono_defaults.string_class) {
3292-
*sp = retval;
3293-
} else {
3294-
sp->data.o = o;
3295-
}
3296-
resume:
3297-
return NULL;
3298-
}
3299-
33003209
static MONO_NEVER_INLINE void
33013210
mono_interp_enum_hasflag (stackval* sp, MonoClass* klass)
33023211
{
@@ -5087,9 +4996,8 @@ call:;
50874996

50884997
MINT_IN_CASE(MINT_NEWOBJ) {
50894998
int dummy;
5090-
// This is split up to:
5091-
// - conserve stack
5092-
// - keep exception handling and resume mostly in the main function
4999+
5000+
// FIXME: Clean this up and make it not recursive.
50935001

50945002
frame->ip = ip;
50955003

@@ -5107,11 +5015,75 @@ call:;
51075015

51085016
child_frame->stack_args = sp;
51095017

5110-
// FIXME remove recursion
5111-
MonoException* const exc = mono_interp_newobj (child_frame, context, error, vt_sp);
5112-
if (exc)
5113-
THROW_EX (exc, ip);
5018+
MonoException *exc = NULL;
5019+
5020+
InterpMethod* const imethod = frame->imethod;
5021+
5022+
MonoObject* o = NULL; // See the comment about GC safety.
5023+
stackval valuetype_this;
5024+
stackval retval;
5025+
5026+
MonoClass * const newobj_class = child_frame->imethod->method->klass;
5027+
/*if (profiling_classes) {
5028+
guint count = GPOINTER_TO_UINT (g_hash_table_lookup (profiling_classes, newobj_class));
5029+
count++;
5030+
g_hash_table_insert (profiling_classes, newobj_class, GUINT_TO_POINTER (count));
5031+
}*/
5032+
5033+
/*
5034+
* First arg is the object.
5035+
*/
5036+
if (m_class_is_valuetype (newobj_class)) {
5037+
MonoType *t = m_class_get_byval_arg (newobj_class);
5038+
memset (&valuetype_this, 0, sizeof (stackval));
5039+
if (!m_class_is_enumtype (newobj_class) && (t->type == MONO_TYPE_VALUETYPE || (t->type == MONO_TYPE_GENERICINST && mono_type_generic_inst_is_valuetype (t)))) {
5040+
sp->data.p = vt_sp;
5041+
valuetype_this.data.p = vt_sp;
5042+
} else {
5043+
sp->data.p = &valuetype_this;
5044+
}
5045+
} else {
5046+
if (newobj_class != mono_defaults.string_class) {
5047+
MonoVTable *vtable = mono_class_vtable_checked (imethod->domain, newobj_class, error);
5048+
if (!is_ok (error) || !mono_runtime_class_init_full (vtable, error)) {
5049+
exc = mono_error_convert_to_exception (error);
5050+
g_assert (exc);
5051+
THROW_EX (exc, ip);
5052+
}
5053+
ERROR_DECL (error);
5054+
OBJREF (o) = mono_object_new_checked (imethod->domain, newobj_class, error);
5055+
mono_error_cleanup (error); // FIXME: do not swallow the error
5056+
EXCEPTION_CHECKPOINT;
5057+
sp->data.o = o;
5058+
#ifndef DISABLE_REMOTING
5059+
if (mono_object_is_transparent_proxy (o)) {
5060+
MonoMethod *remoting_invoke_method = mono_marshal_get_remoting_invoke_with_check (child_frame->imethod->method, error);
5061+
mono_error_assert_ok (error);
5062+
child_frame->imethod = mono_interp_get_imethod (imethod->domain, remoting_invoke_method, error);
5063+
mono_error_assert_ok (error);
5064+
}
5065+
#endif
5066+
} else {
5067+
sp->data.p = NULL;
5068+
child_frame->retval = &retval;
5069+
}
5070+
}
5071+
5072+
interp_exec_method (child_frame, context, error);
5073+
51145074
CHECK_RESUME_STATE (context);
5075+
5076+
/*
5077+
* a constructor returns void, but we need to return the object we created
5078+
*/
5079+
if (m_class_is_valuetype (newobj_class) && !m_class_is_enumtype (newobj_class)) {
5080+
*sp = valuetype_this;
5081+
} else if (newobj_class == mono_defaults.string_class) {
5082+
*sp = retval;
5083+
} else {
5084+
sp->data.o = o;
5085+
}
5086+
51155087
++sp;
51165088
MINT_IN_BREAK;
51175089
}

0 commit comments

Comments
 (0)