diff options
author | Jan Kotas <jkotas@microsoft.com> | 2015-12-11 06:36:06 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2015-12-11 06:36:06 +0300 |
commit | 78d9cf9f7a3d3d68a5a7a626e2193a4de7b38370 (patch) | |
tree | e9fd5002140029642e08f183c27e608db1e81c5c /src/Common | |
parent | aca70b738cd7c5c3c5c693c0aac1db8c2c26ed72 (diff) | |
parent | 0b395e6ba4476b5b63e3610032e7c970b0e925cb (diff) |
Merge pull request #507 from nattress/eetype_optional_fields
Populate EEType Optional Fields
Diffstat (limited to 'src/Common')
-rw-r--r-- | src/Common/src/Internal/Runtime/EEType.Constants.cs (renamed from src/Common/src/Internal/Runtime/EETypeFlags.cs) | 92 | ||||
-rw-r--r-- | src/Common/src/Internal/Runtime/EEType.cs | 56 | ||||
-rw-r--r-- | src/Common/src/Internal/Runtime/EETypeOptionalFieldsBuilder.cs | 106 | ||||
-rw-r--r-- | src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs | 8 |
4 files changed, 262 insertions, 0 deletions
diff --git a/src/Common/src/Internal/Runtime/EETypeFlags.cs b/src/Common/src/Internal/Runtime/EEType.Constants.cs index ac0aca03b..580c9b2e6 100644 --- a/src/Common/src/Internal/Runtime/EETypeFlags.cs +++ b/src/Common/src/Internal/Runtime/EEType.Constants.cs @@ -101,4 +101,96 @@ namespace Internal.Runtime /// </summary> GenericTypeDefEEType = 0x0003, } + + /// <summary> + /// These are flag values that are rarely set for types. If any of them are set then an optional field will + /// be associated with the EEType to represent them. + /// </summary> + [Flags] + internal enum EETypeRareFlags : int + { + /// <summary> + /// This type requires 8-byte alignment for its fields on certain platforms (only ARM currently). + /// </summary> + RequiresAlign8Flag = 0x00000001, + + /// <summary> + /// Type implements ICastable to allow dynamic resolution of interface casts. + /// </summary> + ICastableFlag = 0x00000002, + + /// <summary> + /// Type is an instantiation of Nullable<T>. + /// </summary> + IsNullableFlag = 0x00000004, + + /// <summary> + /// Nullable target type stashed in the EEType is indirected via the IAT. + /// </summary> + NullableTypeViaIATFlag = 0x00000008, + + /// <summary> + /// This EEType was created by generic instantiation loader + /// </summary> + IsDynamicTypeFlag = 0x00000010, + + /// <summary> + /// This EEType has a Class Constructor + /// </summary> + HasCctorFlag = 0x0000020, + + /// <summary> + /// This EEType has sealed vtable entries (note that this flag is only used for + /// dynamically created types because they always have an optional field (hence the + /// very explicit flag name). + /// </summary> + IsDynamicTypeWithSealedVTableEntriesFlag = 0x00000040, + + /// <summary> + /// This EEType was constructed from a universal canonical template, and has + /// its own dynamically created DispatchMap (does not use the DispatchMap of its template type) + /// </summary> + HasDynamicallyAllocatedDispatchMapFlag = 0x00000080, + + /// <summary> + /// This EEType represents a structure that is an HFA + /// </summary> + IsHFAFlag = 0x00000100, + } + + internal enum EETypeOptionalFieldsElement : byte + { + /// <summary> + /// Extra <c>EEType</c> flags not commonly used such as HasClassConstructor + /// </summary> + RareFlags, + + /// <summary> + /// VTable slot of <see cref="ICastable.IsInstanceOfInterface"/> for direct invocation without interface dispatch overhead + /// </summary> + ICastableIsInstSlot, + + /// <summary> + /// Index of the dispatch map pointer in the DispathMap table + /// </summary> + DispatchMap, + + /// <summary> + /// Padding added to a value type when allocated on the GC heap + /// </summary> + ValueTypeFieldPadding, + + /// <summary> + /// VTable slot of <see cref="ICastable.GetImplType"/> for direct invocation without interface dispatch overhead + /// </summary> + ICastableGetImplTypeSlot, + + /// <summary> + /// Offset in Nullable<T> of the value field + /// </summary> + NullableValueOffset, + + // Number of field types we support + Count + } } diff --git a/src/Common/src/Internal/Runtime/EEType.cs b/src/Common/src/Internal/Runtime/EEType.cs new file mode 100644 index 000000000..f7c7bc4ee --- /dev/null +++ b/src/Common/src/Internal/Runtime/EEType.cs @@ -0,0 +1,56 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Diagnostics; + +namespace Internal.Runtime +{ + internal partial class EEType + { + // These masks and paddings have been chosen so that the ValueTypePadding field can always fit in a byte of data + // if the alignment is 8 bytes or less. If the alignment is higher then there may be a need for more bits to hold + // the rest of the padding data. + // If paddings of greater than 7 bytes are necessary, then the high bits of the field represent that padding + private const UInt32 ValueTypePaddingLowMask = 0x7; + private const UInt32 ValueTypePaddingHighMask = 0xFFFFFF00; + private const UInt32 ValueTypePaddingMax = 0x07FFFFFF; + private const int ValueTypePaddingHighShift = 8; + private const UInt32 ValueTypePaddingAlignmentMask = 0xF8; + private const int ValueTypePaddingAlignmentShift = 3; + + /// <summary> + /// Compute the encoded value type padding and alignment that are stored as optional fields on an + /// <c>EEType</c>. This padding as added to naturally align value types when laid out as fields + /// of objects on the GCHeap. The amount of padding is recorded to allow unboxing to locals / + /// arrays of value types which don't need it. + /// </summary> + internal static UInt32 ComputeValueTypeFieldPaddingFieldValue(UInt32 padding, UInt32 alignment) + { + // For the default case, return 0 + if ((padding == 0) && (alignment == IntPtr.Size)) + return 0; + + UInt32 alignmentLog2 = 0; + Debug.Assert(alignment != 0); + + while ((alignment & 1) == 0) + { + alignmentLog2++; + alignment = alignment >> 1; + } + Debug.Assert(alignment == 1); + + Debug.Assert(ValueTypePaddingMax >= padding); + + // Our alignment values here are adjusted by one to allow for a default of 0 (which represents pointer alignment) + alignmentLog2++; + + UInt32 paddingLowBits = padding & ValueTypePaddingLowMask; + UInt32 paddingHighBits = ((padding & ~ValueTypePaddingLowMask) >> ValueTypePaddingAlignmentShift) << ValueTypePaddingHighShift; + UInt32 alignmentLog2Bits = alignmentLog2 << ValueTypePaddingAlignmentShift; + Debug.Assert((alignmentLog2Bits & ~ValueTypePaddingAlignmentMask) == 0); + return paddingLowBits | paddingHighBits | alignmentLog2Bits; + } + } +}
\ No newline at end of file diff --git a/src/Common/src/Internal/Runtime/EETypeOptionalFieldsBuilder.cs b/src/Common/src/Internal/Runtime/EETypeOptionalFieldsBuilder.cs new file mode 100644 index 000000000..01d4f4f8d --- /dev/null +++ b/src/Common/src/Internal/Runtime/EETypeOptionalFieldsBuilder.cs @@ -0,0 +1,106 @@ +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System; +using System.Runtime.InteropServices; +using Internal.Runtime; +using Internal.NativeFormat; +using System.Diagnostics; +using System.Text; + +namespace Internal.Runtime +{ + internal unsafe partial class EETypeOptionalFieldsBuilder + { + NativePrimitiveEncoder _encoder; + OptionalField[] _rgFields = new OptionalField[(int)EETypeOptionalFieldsElement.Count]; + + struct OptionalField + { + internal bool _fieldPresent; + internal UInt32 _value; + } + + internal EETypeOptionalFieldsBuilder() {} + + internal UInt32 GetFieldValue(EETypeOptionalFieldsElement eTag, UInt32 defaultValueIfNotFound) + { + return _rgFields[(int)eTag]._fieldPresent ? _rgFields[(int)eTag]._value : defaultValueIfNotFound; + } + + internal void SetFieldValue(EETypeOptionalFieldsElement eTag, UInt32 value) + { + _rgFields[(int)eTag]._fieldPresent = true; + _rgFields[(int)eTag]._value = value; + } + + internal void ClearField(EETypeOptionalFieldsElement eTag) + { + _rgFields[(int)eTag]._fieldPresent = false; + } + + private int Encode() + { + EETypeOptionalFieldsElement eLastTag = EETypeOptionalFieldsElement.Count; + + for (EETypeOptionalFieldsElement eTag = 0; eTag < EETypeOptionalFieldsElement.Count; eTag++) + eLastTag = _rgFields[(int)eTag]._fieldPresent ? eTag : eLastTag; + + if (eLastTag == EETypeOptionalFieldsElement.Count) + return 0; + + _encoder = new NativePrimitiveEncoder(); + _encoder.Init(); + + for (EETypeOptionalFieldsElement eTag = 0; eTag < EETypeOptionalFieldsElement.Count; eTag++) + { + if (!_rgFields[(int)eTag]._fieldPresent) + continue; + + _encoder.WriteByte((byte)((byte)eTag | (eTag == eLastTag ? 0x80 : 0))); + _encoder.WriteUnsigned(_rgFields[(int)eTag]._value); + } + + return _encoder.Size; + } + + public byte[] GetBytes() + { + Debug.Assert(IsAtLeastOneFieldUsed()); + if (_encoder.Size == 0) + { + Encode(); + } + + return _encoder.GetBytes(); + } + + public bool IsAtLeastOneFieldUsed() + { + for (int i = 0; i < (int)EETypeOptionalFieldsElement.Count; i++) + { + if (_rgFields[i]._fieldPresent) + return true; + } + + return false; + } + + public override string ToString() + { + StringBuilder sb = new StringBuilder(); + + for (int i = 0; i < (int)EETypeOptionalFieldsElement.Count; i++) + { + sb.Append(_rgFields[i]._value.ToString()); + + if (i != (int)EETypeOptionalFieldsElement.Count - 1) + { + sb.Append("_"); + } + } + + return sb.ToString(); + } + } +} diff --git a/src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs b/src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs index 437c51d6e..51604a385 100644 --- a/src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs +++ b/src/Common/src/TypeSystem/Common/DefType.FieldLayout.cs @@ -230,6 +230,14 @@ namespace Internal.TypeSystem } } + /// <summary> + /// Do the fields of the type satisfy the Homogeneous Float Aggregate classification on ARM architecture? + /// </summary> + public virtual bool IsHFA() + { + return false; + } + internal void ComputeInstanceFieldLayout() { var computedLayout = this.Context.GetLayoutAlgorithmForType(this).ComputeInstanceFieldLayout(this); |