Beispiel #1
0
        public void RegisterNewNamedTypeRuntimeTypeHandle(MetadataReader metadataReader, TypeDefinitionHandle typeDefHandle, RuntimeTypeHandle runtimeTypeHandle, IntPtr nonGcStaticFields, IntPtr gcStaticFields)
        {
            NamedTypeMetadataDescription description = new NamedTypeMetadataDescription()
            {
                MetadataReader = metadataReader,
                TypeDefinition = typeDefHandle
            };

            TypeLoaderLogger.WriteLine("Register new type with eetype = " + runtimeTypeHandle.ToIntPtr().LowLevelToString() + " nonGcStaticFields " + nonGcStaticFields.LowLevelToString() + " gcStaticFields " + gcStaticFields.LowLevelToString());
            NamedTypeLookupResult result = _metadataToRuntimeTypeHandleHashtable.GetOrCreateValue(description);

            result.VersionNumber     = _namedTypeLookupLiveVersion + 1;
            result.RuntimeTypeHandle = runtimeTypeHandle;
            result.GcStaticFields    = gcStaticFields;
            result.NonGcStaticFields = nonGcStaticFields;
            unsafe
            {
                result.RuntimeTypeHandleHashcode = (int)runtimeTypeHandle.ToEETypePtr()->HashCode;
            }

            NamedTypeLookupResult rthToMetadataResult = _runtimeTypeHandleToMetadataHashtable.AddOrGetExisting(result);

            if (!Object.ReferenceEquals(rthToMetadataResult, result))
            {
                rthToMetadataResult.TypeDefinition    = typeDefHandle;
                rthToMetadataResult.MetadataReader    = metadataReader;
                rthToMetadataResult.GcStaticFields    = gcStaticFields;
                rthToMetadataResult.NonGcStaticFields = nonGcStaticFields;
            }
        }
Beispiel #2
0
        /// <summary>
        /// Get the NativeLayout for a type from a ReadyToRun image.
        /// </summary>
        public static bool TryGetMetadataNativeLayout(TypeDesc concreteType, out NativeFormatModuleInfo nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = null;
            nativeLayoutInfoToken  = 0;
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            var nativeMetadataType = concreteType.GetTypeDefinition() as TypeSystem.NativeFormat.NativeFormatType;
            if (nativeMetadataType == null)
            {
                return(false);
            }

            var canonForm = concreteType.ConvertToCanonForm(CanonicalFormKind.Specific);
            var hashCode  = canonForm.GetHashCode();

#if SUPPORTS_R2R_LOADING
            foreach (var moduleInfo in ModuleList.EnumerateModules())
            {
                if (moduleInfo.MetadataReader == null)
                {
                    continue;
                }

                ExternalReferencesTable externalFixupsTable;
                NativeHashtable         typeTemplatesHashtable = LoadHashtable(moduleInfo.Handle, ReflectionMapBlob.MetadataBasedTypeTemplateMap, out externalFixupsTable);

                if (typeTemplatesHashtable.IsNull)
                {
                    continue;
                }

                var enumerator         = typeTemplatesHashtable.Lookup(hashCode);
                var nativeMetadataUnit = nativeMetadataType.Context.ResolveMetadataUnit(moduleInfo);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    var      entryTypeHandle = entryParser.GetUnsigned().AsHandle();
                    TypeDesc typeDesc        = nativeMetadataUnit.GetType(entryTypeHandle);
                    Debug.Assert(typeDesc != null);
                    if (typeDesc == canonForm)
                    {
                        TypeLoaderLogger.WriteLine("Found metadata template for type " + concreteType.ToString() + ": " + typeDesc.ToString());
                        nativeLayoutInfoToken = entryParser.GetUnsigned();
                        if (nativeLayoutInfoToken == BadTokenFixupValue)
                        {
                            throw new BadImageFormatException();
                        }

                        nativeLayoutInfoModule = moduleHandle;
                        return(true);
                    }
                }
            }
#endif
#endif

            return(false);
        }
Beispiel #3
0
        private ComputedStaticFieldLayout ParseStaticRegionSizesFromNativeLayout(TypeDesc type)
        {
            LayoutInt nonGcDataSize  = LayoutInt.Zero;
            LayoutInt gcDataSize     = LayoutInt.Zero;
            LayoutInt threadDataSize = LayoutInt.Zero;

            TypeBuilderState state          = type.GetOrCreateTypeBuilderState();
            NativeParser     typeInfoParser = state.GetParserForNativeLayoutInfo();

            BagElementKind kind;

            while ((kind = typeInfoParser.GetBagElementKind()) != BagElementKind.End)
            {
                switch (kind)
                {
                case BagElementKind.NonGcStaticDataSize:
                    TypeLoaderLogger.WriteLine("Found BagElementKind.NonGcStaticDataSize");
                    // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
                    nonGcDataSize = new LayoutInt(checked ((int)typeInfoParser.GetUnsigned()));
                    break;

                case BagElementKind.GcStaticDataSize:
                    TypeLoaderLogger.WriteLine("Found BagElementKind.GcStaticDataSize");
                    // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
                    gcDataSize = new LayoutInt(checked ((int)typeInfoParser.GetUnsigned()));
                    break;

                case BagElementKind.ThreadStaticDataSize:
                    TypeLoaderLogger.WriteLine("Found BagElementKind.ThreadStaticDataSize");
                    // Use checked typecast to int to ensure there aren't any overflows/truncations (size value used in allocation of memory later)
                    threadDataSize = new LayoutInt(checked ((int)typeInfoParser.GetUnsigned()));
                    break;

                default:
                    typeInfoParser.SkipInteger();
                    break;
                }
            }

            ComputedStaticFieldLayout staticLayout = new ComputedStaticFieldLayout()
            {
                GcStatics = new StaticsBlock()
                {
                    Size = gcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible
                },
                NonGcStatics = new StaticsBlock()
                {
                    Size = nonGcDataSize, LargestAlignment = DefType.MaximumAlignmentPossible
                },
                Offsets       = null, // We're not computing field offsets here, so return null
                ThreadStatics = new StaticsBlock()
                {
                    Size = threadDataSize, LargestAlignment = DefType.MaximumAlignmentPossible
                },
            };

            return(staticLayout);
        }
Beispiel #4
0
        /// <summary>
        /// Get the NativeLayout for a method from a ReadyToRun image.
        /// </summary>
        public bool TryGetMetadataNativeLayout(MethodDesc concreteMethod, out IntPtr nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = default(IntPtr);
            nativeLayoutInfoToken  = 0;
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
            var nativeMetadataType = concreteMethod.GetTypicalMethodDefinition() as TypeSystem.NativeFormat.NativeFormatMethod;
            if (nativeMetadataType == null)
            {
                return(false);
            }

            var canonForm = concreteMethod.GetCanonMethodTarget(CanonicalFormKind.Specific);
            var hashCode  = canonForm.GetHashCode();

            var loadedModulesCount  = RuntimeAugments.GetLoadedModules(null);
            var loadedModuleHandles = new IntPtr[loadedModulesCount];
            var loadedModules       = RuntimeAugments.GetLoadedModules(loadedModuleHandles);
            Debug.Assert(loadedModulesCount == loadedModules);

#if SUPPORTS_R2R_LOADING
            foreach (var moduleHandle in loadedModuleHandles)
            {
                ExternalReferencesTable externalFixupsTable;
                NativeHashtable         methodTemplatesHashtable = LoadHashtable(moduleHandle, ReflectionMapBlob.MetadataBasedGenericMethodsTemplateMap, out externalFixupsTable);

                if (methodTemplatesHashtable.IsNull)
                {
                    continue;
                }

                var enumerator         = methodTemplatesHashtable.Lookup(hashCode);
                var nativeMetadataUnit = nativeMetadataType.Context.ResolveMetadataUnit(moduleHandle);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    var        entryTypeHandle = entryParser.GetUnsigned().AsHandle();
                    MethodDesc methodDesc      = nativeMetadataUnit.GetMethod(entryTypeHandle, null);
                    Debug.Assert(methodDesc != null);
                    if (methodDesc == canonForm)
                    {
                        TypeLoaderLogger.WriteLine("Found metadata template for method " + concreteMethod.ToString() + ": " + methodDesc.ToString());
                        nativeLayoutInfoToken = (uint)externalFixupsTable.GetRvaFromIndex(entryParser.GetUnsigned());
                        if (nativeLayoutInfoToken == BadTokenFixupValue)
                        {
                            throw new BadImageFormatException();
                        }

                        nativeLayoutInfoModule = moduleHandle;
                        return(true);
                    }
                }
            }
#endif
#endif
            return(false);
        }
Beispiel #5
0
        private TypeDesc TryGetTypeTemplate_Internal(TypeDesc concreteType, CanonicalFormKind kind, out IntPtr nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = default(IntPtr);
            nativeLayoutInfoToken  = 0;
            var canonForm = concreteType.ConvertToCanonForm(kind);
            var hashCode  = canonForm.GetHashCode();

            var loadedModulesCount  = RuntimeAugments.GetLoadedModules(null);
            var loadedModuleHandles = new IntPtr[loadedModulesCount];
            var loadedModules       = RuntimeAugments.GetLoadedModules(loadedModuleHandles);

            Debug.Assert(loadedModulesCount == loadedModules);

            foreach (var moduleHandle in loadedModuleHandles)
            {
                ExternalReferencesTable externalFixupsTable;
                NativeHashtable         typeTemplatesHashtable = LoadHashtable(moduleHandle, ReflectionMapBlob.TypeTemplateMap, out externalFixupsTable);

                if (typeTemplatesHashtable.IsNull)
                {
                    continue;
                }

                var enumerator = typeTemplatesHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    RuntimeTypeHandle candidateTemplateTypeHandle = externalFixupsTable.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned());
                    TypeDesc          candidateTemplate           = concreteType.Context.ResolveRuntimeTypeHandle(candidateTemplateTypeHandle);

                    if (canonForm == candidateTemplate.ConvertToCanonForm(kind))
                    {
                        TypeLoaderLogger.WriteLine("Found template for type " + concreteType.ToString() + ": " + candidateTemplate.ToString());
                        nativeLayoutInfoToken = (uint)externalFixupsTable.GetRvaFromIndex(entryParser.GetUnsigned());
                        if (nativeLayoutInfoToken == BadTokenFixupValue)
                        {
                            // TODO: once multifile gets fixed up, make this throw a BadImageFormatException
                            TypeLoaderLogger.WriteLine("ERROR: template not fixed up, skipping");
                            continue;
                        }

                        Debug.Assert(
                            (kind != CanonicalFormKind.Universal && candidateTemplate != candidateTemplate.ConvertToCanonForm(kind)) ||
                            (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.ConvertToCanonForm(kind)));

                        nativeLayoutInfoModule = moduleHandle;
                        return(candidateTemplate);
                    }
                }
            }

            TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for type " + concreteType.ToString());
            return(null);
        }
Beispiel #6
0
        public void RegisterNewNamedTypeRuntimeTypeHandle(QTypeDefinition qTypeDefinition, RuntimeTypeHandle runtimeTypeHandle, IntPtr nonGcStaticFields, IntPtr gcStaticFields)
        {
            TypeLoaderLogger.WriteLine("Register new type with MethodTable = " + runtimeTypeHandle.ToIntPtr().LowLevelToString() + " nonGcStaticFields " + nonGcStaticFields.LowLevelToString() + " gcStaticFields " + gcStaticFields.LowLevelToString());
            NamedTypeLookupResult result = _metadataToRuntimeTypeHandleHashtable.GetOrCreateValue(qTypeDefinition);

            result.VersionNumber     = _namedTypeLookupLiveVersion + 1;
            result.RuntimeTypeHandle = runtimeTypeHandle;
            result.GcStaticFields    = gcStaticFields;
            result.NonGcStaticFields = nonGcStaticFields;
            unsafe
            {
                result.RuntimeTypeHandleHashcode = (int)runtimeTypeHandle.ToEETypePtr()->HashCode;
            }

            NamedTypeLookupResult rthToMetadataResult = _runtimeTypeHandleToMetadataHashtable.AddOrGetExisting(result);

            if (!object.ReferenceEquals(rthToMetadataResult, result))
            {
                rthToMetadataResult.QualifiedTypeDefinition = qTypeDefinition;
                rthToMetadataResult.GcStaticFields          = gcStaticFields;
                rthToMetadataResult.NonGcStaticFields       = nonGcStaticFields;
            }
        }
Beispiel #7
0
        // The layout algorithm should probably compute results and let the caller set things
        internal unsafe LayoutInt[] ComputeTypeSizeAndAlignment(TypeDesc type, FieldLoadState loadRequested, out LowLevelList <LayoutInt> fieldOffsets)
        {
            fieldOffsets = null;
            TypeLoaderLogger.WriteLine("Laying out type " + type.ToString() + ". IsValueType: " + (type.IsValueType ? "true" : "false") + ". LoadRequested = " + ((int)loadRequested).LowLevelToString());

            Debug.Assert(loadRequested != FieldLoadState.None);
            Debug.Assert(type is ArrayType || (type is DefType && ((DefType)type).HasInstantiation));

            bool isArray = type is ArrayType;

            LayoutInt[] position      = new LayoutInt[5];
            LayoutInt   alignRequired = LayoutInt.One;

            if ((loadRequested & FieldLoadState.Instance) == FieldLoadState.Instance)
            {
                ComputeTypeSizeBeforeFields(type, out position[(int)NativeFormat.FieldStorage.Instance], out alignRequired);
            }

            if (!isArray)
            {
                // Once this is done, the NativeLayoutFields on the type are initialized
                EnsureFieldLayoutLoadedForGenericType((DefType)type);
                Debug.Assert(type.NativeLayoutFields != null);
            }

            int instanceFields = 0;

            if (!isArray && type.NativeLayoutFields.Length > 0)
            {
                fieldOffsets = new LowLevelList <LayoutInt>(type.NativeLayoutFields.Length);
                for (int i = 0; i < type.NativeLayoutFields.Length; i++)
                {
                    TypeDesc fieldType    = type.NativeLayoutFields[i].FieldType;
                    int      fieldStorage = (int)type.NativeLayoutFields[i].FieldStorage;

                    if (!ShouldProcessField((NativeFormat.FieldStorage)fieldStorage, loadRequested))
                    {
                        continue;
                    }

                    // For value types, we will attempt to get the size and alignment from
                    // the runtime if possible, otherwise GetFieldSizeAndAlignment will
                    // recurse to lay out nested struct fields.
                    LayoutInt alignment;
                    LayoutInt size;
                    GetFieldSizeAlignment(fieldType, out size, out alignment);

                    Debug.Assert(alignment.AsInt > 0);

                    if (fieldStorage == (int)NativeFormat.FieldStorage.Instance)
                    {
                        instanceFields++;

                        // Ensure alignment of type is sufficient for this field
                        alignRequired = LayoutInt.Max(alignRequired, alignment);
                    }

                    position[fieldStorage] = LayoutInt.AlignUp(position[fieldStorage], alignment);
                    TypeLoaderLogger.WriteLine(" --> Field type " + fieldType.ToString() +
                                               " storage " + ((uint)(type.NativeLayoutFields[i].FieldStorage)).LowLevelToString() +
                                               " offset " + position[fieldStorage].LowLevelToString() +
                                               " alignment " + alignment.LowLevelToString());

                    fieldOffsets.Add(position[fieldStorage]);
                    position[fieldStorage] += size;
                }
            }

            // Pad the length of structs to be 1 if they are empty so we have no zero-length structures
            if ((position[(int)NativeFormat.FieldStorage.Instance] == LayoutInt.Zero) && type.IsValueType)
            {
                position[(int)NativeFormat.FieldStorage.Instance] = LayoutInt.One;
            }

            Debug.Assert(alignRequired == new LayoutInt(1) ||
                         alignRequired == new LayoutInt(2) ||
                         alignRequired == new LayoutInt(4) ||
                         alignRequired == new LayoutInt(8));

            position[InstanceAlignmentEntry] = alignRequired;

            return(position);
        }
Beispiel #8
0
        private static InstantiatedMethod TryGetGenericMethodTemplate_Internal(InstantiatedMethod concreteMethod, CanonicalFormKind kind, out NativeFormatModuleInfo nativeLayoutInfoModule, out uint nativeLayoutInfoToken)
        {
            nativeLayoutInfoModule = null;
            nativeLayoutInfoToken  = 0;
            var canonForm = concreteMethod.GetCanonMethodTarget(kind);
            var hashCode  = canonForm.GetHashCode();

            foreach (NativeFormatModuleInfo moduleInfo in ModuleList.EnumerateModules())
            {
                NativeReader nativeLayoutReader = TypeLoaderEnvironment.GetNativeLayoutInfoReader(moduleInfo.Handle);
                if (nativeLayoutReader == null)
                {
                    continue;
                }

                NativeHashtable genericMethodTemplatesHashtable = LoadHashtable(moduleInfo, ReflectionMapBlob.GenericMethodsTemplateMap, out _);

                if (genericMethodTemplatesHashtable.IsNull)
                {
                    continue;
                }

                var context = new NativeLayoutInfoLoadContext
                {
                    _typeSystemContext     = concreteMethod.Context,
                    _typeArgumentHandles   = concreteMethod.OwningType.Instantiation,
                    _methodArgumentHandles = concreteMethod.Instantiation,
                    _module = moduleInfo
                };

                var enumerator = genericMethodTemplatesHashtable.Lookup(hashCode);

                NativeParser entryParser;
                while (!(entryParser = enumerator.GetNext()).IsNull)
                {
                    var methodSignatureParser = new NativeParser(nativeLayoutReader, entryParser.GetUnsigned());

                    // Get the unified generic method holder and convert it to its canonical form
                    var candidateTemplate = (InstantiatedMethod)context.GetMethod(ref methodSignatureParser);
                    Debug.Assert(candidateTemplate.Instantiation.Length > 0);

                    if (canonForm == candidateTemplate.GetCanonMethodTarget(kind))
                    {
                        TypeLoaderLogger.WriteLine("Found template for generic method " + concreteMethod.ToString() + ": " + candidateTemplate.ToString());
                        nativeLayoutInfoModule = moduleInfo;
                        nativeLayoutInfoToken  = entryParser.GetUnsigned();
                        if (nativeLayoutInfoToken == BadTokenFixupValue)
                        {
                            // TODO: once multifile gets fixed up, make this throw a BadImageFormatException
                            TypeLoaderLogger.WriteLine("ERROR: template not fixed up, skipping");
                            continue;
                        }

                        Debug.Assert(
                            (kind != CanonicalFormKind.Universal) ||
                            (kind == CanonicalFormKind.Universal && candidateTemplate == candidateTemplate.GetCanonMethodTarget(kind)));

                        return(candidateTemplate);
                    }
                }
            }

            TypeLoaderLogger.WriteLine("ERROR: Cannot find a suitable template for generic method " + concreteMethod.ToString());
            return(null);
        }
        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);
        }