public EagerlyBuiltVTableSliceNode(TypeDesc type) : base(type) { var slots = new ArrayBuilder <MethodDesc>(); DefType defType = _type.GetClosestDefType(); foreach (var method in defType.GetAllVirtualMethods()) { slots.Add(method); } _slots = slots.ToArray(); }
/// <summary> /// Gets a value indicating whether '<paramref name="type"/>' might have a non-empty dispatch map. /// Note that this is only an approximation because we might not be able to take into account /// whether the interface methods are actually used. /// </summary> public static bool MightHaveInterfaceDispatchMap(TypeDesc type, NodeFactory factory) { if (type.IsArrayTypeWithoutGenericInterfaces()) { return(false); } if (!type.IsArray && !type.IsDefType) { return(false); } // Interfaces don't have a dispatch map because we dispatch them based on the // dispatch map of the implementing class. // The only exception are IDynamicInterfaceCastable scenarios that dispatch // using the interface dispatch map. // We generate the dispatch map irrespective of whether the interface actually // implements any methods (we don't run the for loop below) so that at runtime // we can distinguish between "the interface returned by IDynamicInterfaceCastable // wasn't marked as [DynamicInterfaceCastableImplementation]" and "we couldn't find an // implementation". We don't want to use the custom attribute for that at runtime because // that's reflection and this should work without reflection. if (type.IsInterface) { return(((MetadataType)type).IsDynamicInterfaceCastableImplementation()); } TypeDesc declType = type.GetClosestDefType(); for (int interfaceIndex = 0; interfaceIndex < declType.RuntimeInterfaces.Length; interfaceIndex++) { DefType interfaceType = declType.RuntimeInterfaces[interfaceIndex]; InstantiatedType interfaceOnDefinitionType = interfaceType.IsTypeDefinition ? null : (InstantiatedType)declType.GetTypeDefinition().RuntimeInterfaces[interfaceIndex]; IEnumerable <MethodDesc> slots; // If the vtable has fixed slots, we can query it directly. // If it's a lazily built vtable, we might not be able to query slots // just yet, so approximate by looking at all methods. VTableSliceNode vtableSlice = factory.VTable(interfaceType); if (vtableSlice.HasFixedSlots) { slots = vtableSlice.Slots; } else { slots = interfaceType.GetAllVirtualMethods(); } foreach (MethodDesc slotMethod in slots) { MethodDesc declMethod = slotMethod; Debug.Assert(!declMethod.Signature.IsStatic && declMethod.IsVirtual); if (interfaceOnDefinitionType != null) { declMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(declMethod.GetTypicalMethodDefinition(), interfaceOnDefinitionType); } var implMethod = declType.GetTypeDefinition().ResolveInterfaceMethodToVirtualMethodOnType(declMethod); if (implMethod != null) { return(true); } else { DefaultInterfaceMethodResolution result = declType.ResolveInterfaceMethodToDefaultImplementationOnType(slotMethod, out _); if (result != DefaultInterfaceMethodResolution.None) { return(true); } } } } return(false); }