From 5d648144df1fd27ca0f2f7e11ba42669d7145c0e Mon Sep 17 00:00:00 2001 From: Bill Holmes Date: Thu, 3 Jun 2021 11:07:42 -0400 Subject: [PATCH] Fixing the GetInterfaceMap tests for mono in the runtime repo. (#52566) Addressing 4 issues for GetInterfaceMap and default interface methods - Only methods marked as virtual on on interface should be added to the interface map. (no static or instance) - If the found target method is ambiguous (a diamond) the target is null. - If the found target method's class in an interface, then the target class is the interface class, else it is the class of the RuntimeType (aka this) - If the found target method is abstract (reabstraction) then the target is null. Fixes #34389 --- src/mono/mono/metadata/icall.c | 54 +++++++++++++++++++++++++++++++++++------- src/tests/issues.targets | 3 --- 2 files changed, 45 insertions(+), 12 deletions(-) diff --git a/src/mono/mono/metadata/icall.c b/src/mono/mono/metadata/icall.c index 52b1a4a..cddaa21 100644 --- a/src/mono/mono/metadata/icall.c +++ b/src/mono/mono/metadata/icall.c @@ -2535,10 +2535,36 @@ set_interface_map_data_method_object (MonoMethod *method, MonoClass *iclass, int MONO_HANDLE_ARRAY_SETREF (methods, i, member); - MONO_HANDLE_ASSIGN (member, mono_method_get_object_handle (m_class_get_vtable (klass) [i + ioffset], klass, error)); - goto_if_nok (error, leave); + MonoMethod* foundMethod = m_class_get_vtable (klass) [i + ioffset]; + + if (mono_class_has_dim_conflicts (klass) && mono_class_is_interface (foundMethod->klass)) { + GSList* conflicts = mono_class_get_dim_conflicts (klass); + GSList* l; + MonoMethod* decl = method; - MONO_HANDLE_ARRAY_SETREF (targets, i, member); + if (decl->is_inflated) + decl = ((MonoMethodInflated*)decl)->declaring; + + gboolean in_conflict = FALSE; + for (l = conflicts; l; l = l->next) { + if (decl == l->data) { + in_conflict = TRUE; + break; + } + } + if (in_conflict) { + MONO_HANDLE_ARRAY_SETREF (targets, i, NULL_HANDLE); + goto leave; + } + } + + if (foundMethod->flags & METHOD_ATTRIBUTE_ABSTRACT) + MONO_HANDLE_ARRAY_SETREF (targets, i, NULL_HANDLE); + else { + MONO_HANDLE_ASSIGN (member, mono_method_get_object_handle (foundMethod, mono_class_is_interface (foundMethod->klass) ? foundMethod->klass : klass, error)); + goto_if_nok (error, leave); + MONO_HANDLE_ARRAY_SETREF (targets, i, member); + } leave: HANDLE_FUNCTION_RETURN_VAL (is_ok (error)); @@ -2564,19 +2590,29 @@ ves_icall_RuntimeType_GetInterfaceMapData (MonoReflectionTypeHandle ref_type, Mo if (ioffset == -1) return; - int len = mono_class_num_methods (iclass); - MonoArrayHandle targets_arr = mono_array_new_handle (mono_defaults.method_info_class, len, error); + MonoMethod* method; + int i = 0; + gpointer iter = NULL; + + while ((method = mono_class_get_methods(iclass, &iter))) { + if (method->flags & METHOD_ATTRIBUTE_VIRTUAL) + i++; + } + + MonoArrayHandle targets_arr = mono_array_new_handle (mono_defaults.method_info_class, i, error); return_if_nok (error); MONO_HANDLE_ASSIGN (targets, targets_arr); - MonoArrayHandle methods_arr = mono_array_new_handle (mono_defaults.method_info_class, len, error); + MonoArrayHandle methods_arr = mono_array_new_handle (mono_defaults.method_info_class, i, error); return_if_nok (error); MONO_HANDLE_ASSIGN (methods, methods_arr); - MonoMethod* method; - int i = 0; - gpointer iter = NULL; + i = 0; + iter = NULL; + while ((method = mono_class_get_methods (iclass, &iter))) { + if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) + continue; if (!set_interface_map_data_method_object (method, iclass, ioffset, klass, targets, methods, i, error)) return; i ++; diff --git a/src/tests/issues.targets b/src/tests/issues.targets index 3b55bae..5ae3670 100644 --- a/src/tests/issues.targets +++ b/src/tests/issues.targets @@ -1696,9 +1696,6 @@ needs triage - - https://github.com/dotnet/runtime/issues/34389 - needs triage -- 2.7.4