public static void Validate(MetadataType type, ComputedInstanceFieldLayout layout) { ExplicitLayoutValidator validator = new ExplicitLayoutValidator(type, layout.ByteCountUnaligned.AsInt); foreach (FieldAndOffset fieldAndOffset in layout.Offsets) { validator.AddToFieldLayout(fieldAndOffset.Offset.AsInt, fieldAndOffset.Field.FieldType); } }
public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind) { if (!type.IsTemplateUniversal() && (layoutKind == InstanceLayoutKind.TypeOnly)) { // Non universal generics can just use the template's layout DefType template = (DefType)type.ComputeTemplate(); return _noMetadataFieldLayoutAlgorithm.ComputeInstanceLayout(template, InstanceLayoutKind.TypeOnly); } // Only needed for universal generics, or when looking up an offset for a field for a universal generic LowLevelList<int> fieldOffsets; int[] position = ComputeTypeSizeAndAlignment(type, FieldLoadState.Instance, out fieldOffsets); int numInstanceFields = 0; foreach (NativeLayoutFieldDesc field in type.NativeLayoutFields) { if (!field.IsStatic) { numInstanceFields++; } } int byteCountAlignment = position[InstanceAlignmentEntry]; byteCountAlignment = type.Context.Target.GetObjectAlignment(byteCountAlignment); ComputedInstanceFieldLayout layout = new ComputedInstanceFieldLayout() { Offsets = new FieldAndOffset[numInstanceFields], ByteCountAlignment = byteCountAlignment, ByteCountUnaligned = position[(int)NativeFormat.FieldStorage.Instance], PackValue = 0 // TODO, as we add more metadata handling logic, find out if its necessary to use a meaningful value here }; if (!type.IsValueType) { layout.FieldAlignment = type.Context.Target.PointerSize; layout.FieldSize = type.Context.Target.PointerSize; } else { layout.FieldAlignment = position[InstanceAlignmentEntry]; layout.FieldSize = MemoryHelpers.AlignUp(position[(int)NativeFormat.FieldStorage.Instance], layout.FieldAlignment); } int curInstanceField = 0; foreach (NativeLayoutFieldDesc field in type.NativeLayoutFields) { if (!field.IsStatic) { layout.Offsets[curInstanceField] = new FieldAndOffset(field, fieldOffsets[curInstanceField]); curInstanceField++; } } return layout; }
private static ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType type, int numInstanceFields) { var offsets = new FieldAndOffset[numInstanceFields]; // For types inheriting from another type, field offsets continue on from where they left off int cumulativeInstanceFieldPos = ComputeBytesUsedInParentType(type); int largestAlignmentRequirement = 1; int fieldOrdinal = 0; int packingSize = ComputePackingSize(type); foreach (var field in type.GetFields()) { if (field.IsStatic) { continue; } var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, packingSize); if (fieldSizeAndAlignment.Alignment > largestAlignmentRequirement) { largestAlignmentRequirement = fieldSizeAndAlignment.Alignment; } cumulativeInstanceFieldPos = AlignmentHelper.AlignUp(cumulativeInstanceFieldPos, fieldSizeAndAlignment.Alignment); offsets[fieldOrdinal] = new FieldAndOffset(field, cumulativeInstanceFieldPos); cumulativeInstanceFieldPos = checked (cumulativeInstanceFieldPos + fieldSizeAndAlignment.Size); fieldOrdinal++; } if (type.IsValueType) { var layoutMetadata = type.GetClassLayout(); cumulativeInstanceFieldPos = Math.Max(cumulativeInstanceFieldPos, layoutMetadata.Size); } SizeAndAlignment instanceByteSizeAndAlignment; var instanceSizeAndAlignment = ComputeInstanceSize(type, cumulativeInstanceFieldPos, largestAlignmentRequirement, out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; computedLayout.ByteCountAlignment = instanceByteSizeAndAlignment.Alignment; computedLayout.Offsets = offsets; return(computedLayout); }
public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind) { // Individual field offset layout for a RuntimeDeterminedType is not a supported operation if (layoutKind != InstanceLayoutKind.TypeOnly) { throw new NotSupportedException(); } RuntimeDeterminedType type = (RuntimeDeterminedType)defType; DefType canonicalType = type.CanonicalType; ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout { ByteCountUnaligned = canonicalType.InstanceByteCountUnaligned, ByteCountAlignment = canonicalType.InstanceByteAlignment, FieldAlignment = canonicalType.InstanceFieldAlignment, FieldSize = canonicalType.InstanceFieldSize, Offsets = Array.Empty <FieldAndOffset>() }; return(result); }
public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind) { MetadataType type = (MetadataType)defType; if (type.IsGenericDefinition) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // CLI - Partition 1, section 9.5 - Generic types shall not be marked explicitlayout. if (type.HasInstantiation && type.IsExplicitLayout) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadExplicitGeneric, type.GetTypeDefinition()); } // Count the number of instance fields in advance for convenience int numInstanceFields = 0; foreach (var field in type.GetFields()) { if (field.IsStatic) { continue; } TypeDesc fieldType = field.FieldType; // ByRef instance fields are not allowed. if (fieldType.IsByRef) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // ByRef-like instance fields on non-byref-like types are not allowed. if (fieldType.IsByRefLike && !type.IsByRefLike) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } numInstanceFields++; } if (type.IsModuleType) { // This is a global type, it must not have instance fields. if (numInstanceFields > 0) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } // Global types do not do the rest of instance field layout. ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout(); result.Offsets = Array.Empty <FieldAndOffset>(); return(result); } // CLI - Partition 2, section 22.8 // A type has layout if it is marked SequentialLayout or ExplicitLayout. If any type within an inheritance chain has layout, // then so shall all its base classes, up to the one that descends immediately from System.ValueType (if it exists in the type's // hierarchy); otherwise, from System.Object // Note: While the CLI isn't clearly worded, the layout needs to be the same for the entire chain. // If the current type isn't ValueType or System.Object and has a layout and the parent type isn't // ValueType or System.Object then the layout type attributes need to match if ((!type.IsValueType && !type.IsObject) && (type.IsSequentialLayout || type.IsExplicitLayout) && (!type.BaseType.IsValueType && !type.BaseType.IsObject)) { MetadataType baseType = type.MetadataBaseType; if (type.IsSequentialLayout != baseType.IsSequentialLayout || type.IsExplicitLayout != baseType.IsExplicitLayout) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadBadFormat, type); } } // Enum types must have a single instance field if (type.IsEnum && numInstanceFields != 1) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } if (type.IsPrimitive) { // Primitive types are special - they may have a single field of the same type // as the type itself. They do not do the rest of instance field layout. if (numInstanceFields > 1) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadGeneral, type); } SizeAndAlignment instanceByteSizeAndAlignment; var sizeAndAlignment = ComputeInstanceSize( type, type.Context.Target.GetWellKnownTypeSize(type), type.Context.Target.GetWellKnownTypeAlignment(type), 0, out instanceByteSizeAndAlignment ); ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout { ByteCountUnaligned = instanceByteSizeAndAlignment.Size, ByteCountAlignment = instanceByteSizeAndAlignment.Alignment, FieldAlignment = sizeAndAlignment.Alignment, FieldSize = sizeAndAlignment.Size, }; if (numInstanceFields > 0) { FieldDesc instanceField = null; foreach (FieldDesc field in type.GetFields()) { if (!field.IsStatic) { Debug.Assert(instanceField == null, "Unexpected extra instance field"); instanceField = field; } } Debug.Assert(instanceField != null, "Null instance field"); result.Offsets = new FieldAndOffset[] { new FieldAndOffset(instanceField, LayoutInt.Zero) }; } else { result.Offsets = Array.Empty <FieldAndOffset>(); } return(result); } // If the type has layout, read its packing and size info // If the type has explicit layout, also read the field offset info if (type.IsExplicitLayout || type.IsSequentialLayout) { if (type.IsEnum) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadBadFormat, type); } var layoutMetadata = type.GetClassLayout(); // If packing is out of range or not a power of two, throw that the size is invalid int packing = layoutMetadata.PackingSize; if (packing < 0 || packing > 128 || ((packing & (packing - 1)) != 0)) { ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadBadFormat, type); } Debug.Assert(layoutMetadata.Offsets == null || layoutMetadata.Offsets.Length == numInstanceFields); } // At this point all special cases are handled and all inputs validated return(ComputeInstanceFieldLayout(type, numInstanceFields)); }
private static ComputedInstanceFieldLayout ComputeSequentialFieldLayout(MetadataType type, int numInstanceFields) { var offsets = new FieldAndOffset[numInstanceFields]; // For types inheriting from another type, field offsets continue on from where they left off int cumulativeInstanceFieldPos = ComputeBytesUsedInParentType(type); int largestAlignmentRequirement = 1; int fieldOrdinal = 0; int packingSize = ComputePackingSize(type); foreach (var field in type.GetFields()) { if (field.IsStatic) continue; var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, packingSize); if (fieldSizeAndAlignment.Alignment > largestAlignmentRequirement) largestAlignmentRequirement = fieldSizeAndAlignment.Alignment; cumulativeInstanceFieldPos = AlignmentHelper.AlignUp(cumulativeInstanceFieldPos, fieldSizeAndAlignment.Alignment); offsets[fieldOrdinal] = new FieldAndOffset(field, cumulativeInstanceFieldPos); cumulativeInstanceFieldPos = checked(cumulativeInstanceFieldPos + fieldSizeAndAlignment.Size); fieldOrdinal++; } if (type.IsValueType) { var layoutMetadata = type.GetClassLayout(); cumulativeInstanceFieldPos = Math.Max(cumulativeInstanceFieldPos, layoutMetadata.Size); } SizeAndAlignment instanceByteSizeAndAlignment; var instanceSizeAndAlignment = ComputeInstanceSize(type, cumulativeInstanceFieldPos, largestAlignmentRequirement, out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; computedLayout.ByteCountAlignment = instanceByteSizeAndAlignment.Alignment; computedLayout.Offsets = offsets; return computedLayout; }
private static ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType type, int numInstanceFields) { // Instance slice size is the total size of instance not including the base type. // It is calculated as the field whose offset and size add to the greatest value. int cumulativeInstanceFieldPos = type.HasBaseType && !type.IsValueType ? type.BaseType.InstanceByteCount : 0; int instanceSize = cumulativeInstanceFieldPos; var layoutMetadata = type.GetClassLayout(); int packingSize = ComputePackingSize(type); int largestAlignmentRequired = 1; var offsets = new FieldAndOffset[numInstanceFields]; int fieldOrdinal = 0; foreach (var fieldAndOffset in layoutMetadata.Offsets) { var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldAndOffset.Field.FieldType, packingSize); if (fieldSizeAndAlignment.Alignment > largestAlignmentRequired) largestAlignmentRequired = fieldSizeAndAlignment.Alignment; if (fieldAndOffset.Offset == FieldAndOffset.InvalidOffset) throw new TypeLoadException(); int computedOffset = checked(fieldAndOffset.Offset + cumulativeInstanceFieldPos); switch (fieldAndOffset.Field.FieldType.Category) { case TypeFlags.Array: case TypeFlags.Class: { int offsetModulo = computedOffset % type.Context.Target.PointerSize; if (offsetModulo != 0) { // GC pointers MUST be aligned. if (offsetModulo == 4) { // We must be attempting to compile a 32bit app targeting a 64 bit platform. throw new TypeLoadException(); } else { // Its just wrong throw new TypeLoadException(); } } break; } } offsets[fieldOrdinal] = new FieldAndOffset(fieldAndOffset.Field, computedOffset); int fieldExtent = checked(computedOffset + fieldSizeAndAlignment.Size); if (fieldExtent > instanceSize) { instanceSize = fieldExtent; } fieldOrdinal++; } if (type.IsValueType && layoutMetadata.Size > instanceSize) { instanceSize = layoutMetadata.Size; } SizeAndAlignment instanceByteSizeAndAlignment; var instanceSizeAndAlignment = ComputeInstanceSize(type, instanceSize, largestAlignmentRequired, out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; computedLayout.ByteCountAlignment = instanceByteSizeAndAlignment.Alignment; computedLayout.Offsets = offsets; return computedLayout; }
public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType defType, InstanceLayoutKind layoutKind) { MetadataType type = (MetadataType)defType; // CLI - Partition 1, section 9.5 - Generic types shall not be marked explicitlayout. if (type.HasInstantiation && type.IsExplicitLayout) { throw new TypeLoadException(); } // Count the number of instance fields in advance for convenience int numInstanceFields = 0; foreach (var field in type.GetFields()) if (!field.IsStatic) numInstanceFields++; if (type.IsModuleType) { // This is a global type, it must not have instance fields. if (numInstanceFields > 0) { throw new TypeLoadException(); } // Global types do not do the rest of instance field layout. ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout(); result.PackValue = type.Context.Target.DefaultPackingSize; result.Offsets = Array.Empty<FieldAndOffset>(); return result; } // CLI - Partition 2, section 22.8 // A type has layout if it is marked SequentialLayout or ExplicitLayout. If any type within an inheritance chain has layout, // then so shall all its base classes, up to the one that descends immediately from System.ValueType (if it exists in the type’s // hierarchy); otherwise, from System.Object // Note: While the CLI isn't clearly worded, the layout needs to be the same for the entire chain. // If the current type isn't ValueType or System.Object and has a layout and the parent type isn't // ValueType or System.Object then the layout type attributes need to match if ((!type.IsValueType && !type.IsObject) && (type.IsSequentialLayout || type.IsExplicitLayout) && (!type.BaseType.IsValueType && !type.BaseType.IsObject)) { MetadataType baseType = type.MetadataBaseType; if (type.IsSequentialLayout != baseType.IsSequentialLayout || type.IsExplicitLayout != baseType.IsExplicitLayout) { throw new TypeLoadException(); } } // Enum types must have a single instance field if (type.IsEnum && numInstanceFields != 1) { throw new TypeLoadException(); } if (type.IsPrimitive) { // Primitive types are special - they may have a single field of the same type // as the type itself. They do not do the rest of instance field layout. if (numInstanceFields > 1) { throw new TypeLoadException(); } SizeAndAlignment instanceByteSizeAndAlignment; var sizeAndAlignment = ComputeInstanceSize( type, type.Context.Target.GetWellKnownTypeSize(type), type.Context.Target.GetWellKnownTypeAlignment(type), out instanceByteSizeAndAlignment ); ComputedInstanceFieldLayout result = new ComputedInstanceFieldLayout { ByteCountUnaligned = instanceByteSizeAndAlignment.Size, ByteCountAlignment = instanceByteSizeAndAlignment.Alignment, FieldAlignment = sizeAndAlignment.Alignment, FieldSize = sizeAndAlignment.Size, PackValue = type.Context.Target.DefaultPackingSize }; if (numInstanceFields > 0) { FieldDesc instanceField = null; foreach (FieldDesc field in type.GetFields()) { if (!field.IsStatic) { Debug.Assert(instanceField == null, "Unexpected extra instance field"); instanceField = field; } } Debug.Assert(instanceField != null, "Null instance field"); result.Offsets = new FieldAndOffset[] { new FieldAndOffset(instanceField, 0) }; } else { result.Offsets = Array.Empty<FieldAndOffset>(); } return result; } // Verify that no ByRef types present in this type's fields foreach (var field in type.GetFields()) if (field.FieldType is ByRefType) throw new TypeLoadException(); // If the type has layout, read its packing and size info // If the type has explicit layout, also read the field offset info if (type.IsExplicitLayout || type.IsSequentialLayout) { if (type.IsEnum) { throw new TypeLoadException(); } var layoutMetadata = type.GetClassLayout(); // If packing is out of range or not a power of two, throw that the size is invalid int packing = layoutMetadata.PackingSize; if (packing < 0 || packing > 128 || ((packing & (packing - 1)) != 0)) { throw new TypeLoadException(); } Debug.Assert(layoutMetadata.Offsets == null || layoutMetadata.Offsets.Length == numInstanceFields); } // At this point all special cases are handled and all inputs validated if (type.IsExplicitLayout) { return ComputeExplicitFieldLayout(type, numInstanceFields); } else { // Treat auto layout as sequential for now return ComputeSequentialFieldLayout(type, numInstanceFields); } }
private static ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType type, int numInstanceFields) { // Instance slice size is the total size of instance not including the base type. // It is calculated as the field whose offset and size add to the greatest value. int cumulativeInstanceFieldPos = type.HasBaseType && !type.IsValueType ? type.BaseType.InstanceByteCount : 0; int instanceSize = cumulativeInstanceFieldPos; var layoutMetadata = type.GetClassLayout(); int packingSize = ComputePackingSize(type); int largestAlignmentRequired = 1; var offsets = new FieldAndOffset[numInstanceFields]; int fieldOrdinal = 0; foreach (var fieldAndOffset in layoutMetadata.Offsets) { var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldAndOffset.Field.FieldType, packingSize); if (fieldSizeAndAlignment.Alignment > largestAlignmentRequired) { largestAlignmentRequired = fieldSizeAndAlignment.Alignment; } if (fieldAndOffset.Offset == FieldAndOffset.InvalidOffset) { throw new TypeLoadException(); } int computedOffset = checked (fieldAndOffset.Offset + cumulativeInstanceFieldPos); switch (fieldAndOffset.Field.FieldType.Category) { case TypeFlags.Array: case TypeFlags.Class: { int offsetModulo = computedOffset % type.Context.Target.PointerSize; if (offsetModulo != 0) { // GC pointers MUST be aligned. if (offsetModulo == 4) { // We must be attempting to compile a 32bit app targeting a 64 bit platform. throw new TypeLoadException(); } else { // Its just wrong throw new TypeLoadException(); } } break; } } offsets[fieldOrdinal] = new FieldAndOffset(fieldAndOffset.Field, computedOffset); int fieldExtent = checked (computedOffset + fieldSizeAndAlignment.Size); if (fieldExtent > instanceSize) { instanceSize = fieldExtent; } fieldOrdinal++; } if (type.IsValueType && layoutMetadata.Size > instanceSize) { instanceSize = layoutMetadata.Size; } SizeAndAlignment instanceByteSizeAndAlignment; var instanceSizeAndAlignment = ComputeInstanceSize(type, instanceSize, largestAlignmentRequired, out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; computedLayout.ByteCountAlignment = instanceByteSizeAndAlignment.Alignment; computedLayout.Offsets = offsets; return(computedLayout); }
private static ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType type, int numInstanceFields) { // Instance slice size is the total size of instance not including the base type. // It is calculated as the field whose offset and size add to the greatest value. LayoutInt cumulativeInstanceFieldPos = type.HasBaseType && !type.IsValueType ? type.BaseType.InstanceByteCount : LayoutInt.Zero; LayoutInt instanceSize = cumulativeInstanceFieldPos; var layoutMetadata = type.GetClassLayout(); int packingSize = ComputePackingSize(type); LayoutInt largestAlignmentRequired = LayoutInt.One; var offsets = new FieldAndOffset[numInstanceFields]; int fieldOrdinal = 0; foreach (var fieldAndOffset in layoutMetadata.Offsets) { var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldAndOffset.Field.FieldType, packingSize); largestAlignmentRequired = LayoutInt.Max(fieldSizeAndAlignment.Alignment, largestAlignmentRequired); if (fieldAndOffset.Offset == FieldAndOffset.InvalidOffset) { throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadBadFormat, type); } LayoutInt computedOffset = fieldAndOffset.Offset + cumulativeInstanceFieldPos; if (fieldAndOffset.Field.FieldType.IsGCPointer && !computedOffset.IsIndeterminate) { int offsetModulo = computedOffset.AsInt % type.Context.Target.PointerSize; if (offsetModulo != 0) { // GC pointers MUST be aligned. throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadExplicitLayout, type, fieldAndOffset.Offset.ToStringInvariant()); } } offsets[fieldOrdinal] = new FieldAndOffset(fieldAndOffset.Field, computedOffset); LayoutInt fieldExtent = computedOffset + fieldSizeAndAlignment.Size; instanceSize = LayoutInt.Max(fieldExtent, instanceSize); fieldOrdinal++; } if (type.IsValueType) { instanceSize = LayoutInt.Max(new LayoutInt(layoutMetadata.Size), instanceSize); } SizeAndAlignment instanceByteSizeAndAlignment; var instanceSizeAndAlignment = ComputeInstanceSize(type, instanceSize, largestAlignmentRequired, out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; computedLayout.ByteCountAlignment = instanceByteSizeAndAlignment.Alignment; computedLayout.Offsets = offsets; return(computedLayout); }
private static ComputedInstanceFieldLayout ComputeExplicitFieldLayout(MetadataType type, int numInstanceFields) { // Instance slice size is the total size of instance not including the base type. // It is calculated as the field whose offset and size add to the greatest value. int cumulativeInstanceFieldPos = type.HasBaseType && !type.IsValueType ? type.BaseType.InstanceByteCount : 0; int instanceSize = cumulativeInstanceFieldPos; var layoutMetadata = type.GetClassLayout(); int packingSize = ComputePackingSize(type); int largestAlignmentRequired = 1; var offsets = new FieldAndOffset[numInstanceFields]; int fieldOrdinal = 0; foreach (var fieldAndOffset in layoutMetadata.Offsets) { var fieldSizeAndAlignment = ComputeFieldSizeAndAlignment(fieldAndOffset.Field.FieldType, packingSize); if (fieldSizeAndAlignment.Alignment > largestAlignmentRequired) largestAlignmentRequired = fieldSizeAndAlignment.Alignment; if (fieldAndOffset.Offset == FieldAndOffset.InvalidOffset) throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadBadFormat, type); int computedOffset = checked(fieldAndOffset.Offset + cumulativeInstanceFieldPos); if (fieldAndOffset.Field.FieldType.IsGCPointer) { int offsetModulo = computedOffset % type.Context.Target.PointerSize; if (offsetModulo != 0) { // GC pointers MUST be aligned. throw new TypeSystemException.TypeLoadException(ExceptionStringID.ClassLoadExplicitLayout, type, fieldAndOffset.Offset.ToStringInvariant()); } } offsets[fieldOrdinal] = new FieldAndOffset(fieldAndOffset.Field, computedOffset); int fieldExtent = checked(computedOffset + fieldSizeAndAlignment.Size); if (fieldExtent > instanceSize) { instanceSize = fieldExtent; } fieldOrdinal++; } if (type.IsValueType && layoutMetadata.Size > instanceSize) { instanceSize = layoutMetadata.Size; } SizeAndAlignment instanceByteSizeAndAlignment; var instanceSizeAndAlignment = ComputeInstanceSize(type, instanceSize, largestAlignmentRequired, out instanceByteSizeAndAlignment); ComputedInstanceFieldLayout computedLayout = new ComputedInstanceFieldLayout(); computedLayout.FieldAlignment = instanceSizeAndAlignment.Alignment; computedLayout.FieldSize = instanceSizeAndAlignment.Size; computedLayout.ByteCountUnaligned = instanceByteSizeAndAlignment.Size; computedLayout.ByteCountAlignment = instanceByteSizeAndAlignment.Alignment; computedLayout.Offsets = offsets; return computedLayout; }