runtime
runtime copied to clipboard
Allocate RuntimeType objects on Frozen Object Heap
Follow up to https://github.com/dotnet/runtime/pull/49576 This PR allocates Type objects on the recently-added Frozen Segments so we can bake direct objects' addresses in JIT and avoid helper calls, e.g. for:
Type Test() => typeof(int);
Old codegen:
; Method Program:Test():System.Type:this
G_M50870_IG01:
4883EC28 sub rsp, 40
G_M50870_IG02:
48B968BB53F5FB7F0000 mov rcx, 0x7FFBF553BB68 ; System.Int32
E81D94505F call CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE
90 nop
G_M50870_IG03:
4883C428 add rsp, 40
C3 ret
; Total bytes of code: 25
New codegen:
; Method Program:Test():System.Type:this
G_M50870_IG01:
G_M50870_IG02:
48B8482A63DE29020000 mov rax, 0x229DE632A48 ; System.Int32
G_M50870_IG03:
C3 ret
; Total bytes of code: 11
Jit-diffs (-f --pmi):
PMI CodeSize Diffs for System.Private.CoreLib.dll, framework assemblies for default jit
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 64750613
Total bytes of diff: 64621503
Total bytes of delta: -129110 (-0.20 % of base)
Total relative delta: -715.51
diff is an improvement.
relative diff is an improvement.
Top file improvements (bytes):
-14241 : System.Text.Json.dasm (-1.22% of base)
-12215 : System.Private.Xml.dasm (-0.30% of base)
-11900 : System.Linq.Queryable.dasm (-3.49% of base)
-9901 : System.Private.CoreLib.dasm (-0.17% of base)
-7878 : System.Linq.Expressions.dasm (-0.90% of base)
-6757 : System.Data.Common.dasm (-0.39% of base)
-6516 : System.Private.DataContractSerialization.dasm (-0.71% of base)
-4883 : System.ComponentModel.TypeConverter.dasm (-1.59% of base)
-4275 : Newtonsoft.Json.dasm (-0.44% of base)
-3175 : System.ComponentModel.Composition.dasm (-0.86% of base)
-2984 : Microsoft.CodeAnalysis.VisualBasic.dasm (-0.04% of base)
-2625 : Microsoft.CSharp.dasm (-0.61% of base)
-2537 : System.DirectoryServices.dasm (-0.54% of base)
-2418 : FSharp.Core.dasm (-0.06% of base)
-2219 : System.DirectoryServices.AccountManagement.dasm (-0.52% of base)
-1961 : Microsoft.CodeAnalysis.CSharp.dasm (-0.04% of base)
-1539 : System.Data.OleDb.dasm (-0.45% of base)
-1387 : System.Drawing.Common.dasm (-0.24% of base)
-1309 : xunit.execution.dotnet.dasm (-0.47% of base)
-1196 : Microsoft.VisualBasic.Core.dasm (-0.22% of base)
173 total files with Code Size differences (173 improved, 0 regressed), 101 unchanged.
Top method regressions (bytes):
122 (13.22% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[System.Numerics.Vector`1[float]](System.Object):System.Numerics.Vector`1[float]
115 (13.92% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[int](System.Object):int
115 (13.69% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[long](System.Object):long
115 (13.45% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[short](System.Object):short
115 (13.67% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[ubyte](System.Object):ubyte
112 (11.62% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[double](System.Object):double
99 (11.22% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[System.Nullable`1[int]](System.Object):System.Nullable`1[int]
89 ( 5.45% of base) : System.Composition.TypedParts.dasm - System.Composition.TypedParts.ActivationFeatures.PropertyInjectionFeature:RewriteActivator(System.Reflection.TypeInfo,System.Composition.Hosting.Core.CompositeActivator,System.Collections.Generic.IDictionary`2[System.String,System.Object],System.Collections.Generic.IEnumerable`1[System.Composition.Hosting.Core.CompositionDependency]):System.Composition.Hosting.Core.CompositeActivator:this
69 ( 8.18% of base) : System.Private.CoreLib.dasm - AdjustmentRule:.ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):this
68 ( 2.52% of base) : System.Linq.Expressions.dasm - System.Linq.Expressions.Interpreter.LightCompiler:CompileLiftedLogicalBinaryExpression(System.Linq.Expressions.BinaryExpression,bool):this
62 ( 9.67% of base) : System.Data.Odbc.dasm - System.Data.Common.ADP:UnsafeCreateTimer(System.Threading.TimerCallback,System.Object,int,int):System.Threading.Timer
59 ( 1.45% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationWriterCodeGen:WriteValue(System.Object):this
58 ( 6.39% of base) : FSharp.Core.dasm - Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter:transBinOp(Microsoft.FSharp.Core.FSharpFunc`2[System.Type,bool],Microsoft.FSharp.Quotations.FSharpExpr,ConvEnv,bool,Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Quotations.FSharpExpr,bool,Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`3[System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Reflection.MethodInfo],System.Linq.Expressions.BinaryExpression],System.RuntimeMethodHandle):System.Linq.Expressions.Expression
56 ( 2.79% of base) : FSharp.Core.dasm - Microsoft.FSharp.Linq.RuntimeHelpers.Adapters:ConvImmutableTypeToMutableType(ConversionDescription,System.Type):System.Type
55 ( 3.91% of base) : System.Private.CoreLib.dasm - System.Enum:TryParse[double](System.ReadOnlySpan`1[ushort],bool,bool,byref):bool
55 ( 3.88% of base) : System.Private.CoreLib.dasm - System.Enum:TryParse[System.Numerics.Vector`1[float]](System.ReadOnlySpan`1[ushort],bool,bool,byref):bool
54 ( 5.99% of base) : FSharp.Core.dasm - Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter:transShiftOp(Microsoft.FSharp.Quotations.FSharpExpr,ConvEnv,bool,Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Quotations.FSharpExpr,bool,Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`3[System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Reflection.MethodInfo],System.Linq.Expressions.BinaryExpression],System.RuntimeMethodHandle):System.Linq.Expressions.Expression
54 ( 4.81% of base) : System.Private.CoreLib.dasm - System.Decimal:.ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):this
54 ( 4.26% of base) : System.Private.CoreLib.dasm - System.Enum:TryParse[long](System.ReadOnlySpan`1[ushort],bool,bool,byref):bool
54 ( 4.30% of base) : System.Private.CoreLib.dasm - System.Enum:TryParse[ubyte](System.ReadOnlySpan`1[ushort],bool,bool,byref):bool
Top method improvements (bytes):
-2328 (-26.68% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax.SyntaxFactory:GetNodeTypes():System.Collections.Generic.IEnumerable`1[System.Object]
-1496 (-26.69% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory:GetNodeTypes():System.Collections.Generic.IEnumerable`1[System.Type]
-933 (-12.13% of base) : System.Data.Common.dasm - System.Data.DataTable:DeserializeTableSchema(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext,bool):this
-714 (-12.83% of base) : System.Data.Common.dasm - System.Data.DataTable:SerializeTableSchema(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext,bool):this
-480 (-5.29% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationReaderILGen:WriteLiteralStructMethod(System.Xml.Serialization.StructMapping):this
-462 (-7.88% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationReaderILGen:WriteElement(System.String,System.String,System.String,System.Xml.Serialization.ElementAccessor,System.Xml.Serialization.ChoiceIdentifierAccessor,System.String,bool,bool,int,int):this
-395 (-5.99% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationWriterILGen:WriteStructMethod(System.Xml.Serialization.StructMapping):this
-360 (-6.65% of base) : System.ComponentModel.TypeConverter.dasm - <>c:<get_IntrinsicTypeConverters>b__24_0():System.Collections.Generic.Dictionary`2[System.Object,IntrinsicTypeConverterData]:this
-343 (-17.03% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Converters.IEnumerableConverterFactory:CreateConverter(System.Type,System.Text.Json.JsonSerializerOptions):System.Text.Json.Serialization.JsonConverter:this
-326 (-5.34% of base) : System.Private.DataContractSerialization.dasm - DataContractCriticalHelper:TryCreateBuiltInDataContract(System.String,System.String,byref):bool
-305 (-6.14% of base) : System.Data.Common.dasm - System.Data.DataTableReader:GetSchemaTableFromDataTable(System.Data.DataTable):System.Data.DataTable
-287 (-47.52% of base) : System.Linq.Expressions.dasm - System.Linq.Expressions.Compiler.DelegateHelpers:GetFuncType(System.Type[]):System.Type
-276 (-46.78% of base) : System.Linq.Expressions.dasm - System.Linq.Expressions.Compiler.DelegateHelpers:GetActionType(System.Type[]):System.Type
-264 (-11.64% of base) : System.Private.DataContractSerialization.dasm - DataContractCriticalHelper:GetBuiltInDataContract(System.String):System.Runtime.Serialization.DataContracts.DataContract
-262 (-5.19% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationWriterILGen:WriteMember(System.Xml.Serialization.SourceInfo,System.Xml.Serialization.AttributeAccessor,System.Xml.Serialization.TypeDesc,System.String):this
-240 (-6.39% of base) : System.Private.Xml.dasm - System.Xml.Serialization.SchemaGraph:Depends(System.Xml.Schema.XmlSchemaObject,System.Collections.ArrayList):this
-233 (-6.52% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.ComInterop.ComInvokeBinder:GenerateTryBlock():System.Linq.Expressions.Expression:this
-232 (-6.14% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationWriterILGen:WriteEnumMethod(System.Xml.Serialization.EnumMapping):this
-228 (-5.30% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationWriterILGen:WriteEnumAndArrayTypes():this
-227 (-5.05% of base) : System.Private.Xml.dasm - System.Xml.Serialization.ReflectionAwareCodeGen:WriteTypeInfo(System.Xml.Serialization.TypeScope,System.Xml.Serialization.TypeDesc,System.Type):System.String:this
Top method regressions (percentages):
35 (14.11% of base) : FSharp.Core.dasm - Microsoft.FSharp.Text.StructuredPrintfImpl.Display:isSetOrMapType(System.Type):bool
115 (13.92% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[int](System.Object):int
115 (13.69% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[long](System.Object):long
115 (13.67% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[ubyte](System.Object):ubyte
115 (13.45% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[short](System.Object):short
122 (13.22% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[System.Numerics.Vector`1[float]](System.Object):System.Numerics.Vector`1[float]
11 (11.83% of base) : System.Composition.Hosting.dasm - System.Composition.Hosting.Util.MethodInfoExtensions:CreateStaticDelegate[System.Numerics.Vector`1[float]](System.Reflection.MethodInfo):System.Numerics.Vector`1[float]
112 (11.62% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[double](System.Object):double
99 (11.22% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[System.Nullable`1[int]](System.Object):System.Nullable`1[int]
62 ( 9.67% of base) : System.Data.Odbc.dasm - System.Data.Common.ADP:UnsafeCreateTimer(System.Threading.TimerCallback,System.Object,int,int):System.Threading.Timer
44 ( 9.17% of base) : Microsoft.Extensions.DependencyInjection.Abstractions.dasm - Microsoft.Extensions.DependencyInjection.ActivatorUtilities:CreateFactory(System.Type,System.Type[]):Microsoft.Extensions.DependencyInjection.ObjectFactory
69 ( 8.18% of base) : System.Private.CoreLib.dasm - AdjustmentRule:.ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):this
51 ( 7.92% of base) : FSharp.Core.dasm - Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter:transBoolOpNoWitness(Microsoft.FSharp.Core.FSharpFunc`2[System.Type,bool],ConvEnv,bool,Microsoft.FSharp.Quotations.FSharpExpr,Microsoft.FSharp.Quotations.FSharpExpr,bool,Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`4[System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,bool,System.Reflection.MethodInfo],System.Linq.Expressions.BinaryExpression],System.Reflection.MethodInfo):System.Linq.Expressions.Expression
40 ( 7.60% of base) : System.Composition.TypedParts.dasm - System.Composition.TypedParts.Discovery.DiscoveredPropertyExport:GetExportDescriptor(System.Composition.Hosting.Core.CompositeActivator):System.Composition.Hosting.Core.ExportDescriptor:this
42 ( 7.24% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateMethodCall[System.__Canon](System.Reflection.MethodBase):Newtonsoft.Json.Utilities.MethodCall`2[System.__Canon,System.__Canon]:this
48 ( 6.69% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[double](System.Reflection.FieldInfo):System.Action`2[double,System.Object]:this
48 ( 6.69% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[int](System.Reflection.FieldInfo):System.Action`2[int,System.Object]:this
48 ( 6.69% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[long](System.Reflection.FieldInfo):System.Action`2[long,System.Object]:this
48 ( 6.69% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[short](System.Reflection.FieldInfo):System.Action`2[short,System.Object]:this
48 ( 6.69% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[System.Nullable`1[int]](System.Reflection.FieldInfo):System.Action`2[System.Nullable`1[int],System.Object]:this
Top method improvements (percentages):
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[double]()
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[int]()
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[long]()
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[short]()
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[ubyte]()
-40 (-71.43% of base) : System.Linq.Expressions.dasm - System.Linq.Expressions.Expression:IfThenElse(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):System.Linq.Expressions.ConditionalExpression
-23 (-62.16% of base) : System.Private.CoreLib.dasm - System.Runtime.CompilerServices.TypeHandle:TypeHandleOf[double]():System.Runtime.CompilerServices.TypeHandle
-23 (-62.16% of base) : System.Private.CoreLib.dasm - System.Runtime.CompilerServices.TypeHandle:TypeHandleOf[int]():System.Runtime.CompilerServices.TypeHandle
-23 (-62.16% of base) : System.Private.CoreLib.dasm - System.Runtime.CompilerServices.TypeHandle:TypeHandleOf[long]():System.Runtime.CompilerServices.TypeHandle
-23 (-62.16% of base) : System.Private.CoreLib.dasm - System.Runtime.CompilerServices.TypeHandle:TypeHandleOf[short]():System.Runtime.CompilerServices.TypeHandle
-23 (-62.16% of base) : System.Private.CoreLib.dasm - System.Runtime.CompilerServices.TypeHandle:TypeHandleOf[System.Nullable`1[int]]():System.Runtime.CompilerServices.TypeHandle
-23 (-62.16% of base) : System.Private.CoreLib.dasm - System.Runtime.CompilerServices.TypeHandle:TypeHandleOf[System.Numerics.Vector`1[float]]():System.Runtime.CompilerServices.TypeHandle
-23 (-62.16% of base) : System.Private.CoreLib.dasm - System.Runtime.CompilerServices.TypeHandle:TypeHandleOf[ubyte]():System.Runtime.CompilerServices.TypeHandle
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[double](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[int](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[long](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[short](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[System.Nullable`1[int]](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[System.Numerics.Vector`1[float]](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[ubyte](long)
7846 total methods with Code Size differences (7511 improved, 335 regressed), 383629 unchanged.
Size regressions look to be CSE-related, e.g. https://www.diffchecker.com/eOr1LIyf
E.g. previously call CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE could share its const argument with other places where we only need type handle (like in this diff)
Notes:
In JIT I do the optimization in morph because a lot of other optimizations here and there (mostly in importer) rely on typeof() being a helper call so it's simpler for now, will try to perform a sort of clean up later - current change is minimalistic and doesn't produce regressions.
Closes https://github.com/dotnet/runtime/issues/49429
Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch See info in area-owners.md if you want to be subscribed.
Issue Details
Follow up to https://github.com/dotnet/runtime/pull/49576 This PR allocates Type objects on the recently-added Frozen Segments so we can bake direct objects' addresses in JIT and avoid helper calls, e.g. for:
Type Test() => typeof(int);
Old codegen:
; Method Program:Test():System.Type:this
G_M50870_IG01:
4883EC28 sub rsp, 40
G_M50870_IG02:
48B968BB53F5FB7F0000 mov rcx, 0x7FFBF553BB68 ; System.Int32
E81D94505F call CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE
90 nop
G_M50870_IG03:
4883C428 add rsp, 40
C3 ret
; Total bytes of code: 25
New codegen:
; Method Program:Test():System.Type:this
G_M50870_IG01:
G_M50870_IG02:
48B8482A63DE29020000 mov rax, 0x229DE632A48 ; Type handle
G_M50870_IG03:
C3 ret
; Total bytes of code: 11
Jit-diffs (-f --pmi):
Total bytes of base: 64641078
Total bytes of diff: 64511525
Total bytes of delta: -129553 (-0.20 % of base)
Total relative delta: -714.65
diff is an improvement.
relative diff is an improvement.
Top file improvements (bytes):
-14248 : System.Text.Json.dasm (-1.22% of base)
-12304 : System.Private.Xml.dasm (-0.30% of base)
-11900 : System.Linq.Queryable.dasm (-3.49% of base)
-9846 : System.Private.CoreLib.dasm (-0.17% of base)
-7846 : System.Linq.Expressions.dasm (-0.90% of base)
-6967 : System.Data.Common.dasm (-0.41% of base)
-6519 : System.Private.DataContractSerialization.dasm (-0.71% of base)
-4769 : System.ComponentModel.TypeConverter.dasm (-1.55% of base)
-4491 : Newtonsoft.Json.dasm (-0.47% of base)
-3168 : System.ComponentModel.Composition.dasm (-0.85% of base)
-2984 : Microsoft.CodeAnalysis.VisualBasic.dasm (-0.04% of base)
-2951 : FSharp.Core.dasm (-0.07% of base)
-2662 : Microsoft.CSharp.dasm (-0.62% of base)
-2537 : System.DirectoryServices.dasm (-0.54% of base)
-2219 : System.DirectoryServices.AccountManagement.dasm (-0.52% of base)
173 total files with Code Size differences (173 improved, 0 regressed), 101 unchanged.
Top method regressions (bytes):
122 (13.22% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[System.Numerics.Vector`1[float]](System.Object):System.Numerics.Vector`1[float]
115 (13.92% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[int](System.Object):int
115 (13.69% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[long](System.Object):long
115 (13.45% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[short](System.Object):short
115 (13.67% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[ubyte](System.Object):ubyte
112 (11.62% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[double](System.Object):double
99 (11.22% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[System.Nullable`1[int]](System.Object):System.Nullable`1[int]
89 ( 5.45% of base) : System.Composition.TypedParts.dasm - System.Composition.TypedParts.ActivationFeatures.PropertyInjectionFeature:RewriteActivator(System.Reflection.TypeInfo,System.Composition.Hosting.Core.CompositeActivator,System.Collections.Generic.IDictionary`2[System.String,System.Object],System.Collections.Generic.IEnumerable`1[System.Composition.Hosting.Core.CompositionDependency]):System.Composition.Hosting.Core.CompositeActivator:this
69 ( 8.18% of base) : System.Private.CoreLib.dasm - AdjustmentRule:.ctor(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext):this
68 ( 2.52% of base) : System.Linq.Expressions.dasm - System.Linq.Expressions.Interpreter.LightCompiler:CompileLiftedLogicalBinaryExpression(System.Linq.Expressions.BinaryExpression,bool):this
62 ( 8.65% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[double](System.Reflection.FieldInfo):System.Action`2[double,System.Object]:this
62 ( 8.65% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[int](System.Reflection.FieldInfo):System.Action`2[int,System.Object]:this
62 ( 8.65% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[long](System.Reflection.FieldInfo):System.Action`2[long,System.Object]:this
62 ( 8.65% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[short](System.Reflection.FieldInfo):System.Action`2[short,System.Object]:this
62 ( 8.65% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[System.Nullable`1[int]](System.Reflection.FieldInfo):System.Action`2[System.Nullable`1[int],System.Object]:this
Top method improvements (bytes):
-2328 (-26.68% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax.SyntaxFactory:GetNodeTypes():System.Collections.Generic.IEnumerable`1[System.Object]
-1496 (-26.69% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax.SyntaxFactory:GetNodeTypes():System.Collections.Generic.IEnumerable`1[System.Type]
-933 (-12.13% of base) : System.Data.Common.dasm - System.Data.DataTable:DeserializeTableSchema(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext,bool):this
-714 (-12.83% of base) : System.Data.Common.dasm - System.Data.DataTable:SerializeTableSchema(System.Runtime.Serialization.SerializationInfo,System.Runtime.Serialization.StreamingContext,bool):this
-575 (-2.59% of base) : FSharp.Core.dasm - Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter:ConvExprToLinqInContext(ConvEnv,Microsoft.FSharp.Quotations.FSharpExpr):System.Linq.Expressions.Expression
-480 (-5.29% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationReaderILGen:WriteLiteralStructMethod(System.Xml.Serialization.StructMapping):this
-462 (-7.88% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationReaderILGen:WriteElement(System.String,System.String,System.String,System.Xml.Serialization.ElementAccessor,System.Xml.Serialization.ChoiceIdentifierAccessor,System.String,bool,bool,int,int):this
-395 (-5.99% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationWriterILGen:WriteStructMethod(System.Xml.Serialization.StructMapping):this
-343 (-17.03% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Converters.IEnumerableConverterFactory:CreateConverter(System.Type,System.Text.Json.JsonSerializerOptions):System.Text.Json.Serialization.JsonConverter:this
-326 (-5.34% of base) : System.Private.DataContractSerialization.dasm - DataContractCriticalHelper:TryCreateBuiltInDataContract(System.String,System.String,byref):bool
-305 (-6.14% of base) : System.Data.Common.dasm - System.Data.DataTableReader:GetSchemaTableFromDataTable(System.Data.DataTable):System.Data.DataTable
-287 (-47.52% of base) : System.Linq.Expressions.dasm - System.Linq.Expressions.Compiler.DelegateHelpers:GetFuncType(<unnamed>):System.Type
-276 (-46.78% of base) : System.Linq.Expressions.dasm - System.Linq.Expressions.Compiler.DelegateHelpers:GetActionType(<unnamed>):System.Type
-270 (-5.35% of base) : System.Private.Xml.dasm - System.Xml.Serialization.XmlSerializationWriterILGen:WriteMember(System.Xml.Serialization.SourceInfo,System.Xml.Serialization.AttributeAccessor,System.Xml.Serialization.TypeDesc,System.String):this
-264 (-11.64% of base) : System.Private.DataContractSerialization.dasm - DataContractCriticalHelper:GetBuiltInDataContract(System.String):System.Runtime.Serialization.DataContracts.DataContract
Top method regressions (percentages):
35 (14.11% of base) : FSharp.Core.dasm - Microsoft.FSharp.Text.StructuredPrintfImpl.Display:isSetOrMapType(System.Type):bool
115 (13.92% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[int](System.Object):int
115 (13.69% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[long](System.Object):long
115 (13.67% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[ubyte](System.Object):ubyte
115 (13.45% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[short](System.Object):short
122 (13.22% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[System.Numerics.Vector`1[float]](System.Object):System.Numerics.Vector`1[float]
58 (12.08% of base) : Microsoft.Extensions.DependencyInjection.Abstractions.dasm - Microsoft.Extensions.DependencyInjection.ActivatorUtilities:CreateFactory(System.Type,<unnamed>):Microsoft.Extensions.DependencyInjection.ObjectFactory
11 (11.83% of base) : System.Composition.Hosting.dasm - System.Composition.Hosting.Util.MethodInfoExtensions:CreateStaticDelegate[System.Numerics.Vector`1[float]](System.Reflection.MethodInfo):System.Numerics.Vector`1[float]
112 (11.62% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[double](System.Object):double
99 (11.22% of base) : Microsoft.VisualBasic.Core.dasm - Microsoft.VisualBasic.CompilerServices.Conversions:ToGenericParameter[System.Nullable`1[int]](System.Object):System.Nullable`1[int]
54 (10.27% of base) : System.Composition.TypedParts.dasm - System.Composition.TypedParts.Discovery.DiscoveredPropertyExport:GetExportDescriptor(System.Composition.Hosting.Core.CompositeActivator):System.Composition.Hosting.Core.ExportDescriptor:this
48 ( 9.62% of base) : FSharp.Core.dasm - Microsoft.FSharp.Linq.RuntimeHelpers.LeafExpressionConverter:transBinOp(Microsoft.FSharp.Quotations.FSharpExpr,ConvEnv,bool,Microsoft.FSharp.Collections.FSharpList`1[Microsoft.FSharp.Quotations.FSharpExpr],bool,Microsoft.FSharp.Core.FSharpFunc`2[System.Tuple`2[System.Linq.Expressions.Expression,System.Linq.Expressions.Expression],System.Linq.Expressions.BinaryExpression]):System.Linq.Expressions.Expression
62 ( 8.65% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[double](System.Reflection.FieldInfo):System.Action`2[double,System.Object]:this
62 ( 8.65% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[int](System.Reflection.FieldInfo):System.Action`2[int,System.Object]:this
62 ( 8.65% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Utilities.ExpressionReflectionDelegateFactory:CreateSet[long](System.Reflection.FieldInfo):System.Action`2[long,System.Object]:this
Top method improvements (percentages):
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[double]()
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[int]()
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[long]()
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[short]()
-8 (-88.89% of base) : System.Diagnostics.DiagnosticSource.dasm - System.Diagnostics.Metrics.Instrument:ValidateTypeParameter[ubyte]()
-40 (-71.43% of base) : System.Linq.Expressions.dasm - System.Linq.Expressions.Expression:IfThenElse(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression,System.Linq.Expressions.Expression):System.Linq.Expressions.ConditionalExpression
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[double](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[int](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[long](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[short](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[System.Nullable`1[int]](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[System.Numerics.Vector`1[float]](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.Runtime.InteropServices.Marshal:DestroyStructure[ubyte](long)
-24 (-61.54% of base) : System.Private.CoreLib.dasm - System.RuntimeType:IsCOMObjectImpl():bool:this
-34 (-60.71% of base) : System.Private.DataContractSerialization.dasm - System.Runtime.Serialization.DataContracts.CharDataContract:.ctor(System.Xml.XmlDictionaryString,System.Xml.XmlDictionaryString):this
7830 total methods with Code Size differences (7524 improved, 306 regressed), 383145 unchanged.
Size regressions look to be CSE-related, e.g. https://www.diffchecker.com/lDHsFUcP
Notes:
In JIT I do the optimization in morph because a lot of stuff here and there rely on typeof() being a helper call so it's simpler for now, will try to perform a sort of clean up later - current change is minimalistic and doesn't produce regressions.
| Author: | EgorBo |
|---|---|
| Assignees: | EgorBo |
| Labels: |
|
| Milestone: | - |
Seems to be passing CI tests (SPMI failures are due to JIT-EE change), @jkotas when you have time could you review the vm side?
CI failures are weird, e.g. https://helixre107v0xdeko0k025g8.blob.core.windows.net/dotnet-runtime-refs-pull-75573-merge-3616944558404cd193/System.Linq.Queryable.Tests/1/console.13d74af2.log?helixlogtype=result had no luck trying to reproduce any, going to kick off a single gc stress job - maybe it will help to find a repro.
/azp run Fuzzlyn
Azure Pipelines successfully started running 1 pipeline(s).
/azp run runtime-coreclr gcstress0x3-gcstress0xc
Azure Pipelines successfully started running 1 pipeline(s).
Ok, gcstress=0xc didn't find anything, and it doesn't look like it's a codegen issue (I disabled the jit optimization)
Reproduces for me locally (not every run) for src\libraries\System.Formats.Asn1\tests built with Debug.
Judging by
System.ArrayTypeMismatchException: Attempted to access an element as a type incompatible with the array
it feels like it's related to type co(ntra)variance. Investigating..
Or it's a race condition since it doesn't repro when I ask xunit to run tests without parallelism 🤔
@jkotas Anything else needed from VM side? It seems to be passing all tests (spmi jobs are failing due to JIT-EE guid change), I'll kick off (gently this time) a few outerloop pipelines to make sure. There are a few things I'd love to address separately later:
- Do the same for TypeDesc (diffs are pretty small from it though)
- Wire it up in NativeAOT (or can leave it for anyone interested)
PublishObjectAndNotifyproblem from https://github.com/dotnet/runtime/pull/49576#issuecomment-1250248951
https://github.com/icsharpcode/AvaloniaILSpy - when I run this average-size client app it allocates 12153 objects on the frozen segments (total size is 604kb). Going to check other apps/web services
Do the same for TypeDesc (diffs are pretty small from it though)
I think it would be a good idea to address this as part of this PR. (I expect that you will want to move some the code that you are adding here around.)
The rest can wait for separate PR.
Do the same for TypeDesc (diffs are pretty small from it though)
I think it would be a good idea to address this as part of this PR. (I expect that you will want to move some the code that you are adding here around.)
The rest can wait for separate PR.
Ok, pushed the change for ParamTypeDesc/TypeVarTypeDesc. The only thing I am not sure is the fact they all share the same lock. From the other hand, FrozenObjectHeapManager has its own lock they all will hit anyway if I create 3 different lock objects
Ah, oops forgot to update the logic to extract OBJECTREF from the field for both
/azp run runtime-coreclr outerloop
Azure Pipelines successfully started running 1 pipeline(s).
/azp run runtime-coreclr jitstressregs
Azure Pipelines successfully started running 1 pipeline(s).
Wire it up in NativeAOT (or can leave it for anyone interested)
We'll need to do some work on the reflection stack first - there's no unique RuntimeType type we could preallocate (NativeAOT has like half a dozen RuntimeType descendants), and it has GC-pointer fields (no-no in frozen segments). Having a single RuntimeType is our plan. It's just not there yet.
@jakobbotsch @AndyAyersMS PTAL JIT side, like @jakobbotsch suggested I introduced a separate flag GTF_ICON_OBJ_HDL for both frozen strings and frozen RuntimeType objects. GTF_ICON_STR_HDL is kept for non-frozen string literals (e.g. too large or in unloadable context). Also, removed dangerous eeGetCPString and replaced it with JIT-EE calls (tested with SPMI)
Also note that I do the optimization in Morph (fgMorphCall) and not earlier because a lot of code in JIT expects call helper(handle) for optimizations during import/inlining - that's how I avoided regressions and minimized changes in JIT, will do a clean up at some point.
PS: this PR passed outerloop, jitstress and gcstress pipelines
Current codegen for JIT_GetRuntimeType:

one less branch but + and rdx, 0FFFFFFFFFFFFFFFEh so presumably it's faster. The fast-return block is still too far but looks like MSVC just wants to have a single epilogue, I do hope it will change with native PGO 🙄
Btw, for generics we can probably inline a fast path in jit, e.g. for:
[MethodImpl(MethodImplOptions.NoInlining)]
static Type Foo<T>() => typeof(T);
for __Canon version we currently emit:
488B4938 mov rcx, qword ptr [rcx+38H]
488B09 mov rcx, qword ptr [rcx]
E84BD8505F call CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE
while we can inline the m_Exposed & 1 check if it's worth the effort
The fast-return block is still too far but looks like MSVC just wants to have a single epilogue, I do hope it will change with native PGO
It won't. It is impossible for the C++ compiler to prove that handle - 1 is non-zero so it has to produce the redundant check.
I think there is a reason why the signature of LoaderAllocator::GetHandleValueFast is bool (handle, objectref*) and not objectref (handle). If you change the signature of TypeHandle::GetManagedClassObjectFromHandleFast to be bool (handle, objectref*), you should be able to get rid of the manual inlining and the redundant check.
@jkotas thanks!! now it's clear why the initial shape was like that. I had to also play with GetManagedClassObjectFromHandleFast because it didn't want to inline.
The new codegen is perfect:

VM changes LGTM. Thanks!
Thanks for patience and great help! Learned so many cool tricks and VM internals! 🙂
Btw, a quick prototype for a managed JIT_GetRuntimeType: https://github.com/EgorBo/runtime-1/commit/ef7a46583145b9917865dc1eb1cc85ccc041588e we can enable inlining for CastHelpers and get faster typeof for generics (if it shows any benefit). Although, some other helpers might benefit from inlining (especially on really hot paths with PGO) too.
@jakobbotsch does the jit part look good in this PR?
/azp run runtime-coreclr outerloop, gcstress0x3-gcstress0xc
Azure Pipelines successfully started running 1 pipeline(s).
Btw, a quick prototype for a managed JIT_GetRuntimeType: https://github.com/EgorBo/runtime-1/commit/ef7a46583145b9917865dc1eb1cc85ccc041588e
We will get to this eventually. I think we need to do more cleanup of the runtime structures to make this sort of optimizations interesting and easy to maintain. For example, the writeable data indirection is useless. It should be inlined into Methodtable.
Looks like this can be merged now, two Pri0 failures are from https://github.com/dotnet/runtime/pull/75952, SPMI ones are due to JIT-EE guid change (we still don't know how to avoid triggering those when both JIT and JIT-EE guid are changed in YML)
I plan to look into the profiler/diag issues raised in the other PR for FOH, and test this and the string literals on OSS (and, hopefully, some 1st parties) projects to get a better understanding how many objects make it to FOH.
Then we might look into making static objects (at least those without GC fields inside) also FOH-based
Then we might look into making static objects (at least those without GC fields inside) also FOH-based
How do you plan to do that? I do not think it is feasible without AOT step (or without doing expensive work when JITing static constructors - I do not expect we would want to do that).
Can we do it for static field boxes (the ones created for non-primitives)? Today, JIT needs to create
ADD byref
IND ref
CNS <object slot addr>
CNS 8
for all such accesses, I believe. We could potentially create direct pointer to the boxed contents.