private uint GetEnumTypeIndex(TypeDesc type) { System.Diagnostics.Debug.Assert(type.IsEnum, "GetEnumTypeIndex was called with wrong type"); DefType defType = type as DefType; System.Diagnostics.Debug.Assert(defType != null, "GetEnumTypeIndex was called with non def type"); List <FieldDesc> fieldsDescriptors = new List <FieldDesc>(); foreach (var field in defType.GetFields()) { if (field.IsLiteral) { fieldsDescriptors.Add(field); } } EnumTypeDescriptor enumTypeDescriptor = new EnumTypeDescriptor { ElementCount = (ulong)fieldsDescriptors.Count, ElementType = GetPrimitiveTypeIndex(defType.UnderlyingType), Name = _objectWriter.GetMangledName(type), }; EnumRecordTypeDescriptor[] typeRecords = new EnumRecordTypeDescriptor[enumTypeDescriptor.ElementCount]; for (int i = 0; i < fieldsDescriptors.Count; ++i) { FieldDesc field = fieldsDescriptors[i]; EnumRecordTypeDescriptor recordTypeDescriptor; recordTypeDescriptor.Value = GetEnumRecordValue(field); recordTypeDescriptor.Name = field.Name; typeRecords[i] = recordTypeDescriptor; } uint typeIndex = _objectWriter.GetEnumTypeIndex(enumTypeDescriptor, typeRecords); return(typeIndex); }
public uint GetClassTypeIndex(TypeDesc type, bool needsCompleteType) { DefType defType = type as DefType; System.Diagnostics.Debug.Assert(defType != null, "GetClassTypeIndex was called with non def type"); ClassTypeDescriptor classTypeDescriptor = new ClassTypeDescriptor(); classTypeDescriptor.IsStruct = type.IsValueType ? 1 : 0; classTypeDescriptor.Name = defType.Name; classTypeDescriptor.UniqueName = defType.GetFullName(); classTypeDescriptor.BaseClassId = 0; if (type.HasBaseType && !type.IsValueType) { classTypeDescriptor.BaseClassId = GetVariableTypeIndex(defType.BaseType, false); } uint typeIndex = _objectWriter.GetClassTypeIndex(classTypeDescriptor); _knownTypes[type] = typeIndex; List <DataFieldDescriptor> fieldsDescs = new List <DataFieldDescriptor>(); foreach (var fieldDesc in defType.GetFields()) { if (fieldDesc.HasRva || fieldDesc.IsLiteral) { continue; } DataFieldDescriptor field = new DataFieldDescriptor(); field.FieldTypeIndex = GetVariableTypeIndex(fieldDesc.FieldType, false); field.Offset = fieldDesc.Offset.AsInt; field.Name = fieldDesc.Name; fieldsDescs.Add(field); } DataFieldDescriptor[] fields = new DataFieldDescriptor[fieldsDescs.Count]; for (int i = 0; i < fieldsDescs.Count; ++i) { fields[i] = fieldsDescs[i]; } ClassFieldsTypeDescriptor fieldsDescriptor = new ClassFieldsTypeDescriptor(); fieldsDescriptor.FieldsCount = fieldsDescs.Count; fieldsDescriptor.Size = defType.GetElementSize().AsInt; uint completeTypeIndex = _objectWriter.GetCompleteClassTypeIndex(classTypeDescriptor, fieldsDescriptor, fields); _completeKnownTypes[type] = completeTypeIndex; if (needsCompleteType) { return(completeTypeIndex); } else { return(typeIndex); } }
public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind) { DefType similarSpecifiedVector = GetSimilarVector(type); if (similarSpecifiedVector == null) { List <FieldAndOffset> fieldsAndOffsets = new List <FieldAndOffset>(); foreach (FieldDesc field in type.GetFields()) { if (!field.IsStatic) { fieldsAndOffsets.Add(new FieldAndOffset(field, LayoutInt.Indeterminate)); } } ComputedInstanceFieldLayout instanceLayout = new ComputedInstanceFieldLayout() { FieldSize = LayoutInt.Indeterminate, FieldAlignment = LayoutInt.Indeterminate, ByteCountUnaligned = LayoutInt.Indeterminate, ByteCountAlignment = LayoutInt.Indeterminate, Offsets = fieldsAndOffsets.ToArray(), LayoutAbiStable = false, }; return(instanceLayout); } else { ComputedInstanceFieldLayout layoutFromMetadata = _fallbackAlgorithm.ComputeInstanceLayout(type, layoutKind); ComputedInstanceFieldLayout layoutFromSimilarIntrinsicVector = _vectorFallbackAlgorithm.ComputeInstanceLayout(similarSpecifiedVector, layoutKind); // TODO, enable this code when we switch Vector<T> to follow the same calling convention as its matching similar intrinsic vector #if MATCHING_HARDWARE_VECTOR return(new ComputedInstanceFieldLayout { ByteCountUnaligned = layoutFromSimilarIntrinsicVector.ByteCountUnaligned, ByteCountAlignment = layoutFromSimilarIntrinsicVector.ByteCountAlignment, FieldAlignment = layoutFromSimilarIntrinsicVector.FieldAlignment, FieldSize = layoutFromSimilarIntrinsicVector.FieldSize, Offsets = layoutFromMetadata.Offsets, LayoutAbiStable = _vectorAbiIsStable, }); #else return(new ComputedInstanceFieldLayout { ByteCountUnaligned = layoutFromSimilarIntrinsicVector.ByteCountUnaligned, ByteCountAlignment = layoutFromMetadata.ByteCountAlignment, FieldAlignment = layoutFromMetadata.FieldAlignment, FieldSize = layoutFromSimilarIntrinsicVector.FieldSize, Offsets = layoutFromMetadata.Offsets, LayoutAbiStable = _vectorAbiIsStable, }); #endif } }
private bool ContainsTypeLayoutUncached(TypeDesc type, HashSet <TypeDesc> recursionGuard) { if (type.IsValueType || type.IsObject || type.IsPrimitive || type.IsEnum || type.IsPointer || type.IsFunctionPointer || type.IsByRefLike || type.IsCanonicalDefinitionType(CanonicalFormKind.Any)) { return(true); } DefType defType = type.GetClosestDefType(); if (!ContainsType(defType.GetTypeDefinition())) { return(false); } if (defType.BaseType != null && !ContainsTypeLayout(defType.BaseType, recursionGuard)) { return(false); } foreach (TypeDesc genericArg in defType.Instantiation) { if (!ContainsTypeLayout(genericArg, recursionGuard)) { return(false); } } foreach (FieldDesc field in defType.GetFields()) { if (!field.IsLiteral && !field.IsStatic && !field.HasRva && !ContainsTypeLayout(field.FieldType, recursionGuard)) { return(false); } } return(true); }
/// <summary> /// Get an enumerable list of the fields used for dynamic gc layout calculation. /// </summary> private IEnumerable <FieldDesc> GetFieldsForGCLayout() { DefType defType = (DefType)TypeBeingBuilt; IEnumerable <FieldDesc> fields; if (defType.ComputeTemplate(false) != null) { // we have native layout and a template. Use the NativeLayoutFields as that is the only complete // description of the fields available. (There may be metadata fields, but those aren't guaranteed // to be a complete set of fields due to reflection reduction. NativeLayoutFieldAlgorithm.EnsureFieldLayoutLoadedForGenericType(defType); fields = defType.NativeLayoutFields; } else { // The metadata case. We're loading the type from regular metadata, so use the regular metadata fields fields = defType.GetFields(); } return(fields); }
public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind) { List <FieldAndOffset> fieldsAndOffsets = new List <FieldAndOffset>(); foreach (FieldDesc field in type.GetFields()) { if (!field.IsStatic) { fieldsAndOffsets.Add(new FieldAndOffset(field, LayoutInt.Indeterminate)); } } ComputedInstanceFieldLayout instanceLayout = new ComputedInstanceFieldLayout() { FieldSize = LayoutInt.Indeterminate, FieldAlignment = LayoutInt.Indeterminate, ByteCountUnaligned = LayoutInt.Indeterminate, ByteCountAlignment = LayoutInt.Indeterminate, Offsets = fieldsAndOffsets.ToArray(), }; return(instanceLayout); }
private uint GetClassTypeIndex(TypeDesc type, bool needsCompleteType) { DefType defType = type as DefType; System.Diagnostics.Debug.Assert(defType != null, "GetClassTypeIndex was called with non def type"); ClassTypeDescriptor classTypeDescriptor = new ClassTypeDescriptor { IsStruct = type.IsValueType ? 1 : 0, Name = _objectWriter.GetMangledName(type), BaseClassId = 0 }; uint typeIndex = _objectWriter.GetClassTypeIndex(classTypeDescriptor); _knownTypes[type] = typeIndex; if (type.HasBaseType && !type.IsValueType) { classTypeDescriptor.BaseClassId = GetTypeIndex(defType.BaseType, true); } List <DataFieldDescriptor> fieldsDescs = new List <DataFieldDescriptor>(); List <DataFieldDescriptor> nonGcStaticFields = new List <DataFieldDescriptor>(); List <DataFieldDescriptor> gcStaticFields = new List <DataFieldDescriptor>(); List <DataFieldDescriptor> threadStaticFields = new List <DataFieldDescriptor>(); bool isCanonical = defType.IsCanonicalSubtype(CanonicalFormKind.Any); foreach (var fieldDesc in defType.GetFields()) { if (fieldDesc.HasRva || fieldDesc.IsLiteral) { continue; } if (isCanonical && fieldDesc.IsStatic) { continue; } LayoutInt fieldOffset = fieldDesc.Offset; int fieldOffsetEmit = fieldOffset.IsIndeterminate ? 0xBAAD : fieldOffset.AsInt; DataFieldDescriptor field = new DataFieldDescriptor { FieldTypeIndex = GetVariableTypeIndex(GetFieldDebugType(fieldDesc), false), Offset = (ulong)fieldOffsetEmit, Name = fieldDesc.Name }; if (fieldDesc.IsStatic) { if (fieldDesc.IsThreadStatic) { threadStaticFields.Add(field); } else if (fieldDesc.HasGCStaticBase) { gcStaticFields.Add(field); } else { nonGcStaticFields.Add(field); } } else { fieldsDescs.Add(field); } } InsertStaticFieldRegionMember(fieldsDescs, defType, nonGcStaticFields, WindowsNodeMangler.NonGCStaticMemberName, "__type_" + WindowsNodeMangler.NonGCStaticMemberName, false); InsertStaticFieldRegionMember(fieldsDescs, defType, gcStaticFields, WindowsNodeMangler.GCStaticMemberName, "__type_" + WindowsNodeMangler.GCStaticMemberName, Abi == TargetAbi.CoreRT); InsertStaticFieldRegionMember(fieldsDescs, defType, threadStaticFields, WindowsNodeMangler.ThreadStaticMemberName, "__type_" + WindowsNodeMangler.ThreadStaticMemberName, Abi == TargetAbi.CoreRT); DataFieldDescriptor[] fields = new DataFieldDescriptor[fieldsDescs.Count]; for (int i = 0; i < fieldsDescs.Count; ++i) { fields[i] = fieldsDescs[i]; } LayoutInt elementSize = defType.GetElementSize(); int elementSizeEmit = elementSize.IsIndeterminate ? 0xBAAD : elementSize.AsInt; ClassFieldsTypeDescriptor fieldsDescriptor = new ClassFieldsTypeDescriptor { Size = (ulong)elementSizeEmit, FieldsCount = fieldsDescs.Count }; uint completeTypeIndex = _objectWriter.GetCompleteClassTypeIndex(classTypeDescriptor, fieldsDescriptor, fields); _completeKnownTypes[type] = completeTypeIndex; if (needsCompleteType) { return(completeTypeIndex); } else { return(typeIndex); } }
private uint GetClassTypeIndex(TypeDesc type, bool needsCompleteType) { DefType defType = type as DefType; System.Diagnostics.Debug.Assert(defType != null, "GetClassTypeIndex was called with non def type"); ClassTypeDescriptor classTypeDescriptor = new ClassTypeDescriptor { IsStruct = type.IsValueType ? 1 : 0, Name = _objectWriter.GetMangledName(type), BaseClassId = 0, InstanceSize = 0 }; uint typeIndex = _objectWriter.GetClassTypeIndex(classTypeDescriptor); _knownTypes[type] = typeIndex; if (!defType.InstanceByteCount.IsIndeterminate) { classTypeDescriptor.InstanceSize = (ulong)defType.InstanceByteCount.AsInt; } if (type.HasBaseType && !type.IsValueType) { classTypeDescriptor.BaseClassId = GetTypeIndex(defType.BaseType, true); } List <DataFieldDescriptor> fieldsDescs = new List <DataFieldDescriptor>(); List <DataFieldDescriptor> nonGcStaticFields = new List <DataFieldDescriptor>(); List <DataFieldDescriptor> gcStaticFields = new List <DataFieldDescriptor>(); List <DataFieldDescriptor> threadStaticFields = new List <DataFieldDescriptor>(); List <StaticDataFieldDescriptor> staticsDescs = new List <StaticDataFieldDescriptor>(); string nonGcStaticDataName = NodeFactory.NameMangler.NodeMangler.NonGCStatics(type); string gcStaticDataName = NodeFactory.NameMangler.NodeMangler.GCStatics(type); string threadStaticDataName = NodeFactory.NameMangler.NodeMangler.ThreadStatics(type); bool IsCoreRTAbi = Abi == TargetAbi.CoreRT; bool isCanonical = defType.IsCanonicalSubtype(CanonicalFormKind.Any); foreach (var fieldDesc in defType.GetFields()) { if (fieldDesc.HasRva || fieldDesc.IsLiteral) { continue; } if (isCanonical && fieldDesc.IsStatic) { continue; } LayoutInt fieldOffset = fieldDesc.Offset; int fieldOffsetEmit = fieldOffset.IsIndeterminate ? 0xBAAD : fieldOffset.AsInt; DataFieldDescriptor field = new DataFieldDescriptor { FieldTypeIndex = GetVariableTypeIndex(GetFieldDebugType(fieldDesc), false), Offset = (ulong)fieldOffsetEmit, Name = fieldDesc.Name }; if (fieldDesc.IsStatic) { if (NodeFactory.Target.OperatingSystem != TargetOS.Windows) { StaticDataFieldDescriptor staticDesc = new StaticDataFieldDescriptor { StaticOffset = (ulong)fieldOffsetEmit }; // Mark field as static field.Offset = 0xFFFFFFFF; if (fieldDesc.IsThreadStatic) { staticDesc.StaticDataName = threadStaticDataName; staticDesc.IsStaticDataInObject = IsCoreRTAbi ? 1 : 0; } else if (fieldDesc.HasGCStaticBase) { staticDesc.StaticDataName = gcStaticDataName; staticDesc.IsStaticDataInObject = IsCoreRTAbi ? 1 : 0; } else { staticDesc.StaticDataName = nonGcStaticDataName; staticDesc.IsStaticDataInObject = 0; } staticsDescs.Add(staticDesc); } if (fieldDesc.IsThreadStatic) { threadStaticFields.Add(field); } else if (fieldDesc.HasGCStaticBase) { gcStaticFields.Add(field); } else { nonGcStaticFields.Add(field); } } else { fieldsDescs.Add(field); } } if (NodeFactory.Target.OperatingSystem == TargetOS.Windows) { InsertStaticFieldRegionMember(fieldsDescs, defType, nonGcStaticFields, WindowsNodeMangler.NonGCStaticMemberName, "__type_" + WindowsNodeMangler.NonGCStaticMemberName, false); InsertStaticFieldRegionMember(fieldsDescs, defType, gcStaticFields, WindowsNodeMangler.GCStaticMemberName, "__type_" + WindowsNodeMangler.GCStaticMemberName, IsCoreRTAbi); InsertStaticFieldRegionMember(fieldsDescs, defType, threadStaticFields, WindowsNodeMangler.ThreadStaticMemberName, "__type_" + WindowsNodeMangler.ThreadStaticMemberName, IsCoreRTAbi); } else { fieldsDescs.AddRange(nonGcStaticFields); fieldsDescs.AddRange(gcStaticFields); fieldsDescs.AddRange(threadStaticFields); } DataFieldDescriptor[] fields = new DataFieldDescriptor[fieldsDescs.Count]; for (int i = 0; i < fieldsDescs.Count; ++i) { fields[i] = fieldsDescs[i]; } StaticDataFieldDescriptor[] statics = new StaticDataFieldDescriptor[staticsDescs.Count]; for (int i = 0; i < staticsDescs.Count; ++i) { statics[i] = staticsDescs[i]; } LayoutInt elementSize = defType.GetElementSize(); int elementSizeEmit = elementSize.IsIndeterminate ? 0xBAAD : elementSize.AsInt; ClassFieldsTypeDescriptor fieldsDescriptor = new ClassFieldsTypeDescriptor { Size = (ulong)elementSizeEmit, FieldsCount = fieldsDescs.Count, }; uint completeTypeIndex = _objectWriter.GetCompleteClassTypeIndex(classTypeDescriptor, fieldsDescriptor, fields, statics); _completeKnownTypes[type] = completeTypeIndex; if (needsCompleteType) { return(completeTypeIndex); } else { return(typeIndex); } }
private FieldAndOffset[] CreateDynamicLayout(DefType defType, EcmaModule module) { List <FieldAndOffset> fieldsForType = null; int pointerSize = module.Context.Target.PointerSize; // In accordance with CoreCLR runtime conventions, // index 0 corresponds to regular statics, index 1 to thread-local statics. int[][] nonGcStaticsCount = new int[StaticIndexCount][] { new int[TargetDetails.MaximumLog2PrimitiveSize + 1], new int[TargetDetails.MaximumLog2PrimitiveSize + 1], }; int[] gcPointerCount = new int[StaticIndexCount]; int[] gcBoxedCount = new int[StaticIndexCount]; foreach (FieldDesc field in defType.GetFields()) { FieldDefinition fieldDef = module.MetadataReader.GetFieldDefinition(((EcmaField)field.GetTypicalFieldDefinition()).Handle); if ((fieldDef.Attributes & (FieldAttributes.Static | FieldAttributes.Literal)) == FieldAttributes.Static) { int index = (IsFieldThreadStatic(in fieldDef, module.MetadataReader) ? StaticIndexThreadLocal : StaticIndexRegular); int alignment; int size; bool isGcPointerField; bool isGcBoxedField; CorElementType corElementType; EntityHandle valueTypeHandle; GetFieldElementTypeAndValueTypeHandle(in fieldDef, module.MetadataReader, out corElementType, out valueTypeHandle); GetElementTypeInfo(module, field, valueTypeHandle, corElementType, pointerSize, out alignment, out size, out isGcPointerField, out isGcBoxedField); if (isGcPointerField) { gcPointerCount[index]++; } else if (isGcBoxedField) { gcBoxedCount[index]++; } if (size != 0) { int log2Size = GetLog2Size(size); nonGcStaticsCount[index][log2Size]++; } } } int nonGcInitialOffset; switch (pointerSize) { case 4: nonGcInitialOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlob32Bit; break; case 8: nonGcInitialOffset = DomainLocalModuleNormalDynamicEntryOffsetOfDataBlob64Bit; break; default: throw new NotImplementedException(); } LayoutInt[] nonGcStaticFieldOffsets = new LayoutInt[StaticIndexCount] { new LayoutInt(nonGcInitialOffset), new LayoutInt(nonGcInitialOffset), }; LayoutInt[][] nonGcStatics = new LayoutInt[StaticIndexCount][] { new LayoutInt[TargetDetails.MaximumLog2PrimitiveSize + 1], new LayoutInt[TargetDetails.MaximumLog2PrimitiveSize + 1], }; for (int log2Size = TargetDetails.MaximumLog2PrimitiveSize; log2Size >= 0; log2Size--) { for (int index = 0; index < StaticIndexCount; index++) { LayoutInt offset = nonGcStaticFieldOffsets[index]; nonGcStatics[index][log2Size] = offset; offset += new LayoutInt(nonGcStaticsCount[index][log2Size] << log2Size); nonGcStaticFieldOffsets[index] = offset; } } LayoutInt[] gcBoxedFieldOffsets = new LayoutInt[StaticIndexCount]; LayoutInt[] gcPointerFieldOffsets = new LayoutInt[StaticIndexCount] { new LayoutInt(gcBoxedCount[StaticIndexRegular] * pointerSize), new LayoutInt(gcBoxedCount[StaticIndexThreadLocal] * pointerSize) }; foreach (FieldDesc field in defType.GetFields()) { FieldDefinitionHandle fieldDefHandle = ((EcmaField)field.GetTypicalFieldDefinition()).Handle; FieldDefinition fieldDef = module.MetadataReader.GetFieldDefinition(fieldDefHandle); if ((fieldDef.Attributes & (FieldAttributes.Static | FieldAttributes.Literal)) == FieldAttributes.Static) { int index = (IsFieldThreadStatic(in fieldDef, module.MetadataReader) ? StaticIndexThreadLocal : StaticIndexRegular); int alignment; int size; bool isGcPointerField; bool isGcBoxedField; CorElementType corElementType; EntityHandle valueTypeHandle; GetFieldElementTypeAndValueTypeHandle(in fieldDef, module.MetadataReader, out corElementType, out valueTypeHandle); GetElementTypeInfo(module, field, valueTypeHandle, corElementType, pointerSize, out alignment, out size, out isGcPointerField, out isGcBoxedField); LayoutInt offset = LayoutInt.Zero; if (size != 0) { int log2Size = GetLog2Size(size); offset = nonGcStatics[index][log2Size]; nonGcStatics[index][log2Size] += new LayoutInt(1 << log2Size); } if (isGcPointerField) { offset = gcPointerFieldOffsets[index]; gcPointerFieldOffsets[index] += new LayoutInt(pointerSize); } else if (isGcBoxedField) { offset = gcBoxedFieldOffsets[index]; gcBoxedFieldOffsets[index] += new LayoutInt(pointerSize); } if (fieldsForType == null) { fieldsForType = new List <FieldAndOffset>(); } fieldsForType.Add(new FieldAndOffset(field, offset)); } } return(fieldsForType == null ? null : fieldsForType.ToArray()); }