Skip to content

Commit 695f29e

Browse files
committed
Convert funceval to UCO pattern
1 parent ad023e0 commit 695f29e

File tree

4 files changed

+315
-363
lines changed

4 files changed

+315
-363
lines changed

src/coreclr/System.Private.CoreLib/src/System/Runtime/CompilerServices/RuntimeHelpers.CoreCLR.cs

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)