From 9fbf048726e7d67280f3d073223769a6d39b4ca3 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 5 Aug 2021 19:35:30 +0200 Subject: [PATCH] Implement DefType.IsUnsafeValueType (#56790) MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Co-authored-by: Michal Strehovský --- .../Common/Compiler/VectorFieldLayoutAlgorithm.cs | 6 ++++ .../tools/Common/JitInterface/CorInfoImpl.cs | 5 ++- .../TypeSystem/Common/DefType.FieldLayout.cs | 41 ++++++++++++++++++++++ .../TypeSystem/Common/FieldLayoutAlgorithm.cs | 5 +++ .../Common/MetadataFieldLayoutAlgorithm.cs | 25 +++++++++++++ .../Common/UniversalCanonLayoutAlgorithm.cs | 5 +++ .../RuntimeDeterminedFieldLayoutAlgorithm.cs | 8 +++++ .../Compiler/ReadyToRunCompilerContext.cs | 5 +++ .../Compiler/SystemObjectFieldLayoutAlgorithm.cs | 5 +++ 9 files changed, 102 insertions(+), 3 deletions(-) diff --git a/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs index 95bbf35..a4e49bd 100644 --- a/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/Compiler/VectorFieldLayoutAlgorithm.cs @@ -90,6 +90,12 @@ namespace ILCompiler return false; } + public override bool ComputeIsUnsafeValueType(DefType type) + { + Debug.Assert(!_fallbackAlgorithm.ComputeIsUnsafeValueType(type)); + return false; + } + public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type) { if (type.Context.Target.Architecture == TargetArchitecture.ARM64 && diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index d5dc33b..8cf79f8 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -1875,9 +1875,8 @@ namespace Internal.JitInterface if (metadataType.IsExplicitLayout || (metadataType.IsSequentialLayout && metadataType.GetClassLayout().Size != 0) || metadataType.IsWellKnownType(WellKnownType.TypedReference)) result |= CorInfoFlag.CORINFO_FLG_CUSTOMLAYOUT; - // TODO - // if (type.IsUnsafeValueType) - // result |= CorInfoFlag.CORINFO_FLG_UNSAFE_VALUECLASS; + if (metadataType.IsUnsafeValueType) + result |= CorInfoFlag.CORINFO_FLG_UNSAFE_VALUECLASS; } if (type.IsCanonicalSubtype(CanonicalFormKind.Any)) diff --git a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs index 3e73dcf..71c7423 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/DefType.FieldLayout.cs @@ -53,6 +53,16 @@ namespace Internal.TypeSystem /// True if the layout of the type is not stable for use in the ABI /// public const int ComputedInstanceLayoutAbiUnstable = 0x80; + + /// + /// True if IsUnsafeValueType has been computed + /// + public const int ComputedIsUnsafeValueType = 0x100; + + /// + /// True if type transitively has UnsafeValueTypeAttribute + /// + public const int IsUnsafeValueType = 0x200; } private class StaticBlockInfo @@ -91,6 +101,22 @@ namespace Internal.TypeSystem } /// + /// Does a type transitively have any fields which are marked with System.Runtime.CompilerServices.UnsafeValueTypeAttribute + /// + public bool IsUnsafeValueType + { + get + { + if (!_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedIsUnsafeValueType)) + { + ComputeIsUnsafeValueType(); + } + return _fieldLayoutFlags.HasFlags(FieldLayoutFlags.IsUnsafeValueType); + } + } + + + /// /// The number of bytes required to hold a field of this type /// public LayoutInt InstanceFieldSize @@ -449,5 +475,20 @@ namespace Internal.TypeSystem _fieldLayoutFlags.AddFlags(flagsToAdd); } + + public void ComputeIsUnsafeValueType() + { + if (_fieldLayoutFlags.HasFlags(FieldLayoutFlags.ComputedIsUnsafeValueType)) + return; + + int flagsToAdd = FieldLayoutFlags.ComputedIsUnsafeValueType; + + if (this.Context.GetLayoutAlgorithmForType(this).ComputeIsUnsafeValueType(this)) + { + flagsToAdd |= FieldLayoutFlags.IsUnsafeValueType; + } + + _fieldLayoutFlags.AddFlags(flagsToAdd); + } } } diff --git a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs index 47c8638..863e857 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/FieldLayoutAlgorithm.cs @@ -32,6 +32,11 @@ namespace Internal.TypeSystem public abstract bool ComputeContainsGCPointers(DefType type); /// + /// Compute whether the specified type is a value type that transitively has UnsafeValueTypeAttribute + /// + public abstract bool ComputeIsUnsafeValueType(DefType type); + + /// /// Compute the shape of a value type. The shape information is used to control code generation and allocation /// (such as vectorization, passing the value type by value across method calls, or boxing alignment). /// diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 4109bb7..f445bb1 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -1014,6 +1014,31 @@ namespace Internal.TypeSystem return NotHA; } + public override bool ComputeIsUnsafeValueType(DefType type) + { + if (!type.IsValueType) + return false; + + MetadataType metadataType = (MetadataType)type; + if (metadataType.HasCustomAttribute("System.Runtime.CompilerServices", "UnsafeValueTypeAttribute")) + return true; + + foreach (FieldDesc field in metadataType.GetFields()) + { + if (field.IsStatic) + continue; + + TypeDesc fieldType = field.FieldType; + if (!fieldType.IsValueType || fieldType.IsPrimitive) + continue; + + if (((DefType)fieldType).IsUnsafeValueType) + return true; + } + + return false; + } + private struct SizeAndAlignment { public LayoutInt Size; diff --git a/src/coreclr/tools/Common/TypeSystem/Common/UniversalCanonLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/UniversalCanonLayoutAlgorithm.cs index 9b58069..196aef8 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/UniversalCanonLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/UniversalCanonLayoutAlgorithm.cs @@ -34,6 +34,11 @@ namespace Internal.TypeSystem }; } + public override bool ComputeIsUnsafeValueType(DefType type) + { + throw new NotSupportedException(); + } + public override ComputedStaticFieldLayout ComputeStaticFieldLayout(DefType type, StaticLayoutKind layoutKind) { return new ComputedStaticFieldLayout() diff --git a/src/coreclr/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedFieldLayoutAlgorithm.cs index 5985768..2d26f45 100644 --- a/src/coreclr/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/RuntimeDetermined/RuntimeDeterminedFieldLayoutAlgorithm.cs @@ -58,5 +58,13 @@ namespace Internal.TypeSystem return canonicalType.ValueTypeShapeCharacteristics; } + + public override bool ComputeIsUnsafeValueType(DefType type) + { + RuntimeDeterminedType runtimeDeterminedType = (RuntimeDeterminedType)type; + DefType canonicalType = runtimeDeterminedType.CanonicalType; + + return canonicalType.IsUnsafeValueType; + } } } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs index 5790516..44bddc1 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCompilerContext.cs @@ -154,6 +154,11 @@ namespace ILCompiler return false; } + public override bool ComputeIsUnsafeValueType(DefType type) + { + return false; + } + public override ComputedInstanceFieldLayout ComputeInstanceLayout(DefType type, InstanceLayoutKind layoutKind) { DefType similarSpecifiedVector = GetSimilarVector(type); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/SystemObjectFieldLayoutAlgorithm.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/SystemObjectFieldLayoutAlgorithm.cs index 2d04a02..a0d68d1 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/SystemObjectFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/SystemObjectFieldLayoutAlgorithm.cs @@ -50,6 +50,11 @@ namespace ILCompiler return false; } + public override bool ComputeIsUnsafeValueType(DefType type) + { + return false; + } + public override ValueTypeShapeCharacteristics ComputeValueTypeShapeCharacteristics(DefType type) { return _fallbackAlgorithm.ComputeValueTypeShapeCharacteristics(type); -- 2.7.4