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:
authorLudovic Henry <luhenry@microsoft.com>2018-03-08 05:48:23 +0300
committerGitHub <noreply@github.com>2018-03-08 05:48:23 +0300
commit7f6c3ef15b47f6409e4100355d15f140930f8e93 (patch)
tree2774090bbc9d834cc245b0bf0d05e4126acebb2c
parent30441ea0ac8fa090d8fb88ad5ed79b4d84212a3b (diff)
[2017-10] Only null check target for delegate if method is not static. (#7476)
* Only null check target for delegate if method is not static. Fixes regression introduced by 1cfd52452a4af3fd6eee32f45a8067926af8479e. * pass first stack arg to transform, so we get the correct delegate wrapper the wrapper logic detects if the target method of a delegate is a static method with an argument bound, and handles it properly in the generated code. fixes mono/tests/delegate14.cs
-rw-r--r--mono/mini/interp/interp-internals.h2
-rw-r--r--mono/mini/interp/interp.c4
-rw-r--r--mono/mini/interp/transform.c4
-rw-r--r--mono/mini/method-to-ir.c6
-rw-r--r--mono/tests/delegate14.cs22
5 files changed, 31 insertions, 7 deletions
diff --git a/mono/mini/interp/interp-internals.h b/mono/mini/interp/interp-internals.h
index 894747e23d0..5cfed578253 100644
--- a/mono/mini/interp/interp-internals.h
+++ b/mono/mini/interp/interp-internals.h
@@ -137,7 +137,7 @@ extern int mono_interp_traceopt;
extern GSList *jit_classes;
MonoException *
-mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context);
+mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context, MonoDelegate *del);
void
mono_interp_transform_init (void);
diff --git a/mono/mini/interp/interp.c b/mono/mini/interp/interp.c
index d4a876c2cf6..d742f6539d8 100644
--- a/mono/mini/interp/interp.c
+++ b/mono/mini/interp/interp.c
@@ -1972,7 +1972,7 @@ do_transform_method (InterpFrame *frame, ThreadContext *context)
/* Use the parent frame as the current frame is not complete yet */
interp_push_lmf (&ext, frame->parent);
- frame->ex = mono_interp_transform_method (frame->imethod, context);
+ frame->ex = mono_interp_transform_method (frame->imethod, context, (MonoDelegate *) frame->stack_args [0].data.p);
context->managed_code = 1;
interp_pop_lmf (&ext);
@@ -2456,7 +2456,7 @@ ves_exec_method_with_context (InterpFrame *frame, ThreadContext *context, unsign
if (!new_method->transformed) {
frame->ip = ip;
- frame->ex = mono_interp_transform_method (new_method, context);
+ frame->ex = mono_interp_transform_method (new_method, context, NULL);
if (frame->ex)
goto exit_frame;
}
diff --git a/mono/mini/interp/transform.c b/mono/mini/interp/transform.c
index 0bdb1580534..804235194f6 100644
--- a/mono/mini/interp/transform.c
+++ b/mono/mini/interp/transform.c
@@ -4261,7 +4261,7 @@ mono_interp_transform_init (void)
}
MonoException *
-mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context)
+mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context, MonoDelegate *del)
{
MonoError error;
int i, align, size, offset;
@@ -4340,7 +4340,7 @@ mono_interp_transform_method (InterpMethod *imethod, ThreadContext *context)
char *wrapper_name = g_strdup_printf ("__icall_wrapper_%s", mi->name);
nm = mono_marshal_get_icall_wrapper (mi->sig, wrapper_name, mi->func, TRUE);
} else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
- nm = mono_marshal_get_delegate_invoke (method, NULL);
+ nm = mono_marshal_get_delegate_invoke (method, del);
} else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) {
nm = mono_marshal_get_delegate_begin_invoke (method);
} else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c
index 3185a203fe8..f2808cdfd3b 100644
--- a/mono/mini/method-to-ir.c
+++ b/mono/mini/method-to-ir.c
@@ -3973,8 +3973,10 @@ handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, Mono
/* Set target field */
/* Optimize away setting of NULL target */
if (!MONO_INS_IS_PCONST_NULL (target)) {
- MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, target->dreg, 0);
- MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException");
+ if (!(method->flags & METHOD_ATTRIBUTE_STATIC)) {
+ MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, target->dreg, 0);
+ MONO_EMIT_NEW_COND_EXC (cfg, EQ, "NullReferenceException");
+ }
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, target), target->dreg);
if (cfg->gen_write_barriers) {
dreg = alloc_preg (cfg);
diff --git a/mono/tests/delegate14.cs b/mono/tests/delegate14.cs
index 2fd7d62b1fa..36c6f896e8a 100644
--- a/mono/tests/delegate14.cs
+++ b/mono/tests/delegate14.cs
@@ -6,6 +6,12 @@ public static class Program
{
public static int Main (string[] args)
{
+ // calling delegate on extension method with null target is allowed
+ Func<int> func = null;
+ if (CallFunc(func.CallFuncIfNotNull) != 0)
+ return 2;
+
+ // constructing delegate on instance method with null target should throw
ITest obj = null;
try
{
@@ -23,4 +29,20 @@ public static class Program
{
void Func ();
}
+
+ static int CallFunc(Func<int> func)
+ {
+ return func();
+ }
}
+
+public static class FuncExtensions
+{
+ public static int CallFuncIfNotNull(this Func<int> func)
+ {
+ if (func != null)
+ return func();
+
+ return 0;
+ }
+} \ No newline at end of file