@@ -410,6 +410,14 @@ public uint GetTypeDefToken(TypeHandle typeHandle)
410410 MethodTable methodTable = _methodTables [ typeHandle . Address ] ;
411411 return ( uint ) ( methodTable . Flags . GetTypeDefRid ( ) | ( ( int ) TableIndex . TypeDef << 24 ) ) ;
412412 }
413+ public ushort GetNumVtableSlots ( TypeHandle typeHandle )
414+ {
415+ if ( ! typeHandle . IsMethodTable ( ) )
416+ return 0 ;
417+ MethodTable methodTable = _methodTables [ typeHandle . Address ] ;
418+ ushort numNonVirtualSlots = methodTable . IsCanonMT ? GetClassData ( typeHandle ) . NumNonVirtualSlots : ( ushort ) 0 ;
419+ return checked ( ( ushort ) ( methodTable . NumVirtuals + numNonVirtualSlots ) ) ;
420+ }
413421 public ushort GetNumMethods ( TypeHandle typeHandle ) => ! typeHandle . IsMethodTable ( ) ? ( ushort ) 0 : GetClassData ( typeHandle ) . NumMethods ;
414422 public uint GetTypeDefTypeAttributes ( TypeHandle typeHandle ) => ! typeHandle . IsMethodTable ( ) ? ( uint ) 0 : GetClassData ( typeHandle ) . CorTypeAttr ;
415423 public ushort GetNumInstanceFields ( TypeHandle typeHandle ) => ! typeHandle . IsMethodTable ( ) ? ( ushort ) 0 : GetClassData ( typeHandle ) . NumInstanceFields ;
@@ -699,15 +707,6 @@ private FunctionPointerRetAndArgs(Target target, TargetPointer typePointer)
699707 }
700708 }
701709
702- private ushort GetNumVtableSlots ( TypeHandle typeHandle )
703- {
704- if ( ! typeHandle . IsMethodTable ( ) )
705- return 0 ;
706- MethodTable methodTable = _methodTables [ typeHandle . Address ] ;
707- ushort numNonVirtualSlots = methodTable . IsCanonMT ? GetClassData ( typeHandle ) . NumNonVirtualSlots : ( ushort ) 0 ;
708- return checked ( ( ushort ) ( methodTable . NumVirtuals + numNonVirtualSlots ) ) ;
709- }
710-
711710 public MethodDescHandle GetMethodDescHandle ( TargetPointer methodDescPointer )
712711 => GetMethodDescHandle ( methodDescPointer , validate : true ) ;
713712
@@ -1086,33 +1085,78 @@ private IEnumerable<MethodDescHandle> GetIntroducedMethods(TypeHandle typeHandle
10861085 }
10871086 }
10881087
1088+ IEnumerable < TargetPointer > IRuntimeTypeSystem . GetIntroducedMethodDescs ( TypeHandle typeHandle )
1089+ {
1090+ if ( ! typeHandle . IsMethodTable ( ) )
1091+ throw new ArgumentException ( $ "{ nameof ( typeHandle ) } is not a MethodTable") ;
1092+
1093+ TypeHandle canonMT = GetTypeHandle ( GetCanonicalMethodTable ( typeHandle ) ) ;
1094+ foreach ( MethodDescHandle mdh in GetIntroducedMethods ( canonMT ) )
1095+ {
1096+ yield return mdh . Address ;
1097+ }
1098+ }
1099+
1100+ // Uses GetMethodDescForSlotVtable if slot is less than the number of vtable slots
1101+ // otherwise looks for the slot in the introduced methods
10891102 TargetPointer IRuntimeTypeSystem . GetMethodDescForSlot ( TypeHandle typeHandle , ushort slot )
1103+ {
1104+ if ( ! typeHandle . IsMethodTable ( ) )
1105+ throw new ArgumentException ( $ "{ nameof ( typeHandle ) } is not a MethodTable") ;
1106+
1107+ TypeHandle canonMT = GetTypeHandle ( GetCanonicalMethodTable ( typeHandle ) ) ;
1108+ if ( slot < GetNumVtableSlots ( canonMT ) )
1109+ {
1110+ return GetMethodDescForSlotVtable ( canonMT , slot ) ;
1111+ }
1112+ else
1113+ {
1114+ foreach ( MethodDescHandle mdh in GetIntroducedMethods ( canonMT ) )
1115+ {
1116+ MethodDesc md = _methodDescs [ mdh . Address ] ;
1117+ if ( md . Slot == slot )
1118+ {
1119+ return mdh . Address ;
1120+ }
1121+ }
1122+ return TargetPointer . Null ;
1123+ }
1124+ }
1125+
1126+ private TargetPointer GetMethodDescForSlotVtable ( TypeHandle typeHandle , ushort slot )
10901127 {
10911128 // based on MethodTable::GetMethodDescForSlot_NoThrow
10921129 if ( ! typeHandle . IsMethodTable ( ) )
10931130 throw new ArgumentException ( $ "{ nameof ( typeHandle ) } is not a MethodTable") ;
10941131
10951132 TargetPointer cannonMTPTr = GetCanonicalMethodTable ( typeHandle ) ;
10961133 TypeHandle canonMT = GetTypeHandle ( cannonMTPTr ) ;
1134+ if ( slot >= GetNumVtableSlots ( canonMT ) )
1135+ throw new ArgumentException ( nameof ( slot ) , "Slot number is greater than the number of slots" ) ;
1136+
10971137 TargetPointer slotPtr = GetAddressOfSlot ( canonMT , slot ) ;
10981138 TargetCodePointer pCode = _target . ReadCodePointer ( slotPtr ) ;
10991139
11001140 if ( pCode == TargetCodePointer . Null )
11011141 {
1102- while ( canonMT . Address != TargetPointer . Null )
1142+ TargetPointer lookupMTPtr = cannonMTPTr ;
1143+ while ( lookupMTPtr != TargetPointer . Null )
11031144 {
11041145 // if pCode is null, we iterate through the method descs in the MT.
1105- foreach ( MethodDescHandle mdh in GetIntroducedMethods ( canonMT ) )
1146+ TypeHandle lookupMT = GetTypeHandle ( lookupMTPtr ) ;
1147+ foreach ( MethodDescHandle mdh in GetIntroducedMethods ( lookupMT ) )
11061148 {
11071149 MethodDesc md = _methodDescs [ mdh . Address ] ;
11081150 if ( md . Slot == slot )
11091151 {
11101152 return mdh . Address ;
11111153 }
11121154 }
1113- canonMT = GetTypeHandle ( GetCanonicalMethodTable ( GetTypeHandle ( GetParentMethodTable ( canonMT ) ) ) ) ;
1155+ lookupMTPtr = GetParentMethodTable ( lookupMT ) ;
1156+ if ( lookupMTPtr != TargetPointer . Null )
1157+ lookupMTPtr = GetCanonicalMethodTable ( GetTypeHandle ( lookupMTPtr ) ) ;
11141158 }
1115- Debug . Fail ( "We should never reach here, as there should always be a MethodDesc for a slot" ) ;
1159+ return TargetPointer . Null ;
11161160 }
11171161
11181162 return GetMethodDescForEntrypoint ( pCode ) ;
@@ -1135,6 +1179,21 @@ private readonly TargetPointer GetMethodDescForEntrypoint(TargetCodePointer pCod
11351179 }
11361180 }
11371181
1182+ TargetCodePointer IRuntimeTypeSystem . GetSlot ( TypeHandle typeHandle , uint slot )
1183+ {
1184+ // based on MethodTable::GetSlot(uint slotNumber)
1185+ if ( ! typeHandle . IsMethodTable ( ) )
1186+ throw new ArgumentException ( $ "{ nameof ( typeHandle ) } is not a MethodTable") ;
1187+
1188+ if ( slot < GetNumVtableSlots ( typeHandle ) )
1189+ {
1190+ TargetPointer slotPtr = GetAddressOfSlot ( typeHandle , slot ) ;
1191+ return _target . ReadCodePointer ( slotPtr ) ;
1192+ }
1193+
1194+ return TargetCodePointer . Null ;
1195+ }
1196+
11381197 TargetPointer IRuntimeTypeSystem . GetAddressOfNativeCodeSlot ( MethodDescHandle methodDesc )
11391198 {
11401199 MethodDesc md = _methodDescs [ methodDesc . Address ] ;
@@ -1161,6 +1220,12 @@ TargetCodePointer IRuntimeTypeSystem.GetNativeCode(MethodDescHandle methodDescHa
11611220 return GetStableEntryPoint ( md ) ;
11621221 }
11631222
1223+ TargetCodePointer IRuntimeTypeSystem . GetMethodEntryPointIfExists ( MethodDescHandle methodDescHandle )
1224+ {
1225+ MethodDesc md = _methodDescs [ methodDescHandle . Address ] ;
1226+ return GetMethodEntryPointIfExists ( md ) ;
1227+ }
1228+
11641229 private TargetCodePointer GetStableEntryPoint ( MethodDesc md )
11651230 {
11661231 // TODO(cdac): _ASSERTE(!IsVersionableWithVtableSlotBackpatch());
0 commit comments