| File: Internal\Runtime\TypeLoader\TypeLoaderEnvironment.FieldAccess.cs | Web Access |
| Project: src\runtime\src\coreclr\nativeaot\System.Private.TypeLoader\src\System.Private.TypeLoader.csproj (System.Private.TypeLoader) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Diagnostics; using System.Reflection.Runtime.General; using Internal.Metadata.NativeFormat; using Internal.NativeFormat; using Internal.Runtime.Augments; using Internal.TypeSystem; namespace Internal.Runtime.TypeLoader { /// <summary> /// Helper structure describing all info needed to construct dynamic field accessors. /// </summary> public struct FieldAccessMetadata { /// <summary> /// Module containing the relevant metadata, null when not found /// </summary> public TypeManagerHandle MappingTableModule; /// <summary> /// Cookie for field access. This field is set to IntPtr.Zero when the value is not available. /// </summary> public IntPtr Cookie; /// <summary> /// Field access and characteristics bitmask. /// </summary> public FieldTableFlags Flags; /// <summary> /// Field offset, address or cookie based on field access type. /// </summary> public int Offset; } public sealed partial class TypeLoaderEnvironment { /// <summary> /// Try to look up field access info for given canon in metadata blobs for all available modules. /// </summary> /// <param name="declaringTypeHandle">Declaring type for the method</param> /// <param name="fieldHandle">Field handle</param> /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param> /// <returns>true when found, false otherwise</returns> public static unsafe bool TryGetFieldAccessMetadataFromFieldAccessMap( RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle, out FieldAccessMetadata fieldAccessMetadata) { fieldAccessMetadata = default; CanonicallyEquivalentEntryLocator canonWrapper = new CanonicallyEquivalentEntryLocator(declaringTypeHandle); foreach (NativeFormatModuleInfo mappingTableModule in ModuleList.EnumerateModules(RuntimeAugments.GetModuleFromTypeHandle(declaringTypeHandle))) { NativeReader fieldMapReader; if (!TryGetNativeReaderForBlob(mappingTableModule, ReflectionMapBlob.FieldAccessMap, out fieldMapReader)) continue; NativeParser fieldMapParser = new NativeParser(fieldMapReader, 0); NativeHashtable fieldHashtable = new NativeHashtable(fieldMapParser); ExternalReferencesTable externalReferences = default(ExternalReferencesTable); if (!externalReferences.InitializeCommonFixupsTable(mappingTableModule)) { continue; } var lookup = fieldHashtable.Lookup(canonWrapper.LookupHashCode); NativeParser entryParser; while (!(entryParser = lookup.GetNext()).IsNull) { // Grammar of a hash table entry: // Flags + DeclaringType + MdHandle or Name + Cookie or Ordinal or Offset FieldTableFlags entryFlags = (FieldTableFlags)entryParser.GetUnsigned(); RuntimeTypeHandle entryDeclaringTypeHandle = externalReferences.GetRuntimeTypeHandleFromIndex(entryParser.GetUnsigned()); if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle) && !canonWrapper.IsCanonicallyEquivalent(entryDeclaringTypeHandle)) continue; Handle entryFieldHandle = (((int)HandleType.Field << 25) | (int)entryParser.GetUnsigned()).AsHandle(); if (!fieldHandle.Equals(entryFieldHandle)) continue; int fieldOffset; IntPtr fieldAddressCookie = IntPtr.Zero; if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0) { fieldOffset = (int)entryParser.GetUnsigned(); } else { fieldOffset = 0; fieldAddressCookie = externalReferences.GetAddressFromIndex(entryParser.GetUnsigned()); FieldTableFlags storageClass = entryFlags & FieldTableFlags.StorageClass; if (storageClass == FieldTableFlags.GCStatic || storageClass == FieldTableFlags.ThreadStatic) fieldOffset = (int)entryParser.GetUnsigned(); } fieldAccessMetadata.MappingTableModule = mappingTableModule.Handle; fieldAccessMetadata.Cookie = fieldAddressCookie; fieldAccessMetadata.Flags = entryFlags; fieldAccessMetadata.Offset = fieldOffset; return true; } } return false; } } }