} \
} 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)
{
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)
{
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;
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;
}