unsafe private static IntPtr CallConversionThunk(IntPtr callerTransitionBlockParam, IntPtr callConversionId) { CallConversionParameters conversionParams = default(CallConversionParameters); try { conversionParams = new CallConversionParameters(CallConversionInfo.GetConverter(callConversionId.ToInt32()), callerTransitionBlockParam); #if CCCONVERTER_TRACE System.Threading.Interlocked.Increment(ref s_numConversionsExecuted); CallingConventionConverterLogger.WriteLine("CallConversionThunk executing... COUNT = " + s_numConversionsExecuted.LowLevelToString()); CallingConventionConverterLogger.WriteLine("Executing thunk of type " + conversionParams._conversionInfo.ThunkKindString() + ": "); #endif if (conversionParams._conversionInfo.IsMulticastDelegate) { MulticastDelegateInvoke(ref conversionParams); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } else { // Create a transition block on the stack. // Note that SizeOfFrameArgumentArray does overflow checks with sufficient margin to prevent overflows here int nStackBytes = conversionParams._calleeArgs.SizeOfFrameArgumentArray(); int dwAllocaSize = TransitionBlock.GetNegSpaceSize() + sizeof(TransitionBlock) + nStackBytes; IntPtr invokeTargetPtr = Intrinsics.AddrOf((InvokeTargetDel)InvokeTarget); RuntimeAugments.RunFunctionWithConservativelyReportedBuffer(dwAllocaSize, invokeTargetPtr, ref conversionParams); System.Diagnostics.DebugAnnotations.PreviousCallContainsDebuggerStepInCode(); } return conversionParams._invokeReturnValue; } finally { conversionParams.ResetPinnedObjects(); } }