Exemple #1
0
        internal static void EnsureFieldLayoutLoadedForGenericType(DefType type)
        {
            if (type.NativeLayoutFields != null)
            {
                return;
            }

            if (!type.IsTemplateUniversal())
            {
                // We can hit this case where the template of type in question is not a universal canonical type.
                // Example:
                //  BaseType<T> { ... }
                //  DerivedType<T, U> : BaseType<T> { ... }
                // and an instantiation like DerivedType<string, int>. In that case, BaseType<string> will have a non-universal
                // template type, and requires special handling to compute its size and field layout.
                EnsureFieldLayoutLoadedForNonUniversalType(type);
            }
            else
            {
                TypeBuilderState state             = type.GetOrCreateTypeBuilderState();
                NativeParser     typeInfoParser    = state.GetParserForNativeLayoutInfo();
                NativeParser     fieldLayoutParser = typeInfoParser.GetParserForBagElementKind(BagElementKind.FieldLayout);
                EnsureFieldLayoutLoadedForUniversalType(type, state.NativeLayoutInfo.LoadContext, fieldLayoutParser);
            }
        }
Exemple #2
0
        private static void EnsureFieldLayoutLoadedForNonUniversalType(DefType type)
        {
            Debug.Assert(type.HasInstantiation);
            Debug.Assert(!type.ComputeTemplate().IsCanonicalSubtype(CanonicalFormKind.Universal));

            if (type.NativeLayoutFields != null)
            {
                return;
            }

            // Look up the universal template for this type.  Only the universal template has field layout
            // information, so we have to use it to parse the field layout.
            NativeLayoutInfoLoadContext universalLayoutLoadContext;
            NativeLayoutInfo            universalLayoutInfo;
            NativeParser typeInfoParser = type.GetOrCreateTypeBuilderState().GetParserForUniversalNativeLayoutInfo(out universalLayoutLoadContext, out universalLayoutInfo);

            if (typeInfoParser.IsNull)
            {
                throw new TypeBuilder.MissingTemplateException();
            }

            // Now parse that layout into the NativeLayoutFields array.
            NativeParser fieldLayoutParser = typeInfoParser.GetParserForBagElementKind(BagElementKind.FieldLayout);

            type.NativeLayoutFields = ParseFieldLayout(type, universalLayoutLoadContext, fieldLayoutParser);
        }
Exemple #3
0
        private bool ComputeHasDictionaryInVTable()
        {
            if (!HasDictionarySlotInVTable)
            {
                return(false);
            }

            if (TypeBeingBuilt.RetrieveRuntimeTypeHandleIfPossible())
            {
                // Type was already constructed
                return(TypeBeingBuilt.RuntimeTypeHandle.GetDictionary() != IntPtr.Zero);
            }
            else
            {
                // Type is being newly constructed
                if (TemplateType != null)
                {
                    NativeParser parser = GetParserForNativeLayoutInfo();
                    // Template type loader case
#if GENERICS_FORCE_USG
                    bool isTemplateUniversalCanon = state.TemplateType.IsCanonicalSubtype(CanonicalFormKind.UniversalCanonLookup);
                    if (isTemplateUniversalCanon && type.CanShareNormalGenericCode())
                    {
                        TypeBuilderState tempState = new TypeBuilderState();
                        tempState.NativeLayoutInfo = new NativeLayoutInfo();
                        tempState.TemplateType     = type.Context.TemplateLookup.TryGetNonUniversalTypeTemplate(type, ref tempState.NativeLayoutInfo);
                        if (tempState.TemplateType != null)
                        {
                            Debug.Assert(!tempState.TemplateType.IsCanonicalSubtype(CanonicalFormKind.UniversalCanonLookup));
                            parser = GetNativeLayoutInfoParser(type, ref tempState.NativeLayoutInfo);
                        }
                    }
#endif
                    var dictionaryLayoutParser = parser.GetParserForBagElementKind(BagElementKind.DictionaryLayout);

                    return(!dictionaryLayoutParser.IsNull);
                }
                else
                {
                    NativeParser parser = GetParserForReadyToRunNativeLayoutInfo();
                    // ReadyToRun case
                    // Dictionary is directly encoded instead of the NativeLayout being a collection of bags
                    if (parser.IsNull)
                    {
                        return(false);
                    }

                    // First unsigned value in the native layout is the number of dictionary entries
                    return(parser.GetUnsigned() != 0);
                }
            }
        }
        public override DefType[] ComputeRuntimeInterfaces(TypeDesc type)
        {
            TypeBuilderState state = type.GetOrCreateTypeBuilderState();
            int totalInterfaces    = RuntimeAugments.GetInterfaceCount(state.TemplateType.RuntimeTypeHandle);

            TypeLoaderLogger.WriteLine("Building runtime interfaces for type " + type.ToString() + " (total interfaces = " + totalInterfaces.LowLevelToString() + ") ...");

            DefType[] interfaces    = new DefType[totalInterfaces];
            int       numInterfaces = 0;

            //
            // Copy over all interfaces from base class
            //
            if (type.BaseType != null)
            {
                foreach (var baseInterface in type.BaseType.RuntimeInterfaces)
                {
                    // There should be no duplicates
                    Debug.Assert(!InterfaceInSet(interfaces, numInterfaces, baseInterface));
                    interfaces[numInterfaces++] = baseInterface;
                    TypeLoaderLogger.WriteLine("    -> Added basetype interface " + baseInterface.ToString() + " on type " + type.ToString());
                }
            }

            NativeParser typeInfoParser  = state.GetParserForNativeLayoutInfo();
            NativeParser interfaceParser = typeInfoParser.GetParserForBagElementKind(BagElementKind.ImplementedInterfaces);

            TypeDesc[] implementedInterfaces;
            if (!interfaceParser.IsNull)
            {
                implementedInterfaces = state.NativeLayoutInfo.LoadContext.GetTypeSequence(ref interfaceParser);
            }
            else
            {
                implementedInterfaces = TypeDesc.EmptyTypes;
            }

            // Note that the order in which the interfaces are added to the list is same as the order in which the MDIL binder adds them.
            // It is required for correctness

            foreach (TypeDesc interfaceType in implementedInterfaces)
            {
                DefType interfaceTypeAsDefType = (DefType)interfaceType;

                // Skip duplicates
                if (InterfaceInSet(interfaces, numInterfaces, interfaceTypeAsDefType))
                {
                    continue;
                }
                interfaces[numInterfaces++] = interfaceTypeAsDefType;

                TypeLoaderLogger.WriteLine("    -> Added interface " + interfaceTypeAsDefType.ToString() + " on type " + type.ToString());

                foreach (var inheritedInterface in interfaceTypeAsDefType.RuntimeInterfaces)
                {
                    // Skip duplicates
                    if (InterfaceInSet(interfaces, numInterfaces, inheritedInterface))
                    {
                        continue;
                    }
                    interfaces[numInterfaces++] = inheritedInterface;
                    TypeLoaderLogger.WriteLine("    -> Added inherited interface " + inheritedInterface.ToString() + " on type " + type.ToString());
                }
            }

            // TODO: Handle the screwy cases of generic interface folding
            Debug.Assert(numInterfaces == totalInterfaces, "Unexpected number of interfaces");

            return(interfaces);
        }