Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mcs/class/corlib/System/Delegate.cs10
-rw-r--r--mono/metadata/icall-def.h1
-rw-r--r--mono/metadata/icall.c6
-rw-r--r--mono/metadata/object-internals.h1
-rw-r--r--mono/metadata/object-offsets.h1
-rw-r--r--mono/mini/method-to-ir.c4
-rw-r--r--mono/tests/Makefile.am1
-rw-r--r--mono/tests/delegate12.cs68
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";
+ }
+}