/// <summary> /// Each managed module linked into the final binary may have its own global tables for strings, /// statics, etc that need initializing. InitializeGlobalTables walks through the modules /// and offers each a chance to initialize its global tables. /// </summary> private static unsafe void InitializeGlobalTablesForModule(TypeManagerHandle typeManager, int moduleIndex) { // Configure the module indirection cell with the newly created TypeManager. This allows EETypes to find // their interface dispatch map tables. int length; TypeManagerSlot *section = (TypeManagerSlot *)RuntimeImports.RhGetModuleSection(typeManager, ReadyToRunSectionType.TypeManagerIndirection, out length); section->TypeManager = typeManager; section->ModuleIndex = moduleIndex; #if CORERT // Initialize statics if any are present IntPtr staticsSection = RuntimeImports.RhGetModuleSection(typeManager, ReadyToRunSectionType.GCStaticRegion, out length); if (staticsSection != IntPtr.Zero) { Debug.Assert(length % IntPtr.Size == 0); InitializeStatics(staticsSection, length); } #endif // Initialize frozen object segment with GC present IntPtr frozenObjectSection = RuntimeImports.RhGetModuleSection(typeManager, ReadyToRunSectionType.FrozenObjectRegion, out length); if (frozenObjectSection != IntPtr.Zero) { Debug.Assert(length % IntPtr.Size == 0); InitializeFrozenObjectSegment(frozenObjectSection, length); } }
/// <summary> /// This method is called from a ReadyToRun helper to get base address of thread /// static storage for the given type. /// </summary> internal static unsafe object GetThreadStaticBaseForType(TypeManagerSlot *pModuleData, int typeTlsIndex) { // Get the array that holds thread static memory blocks for each type in the given module object[] storage = RuntimeImports.RhGetThreadStaticStorageForModule(pModuleData->ModuleIndex); // Check whether thread static storage has already been allocated for this module and type. if ((storage != null) && ((uint)typeTlsIndex < (uint)storage.Length) && (storage[typeTlsIndex] != null)) { return(storage[typeTlsIndex]); } return(GetThreadStaticBaseForTypeSlow(pModuleData, typeTlsIndex)); }
internal static unsafe object GetThreadStaticBaseForTypeSlow(TypeManagerSlot *pModuleData, int typeTlsIndex) { // Get the array that holds thread static memory blocks for each type in the given module object[] storage = RuntimeImports.RhGetThreadStaticStorageForModule(pModuleData->ModuleIndex); // This the first access to the thread statics of the type corresponding to typeTlsIndex. // Make sure there is enough storage allocated to hold it. storage = EnsureThreadStaticStorage(pModuleData->ModuleIndex, storage, requiredSize: typeTlsIndex + 1); // Allocate an object that will represent a memory block for all thread static fields of the type object threadStaticBase = AllocateThreadStaticStorageForType(pModuleData->TypeManager, typeTlsIndex); storage[typeTlsIndex] = threadStaticBase; return(threadStaticBase); }
/// <summary> /// This method is called from a ReadyToRun helper to get base address of thread /// static storage for the given type. /// </summary> internal static unsafe object GetThreadStaticBaseForType(TypeManagerSlot *pModuleData, Int32 typeTlsIndex) { // Get the array that holds thread static memory blocks for each type in the given module Int32 moduleIndex = pModuleData->ModuleIndex; object[] storage = (object[])RuntimeImports.RhGetThreadStaticStorageForModule(moduleIndex); // Check whether thread static storage has already been allocated for this module and type. if ((storage != null) && (typeTlsIndex < storage.Length) && (storage[typeTlsIndex] != null)) { return(storage[typeTlsIndex]); } // This the first access to the thread statics of the type corresponding to typeTlsIndex. // Make sure there is enough storage allocated to hold it. storage = EnsureThreadStaticStorage(moduleIndex, storage, requiredSize: typeTlsIndex + 1); // Allocate an object that will represent a memory block for all thread static fields of the type object threadStaticBase = AllocateThreadStaticStorageForType(pModuleData->TypeManager, typeTlsIndex); storage[typeTlsIndex] = threadStaticBase; return(threadStaticBase); }
/// <summary> /// Each managed module linked into the final binary may have its own global tables for strings, /// statics, etc that need initializing. InitializeGlobalTables walks through the modules /// and offers each a chance to initialize its global tables. /// </summary> private static unsafe void InitializeGlobalTablesForModule(TypeManagerHandle typeManager, int moduleIndex, object[] gcStaticBaseSpines) { // Configure the module indirection cell with the newly created TypeManager. This allows EETypes to find // their interface dispatch map tables. int length; TypeManagerSlot *section = (TypeManagerSlot *)RuntimeImports.RhGetModuleSection(typeManager, ReadyToRunSectionType.TypeManagerIndirection, out length); section->TypeManager = typeManager; section->ModuleIndex = moduleIndex; // Initialize statics if any are present IntPtr staticsSection = RuntimeImports.RhGetModuleSection(typeManager, ReadyToRunSectionType.GCStaticRegion, out length); if (staticsSection != IntPtr.Zero) { Debug.Assert(length % IntPtr.Size == 0); object[] spine = InitializeStatics(staticsSection, length); // Call write barrier directly. Assigning object reference does a type check. Debug.Assert((uint)moduleIndex < (uint)gcStaticBaseSpines.Length); ref object rawSpineIndexData = ref Unsafe.As <byte, object>(ref Unsafe.As <RawArrayData>(gcStaticBaseSpines).Data); InternalCalls.RhpAssignRef(ref Unsafe.Add(ref rawSpineIndexData, moduleIndex), spine); }
private static unsafe object CheckStaticClassConstructionReturnThreadStaticBase(TypeManagerSlot *pModuleData, int typeTlsIndex, StaticClassConstructionContext *context) { object threadStaticBase = ThreadStatics.GetThreadStaticBaseForType(pModuleData, typeTlsIndex); EnsureClassConstructorRun(context); return(threadStaticBase); }