@@ -1933,6 +1933,60 @@ mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
1933
1933
return -1 ;
1934
1934
}
1935
1935
1936
+ typedef struct VarianceSearchEntry {
1937
+ MonoClass * klass ;
1938
+ int interface_offset ;
1939
+ } VarianceSearchEntry ;
1940
+
1941
+ static void
1942
+ build_variance_search_table (MonoClass * klass ) {
1943
+ guint buf_size = m_class_get_interface_offsets_count (klass ), buf_count = 0 ;
1944
+ VarianceSearchEntry * buf = g_alloca (buf_size * sizeof (VarianceSearchEntry ));
1945
+ memset (buf , 0 , buf_size * sizeof (VarianceSearchEntry ));
1946
+
1947
+ MonoClass * current = klass ;
1948
+ while (current ) {
1949
+ // g_print ("%s.%s:\n", m_class_get_name_space (current), m_class_get_name (current));
1950
+ MonoClass * * ifaces = m_class_get_interfaces (current );
1951
+ for (guint i = 0 , c = m_class_get_interface_count (current ); i < c ; i ++ ) {
1952
+ MonoClass * iface = ifaces [i ];
1953
+ if (!mono_class_has_variant_generic_params (iface ))
1954
+ continue ;
1955
+
1956
+ // FIXME: Avoid adding duplicates.
1957
+ // g_print ("-> %s.%s\n", m_class_get_name_space (iface), m_class_get_name (iface));
1958
+ g_assert (buf_count < buf_size );
1959
+ buf [buf_count ].klass = iface ;
1960
+ buf [buf_count ].interface_offset = mono_class_interface_offset (klass , iface );
1961
+ buf_count ++ ;
1962
+ }
1963
+
1964
+ current = current -> parent ;
1965
+ }
1966
+
1967
+ if (buf_count ) {
1968
+ guint bytes = buf_count * sizeof (VarianceSearchEntry );
1969
+ klass -> variant_search_table = g_malloc (bytes );
1970
+ memcpy (klass -> variant_search_table , buf , bytes );
1971
+ } else
1972
+ klass -> variant_search_table = NULL ;
1973
+ klass -> variant_search_table_length = buf_count ;
1974
+ klass -> variant_search_table_inited = TRUE;
1975
+ }
1976
+
1977
+ static void
1978
+ get_variance_search_table (MonoClass * klass , VarianceSearchEntry * * table , guint * table_size ) {
1979
+ g_assert (klass );
1980
+ g_assert (table );
1981
+ g_assert (table_size );
1982
+
1983
+ if (!klass -> variant_search_table_inited )
1984
+ build_variance_search_table (klass );
1985
+
1986
+ * table = (VarianceSearchEntry * )klass -> variant_search_table ;
1987
+ * table_size = klass -> variant_search_table_length ;
1988
+ }
1989
+
1936
1990
/**
1937
1991
* mono_class_interface_offset_with_variance:
1938
1992
*
@@ -1959,11 +2013,11 @@ mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gbo
1959
2013
1960
2014
int klass_interface_offsets_count = m_class_get_interface_offsets_count (klass );
1961
2015
1962
- if (m_class_is_array_special_interface (itf ) && m_class_get_rank (klass ) < 2 ) {
2016
+ if (m_class_is_array_special_interface (itf ) && m_class_get_rank (klass ) < 2 ) {
1963
2017
MonoClass * gtd = mono_class_get_generic_type_definition (itf );
1964
2018
int found = -1 ;
1965
2019
1966
- for (i = klass_interface_offsets_count - 1 ; i >= 0 ; i -- ) {
2020
+ for (i = 0 ; i < klass_interface_offsets_count ; i ++ ) {
1967
2021
if (mono_class_is_variant_compatible (itf , m_class_get_interfaces_packed (klass ) [i ], FALSE)) {
1968
2022
/*
1969
2023
g_print (
@@ -1981,7 +2035,7 @@ mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gbo
1981
2035
if (found != -1 )
1982
2036
return m_class_get_interface_offsets_packed (klass ) [found ];
1983
2037
1984
- for (i = klass_interface_offsets_count - 1 ; i >= 0 ; i -- ) {
2038
+ for (i = 0 ; i < klass_interface_offsets_count ; i ++ ) {
1985
2039
if (mono_class_get_generic_type_definition (m_class_get_interfaces_packed (klass ) [i ]) == gtd ) {
1986
2040
/*
1987
2041
g_print (
@@ -2000,22 +2054,17 @@ mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gbo
2000
2054
return -1 ;
2001
2055
2002
2056
return m_class_get_interface_offsets_packed (klass ) [found ];
2003
- }
2057
+ } else if (has_variance ) {
2058
+ VarianceSearchEntry * vst ;
2059
+ guint vst_count ;
2060
+ get_variance_search_table (klass , & vst , & vst_count );
2004
2061
2005
- if (!has_variance )
2006
- return -1 ;
2062
+ for (guint i = 0 ; i < vst_count ; i ++ ) {
2063
+ if (!mono_class_is_variant_compatible (itf , vst [i ].klass , FALSE))
2064
+ continue ;
2007
2065
2008
- for (i = klass_interface_offsets_count - 1 ; i >= 0 ; i -- ) {
2009
- if (mono_class_is_variant_compatible (itf , m_class_get_interfaces_packed (klass ) [i ], FALSE)) {
2010
- /*
2011
- g_print (
2012
- "is_variant_compatible (%s, %s, FALSE) == true\n",
2013
- iname,
2014
- mono_type_get_name_full (m_class_get_byval_arg (m_class_get_interfaces_packed (klass) [i]), MONO_TYPE_NAME_FORMAT_FULL_NAME)
2015
- );
2016
- */
2017
- * non_exact_match = (i != exact_match );
2018
- return m_class_get_interface_offsets_packed (klass ) [i ];
2066
+ * non_exact_match = (vst [i ].interface_offset != exact_match );
2067
+ return vst [i ].interface_offset ;
2019
2068
}
2020
2069
}
2021
2070
0 commit comments