Exemple #1
0
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly)
        {
            ObjectDataBuilder objData = new ObjectDataBuilder(factory, relocsOnly);

            objData.RequireInitialPointerAlignment();
            objData.AddSymbol(this);

            ComputeOptionalEETypeFields(factory, relocsOnly);

            OutputGCDesc(ref objData);
            OutputComponentSize(ref objData);
            OutputFlags(factory, ref objData);
            OutputBaseSize(ref objData);
            OutputRelatedType(factory, ref objData);

            // Number of vtable slots will be only known later. Reseve the bytes for it.
            var vtableSlotCountReservation = objData.ReserveShort();

            // Number of interfaces will only be known later. Reserve the bytes for it.
            var interfaceCountReservation = objData.ReserveShort();

            objData.EmitInt(_type.GetHashCode());
            objData.EmitPointerReloc(factory.TypeManagerIndirection);

            if (EmitVirtualSlotsAndInterfaces)
            {
                // Emit VTable
                Debug.Assert(objData.CountBytes - ((ISymbolDefinitionNode)this).Offset == GetVTableOffset(objData.TargetPointerSize));
                SlotCounter virtualSlotCounter = SlotCounter.BeginCounting(ref /* readonly */ objData);
                OutputVirtualSlots(factory, ref objData, _type, _type, relocsOnly);

                // Update slot count
                int numberOfVtableSlots = virtualSlotCounter.CountSlots(ref /* readonly */ objData);
                objData.EmitShort(vtableSlotCountReservation, checked ((short)numberOfVtableSlots));

                // Emit interface map
                SlotCounter interfaceSlotCounter = SlotCounter.BeginCounting(ref /* readonly */ objData);
                OutputInterfaceMap(factory, ref objData);

                // Update slot count
                int numberOfInterfaceSlots = interfaceSlotCounter.CountSlots(ref /* readonly */ objData);
                objData.EmitShort(interfaceCountReservation, checked ((short)numberOfInterfaceSlots));
            }
            else
            {
                // If we're not emitting any slots, the number of slots is zero.
                objData.EmitShort(vtableSlotCountReservation, 0);
                objData.EmitShort(interfaceCountReservation, 0);
            }

            OutputFinalizerMethod(factory, ref objData);
            OutputOptionalFields(factory, ref objData);
            OutputNullableTypeParameter(factory, ref objData);
            OutputGenericInstantiationDetails(factory, ref objData);

            return(objData.ToObjectData());
        }
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory);

            builder.Alignment = factory.Target.PointerSize;
            builder.DefinedSymbols.Add(this);

            // Don't bother sorting if we're not emitting the contents
            if (!relocsOnly)
            {
                _items.Sort((x, y) => Comparer <int> .Default.Compare((int)x.Id, (int)y.Id));
            }

            // ReadyToRunHeader.Magic
            builder.EmitInt((int)(ReadyToRunHeaderConstants.Signature));

            // ReadyToRunHeader.MajorVersion
            builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMajorVersion));
            builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMinorVersion));

            // ReadyToRunHeader.Flags
            builder.EmitInt(0);

            // ReadyToRunHeader.NumberOfSections
            var sectionCountReservation = builder.ReserveShort();

            // ReadyToRunHeader.EntrySize
            builder.EmitByte((byte)(8 + 2 * factory.Target.PointerSize));

            // ReadyToRunHeader.EntryType
            builder.EmitByte(1);

            int count = 0;

            foreach (var item in _items)
            {
                // Skip empty entries
                if (item.Node.ShouldSkipEmittingObjectNode(factory))
                {
                    continue;
                }

                builder.EmitInt((int)item.Id);

                ModuleInfoFlags flags = 0;
                if (item.EndSymbol != null)
                {
                    flags |= ModuleInfoFlags.HasEndPointer;
                }
                builder.EmitInt((int)flags);

                builder.EmitPointerReloc(item.StartSymbol);

                if (item.EndSymbol != null)
                {
                    builder.EmitPointerReloc(item.EndSymbol);
                }
                else
                {
                    builder.EmitZeroPointer();
                }

                count++;
            }
            builder.EmitShort(sectionCountReservation, checked ((short)count));

            return(builder.ToObjectData());
        }
        void EmitDispatchMap(ref ObjectDataBuilder builder, NodeFactory factory)
        {
            var entryCountReservation              = builder.ReserveShort();
            var defaultEntryCountReservation       = builder.ReserveShort();
            var staticEntryCountReservation        = builder.ReserveShort();
            var defaultStaticEntryCountReservation = builder.ReserveShort();
            int entryCount = 0;

            TypeDesc declType           = _type.GetClosestDefType();
            TypeDesc declTypeDefinition = declType.GetTypeDefinition();

            DefType[] declTypeRuntimeInterfaces           = declType.RuntimeInterfaces;
            DefType[] declTypeDefinitionRuntimeInterfaces = declTypeDefinition.RuntimeInterfaces;

            // Catch any runtime interface collapsing. We shouldn't have any
            Debug.Assert(declTypeRuntimeInterfaces.Length == declTypeDefinitionRuntimeInterfaces.Length);

            var defaultImplementations       = new List <(int InterfaceIndex, int InterfaceMethodSlot, int ImplMethodSlot)>();
            var staticImplementations        = new List <(int InterfaceIndex, int InterfaceMethodSlot, int ImplMethodSlot, int Context)>();
            var staticDefaultImplementations = new List <(int InterfaceIndex, int InterfaceMethodSlot, int ImplMethodSlot, int Context)>();

            // Resolve all the interfaces, but only emit non-static and non-default implementations
            for (int interfaceIndex = 0; interfaceIndex < declTypeRuntimeInterfaces.Length; interfaceIndex++)
            {
                var interfaceType           = declTypeRuntimeInterfaces[interfaceIndex];
                var interfaceDefinitionType = declTypeDefinitionRuntimeInterfaces[interfaceIndex];
                Debug.Assert(interfaceType.IsInterface);

                IReadOnlyList <MethodDesc> virtualSlots = factory.VTable(interfaceType).Slots;

                for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++)
                {
                    MethodDesc declMethod = virtualSlots[interfaceMethodSlot];
                    if (!interfaceType.IsTypeDefinition)
                    {
                        declMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(declMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceDefinitionType);
                    }

                    var implMethod = declMethod.Signature.IsStatic ?
                                     declTypeDefinition.ResolveInterfaceMethodToStaticVirtualMethodOnType(declMethod) :
                                     declTypeDefinition.ResolveInterfaceMethodToVirtualMethodOnType(declMethod);

                    // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface
                    // dispatch will walk the inheritance chain).
                    if (implMethod != null)
                    {
                        TypeDesc implType = declType;
                        while (!implType.HasSameTypeDefinition(implMethod.OwningType))
                        {
                            implType = implType.BaseType;
                        }

                        MethodDesc targetMethod = implMethod;
                        if (!implType.IsTypeDefinition)
                        {
                            targetMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(implMethod.GetTypicalMethodDefinition(), (InstantiatedType)implType);
                        }

                        int emittedInterfaceSlot = interfaceMethodSlot + (interfaceType.HasGenericDictionarySlot() ? 1 : 0);
                        int emittedImplSlot      = VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, declType);
                        if (targetMethod.Signature.IsStatic)
                        {
                            // If this is a static virtual, also remember whether we need generic context.
                            // The implementation is not callable without the generic context.
                            // Instance methods acquire the generic context from `this` and don't need it.
                            // The pointer to the generic context is stored in the owning type's vtable.
                            int genericContext = targetMethod.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg()
                                ? StaticVirtualMethodContextSource.ContextFromThisClass
                                : StaticVirtualMethodContextSource.None;
                            staticImplementations.Add((interfaceIndex, emittedInterfaceSlot, emittedImplSlot, genericContext));
                        }
                        else
                        {
                            builder.EmitShort((short)checked ((ushort)interfaceIndex));
                            builder.EmitShort((short)checked ((ushort)emittedInterfaceSlot));
                            builder.EmitShort((short)checked ((ushort)emittedImplSlot));
                            entryCount++;
                        }
                    }
                    else
                    {
                        // Is there a default implementation?

                        int?implSlot = null;

                        DefaultInterfaceMethodResolution result  = declTypeDefinition.ResolveInterfaceMethodToDefaultImplementationOnType(declMethod, out implMethod);
                        DefType providingInterfaceDefinitionType = null;
                        if (result == DefaultInterfaceMethodResolution.DefaultImplementation)
                        {
                            providingInterfaceDefinitionType = (DefType)implMethod.OwningType;
                            implMethod = implMethod.InstantiateSignature(declType.Instantiation, Instantiation.Empty);
                            implSlot   = VirtualMethodSlotHelper.GetDefaultInterfaceMethodSlot(factory, implMethod, declType, providingInterfaceDefinitionType);
                        }
                        else if (result == DefaultInterfaceMethodResolution.Reabstraction)
                        {
                            implSlot = SpecialDispatchMapSlot.Reabstraction;
                        }
                        else if (result == DefaultInterfaceMethodResolution.Diamond)
                        {
                            implSlot = SpecialDispatchMapSlot.Diamond;
                        }

                        if (implSlot.HasValue)
                        {
                            int emittedInterfaceSlot = interfaceMethodSlot + (interfaceType.HasGenericDictionarySlot() ? 1 : 0);
                            if (declMethod.Signature.IsStatic)
                            {
                                int genericContext = StaticVirtualMethodContextSource.None;
                                if (result == DefaultInterfaceMethodResolution.DefaultImplementation &&
                                    implMethod.GetCanonMethodTarget(CanonicalFormKind.Specific).RequiresInstArg())
                                {
                                    // If this is a static virtual, also remember whether we need generic context.
                                    // The implementation is not callable without the generic context.
                                    // Instance methods acquire the generic context from `this` and don't need it.
                                    // For default interface methods, the generic context is acquired by indexing
                                    // into the interface list of the owning type.
                                    Debug.Assert(providingInterfaceDefinitionType != null);
                                    int indexOfInterface = Array.IndexOf(declTypeDefinitionRuntimeInterfaces, providingInterfaceDefinitionType);
                                    Debug.Assert(indexOfInterface >= 0);
                                    genericContext = StaticVirtualMethodContextSource.ContextFromFirstInterface + indexOfInterface;
                                }
                                staticDefaultImplementations.Add((
                                                                     interfaceIndex,
                                                                     emittedInterfaceSlot,
                                                                     implSlot.Value,
                                                                     genericContext));
                            }
                            else
                            {
                                defaultImplementations.Add((
                                                               interfaceIndex,
                                                               emittedInterfaceSlot,
                                                               implSlot.Value));
                            }
                        }
                    }
                }
            }

            // Now emit the default implementations
            foreach (var defaultImplementation in defaultImplementations)
            {
                builder.EmitShort((short)checked ((ushort)defaultImplementation.InterfaceIndex));
                builder.EmitShort((short)checked ((ushort)defaultImplementation.InterfaceMethodSlot));
                builder.EmitShort((short)checked ((ushort)defaultImplementation.ImplMethodSlot));
            }

            // Now emit the static implementations
            foreach (var staticImplementation in staticImplementations)
            {
                builder.EmitShort((short)checked ((ushort)staticImplementation.InterfaceIndex));
                builder.EmitShort((short)checked ((ushort)staticImplementation.InterfaceMethodSlot));
                builder.EmitShort((short)checked ((ushort)staticImplementation.ImplMethodSlot));
                builder.EmitShort((short)checked ((ushort)staticImplementation.Context));
            }

            // Now emit the static default implementations
            foreach (var staticImplementation in staticDefaultImplementations)
            {
                builder.EmitShort((short)checked ((ushort)staticImplementation.InterfaceIndex));
                builder.EmitShort((short)checked ((ushort)staticImplementation.InterfaceMethodSlot));
                builder.EmitShort((short)checked ((ushort)staticImplementation.ImplMethodSlot));
                builder.EmitShort((short)checked ((ushort)staticImplementation.Context));
            }

            // Update the header
            builder.EmitShort(entryCountReservation, (short)checked ((ushort)entryCount));
            builder.EmitShort(defaultEntryCountReservation, (short)checked ((ushort)defaultImplementations.Count));
            builder.EmitShort(staticEntryCountReservation, (short)checked ((ushort)staticImplementations.Count));
            builder.EmitShort(defaultStaticEntryCountReservation, (short)checked ((ushort)staticDefaultImplementations.Count));
        }
Exemple #4
0
        void EmitDispatchMap(ref ObjectDataBuilder builder, NodeFactory factory)
        {
            var entryCountReservation        = builder.ReserveShort();
            var defaultEntryCountReservation = builder.ReserveShort();
            int entryCount = 0;

            TypeDesc declType           = _type.GetClosestDefType();
            TypeDesc declTypeDefinition = declType.GetTypeDefinition();

            DefType[] declTypeRuntimeInterfaces           = declType.RuntimeInterfaces;
            DefType[] declTypeDefinitionRuntimeInterfaces = declTypeDefinition.RuntimeInterfaces;

            // Catch any runtime interface collapsing. We shouldn't have any
            Debug.Assert(declTypeRuntimeInterfaces.Length == declTypeDefinitionRuntimeInterfaces.Length);

            var defaultImplementations = new List <(int InterfaceIndex, int InterfaceMethodSlot, int ImplMethodSlot)>();

            // Resolve all the interfaces, but only emit non-default implementations
            for (int interfaceIndex = 0; interfaceIndex < declTypeRuntimeInterfaces.Length; interfaceIndex++)
            {
                var interfaceType           = declTypeRuntimeInterfaces[interfaceIndex];
                var interfaceDefinitionType = declTypeDefinitionRuntimeInterfaces[interfaceIndex];
                Debug.Assert(interfaceType.IsInterface);

                IReadOnlyList <MethodDesc> virtualSlots = factory.VTable(interfaceType).Slots;

                for (int interfaceMethodSlot = 0; interfaceMethodSlot < virtualSlots.Count; interfaceMethodSlot++)
                {
                    MethodDesc declMethod = virtualSlots[interfaceMethodSlot];
                    if (!interfaceType.IsTypeDefinition)
                    {
                        declMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(declMethod.GetTypicalMethodDefinition(), (InstantiatedType)interfaceDefinitionType);
                    }

                    var implMethod = declTypeDefinition.ResolveInterfaceMethodToVirtualMethodOnType(declMethod);

                    // Interface methods first implemented by a base type in the hierarchy will return null for the implMethod (runtime interface
                    // dispatch will walk the inheritance chain).
                    if (implMethod != null)
                    {
                        TypeDesc implType = declType;
                        while (!implType.HasSameTypeDefinition(implMethod.OwningType))
                        {
                            implType = implType.BaseType;
                        }

                        MethodDesc targetMethod = implMethod;
                        if (!implType.IsTypeDefinition)
                        {
                            targetMethod = factory.TypeSystemContext.GetMethodForInstantiatedType(implMethod.GetTypicalMethodDefinition(), (InstantiatedType)implType);
                        }

                        builder.EmitShort((short)checked ((ushort)interfaceIndex));
                        builder.EmitShort((short)checked ((ushort)(interfaceMethodSlot + (interfaceType.HasGenericDictionarySlot() ? 1 : 0))));
                        builder.EmitShort((short)checked ((ushort)VirtualMethodSlotHelper.GetVirtualMethodSlot(factory, targetMethod, declType)));
                        entryCount++;
                    }
                    else
                    {
                        // Is there a default implementation?

                        int?implSlot = null;

                        DefaultInterfaceMethodResolution result = declTypeDefinition.ResolveInterfaceMethodToDefaultImplementationOnType(declMethod, out implMethod);
                        if (result == DefaultInterfaceMethodResolution.DefaultImplementation)
                        {
                            DefType providingInterfaceDefinitionType = (DefType)implMethod.OwningType;
                            implMethod = implMethod.InstantiateSignature(declType.Instantiation, Instantiation.Empty);
                            implSlot   = VirtualMethodSlotHelper.GetDefaultInterfaceMethodSlot(factory, implMethod, declType, providingInterfaceDefinitionType);
                        }
                        else if (result == DefaultInterfaceMethodResolution.Reabstraction)
                        {
                            implSlot = SpecialDispatchMapSlot.Reabstraction;
                        }
                        else if (result == DefaultInterfaceMethodResolution.Diamond)
                        {
                            implSlot = SpecialDispatchMapSlot.Diamond;
                        }

                        if (implSlot.HasValue)
                        {
                            defaultImplementations.Add((
                                                           interfaceIndex,
                                                           interfaceMethodSlot + (interfaceType.HasGenericDictionarySlot() ? 1 : 0),
                                                           implSlot.Value));
                        }
                    }
                }
            }

            // Now emit the default implementations
            foreach (var defaultImplementation in defaultImplementations)
            {
                builder.EmitShort((short)checked ((ushort)defaultImplementation.InterfaceIndex));
                builder.EmitShort((short)checked ((ushort)defaultImplementation.InterfaceMethodSlot));
                builder.EmitShort((short)checked ((ushort)defaultImplementation.ImplMethodSlot));
            }

            // Update the header
            builder.EmitShort(entryCountReservation, (short)checked ((ushort)entryCount));
            builder.EmitShort(defaultEntryCountReservation, (short)checked ((ushort)defaultImplementations.Count));
        }
        public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
        {
            ObjectDataBuilder builder = new ObjectDataBuilder(factory);
            builder.Alignment = factory.Target.PointerSize;
            builder.DefinedSymbols.Add(this);

            // Don't bother sorting if we're not emitting the contents
            if (!relocsOnly)
                _items.Sort((x, y) => Comparer<int>.Default.Compare((int)x.Id, (int)y.Id));

            // ReadyToRunHeader.Magic
            builder.EmitInt((int)(ReadyToRunHeaderConstants.Signature));

            // ReadyToRunHeader.MajorVersion
            builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMajorVersion));
            builder.EmitShort((short)(ReadyToRunHeaderConstants.CurrentMinorVersion));

            // ReadyToRunHeader.Flags
            builder.EmitInt(0);

            // ReadyToRunHeader.NumberOfSections
            var sectionCountReservation = builder.ReserveShort();

            // ReadyToRunHeader.EntrySize
            builder.EmitByte((byte)(8 + 2 * factory.Target.PointerSize));

            // ReadyToRunHeader.EntryType
            builder.EmitByte(1);

            int count = 0;
            foreach (var item in _items)
            {
                // Skip empty entries
                if (item.Node.ShouldSkipEmittingObjectNode(factory))
                    continue;

                builder.EmitInt((int)item.Id);

                ModuleInfoFlags flags = 0;
                if (item.EndSymbol != null)
                {
                    flags |= ModuleInfoFlags.HasEndPointer;
                }
                builder.EmitInt((int)flags);

                builder.EmitPointerReloc(item.StartSymbol);

                if (item.EndSymbol != null)
                {
                    builder.EmitPointerReloc(item.EndSymbol);
                }
                else
                {
                    builder.EmitZeroPointer();
                }

                count++;
            }
            builder.EmitShort(sectionCountReservation, checked((short)count));

            return builder.ToObjectData();
        }