Skip to content

Commit 94cb80b

Browse files
authored
Merge pull request #1037 from Unity-Technologies/unity-master-debugger-ref-returns
Handle ref returns in runtime invoke wrappers (case 1076527)
2 parents c86e2f2 + d76f307 commit 94cb80b

File tree

4 files changed

+64
-14
lines changed

4 files changed

+64
-14
lines changed

mcs/class/Mono.Debugger.Soft/Test/dtest-app.cs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ public static int Main (String[] args) {
350350
set_ip ();
351351
step_filters ();
352352
pointers ();
353+
ref_return ();
353354
if (args.Length > 0 && args [0] == "local-reflect")
354355
local_reflect ();
355356
if (args.Length > 0 && args [0] == "domain-test")
@@ -1739,6 +1740,21 @@ public static unsafe void pointers () {
17391740
fixed (int* pa = a)
17401741
pointer_arguments (pa, &s);
17411742
}
1743+
1744+
[MethodImplAttribute (MethodImplOptions.NoInlining)]
1745+
public static void ref_return () {
1746+
1747+
}
1748+
1749+
static int ret_val = 1;
1750+
public static ref int get_ref_int() {
1751+
return ref ret_val;
1752+
}
1753+
1754+
static string ref_return_string = "byref";
1755+
public static ref string get_ref_string() {
1756+
return ref ref_return_string;
1757+
}
17421758
}
17431759

17441760
public class SentinelClass : MarshalByRefObject {

mcs/class/Mono.Debugger.Soft/Test/dtest.cs

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4398,15 +4398,31 @@ public void Pointer_GetValue () {
43984398
}
43994399

44004400
[Test]
4401-
public void InvokeGenericMethod () {
4402-
Event e = run_until ("bp1");
4403-
StackFrame frame = e.Thread.GetFrames()[0];
4404-
TypeMirror t = frame.Method.DeclaringType;
4405-
MethodMirror m;
4406-
m = t.GetMethod ("generic_method");
4407-
AssertThrows<ArgumentException> (delegate {
4408-
t.InvokeMethod (e.Thread, m, null);
4409-
});
4410-
}
4401+
public void InvokeGenericMethod () {
4402+
Event e = run_until ("bp1");
4403+
StackFrame frame = e.Thread.GetFrames()[0];
4404+
TypeMirror t = frame.Method.DeclaringType;
4405+
MethodMirror m;
4406+
m = t.GetMethod ("generic_method");
4407+
AssertThrows<ArgumentException> (delegate {
4408+
t.InvokeMethod (e.Thread, m, null);
4409+
});
4410+
}
4411+
4412+
[Test]
4413+
public void InvokeRefReturnMethod () {
4414+
Event e = run_until ("ref_return");
4415+
StackFrame frame = e.Thread.GetFrames()[0];
4416+
TypeMirror t = frame.Method.DeclaringType;
4417+
MethodMirror m;
4418+
4419+
m = t.GetMethod ("get_ref_int");
4420+
var v = t.InvokeMethod (e.Thread, m, null);
4421+
AssertValue (1, v);
4422+
4423+
m = t.GetMethod ("get_ref_string");
4424+
v = t.InvokeMethod (e.Thread, m, null);
4425+
AssertValue ("byref", v);
4426+
}
44114427
} // class DebuggerTests
44124428
} // namespace

mono/metadata/marshal.c

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3936,6 +3936,11 @@ get_runtime_invoke_type (MonoType *t, gboolean ret)
39363936
if (t->byref) {
39373937
if (t->type == MONO_TYPE_GENERICINST && mono_class_is_nullable (mono_class_from_mono_type (t)))
39383938
return t;
3939+
3940+
/* The result needs loaded indirectly */
3941+
if (ret)
3942+
return t;
3943+
39393944
/* Can't share this with 'I' as that needs another indirection */
39403945
return &mono_defaults.int_class->this_arg;
39413946
}
@@ -4143,8 +4148,10 @@ emit_invoke_call (MonoMethodBuilder *mb, MonoMethod *method,
41434148
}
41444149

41454150
if (sig->ret->byref) {
4146-
/* fixme: */
4147-
g_assert_not_reached ();
4151+
/* perform indirect load and return by value */
4152+
MonoType* ret_byval = &mono_class_from_mono_type (sig->ret)->byval_arg;
4153+
g_assert (!ret_byval->byref);
4154+
mono_mb_emit_byte (mb, mono_type_to_ldind (ret_byval));
41484155
}
41494156

41504157
switch (sig->ret->type) {

mono/mini/debugger-agent.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8366,7 +8366,12 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
83668366
buffer_add_value (buf, &VM_DEFAULTS_VOID_CLASS->byval_arg, NULL, domain);
83678367
}
83688368
} else if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
8369-
buffer_add_value (buf, sig->ret, &res, domain);
8369+
if (sig->ret->byref) {
8370+
MonoType* ret_byval = &mono_class_from_mono_type (sig->ret)->byval_arg;
8371+
buffer_add_value (buf, ret_byval, &res, domain);
8372+
} else {
8373+
buffer_add_value (buf, sig->ret, &res, domain);
8374+
}
83708375
} else if (mono_class_from_mono_type (sig->ret)->valuetype || sig->ret->type == MONO_TYPE_PTR || sig->ret->type == MONO_TYPE_FNPTR) {
83718376
if (mono_class_is_nullable (mono_class_from_mono_type (sig->ret))) {
83728377
MonoClass *k = mono_class_from_mono_type (sig->ret);
@@ -8377,7 +8382,13 @@ do_invoke_method (DebuggerTlsData *tls, Buffer *buf, InvokeData *invoke, guint8
83778382
buffer_add_value (buf, sig->ret, nullable_buf, domain);
83788383
} else {
83798384
g_assert (res);
8380-
buffer_add_value (buf, sig->ret, mono_object_unbox (res), domain);
8385+
8386+
if (sig->ret->byref) {
8387+
MonoType* ret_byval = &mono_class_from_mono_type (sig->ret)->byval_arg;
8388+
buffer_add_value (buf, ret_byval, mono_object_unbox (res), domain);
8389+
} else {
8390+
buffer_add_value (buf, sig->ret, mono_object_unbox (res), domain);
8391+
}
83818392
}
83828393
} else {
83838394
NOT_IMPLEMENTED;

0 commit comments

Comments
 (0)