示例#1
0
            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);
            }
示例#2
0
            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));
            }