public FieldAndOffset[] GetOrAddDynamicLayout(DefType defType, ModuleFieldLayout moduleFieldLayout) { FieldAndOffset[] fieldsForType; if (!moduleFieldLayout.TryGetDynamicLayout(defType, out fieldsForType)) { int nonGcOffset; switch (moduleFieldLayout.Module.Context.Target.PointerSize) { case 4: nonGcOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlob32Bit; break; case 8: nonGcOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlob64Bit; break; default: throw new NotImplementedException(); } OffsetsForType offsetsForType = new OffsetsForType( nonGcOffset: new LayoutInt(nonGcOffset), tlsNonGcOffset: new LayoutInt(nonGcOffset), gcOffset: LayoutInt.Zero, tlsGcOffset: LayoutInt.Zero); fieldsForType = CalculateTypeLayout(defType, moduleFieldLayout.Module, offsetsForType); moduleFieldLayout.AddDynamicLayout(defType, fieldsForType); } return(fieldsForType); }
protected override ModuleFieldLayout CreateValueFromKey(EcmaModule module) { int typeCountInModule = module.MetadataReader.GetTableRowCount(TableIndex.TypeDef); int pointerSize = module.Context.Target.PointerSize; // 0 corresponds to "normal" statics, 1 to thread-local statics LayoutInt[] gcStatics = new LayoutInt[StaticIndex.Count] { LayoutInt.Zero, LayoutInt.Zero }; LayoutInt[] nonGcStatics = new LayoutInt[StaticIndex.Count] { new LayoutInt(DomainLocalModuleDataBlobOffsetAsIntPtrCount * pointerSize + typeCountInModule), new LayoutInt(ThreadLocalModuleDataBlobOffsetAsIntPtrCount * pointerSize + typeCountInModule), }; Dictionary <TypeDefinitionHandle, OffsetsForType> typeOffsets = new Dictionary <TypeDefinitionHandle, OffsetsForType>(); foreach (TypeDefinitionHandle typeDefHandle in module.MetadataReader.TypeDefinitions) { TypeDefinition typeDef = module.MetadataReader.GetTypeDefinition(typeDefHandle); if (typeDef.GetGenericParameters().Count != 0) { // Generic types are exempt from the static field layout algorithm, see // <a href="https://github.com/dotnet/coreclr/blob/659af58047a949ed50d11101708538d2e87f2568/src/vm/ceeload.cpp#L2049">this check</a>. continue; } // 0 corresponds to "normal" statics, 1 to thread-local statics int[] nonGcAlignment = new int[StaticIndex.Count] { 1, 1, }; int[] nonGcBytes = new int[StaticIndex.Count] { 0, 0, }; int[] gcBytes = new int[StaticIndex.Count] { 0, 0, }; foreach (FieldDefinitionHandle fieldDefHandle in typeDef.GetFields()) { FieldDefinition fieldDef = module.MetadataReader.GetFieldDefinition(fieldDefHandle); if ((fieldDef.Attributes & (FieldAttributes.Static | FieldAttributes.Literal)) == FieldAttributes.Static) { int index = (IsFieldThreadStatic(in fieldDef, module.MetadataReader) ? StaticIndex.ThreadLocal : StaticIndex.Regular); int alignment; int size; bool isGcPointerField; bool isGcBoxedField; CorElementType corElementType; EntityHandle valueTypeHandle; GetFieldElementTypeAndValueTypeHandle(in fieldDef, module.MetadataReader, out corElementType, out valueTypeHandle); FieldDesc fieldDesc = module.GetField(fieldDefHandle); GetElementTypeInfo(module, fieldDesc, valueTypeHandle, corElementType, pointerSize, moduleLayout: true, out alignment, out size, out isGcPointerField, out isGcBoxedField); if (size != 0) { nonGcBytes[index] += size; nonGcAlignment[index] = Math.Max(nonGcAlignment[index], alignment); } if (isGcPointerField || isGcBoxedField) { gcBytes[index] += pointerSize; } } } if (nonGcBytes[StaticIndex.Regular] != 0 || nonGcBytes[StaticIndex.ThreadLocal] != 0 || gcBytes[StaticIndex.Regular] != 0 || gcBytes[StaticIndex.ThreadLocal] != 0) { OffsetsForType offsetsForType = new OffsetsForType(LayoutInt.Indeterminate, LayoutInt.Indeterminate, LayoutInt.Indeterminate, LayoutInt.Indeterminate); for (int staticIndex = 0; staticIndex < StaticIndex.Count; staticIndex++) { if (nonGcBytes[staticIndex] != 0) { offsetsForType.NonGcOffsets[staticIndex] = LayoutInt.AlignUp(nonGcStatics[staticIndex], new LayoutInt(nonGcAlignment[staticIndex]), module.Context.Target); nonGcStatics[staticIndex] = offsetsForType.NonGcOffsets[staticIndex] + new LayoutInt(nonGcBytes[staticIndex]); } if (gcBytes[staticIndex] != 0) { offsetsForType.GcOffsets[staticIndex] = gcStatics[staticIndex]; gcStatics[staticIndex] += new LayoutInt(gcBytes[staticIndex]); } } typeOffsets.Add(typeDefHandle, offsetsForType); } } LayoutInt blockAlignment = new LayoutInt(TargetDetails.MaximumPrimitiveSize); return(new ModuleFieldLayout( module, gcStatics: new StaticsBlock() { Size = gcStatics[StaticIndex.Regular], LargestAlignment = blockAlignment }, nonGcStatics: new StaticsBlock() { Size = nonGcStatics[StaticIndex.Regular], LargestAlignment = blockAlignment }, threadGcStatics: new StaticsBlock() { Size = gcStatics[StaticIndex.ThreadLocal], LargestAlignment = blockAlignment }, threadNonGcStatics: new StaticsBlock() { Size = nonGcStatics[StaticIndex.ThreadLocal], LargestAlignment = blockAlignment }, typeOffsets: typeOffsets)); }