Browse Source

Use a zeroed huge object instead of uninitialized one

pull/8105/head
Nikita Tsukanov 4 years ago
parent
commit
77ff52d218
  1. 21
      src/Avalonia.Base/Rendering/Composition/Server/ServerObject.cs
  2. 31
      src/tools/DevGenerators/CompositionGenerator/Generator.cs

21
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<T>() where T : ServerObject => Unsafe.As<T>(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<ServerObjectSubscriptionStore, uint>(ref field))
.ToInt32();
}

31
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(

Loading…
Cancel
Save