[interpreter] if unboxing is required on virtcall, point into object instead of copying
authorBernhard Urban <bernhard.urban@xamarin.com>
Mon, 27 Feb 2017 16:55:53 +0000 (17:55 +0100)
committerBernhard Urban <bernhard.urban@xamarin.com>
Tue, 28 Feb 2017 21:59:28 +0000 (22:59 +0100)
mono/mini/generics.cs
mono/mini/interpreter/interp-internals.h
mono/mini/interpreter/interp.c

index 186fb90db91dd240624db5925aa3f9352ee9be22..eae71e11f5474256db6bf58a45f1d928a78df23d 100644 (file)
@@ -269,7 +269,6 @@ class Tests
                return s.return_field () + s.return_field ();
        }
 
-       [Category ("!INTERPRETER")]
        public static int test_0_generic_get_value_optimization_vtype () {
                TestStruct[] arr = new TestStruct[] { new TestStruct (100, 200), new TestStruct (300, 400) };
                IEnumerator<TestStruct> enumerator = GenericClass<TestStruct>.Y (arr);
index 5e8597a6a6f8b915d09652acb30b29c6ca9c4829..f26e4ff57b3badc3c7a3a9d5c9d91e1d9b3be89a 100644 (file)
@@ -82,7 +82,6 @@ typedef struct _RuntimeMethod
        guint32 *local_offsets;
        unsigned int param_count;
        unsigned int hasthis;
-       unsigned int valuetype;
 } RuntimeMethod;
 
 struct _MonoInvocation {
index b3cc2297693c9b916bdbad4611b323923eb3b973..eee3a042a37214012f2cbc820fa71431e9e14edc 100644 (file)
@@ -271,7 +271,6 @@ mono_interp_get_runtime_method (MonoDomain *domain, MonoMethod *method, MonoErro
        rtm->method = method;
        rtm->param_count = mono_method_signature (method)->param_count;
        rtm->hasthis = mono_method_signature (method)->hasthis;
-       rtm->valuetype = method->klass->valuetype;
        mono_internal_hash_table_insert (&domain->jit_code_hash, method, rtm);
        mono_os_mutex_unlock (&runtime_method_lookup_section);
 
@@ -1806,6 +1805,15 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        }
 
+                       if (csignature->hasthis) {
+                               MonoObject *this_arg = sp->data.p;
+
+                               if (this_arg->vtable->klass->valuetype) {
+                                       gpointer *unboxed = mono_object_unbox (this_arg);
+                                       sp [0].data.p = unboxed;
+                               }
+                       }
+
                        ves_exec_method_with_context (&child_frame, context);
 
                        context->current_frame = frame;
@@ -1885,7 +1893,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                        child_frame.stack_args = sp;
 
                        /* `this' can be NULL for string:.ctor */
-                       if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
+                       if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && sp->data.p && mono_object_is_transparent_proxy (sp->data.p)) {
                                child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        }
@@ -1920,7 +1928,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                                --sp;
                        child_frame.stack_args = sp;
 
-                       if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
+                       if (child_frame.runtime_method->hasthis && !child_frame.runtime_method->method->klass->valuetype && mono_object_is_transparent_proxy (sp->data.p)) {
                                child_frame.runtime_method = mono_interp_get_runtime_method (context->domain, mono_marshal_get_remoting_invoke (child_frame.runtime_method->method), &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                        }
@@ -1959,10 +1967,11 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                                THROW_EX (mono_get_exception_null_reference(), ip - 2);
                        child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
 
-                       if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
+                       MonoClass *this_class = this_arg->vtable->klass;
+                       if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
                                /* unbox */
                                gpointer *unboxed = mono_object_unbox (this_arg);
-                               stackval_from_data (&this_arg->vtable->klass->byval_arg, sp, (char *) unboxed, FALSE);
+                               sp [0].data.p = unboxed;
                        }
 
                        ves_exec_method_with_context (&child_frame, context);
@@ -2006,9 +2015,10 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context)
                                THROW_EX (mono_get_exception_null_reference(), ip - 2);
                        child_frame.runtime_method = get_virtual_method (context->domain, child_frame.runtime_method, this_arg);
 
-                       if (this_arg->vtable->klass->valuetype && child_frame.runtime_method->valuetype) {
+                       MonoClass *this_class = this_arg->vtable->klass;
+                       if (this_class->valuetype && child_frame.runtime_method->method->klass->valuetype) {
                                gpointer *unboxed = mono_object_unbox (this_arg);
-                               stackval_from_data (&this_arg->vtable->klass->byval_arg, sp, (char *) unboxed, FALSE);
+                               sp [0].data.p = unboxed;
                        }
 
                        ves_exec_method_with_context (&child_frame, context);