Skip to content

Commit

Permalink
Fix Native AOT Regression
Browse files Browse the repository at this point in the history
Fix regression and add test cases to prevent future issues
  • Loading branch information
jamescourtney authored Feb 24, 2024
1 parent c6bf3a6 commit 39223d3
Show file tree
Hide file tree
Showing 14 changed files with 358 additions and 92 deletions.
63 changes: 63 additions & 0 deletions .github/workflows/NativeAotTest.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
name: NativeAot Validation

on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
workflow_dispatch:

jobs:
build:
strategy:
matrix:
include:
- os: windows-latest
rid: win-x64
- os: ubuntu-latest
rid: linux-x64
- os: macos-latest
rid: osx-x64

runs-on: ${{ matrix.os }}
env:
AppVeyorBuild: true
steps:
- uses: actions/checkout@v2

- name: Setup .NET 8
uses: actions/setup-dotnet@v1
with:
dotnet-version: 8.0.x

- name: Restore dependencies
working-directory: src
run: dotnet restore

- name: Build FlatSharp.Compiler
working-directory: src/FlatSharp.Compiler
run: dotnet build -c Release

- name: Run FlatSharp.Compiler
# You may pin to the exact commit or the version.
# uses: Amadevus/pwsh-script@97a8b211a5922816aa8a69ced41fa32f23477186
uses: Amadevus/pwsh-script@v2.0.3
with:
# PowerShell script to execute in Actions-hydrated context
script: |
$fbs = (gci -r src/Tests/CompileTests/NativeAot/*.fbs) -join ";"
dotnet src/FlatSharp.Compiler/bin/Release/net8.0/FlatSharp.Compiler.dll --nullable-warnings false --normalize-field-names true --input "$fbs" -o src/Tests/CompileTests/NativeAot
- name: Build
working-directory: src/Tests/CompileTests/NativeAot
run: dotnet publish -c Release -r ${{ matrix.rid }} -f net8.0

- name: Run
working-directory: src/Tests/CompileTests/NativeAot/bin/Release/net8.0/${{ matrix.rid }}/publish
run: ./NativeAot

- name: Upload Files
uses: actions/upload-artifact@v3
with:
name: assembly
path: src/Tests/CompileTests/NativeAot/bin/**/*.*
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@
/src/Benchmarks/ExperimentalBenchmark/FlatSharp.generated.cs
/src/Tests/FlatSharpEndToEndTests_Generated/FlatSharpEndToEndTestsGenerated.xml
**/BenchmarkDotNet.Artifacts/**
/src/Tests/CompileTests/NativeAot/FlatSharp.generated.cs
1 change: 1 addition & 0 deletions src/FlatSharp.Runtime/FlatSharp.Runtime.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

<PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
<Nullable>enable</Nullable>
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>

<ItemGroup>
Expand Down
8 changes: 4 additions & 4 deletions src/FlatSharp.Runtime/GeneratedSerializerWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -119,19 +119,19 @@ public T Parse<TInputBuffer>(TInputBuffer buffer, FlatBufferDeserializationOptio
switch (option ?? this.option)
{
case FlatBufferDeserializationOption.Lazy:
item = buffer.InvokeLazyParse(inner, in parseArgs);
item = inner.ParseLazy(buffer, in parseArgs);
break;

case FlatBufferDeserializationOption.Greedy:
item = buffer.InvokeGreedyParse(inner, in parseArgs);
item = inner.ParseGreedy(buffer, in parseArgs);
break;

case FlatBufferDeserializationOption.GreedyMutable:
item = buffer.InvokeGreedyMutableParse(inner, in parseArgs);
item = inner.ParseGreedyMutable(buffer, in parseArgs);
break;

case FlatBufferDeserializationOption.Progressive:
item = buffer.InvokeProgressiveParse(inner, in parseArgs);
item = inner.ParseProgressive(buffer, in parseArgs);
break;

default:
Expand Down
16 changes: 0 additions & 16 deletions src/FlatSharp.Runtime/IO/ArrayInputBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -133,20 +133,4 @@ public ReadOnlyMemory<byte> GetReadOnlyMemory()
{
return this.memory;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeLazyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseLazy(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeProgressiveParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseProgressive(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeGreedyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseGreedy(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeGreedyMutableParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseGreedyMutable(this, in arguments);
}
16 changes: 0 additions & 16 deletions src/FlatSharp.Runtime/IO/ArraySegmentInputBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,22 +134,6 @@ public ReadOnlyMemory<byte> GetReadOnlyMemory()
return this.pointer.segment;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeLazyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseLazy(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeProgressiveParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseProgressive(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeGreedyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseGreedy(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeGreedyMutableParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseGreedyMutable(this, in arguments);

// Array Segment is a relatively heavy struct. It contains an array pointer, an int offset, and and int length.
// Copying this by value for each method call is actually slower than having a little private pointer to a single item.
private class ArraySegmentPointer
Expand Down
24 changes: 0 additions & 24 deletions src/FlatSharp.Runtime/IO/IInputBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,28 +112,4 @@ public interface IInputBuffer
/// Gets a memory covering the entire input buffer.
/// </summary>
Memory<byte> GetMemory();

/// <summary>
/// Invokes the parse method on the <see cref="IGeneratedSerializer{T}"/> parameter. Allows passing
/// generic parameters.
/// </summary>
TItem InvokeLazyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments);

/// <summary>
/// Invokes the parse method on the <see cref="IGeneratedSerializer{T}"/> parameter. Allows passing
/// generic parameters.
/// </summary>
TItem InvokeProgressiveParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments);

/// <summary>
/// Invokes the parse method on the <see cref="IGeneratedSerializer{T}"/> parameter. Allows passing
/// generic parameters.
/// </summary>
TItem InvokeGreedyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments);

/// <summary>
/// Invokes the parse method on the <see cref="IGeneratedSerializer{T}"/> parameter. Allows passing
/// generic parameters.
/// </summary>
TItem InvokeGreedyMutableParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments);
}
16 changes: 0 additions & 16 deletions src/FlatSharp.Runtime/IO/MemoryInputBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -138,22 +138,6 @@ public Memory<byte> GetMemory()
return this.pointer.memory;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeLazyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseLazy(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeProgressiveParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseProgressive(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeGreedyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseGreedy(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeGreedyMutableParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseGreedyMutable(this, in arguments);

// Memory<byte> is a relatively heavy struct. It's cheaper to wrap it in a
// a reference that will be collected ephemerally in Gen0 than it is to
// copy it around.
Expand Down
16 changes: 0 additions & 16 deletions src/FlatSharp.Runtime/IO/ReadOnlyMemoryInputBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -132,22 +132,6 @@ public ReadOnlyMemory<byte> GetReadOnlyMemory()
return this.pointer.memory;
}

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeLazyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseLazy(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeProgressiveParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseProgressive(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeGreedyParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseGreedy(this, in arguments);

[MethodImpl(MethodImplOptions.AggressiveInlining)]
public TItem InvokeGreedyMutableParse<TItem>(IGeneratedSerializer<TItem> serializer, in GeneratedSerializerParseArguments arguments)
=> serializer.ParseGreedyMutable(this, in arguments);

public Span<byte> GetSpan()
{
FSThrow.InvalidOperation(ErrorMessage);
Expand Down
10 changes: 10 additions & 0 deletions src/FlatSharp.Runtime/SortedVectorHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ of this software and associated documentation files (the "Software"), to deal
using System.Reflection;
using System.Diagnostics.CodeAnalysis;
using System.Net.WebSockets;
using System.Runtime.InteropServices;

namespace FlatSharp;

Expand Down Expand Up @@ -187,9 +188,18 @@ internal static class KeyLookup<TTable, TKey>
{
static KeyLookup()
{
#if NETCOREAPP || NETSTANDARD2_1_OR_GREATER
// Convention is for static constructors in the table to register key lookups. Force them to run here before fields
// are accessed.
if (RuntimeFeature.IsDynamicCodeSupported) // this should be true for all cases except native AOT. This does not need to run for NativeAOT since static constructors are pre-executed.
{
#pragma warning disable IL2059
RuntimeHelpers.RunClassConstructor(typeof(TTable).TypeHandle);
#pragma warning restore IL2059
}
#else
RuntimeHelpers.RunClassConstructor(typeof(TTable).TypeHandle);
#endif
}

private static string NotInitializedErrorMessage = $"Type '{typeof(TTable).Name}' has not registered a sorted vector key of type '{typeof(TKey).Name}'.";
Expand Down
17 changes: 17 additions & 0 deletions src/Tests/CompileTests/NativeAot/NativeAot.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>annotations</Nullable>
<PublishAot>true</PublishAot>
<StripSymbols>true</StripSymbols>
<InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\..\FlatSharp.Runtime\FlatSharp.Runtime.csproj" />
</ItemGroup>

</Project>
31 changes: 31 additions & 0 deletions src/Tests/CompileTests/NativeAot/NativeAot.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.9.34616.47
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NativeAot", "NativeAot.csproj", "{FE0D4FB2-1E8E-4A2B-81C0-A23384C66598}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FlatSharp.Runtime", "..\..\..\FlatSharp.Runtime\FlatSharp.Runtime.csproj", "{39A4F280-BC8A-498A-8F0A-E617DEA455FA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{FE0D4FB2-1E8E-4A2B-81C0-A23384C66598}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FE0D4FB2-1E8E-4A2B-81C0-A23384C66598}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE0D4FB2-1E8E-4A2B-81C0-A23384C66598}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE0D4FB2-1E8E-4A2B-81C0-A23384C66598}.Release|Any CPU.Build.0 = Release|Any CPU
{39A4F280-BC8A-498A-8F0A-E617DEA455FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39A4F280-BC8A-498A-8F0A-E617DEA455FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39A4F280-BC8A-498A-8F0A-E617DEA455FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39A4F280-BC8A-498A-8F0A-E617DEA455FA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DAA100EE-7E3A-4209-985E-2CA4FCB8F1E4}
EndGlobalSection
EndGlobal
Loading

0 comments on commit 39223d3

Please sign in to comment.