diff options
-rw-r--r-- | mcs/class/corlib/System/Delegate.cs | 10 | ||||
-rw-r--r-- | mono/metadata/icall-def.h | 1 | ||||
-rw-r--r-- | mono/metadata/icall.c | 6 | ||||
-rw-r--r-- | mono/metadata/object-internals.h | 1 | ||||
-rw-r--r-- | mono/metadata/object-offsets.h | 1 | ||||
-rw-r--r-- | mono/mini/method-to-ir.c | 4 | ||||
-rw-r--r-- | mono/tests/Makefile.am | 1 | ||||
-rw-r--r-- | mono/tests/delegate12.cs | 68 |
8 files changed, 91 insertions, 1 deletions
diff --git a/mcs/class/corlib/System/Delegate.cs b/mcs/class/corlib/System/Delegate.cs index c2f92a7f73b..ba97e726509 100644 --- a/mcs/class/corlib/System/Delegate.cs +++ b/mcs/class/corlib/System/Delegate.cs @@ -68,6 +68,8 @@ namespace System private MethodInfo original_method_info; private DelegateData data; + + private bool method_is_virtual; #pragma warning restore 169, 414, 649 #endregion @@ -103,13 +105,19 @@ namespace System return method_info; } else { if (method != IntPtr.Zero) { - method_info = (MethodInfo)MethodBase.GetMethodFromHandleNoGenericCheck (new RuntimeMethodHandle (method)); + if (!method_is_virtual) + method_info = (MethodInfo)MethodBase.GetMethodFromHandleNoGenericCheck (new RuntimeMethodHandle (method)); + else + method_info = GetVirtualMethod_internal (); } return method_info; } } } + [MethodImplAttribute (MethodImplOptions.InternalCall)] + extern MethodInfo GetVirtualMethod_internal (); + public object Target { get { return m_target; diff --git a/mono/metadata/icall-def.h b/mono/metadata/icall-def.h index 35c6e52146c..4a96fd512b0 100644 --- a/mono/metadata/icall-def.h +++ b/mono/metadata/icall-def.h @@ -152,6 +152,7 @@ ICALL(DECIMAL_13, "ToSingle", mono_decimal_to_float) ICALL_TYPE(DELEGATE, "System.Delegate", DELEGATE_1) ICALL(DELEGATE_1, "AllocDelegateLike_internal", ves_icall_System_Delegate_AllocDelegateLike_internal) ICALL(DELEGATE_2, "CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal) +ICALL(DELEGATE_3, "GetVirtualMethod_internal", ves_icall_System_Delegate_GetVirtualMethod_internal) ICALL_TYPE(DEBUGR, "System.Diagnostics.Debugger", DEBUGR_1) ICALL(DEBUGR_1, "IsAttached_internal", ves_icall_System_Diagnostics_Debugger_IsAttached_internal) diff --git a/mono/metadata/icall.c b/mono/metadata/icall.c index 675ead03dec..6ebd10e4182 100644 --- a/mono/metadata/icall.c +++ b/mono/metadata/icall.c @@ -5610,6 +5610,12 @@ ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate) return ret; } +ICALL_EXPORT MonoReflectionMethod* +ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate) +{ + return mono_method_get_object (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target)); +} + /* System.Buffer */ static inline gint32 diff --git a/mono/metadata/object-internals.h b/mono/metadata/object-internals.h index a303331d444..9860f379330 100644 --- a/mono/metadata/object-internals.h +++ b/mono/metadata/object-internals.h @@ -786,6 +786,7 @@ struct _MonoDelegate { MonoReflectionMethod *method_info; MonoReflectionMethod *original_method_info; MonoObject *data; + MonoBoolean method_is_virtual; }; typedef struct _MonoMulticastDelegate MonoMulticastDelegate; diff --git a/mono/metadata/object-offsets.h b/mono/metadata/object-offsets.h index 2e753bcfe5d..267b9655b34 100644 --- a/mono/metadata/object-offsets.h +++ b/mono/metadata/object-offsets.h @@ -71,6 +71,7 @@ DECL_OFFSET(MonoDelegate, method_ptr) DECL_OFFSET(MonoDelegate, invoke_impl) DECL_OFFSET(MonoDelegate, method) DECL_OFFSET(MonoDelegate, method_code) +DECL_OFFSET(MonoDelegate, method_is_virtual) DECL_OFFSET(MonoInternalThread, tid) DECL_OFFSET(MonoInternalThread, small_id) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 8901046041b..24b171b7d02 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -4998,6 +4998,10 @@ handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, Mono MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr), dreg); } + dreg = alloc_preg (cfg); + MONO_EMIT_NEW_ICONST (cfg, dreg, virtual ? 1 : 0); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_is_virtual), dreg); + /* All the checks which are in mono_delegate_ctor () are done by the delegate trampoline */ return obj; diff --git a/mono/tests/Makefile.am b/mono/tests/Makefile.am index 0b83b4fb967..23c9d1075d1 100644 --- a/mono/tests/Makefile.am +++ b/mono/tests/Makefile.am @@ -181,6 +181,7 @@ BASE_TEST_CS_SRC= \ delegate9.cs \ delegate10.cs \ delegate11.cs \ + delegate12.cs \ remoting1.cs \ remoting2.cs \ remoting3.cs \ diff --git a/mono/tests/delegate12.cs b/mono/tests/delegate12.cs new file mode 100644 index 00000000000..103650c72cb --- /dev/null +++ b/mono/tests/delegate12.cs @@ -0,0 +1,68 @@ +using System; + +class MainClass +{ + public static int Main(string[] args) + { + DerivedClass o = new DerivedClass(); + + Func<string> del1 = GetDel1 (o); + Func<string> del2 = GetDel2 (o); + + + Console.WriteLine("Action\n======\nReflected type: {0}\nDeclaring type: {1}\nAttributes: {2}\nResult: {3}", + del1.Method.ReflectedType, del1.Method.DeclaringType, del1.Method.Attributes, del1 ()); + + Console.WriteLine (); + + Console.WriteLine("Delegate\n========\nReflected type: {0}\nDeclaring type: {1}\nAttributes: {2}\nResult: {3}", + del2.Method.ReflectedType, del2.Method.DeclaringType, del2.Method.Attributes, del2 ()); + + if (del1.Method.ReflectedType != typeof (DerivedClass)) + return 10; + if (del1.Method.DeclaringType != typeof (DerivedClass)) + return 11; + if (del1 () != "Derived method") + return 12; + + if (del2.Method.ReflectedType != typeof (DerivedClass)) + return 20; + if (del2.Method.DeclaringType != typeof (DerivedClass)) + return 21; + if (del2 () != "Derived method") + return 22; + + return 0; + } + + static Func<string> GetDel1 (DerivedClass o) + { + return o.GetMethod(); + } + + static Func<string> GetDel2 (DerivedClass o) + { + return (Func<string>) Delegate.CreateDelegate(typeof(Func<string>), o, o.GetMethod().Method); + } +} + +class BaseClass +{ + public Func<string> GetMethod() + { + return MyMethod; + } + + public virtual string MyMethod() + { + return "Base method"; + } +} + +class DerivedClass : BaseClass +{ + public override string MyMethod() + { + return "Derived method"; + } +} |