Example #1
0
        private void ComputeCalleeFlagsAndFunctionPointerForReflectionInvokeThunk()
        {
            Debug.Assert(_conversionInfo.IsReflectionDynamicInvokerThunk);
            Debug.Assert(!_callerArgs.Equals(default(ArgIterator)) && !_calleeArgs.Equals(default(ArgIterator)));

            _callerArgs.GetNextOffset();     // Skip thisPtr

            {
                int ofsCaller = _callerArgs.GetNextOffset();     // methodToCall
                Debug.Assert(TransitionBlock.InvalidOffset != ofsCaller);

                void **pSrc = (void **)(_callerTransitionBlock + ofsCaller);

                IntPtr functionPointer = new IntPtr(*pSrc);

                bool forceCalleeHasParamType = UpdateCalleeFunctionPointer(functionPointer);
                _calleeArgs.SetHasParamTypeAndReset(forceCalleeHasParamType);
            }

            _callerArgs.GetNextOffset();     // Skip argSetupState

            // targetIsThisCall
            {
                int ofsCaller = _callerArgs.GetNextOffset();     // targetIsThisCall
                Debug.Assert(TransitionBlock.InvalidOffset != ofsCaller);

                bool *pSrc = (bool *)(_callerTransitionBlock + ofsCaller);

                bool targetIsThisCall = *pSrc;

                _calleeArgs.SetHasThisAndReset(targetIsThisCall);
            }

            _callerArgs.Reset();
        }
        internal CallConversionParameters(CallConversionInfo conversionInfo, IntPtr callerTransitionBlockParam)
        {
            // Make sure the thred static variable has been initialized for this thread
            s_pinnedGCHandles = s_pinnedGCHandles ?? new GCHandleContainer();

            _conversionInfo = conversionInfo;
            _callerTransitionBlock = (byte*)callerTransitionBlockParam.ToPointer();
            _functionPointerToCall = conversionInfo.TargetFunctionPointer;
            _instantiatingStubArgument = conversionInfo.InstantiatingStubArgument;
            _delegateData = default(DelegateData);
            _calleeArgs = default(ArgIterator);
            _invokeReturnValue = IntPtr.Zero;
            _copyReturnValue = true;
            _dynamicInvokeParams = null;
            _dynamicInvokeByRefObjectArgs = null;

            // 
            // Setup input argument iterator for the caller
            //
            ArgIteratorData callerIteratorData;

            if (conversionInfo.IsDelegateDynamicInvokeThunk)
                callerIteratorData = s_delegateDynamicInvokeImplArgIteratorData;
            else if (conversionInfo.IsReflectionDynamicInvokerThunk)
                callerIteratorData = s_reflectionDynamicInvokeImplArgIteratorData;
            else
                callerIteratorData = conversionInfo.ArgIteratorData;

            _callerArgs = new ArgIterator(callerIteratorData,
                                              callerIteratorData.HasThis() ?
                                                CallingConvention.ManagedInstance :
                                                CallingConvention.ManagedStatic,
                                              conversionInfo.CallerHasParamType,
                                              conversionInfo.CallerHasExtraParameterWhichIsFunctionTarget,
                                              conversionInfo.CallerForcedByRefData,
                                              false, false); // Setup input

            bool forceCalleeHasParamType = false;

            // If the callee MAY have a param type, we need to know before we create the callee arg iterator
            // To do this we need to actually load the target address and see if it has the generic method pointer
            // bit set.
            if (conversionInfo.CalleeMayHaveParamType)
            {
                ArgIterator callerArgsLookupTargetFunctionPointer = new ArgIterator(conversionInfo.ArgIteratorData,
                                                                                        conversionInfo.ArgIteratorData.HasThis() ?
                                                                                            CallingConvention.ManagedInstance :
                                                                                            CallingConvention.ManagedStatic,
                                                                                        conversionInfo.CallerHasParamType,
                                                                                        conversionInfo.CallerHasExtraParameterWhichIsFunctionTarget,
                                                                                        conversionInfo.CallerForcedByRefData,
                                                                                        false, false);

                // Find the last valid caller offset. That's the offset of the target function pointer.
                int ofsCallerValid = TransitionBlock.InvalidOffset;
                while (true)
                {
                    // Setup argument offsets.
                    int ofsCallerTemp = callerArgsLookupTargetFunctionPointer.GetNextOffset();

                    // Check to see if we've handled all the arguments that we are to pass to the callee. 
                    if (TransitionBlock.InvalidOffset == ofsCallerTemp)
                        break;

                    ofsCallerValid = ofsCallerTemp;
                }

                if (ofsCallerValid == TransitionBlock.InvalidOffset)
                    throw new InvalidProgramException();

                int stackSizeCaller = callerArgsLookupTargetFunctionPointer.GetArgSize();
                Debug.Assert(stackSizeCaller == IntPtr.Size);
                void* pSrc = _callerTransitionBlock + ofsCallerValid;
                IntPtr tempFunctionPointer = *((IntPtr*)pSrc);

                forceCalleeHasParamType = UpdateCalleeFunctionPointer(tempFunctionPointer);
            }

            // Retrieve target function pointer and instantiation argument for delegate thunks
            if (conversionInfo.IsDelegateThunk)
            {
                Debug.Assert(_callerArgs.HasThis() && !_conversionInfo.IsUnboxingThunk);

                IntPtr locationOfThisPointer = (IntPtr)(_callerTransitionBlock + ArgIterator.GetThisOffset());
                _delegateData._delegateObject = (Delegate)Unsafe.As<IntPtr, Object>(ref *(IntPtr*)locationOfThisPointer);
                Debug.Assert(_delegateData._delegateObject != null);

                RuntimeAugments.GetDelegateData(
                    _delegateData._delegateObject,
                    out _delegateData._firstParameter,
                    out _delegateData._helperObject,
                    out _delegateData._extraFunctionPointerOrData,
                    out _delegateData._functionPointer);

                if (conversionInfo.TargetDelegateFunctionIsExtraFunctionPointerOrDataField)
                {
                    if (conversionInfo.IsOpenInstanceDelegateThunk)
                    {
                        _delegateData._boxedFirstParameter = BoxedCallerFirstArgument;
                        Debug.Assert(_delegateData._boxedFirstParameter != null);
                        _callerArgs.Reset();

                        IntPtr resolvedTargetFunctionPointer = OpenMethodResolver.ResolveMethod(_delegateData._extraFunctionPointerOrData, _delegateData._boxedFirstParameter);
                        forceCalleeHasParamType = UpdateCalleeFunctionPointer(resolvedTargetFunctionPointer);
                    }
                    else
                    {
                        forceCalleeHasParamType = UpdateCalleeFunctionPointer(_delegateData._extraFunctionPointerOrData);
                    }
                }
                else if (conversionInfo.IsMulticastDelegate)
                {
                    _delegateData._multicastTargetCount = (int)_delegateData._extraFunctionPointerOrData;
                }
            }

            // 
            // Setup output argument iterator for the callee
            //
            _calleeArgs = new ArgIterator(conversionInfo.ArgIteratorData,
                                                (conversionInfo.ArgIteratorData.HasThis() && !conversionInfo.IsStaticDelegateThunk) ?
                                                    CallingConvention.ManagedInstance :
                                                    CallingConvention.ManagedStatic,
                                                forceCalleeHasParamType || conversionInfo.CalleeHasParamType,
                                                false,
                                                conversionInfo.CalleeForcedByRefData,
                                                conversionInfo.IsOpenInstanceDelegateThunk,
                                                conversionInfo.IsClosedStaticDelegate);

            // The function pointer, 'hasParamType', and 'hasThis' flags for the callee arg iterator need to be computed/read from the caller's 
            // input arguments in the case of a reflection invoker thunk (the target method pointer and 'hasThis' flags are
            // passed in as parameters from the caller, not loaded from a static method signature in native layout)
            if (conversionInfo.IsReflectionDynamicInvokerThunk)
                ComputeCalleeFlagsAndFunctionPointerForReflectionInvokeThunk();

#if CALLINGCONVENTION_CALLEE_POPS
            // Ensure that the count of bytes in the stack is available
            _callerArgs.CbStackPop();
#endif
        }
Example #3
0
        internal CallConversionParameters(CallConversionInfo conversionInfo, IntPtr callerTransitionBlockParam)
        {
            // Make sure the thred static variable has been initialized for this thread
            s_pinnedGCHandles = s_pinnedGCHandles ?? new GCHandleContainer();

            _conversionInfo            = conversionInfo;
            _callerTransitionBlock     = (byte *)callerTransitionBlockParam.ToPointer();
            _functionPointerToCall     = conversionInfo.TargetFunctionPointer;
            _instantiatingStubArgument = conversionInfo.InstantiatingStubArgument;
            _delegateData                 = default(DelegateData);
            _calleeArgs                   = default(ArgIterator);
            _invokeReturnValue            = IntPtr.Zero;
            _copyReturnValue              = true;
            _dynamicInvokeParams          = null;
            _dynamicInvokeByRefObjectArgs = null;

            //
            // Setup input argument iterator for the caller
            //
            ArgIteratorData callerIteratorData;

            if (conversionInfo.IsDelegateDynamicInvokeThunk)
            {
                callerIteratorData = s_delegateDynamicInvokeImplArgIteratorData;
            }
            else if (conversionInfo.IsReflectionDynamicInvokerThunk)
            {
                callerIteratorData = s_reflectionDynamicInvokeImplArgIteratorData;
            }
            else
            {
                callerIteratorData = conversionInfo.ArgIteratorData;
            }

            _callerArgs = new ArgIterator(callerIteratorData,
                                          callerIteratorData.HasThis() ?
                                          CallingConvention.ManagedInstance :
                                          CallingConvention.ManagedStatic,
                                          conversionInfo.CallerHasParamType,
                                          conversionInfo.CallerHasExtraParameterWhichIsFunctionTarget,
                                          conversionInfo.CallerForcedByRefData,
                                          false, false);     // Setup input

            bool forceCalleeHasParamType = false;

            // If the callee MAY have a param type, we need to know before we create the callee arg iterator
            // To do this we need to actually load the target address and see if it has the generic method pointer
            // bit set.
            if (conversionInfo.CalleeMayHaveParamType)
            {
                ArgIterator callerArgsLookupTargetFunctionPointer = new ArgIterator(conversionInfo.ArgIteratorData,
                                                                                    conversionInfo.ArgIteratorData.HasThis() ?
                                                                                    CallingConvention.ManagedInstance :
                                                                                    CallingConvention.ManagedStatic,
                                                                                    conversionInfo.CallerHasParamType,
                                                                                    conversionInfo.CallerHasExtraParameterWhichIsFunctionTarget,
                                                                                    conversionInfo.CallerForcedByRefData,
                                                                                    false, false);

                // Find the last valid caller offset. That's the offset of the target function pointer.
                int ofsCallerValid = TransitionBlock.InvalidOffset;
                while (true)
                {
                    // Setup argument offsets.
                    int ofsCallerTemp = callerArgsLookupTargetFunctionPointer.GetNextOffset();

                    // Check to see if we've handled all the arguments that we are to pass to the callee.
                    if (TransitionBlock.InvalidOffset == ofsCallerTemp)
                    {
                        break;
                    }

                    ofsCallerValid = ofsCallerTemp;
                }

                if (ofsCallerValid == TransitionBlock.InvalidOffset)
                {
                    throw new InvalidProgramException();
                }

                int stackSizeCaller = callerArgsLookupTargetFunctionPointer.GetArgSize();
                Debug.Assert(stackSizeCaller == IntPtr.Size);
                void * pSrc = _callerTransitionBlock + ofsCallerValid;
                IntPtr tempFunctionPointer = *((IntPtr *)pSrc);

                forceCalleeHasParamType = UpdateCalleeFunctionPointer(tempFunctionPointer);
            }

            // Retrieve target function pointer and instantiation argument for delegate thunks
            if (conversionInfo.IsDelegateThunk)
            {
                Debug.Assert(_callerArgs.HasThis() && !_conversionInfo.IsUnboxingThunk);

                IntPtr locationOfThisPointer = (IntPtr)(_callerTransitionBlock + ArgIterator.GetThisOffset());
                _delegateData._delegateObject = (Delegate)Unsafe.As <IntPtr, Object>(ref *(IntPtr *)locationOfThisPointer);
                Debug.Assert(_delegateData._delegateObject != null);

                RuntimeAugments.GetDelegateData(
                    _delegateData._delegateObject,
                    out _delegateData._firstParameter,
                    out _delegateData._helperObject,
                    out _delegateData._extraFunctionPointerOrData,
                    out _delegateData._functionPointer);

                if (conversionInfo.TargetDelegateFunctionIsExtraFunctionPointerOrDataField)
                {
                    if (conversionInfo.IsOpenInstanceDelegateThunk)
                    {
                        _delegateData._boxedFirstParameter = BoxedCallerFirstArgument;
                        _callerArgs.Reset();

                        IntPtr resolvedTargetFunctionPointer = OpenMethodResolver.ResolveMethod(_delegateData._extraFunctionPointerOrData, _delegateData._boxedFirstParameter);
                        forceCalleeHasParamType = UpdateCalleeFunctionPointer(resolvedTargetFunctionPointer);
                    }
                    else
                    {
                        forceCalleeHasParamType = UpdateCalleeFunctionPointer(_delegateData._extraFunctionPointerOrData);
                    }
                }
                else if (conversionInfo.IsMulticastDelegate)
                {
                    _delegateData._multicastTargetCount = (int)_delegateData._extraFunctionPointerOrData;
                }
            }

            //
            // Setup output argument iterator for the callee
            //
            _calleeArgs = new ArgIterator(conversionInfo.ArgIteratorData,
                                          (conversionInfo.ArgIteratorData.HasThis() && !conversionInfo.IsStaticDelegateThunk) ?
                                          CallingConvention.ManagedInstance :
                                          CallingConvention.ManagedStatic,
                                          forceCalleeHasParamType || conversionInfo.CalleeHasParamType,
                                          false,
                                          conversionInfo.CalleeForcedByRefData,
                                          conversionInfo.IsOpenInstanceDelegateThunk,
                                          conversionInfo.IsClosedStaticDelegate);

            // The function pointer, 'hasParamType', and 'hasThis' flags for the callee arg iterator need to be computed/read from the caller's
            // input arguments in the case of a reflection invoker thunk (the target method pointer and 'hasThis' flags are
            // passed in as parameters from the caller, not loaded from a static method signature in native layout)
            if (conversionInfo.IsReflectionDynamicInvokerThunk)
            {
                ComputeCalleeFlagsAndFunctionPointerForReflectionInvokeThunk();
            }

#if CALLINGCONVENTION_CALLEE_POPS
            // Ensure that the count of bytes in the stack is available
            _callerArgs.CbStackPop();
#endif
        }