@@ -1933,6 +1933,60 @@ mono_class_interface_offset (MonoClass *klass, MonoClass *itf)
19331933	return  -1 ;
19341934}
19351935
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+ 
19361990/** 
19371991 * mono_class_interface_offset_with_variance: 
19381992 * 
@@ -1959,11 +2013,11 @@ mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gbo
19592013
19602014	int  klass_interface_offsets_count  =  m_class_get_interface_offsets_count  (klass );
19612015
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 ) {
19632017		MonoClass  * gtd  =  mono_class_get_generic_type_definition  (itf );
19642018		int  found  =  -1 ;
19652019
1966- 		for  (i  =  klass_interface_offsets_count   -   1 ; i  >=  0 ; i -- ) {
2020+ 		for  (i  =  0 ; i  <   klass_interface_offsets_count ; i ++ ) {
19672021			if  (mono_class_is_variant_compatible  (itf , m_class_get_interfaces_packed  (klass ) [i ], FALSE)) {
19682022				/* 
19692023				g_print ( 
@@ -1981,7 +2035,7 @@ mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gbo
19812035		if  (found  !=  -1 )
19822036			return  m_class_get_interface_offsets_packed  (klass ) [found ];
19832037
1984- 		for  (i  =  klass_interface_offsets_count   -   1 ; i  >=  0 ; i -- ) {
2038+ 		for  (i  =  0 ; i  <   klass_interface_offsets_count ; i ++ ) {
19852039			if  (mono_class_get_generic_type_definition  (m_class_get_interfaces_packed  (klass ) [i ]) ==  gtd ) {
19862040				/* 
19872041				g_print ( 
@@ -2000,22 +2054,17 @@ mono_class_interface_offset_with_variance (MonoClass *klass, MonoClass *itf, gbo
20002054			return  -1 ;
20012055
20022056		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 );
20042061
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 ;
20072065
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 ;
20192068		}
20202069	}
20212070
0 commit comments