From 77ff52d21840627f99dc2312916c6dcf8cceceb8 Mon Sep 17 00:00:00 2001 From: Nikita Tsukanov Date: Sun, 26 Jun 2022 02:30:56 +0300 Subject: [PATCH] Use a zeroed huge object instead of uninitialized one --- .../Composition/Server/ServerObject.cs | 21 +++++++++++-- .../CompositionGenerator/Generator.cs | 31 +++++++------------ 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs b/src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs index a2af34c7f0..4c358605fc 100644 --- a/src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs +++ b/src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs @@ -61,11 +61,28 @@ namespace Avalonia.Rendering.Composition.Server { } + + [StructLayout(LayoutKind.Sequential)] + protected class OffsetDummy + { +#pragma warning disable CS0649 + public FillerStruct Filler; +#pragma warning restore CS0649 + } + [StructLayout(LayoutKind.Sequential)] + protected unsafe struct FillerStruct + { + public fixed byte FillerData[8192]; + } + + private static readonly object s_OffsetDummy = new OffsetDummy(); + protected static T GetOffsetDummy() where T : ServerObject => Unsafe.As(s_OffsetDummy); + [MethodImpl(MethodImplOptions.AggressiveInlining)] - protected int GetOffset(ref ServerObjectSubscriptionStore field) + protected static int GetOffset(ServerObject obj, ref ServerObjectSubscriptionStore field) { - return Unsafe.ByteOffset(ref _activationCount, + return Unsafe.ByteOffset(ref obj._activationCount, ref Unsafe.As(ref field)) .ToInt32(); } diff --git a/src/tools/DevGenerators/CompositionGenerator/Generator.cs b/src/tools/DevGenerators/CompositionGenerator/Generator.cs index 4df5a91c4b..0bb4e30f75 100644 --- a/src/tools/DevGenerators/CompositionGenerator/Generator.cs +++ b/src/tools/DevGenerators/CompositionGenerator/Generator.cs @@ -153,18 +153,10 @@ namespace Avalonia.SourceGenerator.CompositionGenerator ); var uninitializedObjectName = "dummy"; - var serverStaticCtorBody = cl.Abstract - ? Block() - : Block( - ParseStatement( - $"var dummy = ({serverName})System.Runtime.Serialization.FormatterServices.GetUninitializedObject(typeof({serverName}));"), - ParseStatement($"System.GC.SuppressFinalize(dummy);"), - ParseStatement("InitializeFieldOffsets(dummy);") - ); + var serverStaticCtorBody = Block( + ParseStatement($"var dummy = GetOffsetDummy<{serverName}>();") + ); - var initializeFieldOffsetsBody = cl.Inherits == null - ? Block() - : Block(ParseStatement($"Server{cl.Inherits}.InitializeFieldOffsets(dummy);")); var resetBody = Block(); var startAnimationBody = Block(); @@ -294,11 +286,15 @@ namespace Avalonia.SourceGenerator.CompositionGenerator serverGetFieldOffsetBody = ApplyGetProperty(serverGetFieldOffsetBody, prop, fieldOffsetName); server = server.AddMembers(DeclareField("int", fieldOffsetName, SyntaxKind.StaticKeyword)); - initializeFieldOffsetsBody = initializeFieldOffsetsBody.AddStatements(ExpressionStatement( + serverStaticCtorBody = serverStaticCtorBody.AddStatements(ExpressionStatement( AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, IdentifierName(fieldOffsetName), - InvocationExpression(MemberAccess(IdentifierName(uninitializedObjectName), "GetOffset"), - ArgumentList(SingletonSeparatedList(Argument( - RefExpression(MemberAccess(MemberAccess(IdentifierName(uninitializedObjectName), fieldName), "Subscriptions"))))))))); + InvocationExpression(IdentifierName("GetOffset"), + ArgumentList(SeparatedList(new[] + { + Argument(IdentifierName(uninitializedObjectName)), + Argument(RefExpression(MemberAccess( + MemberAccess(IdentifierName(uninitializedObjectName), fieldName), "Subscriptions"))) + })))))); if (prop.DefaultValue != null) { @@ -312,11 +308,6 @@ namespace Avalonia.SourceGenerator.CompositionGenerator server = server.AddMembers(ConstructorDeclaration(serverName) .WithModifiers(TokenList(Token(SyntaxKind.StaticKeyword))) .WithBody(serverStaticCtorBody)); - - server = server.AddMembers( - ((MethodDeclarationSyntax)ParseMemberDeclaration( - $"protected static void InitializeFieldOffsets({serverName} dummy){{}}")!) - .WithBody(initializeFieldOffsetsBody)); server = server .AddMembers(((MethodDeclarationSyntax)ParseMemberDeclaration(