Skip to content

Commit 6f549af

Browse files
fanyang-monolewing
andauthored
[mono] UnsafeAccessor: Add support for non-generic method instance (#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 cdfc8f2 commit 6f549af

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
@@ -2371,6 +2371,44 @@ emit_missing_method_error (MonoMethodBuilder *mb, MonoError *failure, const char
23712371
}
23722372
}
23732373

2374+
static MonoMethodSignature *
2375+
update_signature (MonoMethod *accessor_method)
2376+
{
2377+
MonoClass *accessor_method_class_instance = accessor_method->klass;
2378+
MonoClass *accessor_method_class = mono_class_get_generic_type_definition (accessor_method_class_instance);
2379+
2380+
const char *accessor_method_name = accessor_method->name;
2381+
2382+
gpointer iter = NULL;
2383+
MonoMethod *m = NULL;
2384+
while ((m = mono_class_get_methods (accessor_method_class, &iter))) {
2385+
if (!m)
2386+
continue;
2387+
2388+
if (strcmp (m->name, accessor_method_name))
2389+
continue;
2390+
2391+
return mono_metadata_signature_dup_full (get_method_image (m), mono_method_signature_internal (m));
2392+
}
2393+
g_assert_not_reached ();
2394+
}
2395+
2396+
static MonoMethod *
2397+
inflate_method (MonoClass *klass, MonoMethod *method, MonoMethod *accessor_method, MonoError *error)
2398+
{
2399+
MonoMethod *result = method;
2400+
MonoGenericContext context = { NULL, NULL };
2401+
if (mono_class_is_ginst (klass))
2402+
context.class_inst = mono_class_get_generic_class (klass)->context.class_inst;
2403+
if (accessor_method->is_inflated)
2404+
context.method_inst = mono_method_get_context (accessor_method)->method_inst;
2405+
if ((context.class_inst != NULL) || (context.method_inst != NULL))
2406+
result = mono_class_inflate_generic_method_checked (method, &context, error);
2407+
mono_error_assert_ok (error);
2408+
2409+
return result;
2410+
}
2411+
23742412
static void
23752413
emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_method, MonoMethodSignature *sig, MonoGenericContext *ctx, MonoUnsafeAccessorKind kind, const char *member_name)
23762414
{
@@ -2389,12 +2427,17 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_m
23892427
return;
23902428
}
23912429

2392-
MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig, ctx);
2393-
23942430
MonoClass *target_class = mono_class_from_mono_type_internal (target_type);
23952431

23962432
ERROR_DECL(find_method_error);
2397-
MonoClass *in_class = mono_class_is_ginst (target_class) ? mono_class_get_generic_class (target_class)->container_class : target_class;
2433+
if (accessor_method->is_inflated) {
2434+
sig = update_signature(accessor_method);
2435+
}
2436+
2437+
MonoMethodSignature *member_sig = ctor_sig_from_accessor_sig (mb, sig, ctx);
2438+
2439+
MonoClass *in_class = mono_class_get_generic_type_definition (target_class);
2440+
23982441
MonoMethod *target_method = mono_unsafe_accessor_find_ctor (in_class, member_sig, target_class, find_method_error);
23992442
if (!is_ok (find_method_error) || target_method == NULL) {
24002443
if (mono_error_get_error_code (find_method_error) == MONO_ERROR_GENERIC)
@@ -2404,6 +2447,9 @@ emit_unsafe_accessor_ctor_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor_m
24042447
mono_error_cleanup (find_method_error);
24052448
return;
24062449
}
2450+
2451+
target_method = inflate_method (target_class, target_method, accessor_method, find_method_error);
2452+
24072453
g_assert (target_method->klass == target_class);
24082454

24092455
emit_unsafe_accessor_ldargs (mb, sig, 0);
@@ -2425,11 +2471,9 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor
24252471
mono_mb_emit_exception_full (mb, "System", "BadImageFormatException", "Invalid usage of UnsafeAccessorAttribute.");
24262472
return;
24272473
}
2428-
gboolean hasthis = kind == MONO_UNSAFE_ACCESSOR_METHOD;
2429-
MonoType *target_type = sig->params[0];
2430-
2431-
MonoMethodSignature *member_sig = method_sig_from_accessor_sig (mb, hasthis, sig, ctx);
24322474

2475+
MonoType *target_type = sig->params[0];
2476+
gboolean hasthis = kind == MONO_UNSAFE_ACCESSOR_METHOD;
24332477
MonoClass *target_class = mono_class_from_mono_type_internal (target_type);
24342478

24352479
if (hasthis && m_class_is_valuetype (target_class) && !m_type_is_byref (target_type)) {
@@ -2438,7 +2482,14 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor
24382482
}
24392483

24402484
ERROR_DECL(find_method_error);
2441-
MonoClass *in_class = mono_class_is_ginst (target_class) ? mono_class_get_generic_class (target_class)->container_class : target_class;
2485+
if (accessor_method->is_inflated) {
2486+
sig = update_signature(accessor_method);
2487+
}
2488+
2489+
MonoMethodSignature *member_sig = method_sig_from_accessor_sig (mb, hasthis, sig, ctx);
2490+
2491+
MonoClass *in_class = mono_class_get_generic_type_definition (target_class);
2492+
24422493
MonoMethod *target_method = NULL;
24432494
if (!ctor_as_method)
24442495
target_method = mono_unsafe_accessor_find_method (in_class, member_name, member_sig, target_class, find_method_error);
@@ -2452,11 +2503,15 @@ emit_unsafe_accessor_method_wrapper (MonoMethodBuilder *mb, MonoMethod *accessor
24522503
mono_error_cleanup (find_method_error);
24532504
return;
24542505
}
2506+
2507+
target_method = inflate_method (target_class, target_method, accessor_method, find_method_error);
2508+
24552509
if (!hasthis && target_method->klass != target_class) {
24562510
emit_missing_method_error (mb, find_method_error, member_name);
24572511
return;
24582512
}
2459-
g_assert (target_method->klass == target_class); // are instance methods allowed to be looked up using inheritance?
2513+
2514+
g_assert (target_method->klass == target_class);
24602515

24612516
emit_unsafe_accessor_ldargs (mb, sig, !hasthis ? 1 : 0);
24622517

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
@@ -7864,7 +7864,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
78647864
UNVERIFIED;
78657865

78667866
if (!cfg->gshared)
7867-
g_assert (!mono_method_check_context_used (cmethod));
7867+
g_assertf (!mono_method_check_context_used (cmethod), "cmethod is %s", mono_method_get_full_name (cmethod));
78687868

78697869
CHECK_STACK (n);
78707870

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)