Skip to content

Commit cd7662e

Browse files
fanyang-monolewing
authored andcommitted
[mono] UnsafeAccessor: Add support for non-generic method instance (dotnet#101442)
* Support non generic instance * Create helper function for shared code * Use an existing API * Add an assert --------- Co-authored-by: Larry Ewing <lewing@microsoft.com>
1 parent f387d8e commit cd7662e

File tree

5 files changed

+72
-31
lines changed

5 files changed

+72
-31
lines changed

src/mono/mono/metadata/class.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -5264,7 +5264,7 @@ mono_class_get_fields_internal (MonoClass *klass, gpointer *iter)
52645264
* mono_class_get_methods:
52655265
* \param klass the \c MonoClass to act on
52665266
*
5267-
* This routine is an iterator routine for retrieving the fields in a class.
5267+
* This routine is an iterator routine for retrieving the methods in a class.
52685268
*
52695269
* You must pass a \c gpointer that points to zero and is treated as an opaque handle to
52705270
* iterate over all of the elements. When no more values are

src/mono/mono/metadata/marshal-lightweight.c

+64-9
Original file line numberDiff line numberDiff line change
@@ -2424,6 +2424,44 @@ emit_missing_method_error (MonoMethodBuilder *mb, MonoError *failure, const char
24242424
}
24252425
}
24262426

2427+
static MonoMethodSignature *
2428+
update_signature (MonoMethod *accessor_method)
2429+
{
2430+
MonoClass *accessor_method_class_instance = accessor_method->klass;
2431+
MonoClass *accessor_method_class = mono_class_get_generic_type_definition (accessor_method_class_instance);
2432+
2433+
const char *accessor_method_name = accessor_method->name;
2434+
2435+
gpointer iter = NULL;
2436+
MonoMethod *m = NULL;
2437+
while ((m = mono_class_get_methods (accessor_method_class, &iter))) {
2438+
if (!m)
2439+
continue;
2440+
2441+
if (strcmp (m->name, accessor_method_name))
2442+
continue;
2443+
2444+
return mono_metadata_signature_dup_full (get_method_image (m), mono_method_signature_internal (m));
2445+
}
2446+
g_assert_not_reached ();
2447+
}
2448+
2449+
static MonoMethod *
2450+
inflate_method (MonoClass *klass, MonoMethod *method, MonoMethod *accessor_method, MonoError *error)
2451+
{
2452+
MonoMethod *result = method;
2453+
MonoGenericContext context = { NULL, NULL };
2454+
if (mono_class_is_ginst (klass))
2455+
context.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
2456+
if (accessor_method->is_inflated)
2457+
context.method_inst = mono_method_get_context (accessor_method)->method_inst;
2458+
if ((context.class_inst != NULL) || (context.method_inst != NULL))
2459+
result = mono_class_inflate_generic_method_checked (method, &context, error);
2460+
mono_error_assert_ok (error);
2461+
2462+
return result;
2463+
}
2464+
24272465
static void
24282466
emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoGenericContext *ctx, MonoUnsafeAccessorKind kind, const char *member_name)
24292467
{
@@ -2442,12 +2480,17 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_m
24422480
return;
24432481
}
24442482

2445-
MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig, ctx);
2446-
24472483
MonoClass *target_class = mono_class_from_mono_type_internal (target_type);
24482484

24492485
ERROR_DECL(find_method_error);
2450-
MonoClass *in_class = mono_class_is_ginst (target_class) ? mono_class_get_generic_class (target_class)->container_class : target_class;
2486+
if (accessor_method->is_inflated) {
2487+
sig = update_signature(accessor_method);
2488+
}
2489+
2490+
MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig, ctx);
2491+
2492+
MonoClass *in_class = mono_class_get_generic_type_definition (target_class);
2493+
24512494
MonoMethod *target_method = mono_unsafe_accessor_find_ctor (in_class, member_sig, target_class, find_method_error);
24522495
if (!is_ok (find_method_error) || target_method == NULL) {
24532496
if (mono_error_get_error_code (find_method_error) == MONO_ERROR_GENERIC)
@@ -2457,6 +2500,9 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_m
24572500
mono_error_cleanup (find_method_error);
24582501
return;
24592502
}
2503+
2504+
target_method = inflate_method (target_class, target_method, accessor_method, find_method_error);
2505+
24602506
g_assert (target_method->klass == target_class);
24612507

24622508
emit_unsafe_accessor_ldargs (mb, sig, 0);
@@ -2478,11 +2524,9 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor
24782524
mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute.");
24792525
return;
24802526
}
2481-
gboolean hasthis = kind == MONO_UNSAFE_ACCESSOR_METHOD;
2482-
MonoType *target_type = sig->params[0];
2483-
2484-
MonoMethodSignature *member_sig = method_sig_from_accessor_sig (mb, hasthis, sig, ctx);
24852527

2528+
MonoType *target_type = sig->params[0];
2529+
gboolean hasthis = kind == MONO_UNSAFE_ACCESSOR_METHOD;
24862530
MonoClass *target_class = mono_class_from_mono_type_internal (target_type);
24872531

24882532
if (hasthis && m_class_is_valuetype (target_class) && !m_type_is_byref (target_type)) {
@@ -2491,7 +2535,14 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor
24912535
}
24922536

24932537
ERROR_DECL(find_method_error);
2494-
MonoClass *in_class = mono_class_is_ginst (target_class) ? mono_class_get_generic_class (target_class)->container_class : target_class;
2538+
if (accessor_method->is_inflated) {
2539+
sig = update_signature(accessor_method);
2540+
}
2541+
2542+
MonoMethodSignature *member_sig = method_sig_from_accessor_sig (mb, hasthis, sig, ctx);
2543+
2544+
MonoClass *in_class = mono_class_get_generic_type_definition (target_class);
2545+
24952546
MonoMethod *target_method = NULL;
24962547
if (!ctor_as_method)
24972548
target_method = mono_unsafe_accessor_find_method (in_class, member_name, member_sig, target_class, find_method_error);
@@ -2505,11 +2556,15 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor
25052556
mono_error_cleanup (find_method_error);
25062557
return;
25072558
}
2559+
2560+
target_method = inflate_method (target_class, target_method, accessor_method, find_method_error);
2561+
25082562
if (!hasthis && target_method->klass != target_class) {
25092563
emit_missing_method_error (mb, find_method_error, member_name);
25102564
return;
25112565
}
2512-
g_assert (target_method->klass == target_class); // are instance methods allowed to be looked up using inheritance?
2566+
2567+
g_assert (target_method->klass == target_class);
25132568

25142569
emit_unsafe_accessor_ldargs (mb, sig, !hasthis ? 1 : 0);
25152570

src/mono/mono/metadata/unsafe-accessor.c

+6-16
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
#include "mono/metadata/class-internals.h"
1515
#include "mono/utils/mono-error-internals.h"
1616
#include "mono/metadata/unsafe-accessor.h"
17-
17+
#include <mono/metadata/debug-helpers.h>
1818

1919

2020
static MonoMethod *
@@ -134,7 +134,10 @@ find_method_slow (MonoClass *klass, const char *name, const char *qname, const c
134134
return precise_match;
135135
}
136136
mono_error_set_generic_error (error, "System.Reflection", "AmbiguousMatchException", "Ambiguity in binding of UnsafeAccessorAttribute.");
137-
return NULL;
137+
result->i = -1;
138+
result->m = NULL;
139+
result->matched = FALSE;
140+
return result;
138141
}
139142
matched = TRUE;
140143
result->i = i;
@@ -176,23 +179,10 @@ find_method_in_class_unsafe_accessor (MonoClass *klass, const char *name, const
176179
if (!is_ok(error) && mono_error_get_error_code (error) == MONO_ERROR_GENERIC)
177180
return NULL;
178181

179-
int mcount = mono_class_get_method_count (klass);
180182

181183
g_assert (result != NULL);
182184
if (result->matched) {
183-
if (result->i < mcount)
184-
return mono_class_get_method_by_index (from_class, result->i);
185-
else if (result->m != NULL) {
186-
// FIXME: metadata-update: hack
187-
// it's from a metadata-update, probably
188-
MonoMethod * m = mono_class_inflate_generic_method_full_checked (
189-
result->m, from_class, mono_class_get_context (from_class), error);
190-
mono_error_assert_ok (error);
191-
g_assert (m != NULL);
192-
g_assert (m->klass == from_class);
193-
g_assert (m->is_inflated);
194-
return m;
195-
}
185+
return result->m;
196186
}
197187

198188
g_free (result);

src/mono/mono/mini/method-to-ir.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -7901,7 +7901,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
79017901
UNVERIFIED;
79027902

79037903
if (!cfg->gshared)
7904-
g_assert (!mono_method_check_context_used (cmethod));
7904+
g_assertf (!mono_method_check_context_used (cmethod), "cmethod is %s", mono_method_get_full_name (cmethod));
79057905

79067906
CHECK_STACK (n);
79077907

src/tests/baseservices/compilerservices/UnsafeAccessors/UnsafeAccessorsTests.Generics.cs

-4
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,6 @@ sealed class Derived2 : GenericBase<string>
140140
}
141141

142142
[Fact]
143-
[ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)]
144143
public static void Verify_Generic_InheritanceMethodResolution()
145144
{
146145
string expect = "abc";
@@ -230,7 +229,6 @@ sealed class Accessors<V>
230229
}
231230

232231
[Fact]
233-
[ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)]
234232
public static void Verify_Generic_CallCtor()
235233
{
236234
Console.WriteLine($"Running {nameof(Verify_Generic_CallCtor)}");
@@ -312,7 +310,6 @@ public static void Verify_Generic_GenericTypeNonGenericInstanceMethod()
312310
}
313311

314312
[Fact]
315-
[ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)]
316313
public static void Verify_Generic_GenericTypeGenericInstanceMethod()
317314
{
318315
Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeGenericInstanceMethod)}");
@@ -366,7 +363,6 @@ public static void Verify_Generic_GenericTypeNonGenericStaticMethod()
366363
}
367364

368365
[Fact]
369-
[ActiveIssue("https://github.com/dotnet/runtime/issues/89439", TestRuntimes.Mono)]
370366
public static void Verify_Generic_GenericTypeGenericStaticMethod()
371367
{
372368
Console.WriteLine($"Running {nameof(Verify_Generic_GenericTypeGenericStaticMethod)}");

0 commit comments

Comments
 (0)