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 static LayoutInt AlignUp(LayoutInt value, LayoutInt alignment, TargetDetails target) { if (value.IsIndeterminate || alignment.IsIndeterminate) { // If value is already aligned to maximum possible alignment, then whatever // alignment is can't change value if (!value.IsIndeterminate) { if (value.AsInt.AlignUp(target.MaximumAlignment) == value.AsInt) { return(value); } } return(Indeterminate); } Debug.Assert(alignment._value <= target.MaximumAlignment); // Assert that the alignment handling for indeterminate types is safe Debug.Assert(alignment._value >= 1 || ((value._value == 0) && (alignment._value == 0))); // Alignment to less than one doesn't make sense, except for 0 to 0 alignment return(new LayoutInt(AlignmentHelper.AlignUp(value._value, alignment._value))); }
private static SizeAndAlignment ComputeInstanceSize(MetadataType type, int count, int alignment, out SizeAndAlignment byteCount) { SizeAndAlignment result; int targetPointerSize = type.Context.Target.PointerSize; // Pad the length of structs to be 1 if they are empty so we have no zero-length structures if (type.IsValueType && count == 0) { count = 1; } if (type.IsValueType) { count = AlignmentHelper.AlignUp(count, alignment); result.Size = count; result.Alignment = alignment; } else { result.Size = targetPointerSize; result.Alignment = targetPointerSize; if (type.HasBaseType) { alignment = Math.Max(alignment, type.BaseType.InstanceByteAlignment); } } // Determine the alignment needed by the type when allocated // This is target specific, and not just pointer sized due to // 8 byte alignment requirements on ARM for longs and doubles alignment = type.Context.Target.GetObjectAlignment(alignment); byteCount.Size = count; byteCount.Alignment = alignment; return(result); }
public unsafe override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType defType) { MetadataType type = (MetadataType)defType; int numStaticFields = 0; foreach (var field in type.GetFields()) { if (!field.IsStatic || field.HasRva || field.IsLiteral) { continue; } numStaticFields++; } ComputedStaticFieldLayout result; result.GcStatics = new StaticsBlock(); result.NonGcStatics = new StaticsBlock(); result.ThreadStatics = new StaticsBlock(); if (numStaticFields == 0) { result.Offsets = null; return(result); } result.Offsets = new FieldAndOffset[numStaticFields]; PrepareRuntimeSpecificStaticFieldLayout(type.Context, ref result); int index = 0; foreach (var field in type.GetFields()) { // Nonstatic fields, literal fields, and RVA mapped fields don't participate in layout if (!field.IsStatic || field.HasRva || field.IsLiteral) { continue; } StaticsBlock *block = field.IsThreadStatic ? &result.ThreadStatics : field.HasGCStaticBase ? &result.GcStatics : &result.NonGcStatics; SizeAndAlignment sizeAndAlignment = ComputeFieldSizeAndAlignment(field.FieldType, type.Context.Target.DefaultPackingSize); block->Size = AlignmentHelper.AlignUp(block->Size, sizeAndAlignment.Alignment); result.Offsets[index] = new FieldAndOffset(field, block->Size); block->Size = checked (block->Size + sizeAndAlignment.Size); block->LargestAlignment = Math.Max(block->LargestAlignment, sizeAndAlignment.Alignment); index++; } FinalizeRuntimeSpecificStaticFieldLayout(type.Context, ref result); return(result); }