|| (corElemType == CorElementType.ELEMENT_TYPE_BYREF); // IsByRef
}
+ // ** WARNING **
+ // Caller bears responsibility for ensuring that the provided Types remain
+ // GC-reachable while the unmanaged handles are being manipulated. The caller
+ // may need to make a defensive copy of the input array to ensure it's not
+ // mutated by another thread, and this defensive copy should be passed to
+ // a KeepAlive routine.
internal static IntPtr[]? CopyRuntimeTypeHandles(RuntimeTypeHandle[]? inHandles, out int length)
{
if (inHandles == null || inHandles.Length == 0)
return outHandles;
}
+ // ** WARNING **
+ // Caller bears responsibility for ensuring that the provided Types remain
+ // GC-reachable while the unmanaged handles are being manipulated. The caller
+ // may need to make a defensive copy of the input array to ensure it's not
+ // mutated by another thread, and this defensive copy should be passed to
+ // a KeepAlive routine.
internal static IntPtr[]? CopyRuntimeTypeHandles(Type[]? inHandles, out int length)
{
if (inHandles == null || inHandles.Length == 0)
[MethodImpl(MethodImplOptions.InternalCall)]
internal static extern object Allocate(RuntimeType type);
- [MethodImpl(MethodImplOptions.InternalCall)]
- internal static extern object CreateInstanceForAnotherGenericParameter(RuntimeType type, RuntimeType genericParameter);
+ internal static object CreateInstanceForAnotherGenericParameter(RuntimeType type, RuntimeType genericParameter)
+ {
+ object? instantiatedObject = null;
+
+ IntPtr typeHandle = genericParameter.GetTypeHandleInternal().Value;
+ CreateInstanceForAnotherGenericParameter(
+ new QCallTypeHandle(ref type),
+ &typeHandle,
+ 1,
+ ObjectHandleOnStack.Create(ref instantiatedObject));
+
+ GC.KeepAlive(genericParameter);
+ return instantiatedObject!;
+ }
+
+ internal static object CreateInstanceForAnotherGenericParameter(RuntimeType type, RuntimeType genericParameter1, RuntimeType genericParameter2)
+ {
+ object? instantiatedObject = null;
+
+ IntPtr* pTypeHandles = stackalloc IntPtr[]
+ {
+ genericParameter1.GetTypeHandleInternal().Value,
+ genericParameter2.GetTypeHandleInternal().Value
+ };
+
+ CreateInstanceForAnotherGenericParameter(
+ new QCallTypeHandle(ref type),
+ pTypeHandles,
+ 2,
+ ObjectHandleOnStack.Create(ref instantiatedObject));
+
+ GC.KeepAlive(genericParameter1);
+ GC.KeepAlive(genericParameter2);
+
+ return instantiatedObject!;
+ }
+
+ [DllImport(RuntimeHelpers.QCall, CharSet = CharSet.Unicode)]
+ private static extern void CreateInstanceForAnotherGenericParameter(
+ QCallTypeHandle baseType,
+ IntPtr* pTypeHandles,
+ int cTypeHandles,
+ ObjectHandleOnStack instantiatedObject);
internal RuntimeType GetRuntimeType()
{
internal RuntimeType Instantiate(Type[]? inst)
{
- // defensive copy to be sure array is not mutated from the outside during processing
IntPtr[]? instHandles = CopyRuntimeTypeHandles(inst, out int instCount);
fixed (IntPtr* pInst = instHandles)
throw new ArgumentOutOfRangeException(nameof(typeToken),
SR.Format(SR.Argument_InvalidToken, typeToken, new ModuleHandle(module)));
+ // defensive copy of user-provided array, per CopyRuntimeTypeHandles contract
+ typeInstantiationContext = (RuntimeTypeHandle[]?)typeInstantiationContext?.Clone();
+ methodInstantiationContext = (RuntimeTypeHandle[]?)methodInstantiationContext?.Clone();
+
IntPtr[]? typeInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(typeInstantiationContext, out int typeInstCount);
IntPtr[]? methodInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(methodInstantiationContext, out int methodInstCount);
internal static IRuntimeMethodInfo ResolveMethodHandleInternal(RuntimeModule module, int methodToken, RuntimeTypeHandle[]? typeInstantiationContext, RuntimeTypeHandle[]? methodInstantiationContext)
{
+ // defensive copy of user-provided array, per CopyRuntimeTypeHandles contract
+ typeInstantiationContext = (RuntimeTypeHandle[]?)typeInstantiationContext?.Clone();
+ methodInstantiationContext = (RuntimeTypeHandle[]?)methodInstantiationContext?.Clone();
IntPtr[]? typeInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(typeInstantiationContext, out int typeInstCount);
IntPtr[]? methodInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(methodInstantiationContext, out int methodInstCount);
throw new ArgumentOutOfRangeException(nameof(fieldToken),
SR.Format(SR.Argument_InvalidToken, fieldToken, new ModuleHandle(module)));
+ // defensive copy of user-provided array, per CopyRuntimeTypeHandles contract
+ typeInstantiationContext = (RuntimeTypeHandle[]?)typeInstantiationContext?.Clone();
+ methodInstantiationContext = (RuntimeTypeHandle[]?)methodInstantiationContext?.Clone();
+
// defensive copy to be sure array is not mutated from the outside during processing
IntPtr[]? typeInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(typeInstantiationContext, out int typeInstCount);
IntPtr[]? methodInstantiationContextHandles = RuntimeTypeHandle.CopyRuntimeTypeHandles(methodInstantiationContext, out int methodInstCount);
}
FCIMPLEND
-FCIMPL2(Object*, RuntimeTypeHandle::CreateInstanceForGenericType, ReflectClassBaseObject* pTypeUNSAFE, ReflectClassBaseObject* pParameterTypeUNSAFE) {
- FCALL_CONTRACT;
-
- struct _gc
- {
- OBJECTREF rv;
- REFLECTCLASSBASEREF refType;
- REFLECTCLASSBASEREF refParameterType;
- } gc;
-
- gc.rv = NULL;
- gc.refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
- gc.refParameterType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pParameterTypeUNSAFE);
+void QCALLTYPE RuntimeTypeHandle::CreateInstanceForAnotherGenericParameter(
+ QCall::TypeHandle pTypeHandle,
+ TypeHandle* pInstArray,
+ INT32 cInstArray,
+ QCall::ObjectHandleOnStack pInstantiatedObject
+)
+{
+ CONTRACTL{
+ QCALL_CHECK;
+ PRECONDITION(!pTypeHandle.AsTypeHandle().IsNull());
+ PRECONDITION(cInstArray >= 0);
+ PRECONDITION(cInstArray == 0 || pInstArray != NULL);
+ }
+ CONTRACTL_END;
- MethodDesc* pMeth;
- TypeHandle genericType = gc.refType->GetType();
+ TypeHandle genericType = pTypeHandle.AsTypeHandle();
- TypeHandle parameterHandle = gc.refParameterType->GetType();
+ BEGIN_QCALL;
_ASSERTE (genericType.HasInstantiation());
- HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
-
- TypeHandle instantiatedType = ((TypeHandle)genericType.GetCanonicalMethodTable()).Instantiate(Instantiation(¶meterHandle, 1));
+ TypeHandle instantiatedType = ((TypeHandle)genericType.GetCanonicalMethodTable()).Instantiate(Instantiation(pInstArray, (DWORD)cInstArray));
// Get the type information associated with refThis
MethodTable* pVMT = instantiatedType.GetMethodTable();
_ASSERTE( !pVMT->IsAbstract() ||! instantiatedType.ContainsGenericVariables());
_ASSERTE(!pVMT->IsByRefLike() && pVMT->HasDefaultConstructor());
- pMeth = pVMT->GetDefaultConstructor();
- MethodDescCallSite ctor(pMeth);
-
// We've got the class, lets allocate it and call the constructor
// Nullables don't take this path, if they do we need special logic to make an instance
_ASSERTE(!Nullable::IsNullableType(instantiatedType));
- gc.rv = instantiatedType.GetMethodTable()->Allocate();
- ARG_SLOT arg = ObjToArgSlot(gc.rv);
+ {
+ GCX_COOP();
- // Call the method
- TryCallMethod(&ctor, &arg, true);
+ OBJECTREF newObj = instantiatedType.GetMethodTable()->Allocate();
+ GCPROTECT_BEGIN(newObj);
+ CallDefaultConstructor(newObj);
+ GCPROTECT_END();
- HELPER_METHOD_FRAME_END();
- return OBJECTREFToObject(gc.rv);
+ pInstantiatedObject.Set(newObj);
+ }
+
+ END_QCALL;
}
-FCIMPLEND
NOINLINE FC_BOOL_RET IsInstanceOfTypeHelper(OBJECTREF obj, REFLECTCLASSBASEREF refType)
{