diff options
author | Jan Kotas <jkotas@microsoft.com> | 2017-08-08 16:38:12 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-08-08 16:38:12 +0300 |
commit | 8f49f98c13a92637fef9a4873eb62cd7d546d6cd (patch) | |
tree | cf26d303bac1a32813503d35b86338d2096bb414 /src/System.Private.TypeLoader | |
parent | 822fbe9929509833283fe085ac0943e625acb69c (diff) | |
parent | c15fafd7c8659d18ebf23bb324afc3a9a000233b (diff) |
Merge pull request #4278 from dotnet/nmirror
Merge nmirror to master
Diffstat (limited to 'src/System.Private.TypeLoader')
3 files changed, 60 insertions, 101 deletions
diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/PermanentAllocatedMemoryBlobs.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/PermanentAllocatedMemoryBlobs.cs index 4e8781617..a55f50d25 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/PermanentAllocatedMemoryBlobs.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/PermanentAllocatedMemoryBlobs.cs @@ -19,9 +19,8 @@ namespace Internal.Runtime.TypeLoader { public sealed partial class PermanentAllocatedMemoryBlobs { - // Various functions in the type loader need to create permanent pointers for use by thread static lookup, or other purposes. + // Various functions in the type loader need to create permanent pointers for various purposes. - private static PermanentlyAllocatedMemoryRegions_ThreadStaticFieldOffsets s_threadStaticFieldCookies = new PermanentlyAllocatedMemoryRegions_ThreadStaticFieldOffsets(); private static PermanentlyAllocatedMemoryRegions_Uint_In_IntPtr s_uintCellValues = new PermanentlyAllocatedMemoryRegions_Uint_In_IntPtr(); private static PermanentlyAllocatedMemoryRegions_IntPtr_In_IntPtr s_pointerIndirectionCellValues = new PermanentlyAllocatedMemoryRegions_IntPtr_In_IntPtr(); @@ -69,57 +68,6 @@ namespace Internal.Runtime.TypeLoader } } - public struct ThreadStaticFieldOffsets : IEquatable<ThreadStaticFieldOffsets> - { - public uint StartingOffsetInTlsBlock; // Offset in the TLS block containing the thread static fields of a given type - public uint FieldOffset; // Offset of a thread static field from the start of its containing type's TLS fields block - // (in other words, the address of a field is 'TLS block + StartingOffsetInTlsBlock + FieldOffset') - - public override int GetHashCode() - { - return (int)(StartingOffsetInTlsBlock ^ FieldOffset << 8); - } - - public override bool Equals(object obj) - { - if (obj is ThreadStaticFieldOffsets) - { - return Equals((ThreadStaticFieldOffsets)obj); - } - return false; - } - - public bool Equals(ThreadStaticFieldOffsets other) - { - if (StartingOffsetInTlsBlock != other.StartingOffsetInTlsBlock) - return false; - - return FieldOffset == other.FieldOffset; - } - } - - private class PermanentlyAllocatedMemoryRegions_ThreadStaticFieldOffsets - { - private LowLevelDictionary<ThreadStaticFieldOffsets, IntPtr> _allocatedBlocks = new LowLevelDictionary<ThreadStaticFieldOffsets, IntPtr>(); - private Lock _lock = new Lock(); - - public unsafe IntPtr GetMemoryBlockForValue(ThreadStaticFieldOffsets value) - { - using (LockHolder.Hold(_lock)) - { - IntPtr result; - if (_allocatedBlocks.TryGetValue(value, out result)) - { - return result; - } - result = MemoryHelpers.AllocateMemory(sizeof(ThreadStaticFieldOffsets)); - *(ThreadStaticFieldOffsets*)(result.ToPointer()) = value; - _allocatedBlocks.Add(value, result); - return result; - } - } - } - public static IntPtr GetPointerToUInt(uint value) { return s_uintCellValues.GetMemoryBlockForValue(value); @@ -129,10 +77,5 @@ namespace Internal.Runtime.TypeLoader { return s_pointerIndirectionCellValues.GetMemoryBlockForValue(value); } - - public static IntPtr GetPointerToThreadStaticFieldOffsets(ThreadStaticFieldOffsets value) - { - return s_threadStaticFieldCookies.GetMemoryBlockForValue(value); - } } } diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs index 5c9662eff..3149f10a7 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.FieldAccess.cs @@ -48,6 +48,14 @@ namespace Internal.Runtime.TypeLoader public int Offset; } + [StructLayout(LayoutKind.Sequential)] + struct ThreadStaticFieldOffsets + { + public uint StartingOffsetInTlsBlock; // Offset in the TLS block containing the thread static fields of a given type + public uint FieldOffset; // Offset of a thread static field from the start of its containing type's TLS fields block + // (in other words, the address of a field is 'TLS block + StartingOffsetInTlsBlock + FieldOffset') + } + public sealed partial class TypeLoaderEnvironment { /// <summary> @@ -110,7 +118,7 @@ namespace Internal.Runtime.TypeLoader /// <param name="canonFormKind">Canonical form to use</param> /// <param name="fieldAccessMetadata">Output - metadata information for field accessor construction</param> /// <returns>true when found, false otherwise</returns> - private static bool TryGetFieldAccessMetadataFromFieldAccessMap( + private unsafe static bool TryGetFieldAccessMetadataFromFieldAccessMap( MetadataReader metadataReader, RuntimeTypeHandle declaringTypeHandle, FieldHandle fieldHandle, @@ -184,13 +192,13 @@ namespace Internal.Runtime.TypeLoader continue; } - int cookieOrOffsetOrOrdinal = (int)entryParser.GetUnsigned(); - int fieldOffset; + int fieldOffset = -1; + int threadStaticsStartOffset = -1; IntPtr fieldAddressCookie = IntPtr.Zero; if (canonFormKind == CanonicalFormKind.Universal) { - if (!TypeLoaderEnvironment.Instance.TryGetFieldOffset(declaringTypeHandle, (uint)cookieOrOffsetOrOrdinal, out fieldOffset)) + if (!TypeLoaderEnvironment.Instance.TryGetFieldOffset(declaringTypeHandle, entryParser.GetUnsigned() /* field ordinal */, out fieldOffset)) { Debug.Assert(false); return false; @@ -198,19 +206,46 @@ namespace Internal.Runtime.TypeLoader } else { - if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0) - fieldOffset = cookieOrOffsetOrOrdinal; + if ((entryFlags & FieldTableFlags.StorageClass) == FieldTableFlags.ThreadStatic) + { + if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0) + { + if ((entryFlags & FieldTableFlags.IsAnyCanonicalEntry) == 0) + { + int rvaToThreadStaticFieldOffsets = (int)externalReferences.GetRvaFromIndex(entryParser.GetUnsigned()); + fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule.Handle, rvaToThreadStaticFieldOffsets); + threadStaticsStartOffset = *(int*)fieldAddressCookie.ToPointer(); + } + fieldOffset = (int)entryParser.GetUnsigned(); + } + else + { + int rvaToThreadStaticFieldOffsets = (int)externalReferences.GetRvaFromIndex(entryParser.GetUnsigned()); + fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule.Handle, rvaToThreadStaticFieldOffsets); + ThreadStaticFieldOffsets* pThreadStaticFieldOffsets = (ThreadStaticFieldOffsets*)fieldAddressCookie.ToPointer(); + + threadStaticsStartOffset = (int)pThreadStaticFieldOffsets->StartingOffsetInTlsBlock; + fieldOffset = (int)pThreadStaticFieldOffsets->FieldOffset; + } + } else { + if ((entryFlags & FieldTableFlags.FieldOffsetEncodedDirectly) != 0) + { + fieldOffset = (int)entryParser.GetUnsigned(); + } + else + { #if CORERT - fieldOffset = 0; - fieldAddressCookie = externalReferences.GetFieldAddressFromIndex((uint)cookieOrOffsetOrOrdinal); + fieldOffset = 0; + fieldAddressCookie = externalReferences.GetFieldAddressFromIndex(entryParser.GetUnsigned()); - if((entryFlags & FieldTableFlags.IsGcSection) != 0) - fieldOffset = (int)entryParser.GetUnsigned(); + if((entryFlags & FieldTableFlags.IsGcSection) != 0) + fieldOffset = (int)entryParser.GetUnsigned(); #else - fieldOffset = (int)externalReferences.GetRvaFromIndex((uint)cookieOrOffsetOrOrdinal); + fieldOffset = (int)externalReferences.GetRvaFromIndex(entryParser.GetUnsigned()); #endif + } } } @@ -218,26 +253,13 @@ namespace Internal.Runtime.TypeLoader { // TODO: CoreRT support - if (canonFormKind != CanonicalFormKind.Universal) - { - fieldAddressCookie = RvaToNonGenericStaticFieldAddress(mappingTableModule.Handle, fieldOffset); - } - if (!entryDeclaringTypeHandle.Equals(declaringTypeHandle)) { - // In this case we didn't find an exact match, but we did find a canonically equivalent match - // We might be in the dynamic type case, or the canonically equivalent, but not the same case. - - if (!RuntimeAugments.IsDynamicType(declaringTypeHandle)) - { - int offsetToCreateCookieFor = fieldOffset; - // We're working with a statically generated type, but we didn't find an exact match in the tables - if (canonFormKind != CanonicalFormKind.Universal) - offsetToCreateCookieFor = checked((int)TypeLoaderEnvironment.GetThreadStaticTypeOffsetFromThreadStaticCookie(fieldAddressCookie)); - - fieldAddressCookie = TypeLoaderEnvironment.Instance.TryGetThreadStaticFieldOffsetCookieForTypeAndFieldOffset(declaringTypeHandle, checked((uint)offsetToCreateCookieFor)); - } + if (!TypeLoaderEnvironment.Instance.TryGetThreadStaticStartOffset(declaringTypeHandle, out threadStaticsStartOffset)) + return false; } + + fieldAddressCookie = new IntPtr(threadStaticsStartOffset); } fieldAccessMetadata.MappingTableModule = mappingTableModule.Handle; diff --git a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.StaticsLookup.cs b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.StaticsLookup.cs index dfca3feaf..dedadaf92 100644 --- a/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.StaticsLookup.cs +++ b/src/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.StaticsLookup.cs @@ -354,32 +354,26 @@ namespace Internal.Runtime.TypeLoader } - public unsafe IntPtr TryGetThreadStaticFieldOffsetCookieForTypeAndFieldOffset(RuntimeTypeHandle runtimeTypeHandle, uint fieldOffset) + public unsafe bool TryGetThreadStaticStartOffset(RuntimeTypeHandle runtimeTypeHandle, out int threadStaticsStartOffset) { - var cookieData = new PermanentAllocatedMemoryBlobs.ThreadStaticFieldOffsets(); + threadStaticsStartOffset = -1; if (runtimeTypeHandle.IsDynamicType()) { - cookieData.StartingOffsetInTlsBlock = 0; - cookieData.FieldOffset = fieldOffset; + // Specific TLS storage is allocated for each dynamic type. There is no starting offset since it's not a + // TLS storage block shared by multiple types. + threadStaticsStartOffset = 0; + return true; } else { IntPtr ptrToTlsOffset = TryGetTlsOffsetDictionaryCellForStaticType(runtimeTypeHandle); if (ptrToTlsOffset == IntPtr.Zero) - return IntPtr.Zero; + return false; - uint tlsOffset = *(uint*)ptrToTlsOffset; - cookieData.StartingOffsetInTlsBlock = tlsOffset; - cookieData.FieldOffset = fieldOffset; + threadStaticsStartOffset = *(int*)ptrToTlsOffset; + return true; } - - return PermanentAllocatedMemoryBlobs.GetPointerToThreadStaticFieldOffsets(cookieData); - } - - public static unsafe uint GetThreadStaticTypeOffsetFromThreadStaticCookie(IntPtr threadStaticFieldCookie) - { - return ((PermanentAllocatedMemoryBlobs.ThreadStaticFieldOffsets*)threadStaticFieldCookie.ToPointer())->FieldOffset; } private IntPtr TryGetTlsIndexDictionaryCellForStaticType(RuntimeTypeHandle runtimeTypeHandle) |