C#: Remove VariantSpanDisposer and use constants in stackalloc

- Remove `VariantSpanDisposer`, no need to dispose of the Variant Spans
since we are now borrowing the Variants instead of copying them.
- Remove `VariantSpanExtensions.Cleared` that was only used so the
Span was initialized for `VariantSpanDisposer` to know what to dispose.
- Fix stackalloc Spans to use constant VarArgsSpanThreshold
and avoid bound checks.
This commit is contained in:
Raul Santos 2022-11-25 20:27:36 +01:00
parent c7ceb94e37
commit 3ff181096a
No known key found for this signature in database
GPG key ID: B532473AE3A803E4
5 changed files with 10 additions and 50 deletions

View file

@ -2542,15 +2542,13 @@ Error BindingsGenerator::_generate_cs_native_calls(const InternalCall &p_icall,
<< INDENT2 "int total_length = " << real_argc_str << " + vararg_length;\n";
r_output << INDENT2 "Span<godot_variant.movable> varargs_span = vararg_length <= VarArgsSpanThreshold ?\n"
<< INDENT3 "stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :\n"
<< INDENT3 "stackalloc godot_variant.movable[VarArgsSpanThreshold] :\n"
<< INDENT3 "new godot_variant.movable[vararg_length];\n";
r_output << INDENT2 "Span<IntPtr> " C_LOCAL_PTRCALL_ARGS "_span = total_length <= VarArgsSpanThreshold ?\n"
<< INDENT3 "stackalloc IntPtr[VarArgsSpanThreshold] :\n"
<< INDENT3 "new IntPtr[total_length];\n";
r_output << INDENT2 "using var variantSpanDisposer = new VariantSpanDisposer(varargs_span);\n";
r_output << INDENT2 "fixed (godot_variant.movable* varargs = &MemoryMarshal.GetReference(varargs_span))\n"
<< INDENT2 "fixed (IntPtr* " C_LOCAL_PTRCALL_ARGS " = "
"&MemoryMarshal.GetReference(" C_LOCAL_PTRCALL_ARGS "_span))\n"

View file

@ -827,7 +827,7 @@ namespace Godot.Bridge
{
// Weird limitation, hence the need for aux:
// "In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable."
var aux = stackalloc godotsharp_property_info[length];
var aux = stackalloc godotsharp_property_info[stackMaxLength];
interopProperties = aux;
}
else
@ -947,7 +947,7 @@ namespace Godot.Bridge
{
// Weird limitation, hence the need for aux:
// "In the case of pointer types, you can use a stackalloc expression only in a local variable declaration to initialize the variable."
var aux = stackalloc godotsharp_property_def_val_pair[length];
var aux = stackalloc godotsharp_property_def_val_pair[stackMaxLength];
interopDefaultValues = aux;
}
else

View file

@ -77,7 +77,7 @@ namespace Godot
_trampoline = trampoline;
}
private const int VarArgsSpanThreshold = 5;
private const int VarArgsSpanThreshold = 10;
/// <summary>
/// Calls the method represented by this <see cref="Callable"/>.
@ -92,15 +92,13 @@ namespace Godot
int argc = args.Length;
Span<godot_variant.movable> argsStoreSpan = argc <= VarArgsSpanThreshold ?
stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :
stackalloc godot_variant.movable[VarArgsSpanThreshold] :
new godot_variant.movable[argc];
Span<IntPtr> argsSpan = argc <= 10 ?
stackalloc IntPtr[argc] :
Span<IntPtr> argsSpan = argc <= VarArgsSpanThreshold ?
stackalloc IntPtr[VarArgsSpanThreshold] :
new IntPtr[argc];
using var variantSpanDisposer = new VariantSpanDisposer(argsStoreSpan);
fixed (godot_variant* varargs = &MemoryMarshal.GetReference(argsStoreSpan).DangerousSelfRef)
fixed (IntPtr* argsPtr = &MemoryMarshal.GetReference(argsSpan))
{
@ -128,15 +126,13 @@ namespace Godot
int argc = args.Length;
Span<godot_variant.movable> argsStoreSpan = argc <= VarArgsSpanThreshold ?
stackalloc godot_variant.movable[VarArgsSpanThreshold].Cleared() :
stackalloc godot_variant.movable[VarArgsSpanThreshold] :
new godot_variant.movable[argc];
Span<IntPtr> argsSpan = argc <= 10 ?
stackalloc IntPtr[argc] :
Span<IntPtr> argsSpan = argc <= VarArgsSpanThreshold ?
stackalloc IntPtr[VarArgsSpanThreshold] :
new IntPtr[argc];
using var variantSpanDisposer = new VariantSpanDisposer(argsStoreSpan);
fixed (godot_variant* varargs = &MemoryMarshal.GetReference(argsStoreSpan).DangerousSelfRef)
fixed (IntPtr* argsPtr = &MemoryMarshal.GetReference(argsSpan))
{

View file

@ -1,33 +0,0 @@
using System;
namespace Godot.NativeInterop
{
internal readonly ref struct VariantSpanDisposer
{
private readonly Span<godot_variant.movable> _variantSpan;
// IMPORTANT: The span element must be default initialized.
// Make sure call Clear() on the span if it was created with stackalloc.
public VariantSpanDisposer(Span<godot_variant.movable> variantSpan)
{
_variantSpan = variantSpan;
}
public void Dispose()
{
for (int i = 0; i < _variantSpan.Length; i++)
_variantSpan[i].DangerousSelfRef.Dispose();
}
}
internal static class VariantSpanExtensions
{
// Used to make sure we always initialize the span values to the default,
// as we need that in order to safely dispose all elements after.
public static Span<godot_variant.movable> Cleared(this Span<godot_variant.movable> span)
{
span.Clear();
return span;
}
}
}

View file

@ -101,7 +101,6 @@
<Compile Include="Core\NativeInterop\InteropUtils.cs" />
<Compile Include="Core\NativeInterop\NativeFuncs.extended.cs" />
<Compile Include="Core\NativeInterop\NativeVariantPtrArgs.cs" />
<Compile Include="Core\NativeInterop\VariantSpanHelpers.cs" />
<Compile Include="Core\NativeInterop\VariantUtils.cs" />
<Compile Include="Core\NativeInterop\VariantUtils.generic.cs" />
<Compile Include="Core\NodePath.cs" />