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; } }
/// <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); }
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); }
/// <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); }
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); }
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; } }
// 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); }
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); }