/// <summary> /// Get a pointer to a pointer to the nongc static field data of a type. This function works for all generic types /// </summary> public IntPtr TryGetNonGcStaticFieldData(RuntimeTypeHandle runtimeTypeHandle) { unsafe { // Non-generic, non-dynamic static data is found via the FieldAccessMap EEType *typeAsEEType = runtimeTypeHandle.ToEETypePtr(); // Non-generic, non-dynamic types need special handling. Debug.Assert(typeAsEEType->IsDynamicType || typeAsEEType->IsGeneric); } // Search hashtable for static entry ExternalReferencesTable staticInfoLookup; var parser = GetStaticInfo(runtimeTypeHandle, out staticInfoLookup); if (!parser.IsNull) { var index = parser.GetUnsignedForBagElementKind(BagElementKind.NonGcStaticData); return(index.HasValue ? staticInfoLookup.GetIntPtrFromIndex(index.Value) : IntPtr.Zero); } // Not found in hashtable... must be a dynamically created type Debug.Assert(runtimeTypeHandle.IsDynamicType()); unsafe { EEType *typeAsEEType = runtimeTypeHandle.ToEETypePtr(); if ((typeAsEEType->RareFlags & EETypeRareFlags.IsDynamicTypeWithNonGcStatics) != 0) { return(typeAsEEType->DynamicNonGcStaticsData); } } // Type has no non-GC statics return(IntPtr.Zero); }
public void RegisterDynamicThreadStaticsInfo(RuntimeTypeHandle runtimeTypeHandle, uint offsetValue, int storageSize) { bool registered = false; Debug.Assert(offsetValue != 0 && storageSize > 0 && runtimeTypeHandle.IsDynamicType()); _threadStaticsLock.Acquire(); try { // Sanity check to make sure we do not register thread statics for the same type more than once uint temp; Debug.Assert(!_dynamicGenericsThreadStatics.TryGetValue(runtimeTypeHandle, out temp) && storageSize > 0); _dynamicGenericsThreadStatics.Add(runtimeTypeHandle, offsetValue); _dynamicGenericsThreadStaticSizes.Add(offsetValue, storageSize); registered = true; } finally { if (!registered) { _dynamicGenericsThreadStatics.Remove(runtimeTypeHandle); _dynamicGenericsThreadStaticSizes.Remove(offsetValue); } _threadStaticsLock.Release(); } }
public void RegisterDynamicThreadStaticsInfo(RuntimeTypeHandle runtimeTypeHandle, uint offsetValue, IntPtr gcDesc) { bool registered = false; Debug.Assert(offsetValue != 0 && runtimeTypeHandle.IsDynamicType()); IntPtr typeManager = runtimeTypeHandle.GetTypeManager().GetIntPtrUNSAFE(); _threadStaticsLock.Acquire(); try { if (!_dynamicGenericsThreadStaticDescs.TryGetValue(typeManager, out LowLevelDictionary <uint, IntPtr> gcDescs)) { _dynamicGenericsThreadStaticDescs.Add(typeManager, gcDescs = new LowLevelDictionary <uint, IntPtr>()); } gcDescs.Add(offsetValue, gcDesc); registered = true; } finally { if (!registered) { if (_dynamicGenericsThreadStaticDescs.TryGetValue(typeManager, out LowLevelDictionary <uint, IntPtr> gcDescs)) { gcDescs.Remove(offsetValue); } } _threadStaticsLock.Release(); } }
public unsafe IntPtr TryGetThreadStaticFieldOffsetCookieForTypeAndFieldOffset(RuntimeTypeHandle runtimeTypeHandle, uint fieldOffset) { var cookieData = new PermanentAllocatedMemoryBlobs.ThreadStaticFieldOffsets(); if (runtimeTypeHandle.IsDynamicType()) { cookieData.StartingOffsetInTlsBlock = 0; cookieData.FieldOffset = fieldOffset; } else { IntPtr ptrToTlsOffset = TryGetTlsOffsetDictionaryCellForStaticType(runtimeTypeHandle); if (ptrToTlsOffset == IntPtr.Zero) { return(IntPtr.Zero); } IntPtr tlsOffsetAsIntPtr = *(IntPtr *)ptrToTlsOffset.ToPointer(); uint tlsOffset = (uint)tlsOffsetAsIntPtr.ToInt32(); cookieData.StartingOffsetInTlsBlock = tlsOffset; cookieData.FieldOffset = fieldOffset; } return(PermanentAllocatedMemoryBlobs.GetPointerToThreadStaticFieldOffsets(cookieData)); }
private IntPtr TryGetTlsOffsetDictionaryCellForDynamicType(RuntimeTypeHandle runtimeTypeHandle) { Debug.Assert(runtimeTypeHandle.IsDynamicType()); using (LockHolder.Hold(_threadStaticsLock)) { uint offsetValue; if (_dynamicGenericsThreadStatics.TryGetValue(runtimeTypeHandle, out offsetValue)) { return(TryCreateDictionaryCellWithValue(offsetValue)); } } return(IntPtr.Zero); }
public static unsafe bool IsPregeneratedOrTemplateRuntimeTypeHandle(RuntimeTypeHandle rtth) { #if SUPPORTS_NATIVE_METADATA_TYPE_LOADING if (!rtth.IsDynamicType()) { return(true); } if (rtth.ToEETypePtr()->DynamicModule == null) { return(true); } return(rtth.ToEETypePtr()->DynamicModule->DynamicTypeSlotDispatchResolve == IntPtr.Zero); #else return(true); #endif }
public unsafe bool TryGetThreadStaticStartOffset(RuntimeTypeHandle runtimeTypeHandle, out int threadStaticsStartOffset) { threadStaticsStartOffset = -1; if (runtimeTypeHandle.IsDynamicType()) { // 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(false); } threadStaticsStartOffset = *(int *)ptrToTlsOffset; return(true); } }
private IntPtr TryGetTlsIndexDictionaryCellForDynamicType(RuntimeTypeHandle runtimeTypeHandle) { // Use TLS index of 0 for dynamic types (the index won't really be used) Debug.Assert(runtimeTypeHandle.IsDynamicType()); return(TryCreateDictionaryCellWithValue(0)); }
// Various functions in static access need to create permanent pointers for use by thread static lookup. #region GC/Non-GC Statics /// <summary> /// Get a pointer to the nongc static field data of a type. This function works for dynamic /// types, reflectable types, and for all generic types /// </summary> public IntPtr TryGetNonGcStaticFieldData(RuntimeTypeHandle runtimeTypeHandle) { unsafe { MethodTable *typeAsEEType = runtimeTypeHandle.ToEETypePtr(); // Non-generic, non-dynamic types need special handling. if (!typeAsEEType->IsDynamicType && !typeAsEEType->IsGeneric) { if (typeAsEEType->HasCctor) { // The non-gc area for a type is immediately following its cctor context if it has one IntPtr dataAddress = TryGetStaticClassConstructionContext(runtimeTypeHandle); if (dataAddress != IntPtr.Zero) { return((IntPtr)(((byte *)dataAddress.ToPointer()) + sizeof(System.Runtime.CompilerServices.StaticClassConstructionContext))); } } else { // If the type does not have a Cctor context, search for the field on the type in the field map which has the lowest offset, // yet has the the correct type of storage. IntPtr staticAddress; if (TryGetStaticFieldBaseFromFieldAccessMap(runtimeTypeHandle, FieldAccessStaticDataKind.NonGC, out staticAddress)) { return(staticAddress); } } } } IntPtr nonGcStaticsAddress; IntPtr gcStaticsAddress; if (TryGetStaticsInfoForNamedType(runtimeTypeHandle, out nonGcStaticsAddress, out gcStaticsAddress)) { return(nonGcStaticsAddress); } unsafe { // Non-generic, non-dynamic static data is found via the FieldAccessMap MethodTable *typeAsEEType = runtimeTypeHandle.ToEETypePtr(); // Non-generic, non-dynamic types need special handling. Debug.Assert(typeAsEEType->IsDynamicType || typeAsEEType->IsGeneric); } // Search hashtable for static entry ExternalReferencesTable staticInfoLookup; var parser = GetStaticInfo(runtimeTypeHandle, out staticInfoLookup); if (!parser.IsNull) { var index = parser.GetUnsignedForBagElementKind(BagElementKind.NonGcStaticData); return(index.HasValue ? staticInfoLookup.GetIntPtrFromIndex(index.Value) : IntPtr.Zero); } // Not found in hashtable... must be a dynamically created type Debug.Assert(runtimeTypeHandle.IsDynamicType()); unsafe { MethodTable *typeAsEEType = runtimeTypeHandle.ToEETypePtr(); if ((typeAsEEType->RareFlags & EETypeRareFlags.IsDynamicTypeWithNonGcStatics) != 0) { return(typeAsEEType->DynamicNonGcStaticsData); } } // Type has no non-GC statics return(IntPtr.Zero); }
/// <summary> /// Get a pointer to the gc static field data of a type. This function works for dynamic /// types, reflectable types, and for all generic types /// </summary> public IntPtr TryGetGcStaticFieldData(RuntimeTypeHandle runtimeTypeHandle) { unsafe { // Non-generic, non-dynamic static data is found via the FieldAccessMap MethodTable *typeAsEEType = runtimeTypeHandle.ToEETypePtr(); // Non-generic, non-dynamic types need special handling. if (!typeAsEEType->IsDynamicType && !typeAsEEType->IsGeneric) { //search for the field on the type in the field map which has the lowest offset, // yet has the the correct type of storage. IntPtr staticAddress; if (TryGetStaticFieldBaseFromFieldAccessMap(runtimeTypeHandle, FieldAccessStaticDataKind.GC, out staticAddress)) { return(staticAddress); } else { return(IntPtr.Zero); } } } IntPtr nonGcStaticsAddress; IntPtr gcStaticsAddress; if (TryGetStaticsInfoForNamedType(runtimeTypeHandle, out nonGcStaticsAddress, out gcStaticsAddress)) { return(gcStaticsAddress); } unsafe { // Non-generic, non-dynamic static data is found via the FieldAccessMap MethodTable *typeAsEEType = runtimeTypeHandle.ToEETypePtr(); // Non-generic, non-dynamic types need special handling. Debug.Assert(typeAsEEType->IsDynamicType || typeAsEEType->IsGeneric); } // Search hashtable for static entry ExternalReferencesTable staticInfoLookup; var parser = GetStaticInfo(runtimeTypeHandle, out staticInfoLookup); if (!parser.IsNull) { var index = parser.GetUnsignedForBagElementKind(BagElementKind.GcStaticData); return(index.HasValue ? staticInfoLookup.GetIntPtrFromIndex(index.Value) : IntPtr.Zero); } // Not found in hashtable... must be a dynamically created type Debug.Assert(runtimeTypeHandle.IsDynamicType()); unsafe { MethodTable *typeAsEEType = runtimeTypeHandle.ToEETypePtr(); if ((typeAsEEType->RareFlags & EETypeRareFlags.IsDynamicTypeWithGcStatics) != 0) { return(typeAsEEType->DynamicGcStaticsData); } } // Type has no GC statics return(IntPtr.Zero); }