Skip to content

Commit

Permalink
Remove Unsafe.SkipInit, just use default.
Browse files Browse the repository at this point in the history
  • Loading branch information
timcassell committed Jun 9, 2023
1 parent 149ea7a commit c4f5f0d
Show file tree
Hide file tree
Showing 3 changed files with 2 additions and 57 deletions.
13 changes: 1 addition & 12 deletions src/BenchmarkDotNet/Code/DeclarationsProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,18 +86,7 @@ public override string ConsumeField
: null;

public override string OverheadImplementation
{
get
{
var type = WorkloadMethodReturnType;
// ByRefLike types and pointers use default, everything else uses Unsafe.SkipInit.
if (type.IsByRefLike() || type.IsPointer)
{
return $"return default({type.GetCorrectCSharpTypeName()});";
}
return $"System.Runtime.CompilerServices.Unsafe.SkipInit(out {type.GetCorrectCSharpTypeName()} value);\nreturn value;";
}
}
=> $"return default({WorkloadMethodReturnType.GetCorrectCSharpTypeName()});";

public override string ReturnsDefinition
=> Consumer.IsConsumable(WorkloadMethodReturnType) || Consumer.HasConsumableField(WorkloadMethodReturnType, out _)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,48 +78,6 @@ protected override void OnEmitCtorBodyOverride(ConstructorBuilder constructorBui
ilBuilder.Emit(OpCodes.Stfld, consumerField);
}

public override void EmitOverheadImplementation(ILGenerator ilBuilder, Type returnType)
{
// ByRefLike types and pointers use default, everything else uses Unsafe.SkipInit.
if (returnType.IsByRefLike() || returnType.IsPointer)
{
/*
// return default;
IL_0000: ldc.i4.0
IL_0001: ret
*/
// optional local if default(T) uses .initobj
var optionalLocalForInitobj = ilBuilder.DeclareOptionalLocalForReturnDefault(returnType);
ilBuilder.EmitReturnDefault(returnType, optionalLocalForInitobj);
return;
}

/*
// System.Runtime.CompilerServices.Unsafe.SkipInit(out BenchmarkDotNet.Samples.CustomWithConsumable value);
// return value;
.locals init (
[0] valuetype BenchmarkDotNet.Samples.CustomWithConsumable
)
IL_0000: ldloca.s 0
IL_0002: call void Unsafe::SkipInit<valuetype BenchmarkDotNet.Samples.CustomWithConsumable>(!!0&)
IL_0007: ldloc.0
IL_0008: ret
*/
var local = ilBuilder.DeclareLocal(returnType);
ilBuilder.EmitLdloca(local);
ilBuilder.Emit(OpCodes.Call, GetGenericSkipInitMethod(returnType));
ilBuilder.EmitLdloc(local);
ilBuilder.Emit(OpCodes.Ret);
}

private static MethodInfo GetGenericSkipInitMethod(Type skipInitType)
{
return typeof(Unsafe).GetMethods(BindingFlags.Static | BindingFlags.Public)
.Single(m => m.Name == nameof(Unsafe.SkipInit) && m.IsGenericMethodDefinition && m.ReturnType == typeof(void) && m.GetParameters().Single().IsOut)
.MakeGenericMethod(skipInitType);
}

protected override void EmitActionBeforeCallOverride(ILGenerator ilBuilder)
{
/*
Expand Down
4 changes: 1 addition & 3 deletions src/BenchmarkDotNet/Toolchains/Roslyn/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Extensions;
using BenchmarkDotNet.Portability;
using BenchmarkDotNet.Running;
Expand Down Expand Up @@ -57,8 +56,7 @@ internal static IEnumerable<Assembly> GetAllReferences(BenchmarkCase benchmarkCa
new[]
{
benchmarkCase.Descriptor.Type.GetTypeInfo().Assembly, // this assembly does not has to have a reference to BenchmarkDotNet (e.g. custom framework for benchmarking that internally uses BenchmarkDotNet
typeof(BenchmarkCase).Assembly, // BenchmarkDotNet
typeof(Unsafe).Assembly // Unsafe
typeof(BenchmarkCase).Assembly // BenchmarkDotNet
})
.Distinct();
}
Expand Down

0 comments on commit c4f5f0d

Please sign in to comment.