@@ -684,6 +684,55 @@ internal static unsafe void CallDefaultConstructor(object* pObj, delegate*<objec
684684 * pException = ex ;
685685 }
686686 }
687+
688+ [ StructLayout ( LayoutKind . Sequential ) ]
689+ private unsafe struct FuncEvalInvokeContract
690+ {
691+ public nint MethodHandle ;
692+ public nint OwnerType ;
693+ public object * ThisObj ;
694+ public object ? [ ] * Args ;
695+ public int IsNewObj ;
696+ }
697+
698+ [ UnmanagedCallersOnly ]
699+ [ RequiresUnsafe ]
700+ private static unsafe void InvokeFuncEval ( FuncEvalInvokeContract * pContract , object * pResult , Exception * pException )
701+ {
702+ try
703+ {
704+ RuntimeMethodHandleInternal handle = new RuntimeMethodHandleInternal ( pContract ->MethodHandle ) ;
705+ RuntimeType ? ownerType = pContract ->OwnerType != 0
706+ ? RuntimeTypeHandle . GetRuntimeTypeFromHandle ( pContract ->OwnerType )
707+ : null ;
708+ MethodBase method = RuntimeType . GetMethodBase ( ownerType , handle ) ! ;
709+
710+ object ? thisObj = * pContract ->ThisObj ;
711+ object ? [ ] ? args = * pContract ->Args ;
712+
713+ if ( pContract ->IsNewObj != 0 )
714+ {
715+ // Call constructor on the pre-allocated instance.
716+ // ConstructorInfo.Invoke(object, ...) invokes on an existing instance and returns null.
717+ method . Invoke ( thisObj , BindingFlags . DoNotWrapExceptions , binder : null , args , culture : null ) ;
718+ * pResult = thisObj ! ;
719+ }
720+ else
721+ {
722+ object ? result = method . Invoke ( thisObj , BindingFlags . DoNotWrapExceptions , binder : null , args , culture : null ) ;
723+ if ( result is not null )
724+ * pResult = result ;
725+ }
726+
727+ // Write back any modified byref args into the args array so native can read them.
728+ if ( args is not null )
729+ * pContract ->Args = args ;
730+ }
731+ catch ( Exception ex )
732+ {
733+ * pException = ex ;
734+ }
735+ }
687736 }
688737 // Helper class to assist with unsafe pinning of arbitrary objects.
689738 // It's used by VM code.
@@ -736,7 +785,7 @@ internal unsafe struct MethodDesc
736785 internal unsafe struct MethodDescChunk
737786 {
738787 public MethodTable * MethodTable ;
739- public MethodDescChunk * Next ;
788+ public MethodDescChunk * Next ;
740789 public byte Size ; // The size of this chunk minus 1 (in multiples of MethodDesc::ALIGNMENT)
741790 public byte Count ; // The number of MethodDescs in this chunk minus 1
742791 public ushort FlagsAndTokenRange ;
@@ -1132,11 +1181,11 @@ internal unsafe struct MethodTableAuxiliaryData
11321181 private const uint enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode = 0x0002 ; // Whether we have checked the overridden Equals or GetHashCode
11331182 private const uint enum_flag_CanCompareBitsOrUseFastGetHashCode = 0x0004 ; // Is any field type or sub field type overridden Equals or GetHashCode
11341183
1135- private const uint enum_flag_Initialized = 0x0001 ;
1136- private const uint enum_flag_HasCheckedStreamOverride = 0x0400 ;
1137- private const uint enum_flag_StreamOverriddenRead = 0x0800 ;
1138- private const uint enum_flag_StreamOverriddenWrite = 0x1000 ;
1139- private const uint enum_flag_EnsuredInstanceActive = 0x2000 ;
1184+ private const uint enum_flag_Initialized = 0x0001 ;
1185+ private const uint enum_flag_HasCheckedStreamOverride = 0x0400 ;
1186+ private const uint enum_flag_StreamOverriddenRead = 0x0800 ;
1187+ private const uint enum_flag_StreamOverriddenWrite = 0x1000 ;
1188+ private const uint enum_flag_EnsuredInstanceActive = 0x2000 ;
11401189
11411190
11421191 public bool HasCheckedCanCompareBitsOrUseFastGetHashCode => ( Flags & enum_flag_HasCheckedCanCompareBitsOrUseFastGetHashCode ) != 0 ;
0 commit comments