public static unsafe bool TryGetNonUnboxingFunctionPointerFromUnboxingAndInstantiatingStub(IntPtr potentialStub, RuntimeTypeHandle exactType, out IntPtr nonUnboxingMethod) { IntPtr callConversionId; IntPtr commonStubDataPtr; if (!RuntimeAugments.TryGetThunkData(s_thunkPoolHeap, potentialStub, out callConversionId, out commonStubDataPtr)) { // This isn't a call conversion stub nonUnboxingMethod = IntPtr.Zero; return false; } CallConversionInfo conversionInfo = CallConversionInfo.GetConverter(callConversionId.ToInt32()); if (conversionInfo.IsUnboxingThunk) { // In this case the call converter is serving as an unboxing/instantiating stub // This case is not yet handled, and we don't need support for it yet. throw NotImplemented.ByDesign; } IntPtr underlyingTargetMethod; IntPtr newInstantiatingArg; if (conversionInfo.CalleeHasParamType) { // In this case the call converter is an instantiating stub wrapping an unboxing thunk. // Use the redhawk GetCodeTarget to see through the unboxing stub and get the real underlying method // and the instantiation arg does not need changing. underlyingTargetMethod = RuntimeAugments.GetCodeTarget(conversionInfo.TargetFunctionPointer); newInstantiatingArg = conversionInfo.InstantiatingStubArgument; } else { // At this point we've got a standard to generic converter wrapping an unboxing and instantiating // stub. We need to convert that into a fat function pointer directly calling the underlying method // or a calling convention converter instantiating stub wrapping the underlying method IntPtr underlyingUnboxingAndInstantiatingMethod = RuntimeAugments.GetCodeTarget(conversionInfo.TargetFunctionPointer); if (!TypeLoaderEnvironment.TryGetTargetOfUnboxingAndInstantiatingStub(underlyingUnboxingAndInstantiatingMethod, out underlyingTargetMethod)) { // We aren't wrapping an unboxing and instantiating stub. This should never happen throw new NotSupportedException(); } newInstantiatingArg = exactType.ToIntPtr(); } Debug.Assert(conversionInfo.CallerForcedByRefData == null); bool canUseFatFunctionPointerInsteadOfThunk = true; if (conversionInfo.CalleeForcedByRefData != null) { foreach (bool forcedByRef in conversionInfo.CalleeForcedByRefData) { if (forcedByRef) { canUseFatFunctionPointerInsteadOfThunk = false; break; } } } if (canUseFatFunctionPointerInsteadOfThunk) { nonUnboxingMethod = FunctionPointerOps.GetGenericMethodFunctionPointer(underlyingTargetMethod, newInstantiatingArg); return true; } else { // Construct a new StandardToGenericInstantiating thunk around the underlyingTargetMethod nonUnboxingMethod = MakeThunk(ThunkKind.StandardToGenericInstantiating, underlyingTargetMethod, newInstantiatingArg, conversionInfo.ArgIteratorData, conversionInfo.CalleeForcedByRefData); return true; } }