/// <summary> /// Given a virtual method decl, return its VTable slot if the method is used on its containing type. /// Return -1 if the virtual method is not used. /// </summary> public static int GetVirtualMethodSlot(NodeFactory factory, MethodDesc method, TypeDesc implType, bool countDictionarySlots = true) { if (method.CanMethodBeInSealedVTable()) { // If the method is a sealed newslot method, it will be put in the sealed vtable instead of the type's vtable. In this // case, the slot index return should be the index in the sealed vtable, plus the total number of vtable slots. // First, make sure we are not attempting to resolve the slot of a sealed vtable method on a special array type, which // does not get any sealed vtable entries Debug.Assert(!implType.IsArrayTypeWithoutGenericInterfaces()); SealedVTableNode sealedVTable = factory.SealedVTable(implType); // Ensure the sealed vtable is built before computing the slot sealedVTable.BuildSealedVTableSlots(factory, relocsOnly: false /* GetVirtualMethodSlot is called in the final emission phase */); int sealedVTableSlot = sealedVTable.ComputeSealedVTableSlot(method); if (sealedVTableSlot == -1) { return(-1); } int numVTableSlots = GetNumberOfSlotsInCurrentType(factory, implType, countDictionarySlots); return(numVTableSlots + sealedVTableSlot); } else { // TODO: More efficient lookup of the slot TypeDesc owningType = method.OwningType; int baseSlots = GetNumberOfBaseSlots(factory, owningType, countDictionarySlots); // For types that have a generic dictionary, the introduced virtual method slots are // prefixed with a pointer to the generic dictionary. if (owningType.HasGenericDictionarySlot() && countDictionarySlots) { baseSlots++; } IReadOnlyList <MethodDesc> virtualSlots = factory.VTable(owningType).Slots; int methodSlot = -1; int numSealedVTableEntries = 0; for (int slot = 0; slot < virtualSlots.Count; slot++) { if (virtualSlots[slot].CanMethodBeInSealedVTable()) { numSealedVTableEntries++; continue; } if (virtualSlots[slot] == method) { methodSlot = slot; break; } } return(methodSlot == -1 ? -1 : baseSlots + methodSlot - numSealedVTableEntries); } }
public static int GetDefaultInterfaceMethodSlot(NodeFactory factory, MethodDesc method, TypeDesc implType, DefType interfaceOnDefinition, bool countDictionarySlots = true) { Debug.Assert(method.GetTypicalMethodDefinition().OwningType == interfaceOnDefinition.GetTypeDefinition()); SealedVTableNode sealedVTable = factory.SealedVTable(implType); // Ensure the sealed vtable is built before computing the slot sealedVTable.BuildSealedVTableSlots(factory, relocsOnly: false /* GetVirtualMethodSlot is called in the final emission phase */); int sealedVTableSlot = sealedVTable.ComputeDefaultInterfaceMethodSlot(method, interfaceOnDefinition); if (sealedVTableSlot == -1) { return(-1); } int numVTableSlots = GetNumberOfSlotsInCurrentType(factory, implType, countDictionarySlots); return(numVTableSlots + sealedVTableSlot); }