diff --git a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
index c9c3bca531be0f..072b16cad05712 100644
--- a/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
+++ b/src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj
@@ -160,6 +160,7 @@
+
@@ -315,7 +316,7 @@
-
+
diff --git a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
index 18428b0eb34ad1..0942a3a0312002 100644
--- a/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
+++ b/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/DynamicMethod.cs
@@ -8,6 +8,7 @@
using System.Runtime.Loader;
using System.Text;
using System.Threading;
+using static System.Runtime.CompilerServices.RuntimeHelpers;
namespace System.Reflection.Emit
{
@@ -22,6 +23,8 @@ public sealed class DynamicMethod : MethodInfo
private RuntimeModule m_module = null!;
internal bool m_skipVisibility;
internal RuntimeType? m_typeOwner; // can be null
+ private DynamicMethodInvoker? _invoker;
+ private Signature? _signature;
// We want the creator of the DynamicMethod to control who has access to the
// DynamicMethod (just like we do for delegates). However, a user can get to
@@ -417,6 +420,37 @@ internal RuntimeMethodHandle GetMethodDescriptor()
public override bool IsSecurityTransparent => false;
+ private DynamicMethodInvoker Invoker
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ _invoker ??= new DynamicMethodInvoker(this);
+
+ return _invoker;
+ }
+ }
+
+ internal Signature Signature
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ [MethodImpl(MethodImplOptions.NoInlining)] // move lazy sig generation out of the hot path
+ Signature LazyCreateSignature()
+ {
+ Debug.Assert(m_methodHandle != null);
+ Debug.Assert(m_parameterTypes != null);
+
+ Signature newSig = new Signature(m_methodHandle, m_parameterTypes, m_returnType, CallingConvention);
+ Volatile.Write(ref _signature, newSig);
+ return newSig;
+ }
+
+ return _signature ?? LazyCreateSignature();
+ }
+ }
+
public override object? Invoke(object? obj, BindingFlags invokeAttr, Binder? binder, object?[]? parameters, CultureInfo? culture)
{
if ((CallingConvention & CallingConventions.VarArgs) == CallingConventions.VarArgs)
@@ -431,38 +465,139 @@ internal RuntimeMethodHandle GetMethodDescriptor()
_ = GetMethodDescriptor();
// ignore obj since it's a static method
- // create a signature object
- Signature sig = new Signature(
- this.m_methodHandle!, m_parameterTypes, m_returnType, CallingConvention);
-
-
// verify arguments
- int formalCount = sig.Arguments.Length;
- int actualCount = (parameters != null) ? parameters.Length : 0;
- if (formalCount != actualCount)
+ int argCount = (parameters != null) ? parameters.Length : 0;
+ if (Signature.Arguments.Length != argCount)
throw new TargetParameterCountException(SR.Arg_ParmCnt);
- // if we are here we passed all the previous checks. Time to look at the arguments
- bool wrapExceptions = (invokeAttr & BindingFlags.DoNotWrapExceptions) == 0;
+ object? retValue;
- StackAllocedArguments stackArgs = default;
- Span