예제 #1
0
        /// <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);
            }
        }
예제 #2
0
        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);
        }