@@ -611,7 +611,8 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
611611 int ofsCallee;
612612 int ofsCaller;
613613 TypeHandle thDummy;
614- TypeHandle thValueType;
614+ TypeHandle thArgType;
615+ TypeHandle thRetType;
615616 IntPtr argPtr;
616617#if CALLDESCR_FPARGREGS
617618 FloatArgumentRegisters * pFloatArgumentRegisters = null ;
@@ -688,7 +689,8 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
688689 InvokeUtils. DynamicInvokeParamLookupType paramLookupType;
689690
690691 RuntimeTypeHandle argumentRuntimeTypeHandle;
691- CorElementType argType = conversionParams . _calleeArgs . GetArgType ( out thValueType ) ;
692+ CorElementType argType = conversionParams . _calleeArgs . GetArgType ( out thArgType ) ;
693+ Debug. Assert ( ! thArgType . IsNull ( ) ) ;
692694
693695 if ( argType == CorElementType . ELEMENT_TYPE_BYREF )
694696 {
@@ -700,14 +702,15 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
700702 }
701703 else
702704 {
703- argumentRuntimeTypeHandle = ( thValueType . IsNull ( ) ? typeof ( object ) . TypeHandle : thValueType . GetRuntimeTypeHandle ( ) ) ;
705+ // We need to check the exact type handle of the argument being passed during reflection invoke scenarios.
706+ argumentRuntimeTypeHandle = thArgType. GetRuntimeTypeHandle ( ) ;
704707 }
705708
706709 object invokeParam = InvokeUtils. DynamicInvokeParamHelperCore (
707710 argumentRuntimeTypeHandle ,
708711 out paramLookupType ,
709712 out index ,
710- conversionParams . _calleeArgs . IsArgPassedByRef ( ) ? InvokeUtils . DynamicInvokeParamType . Ref : InvokeUtils . DynamicInvokeParamType . In ) ;
713+ argType == CorElementType . ELEMENT_TYPE_BYREF ? InvokeUtils . DynamicInvokeParamType . Ref : InvokeUtils . DynamicInvokeParamType . In ) ;
711714
712715 if ( paramLookupType == InvokeUtils . DynamicInvokeParamLookupType . ValuetypeObjectReturned )
713716 {
@@ -786,9 +789,10 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
786789
787790 argumentsAsObjectArray = argumentsAsObjectArray ?? new object [ conversionParams . _callerArgs . NumFixedArgs ( ) ] ;
788791
789- conversionParams. _callerArgs . GetArgType ( out thValueType ) ;
792+ conversionParams. _callerArgs . GetArgType ( out thArgType ) ;
793+ Debug. Assert ( ! thArgType . IsNull ( ) ) ;
790794
791- if ( thValueType . IsNull ( ) )
795+ if ( ! thArgType . IsValueType ( ) )
792796 {
793797 Debug. Assert ( ! isCallerArgPassedByRef ) ;
794798 Debug. Assert ( conversionParams . _callerArgs . GetArgSize ( ) == IntPtr . Size ) ;
@@ -798,11 +802,11 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
798802 {
799803 if ( isCallerArgPassedByRef )
800804 {
801- argumentsAsObjectArray [ arg ] = RuntimeAugments . Box ( thValueType . GetRuntimeTypeHandle ( ) , new IntPtr ( * ( ( void * * ) pSrc ) ) ) ;
805+ argumentsAsObjectArray [ arg ] = RuntimeAugments . Box ( thArgType . GetRuntimeTypeHandle ( ) , new IntPtr ( * ( ( void * * ) pSrc ) ) ) ;
802806 }
803807 else
804808 {
805- argumentsAsObjectArray [ arg ] = RuntimeAugments . Box ( thValueType . GetRuntimeTypeHandle ( ) , new IntPtr ( pSrc ) ) ;
809+ argumentsAsObjectArray [ arg ] = RuntimeAugments . Box ( thArgType . GetRuntimeTypeHandle ( ) , new IntPtr ( pSrc ) ) ;
806810 }
807811 }
808812 }
@@ -817,7 +821,7 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
817821 }
818822 else
819823 {
820- CorElementType argElemType = conversionParams. _calleeArgs. GetArgType( out thValueType ) ;
824+ CorElementType argElemType = conversionParams. _calleeArgs. GetArgType( out thArgType ) ;
821825 ExtendingCopy_NoWriteBarrier ( pSrc , pDest , argElemType , stackSizeCaller ) ;
822826 }
823827 }
@@ -834,7 +838,7 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
834838 {
835839 // Copy into the destination the data pointed at by the pointer in the source(caller) data.
836840 byte * pRealSrc = * ( byte * * ) pSrc ;
837- CorElementType argElemType = conversionParams . _calleeArgs . GetArgType ( out thValueType ) ;
841+ CorElementType argElemType = conversionParams . _calleeArgs . GetArgType ( out thArgType ) ;
838842 ExtendingCopy_NoWriteBarrier( pRealSrc , pDest , argElemType , stackSizeCaller ) ;
839843 }
840844 }
@@ -970,16 +974,17 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
970974 // the target method called by the delegate. Use the callee's ArgIterator instead to get the return type info
971975 if ( conversionParams . _conversionInfo . IsAnyDynamicInvokerThunk )
972976 {
973- returnType = conversionParams. _calleeArgs . GetReturnType ( out thValueType , out forceByRefUnused ) ;
977+ returnType = conversionParams. _calleeArgs . GetReturnType ( out thRetType , out forceByRefUnused ) ;
974978 }
975979 else
976980 {
977- returnType = conversionParams. _callerArgs . GetReturnType ( out thValueType , out forceByRefUnused ) ;
981+ returnType = conversionParams. _callerArgs . GetReturnType ( out thRetType , out forceByRefUnused ) ;
978982 }
979- int returnSize = TypeHandle. GetElemSize ( returnType , thValueType ) ;
983+ Debug. Assert ( ! thRetType . IsNull ( ) ) ;
984+ int returnSize = TypeHandle. GetElemSize ( returnType , thRetType ) ;
980985
981986 // Unbox result of object array delegate call
982- if ( conversionParams . _conversionInfo . IsObjectArrayDelegateThunk && ! thValueType . IsNull ( ) && pinnedResultObject != IntPtr . Zero )
987+ if ( conversionParams . _conversionInfo . IsObjectArrayDelegateThunk && thRetType . IsValueType ( ) && pinnedResultObject != IntPtr . Zero )
983988 pinnedResultObject += IntPtr. Size ;
984989
985990 // Process return values
@@ -1009,7 +1014,7 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
10091014
10101015 bool useGCSafeCopy = false;
10111016
1012- if ( ( returnType = = CorElementType . ELEMENT_TYPE_CLASS ) || ! thValueType . IsNull ( ) )
1017+ if ( ( returnType = = CorElementType . ELEMENT_TYPE_CLASS ) || thRetType . IsValueType ( ) )
10131018 {
10141019 // The GC Safe copy assumes that memory pointers are pointer-aligned and copy length is a multiple of pointer-size
10151020 if ( isPointerAligned ( incomingRetBufPointer ) && isPointerAligned ( sourceBuffer ) && ( returnSize % sizeof ( IntPtr ) == 0 ) )
@@ -1082,7 +1087,7 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
10821087
10831088 if ( conversionParams . _conversionInfo . IsObjectArrayDelegateThunk )
10841089 {
1085- if ( ! thValueType . IsNull ( ) )
1090+ if ( thRetType . IsValueType ( ) )
10861091 {
10871092 returnValueToCopy = ( void * ) pinnedResultObject ;
10881093#if _TARGET_X86_
@@ -1107,22 +1112,30 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
11071112#endif
11081113 }
11091114 }
1110- else if ( conversionParams . _conversionInfo . IsAnyDynamicInvokerThunk && ! thValueType . IsNull ( ) )
1115+ else if ( conversionParams . _conversionInfo . IsAnyDynamicInvokerThunk && thRetType . IsValueType ( ) )
11111116 {
11121117 Debug . Assert ( returnValueToCopy != null ) ;
11131118
1114- if ( ! conversionParams . _callerArgs . HasRetBuffArg ( ) && conversionParams . _calleeArgs . HasRetBuffArg ( ) )
1115- returnValueToCopy = ( void * ) ( new IntPtr ( * ( ( void * * ) returnValueToCopy ) ) + IntPtr . Size ) ;
1119+ if ( conversionParams . _calleeArgs . GetReturnType ( out thDummy , out dummyBool ) == CorElementType . ELEMENT_TYPE_VOID )
1120+ {
1121+ // Invokers returning void need to return a null object
1122+ returnValueToCopy = null ;
1123+ }
1124+ else
1125+ {
1126+ if ( ! conversionParams . _callerArgs . HasRetBuffArg ( ) && conversionParams . _calleeArgs . HasRetBuffArg ( ) )
1127+ returnValueToCopy = ( void * ) ( new IntPtr ( * ( ( void * * ) returnValueToCopy ) ) + IntPtr . Size ) ;
11161128
1117- // Need to box value type before returning it
1118- object returnValue = RuntimeAugments. Box( thValueType . GetRuntimeTypeHandle ( ) , new IntPtr ( returnValueToCopy ) ) ;
1119- CallConversionParameters . s_pinnedGCHandles . _returnObjectHandle . Target = returnValue ;
1120- pinnedResultObject = CallConversionParameters . s_pinnedGCHandles . _returnObjectHandle . GetRawTargetAddress ( ) ;
1121- returnValueToCopy = ( void * ) & pinnedResultObject ;
1129+ // Need to box value type before returning it
1130+ object returnValue = RuntimeAugments. Box( thRetType . GetRuntimeTypeHandle ( ) , new IntPtr ( returnValueToCopy ) ) ;
1131+ CallConversionParameters . s_pinnedGCHandles . _returnObjectHandle . Target = returnValue ;
1132+ pinnedResultObject = CallConversionParameters . s_pinnedGCHandles . _returnObjectHandle . GetRawTargetAddress ( ) ;
1133+ returnValueToCopy = ( void * ) & pinnedResultObject ;
1134+ }
11221135 // Since we've changed the returnValueToCopy here, we need to update the idea of what we are returning
11231136 returnType = CorElementType . ELEMENT_TYPE_OBJECT ;
1124- thValueType = default ( TypeHandle ) ;
1125- returnSize = TypeHandle . GetElemSize ( returnType , thValueType ) ;
1137+ thRetType = default ( TypeHandle ) ;
1138+ returnSize = TypeHandle . GetElemSize ( returnType , thRetType ) ;
11261139
11271140#if _TARGET_X86_
11281141 ( ( TransitionBlock * ) callerTransitionBlock ) ->m_returnBlock . returnValue = pinnedResultObject ;
@@ -1188,23 +1201,14 @@ unsafe private static void InvokeTarget(void* allocatedStackBuffer, ref CallConv
11881201 return ;
11891202#else
11901203 // If we reach here, we are returning value in the integer registers.
1191- if ( conversionParams . _conversionInfo . IsObjectArrayDelegateThunk && ( ! thValueType . IsNull ( ) ) )
1204+ if ( returnValueToCopy == null )
11921205 {
1193- if ( returnValueToCopy == null )
1194- {
1195- // object array delegate thunk result is a null object. We'll fill the return buffer with 'returnSize' zeros in that case
1196- memzeroPointer( callerTransitionBlock + TransitionBlock . GetOffsetOfArgumentRegisters ( ) , returnSize ) ;
1197- }
1198- else
1199- {
1200- ExtendingCopy_WriteBarrier( returnValueToCopy , callerTransitionBlock + TransitionBlock . GetOffsetOfArgumentRegisters ( ) , returnType , returnSize ) ;
1201- }
1206+ // Return result is a null object. We'll fill the return buffer with 'returnSize' zeros in that case
1207+ memzeroPointer ( callerTransitionBlock + TransitionBlock . GetOffsetOfArgumentRegisters ( ) , returnSize ) ;
12021208 }
12031209 else
12041210 {
1205- Debug. Assert ( returnValueToCopy != null ) ;
1206-
1207- ExtendingCopy_NoWriteBarrier( returnValueToCopy , callerTransitionBlock + TransitionBlock . GetOffsetOfArgumentRegisters ( ) , returnType , returnSize ) ;
1211+ ExtendingCopy_WriteBarrier ( returnValueToCopy , callerTransitionBlock + TransitionBlock . GetOffsetOfArgumentRegisters ( ) , returnType , returnSize ) ;
12081212 }
12091213 conversionParams . _invokeReturnValue = ReturnIntegerPointReturnThunk ;
12101214#endif
0 commit comments