HRESULT CLR_RT_StackFrame::FixCall() { NATIVE_PROFILE_CLR_CORE(); TINYCLR_HEADER(); const CLR_RECORD_METHODDEF* target = m_call.m_target; CLR_UINT8 numArgs = target->numArgs; // // The copy of ValueTypes is delayed as much as possible. // // If an argument is a ValueType, now it's a good time to clone it. // if(numArgs) { CLR_RT_SignatureParser parser; parser.Initialize_MethodSignature( m_call.m_assm, target ); CLR_RT_SignatureParser::Element res; CLR_RT_HeapBlock* args = m_arguments; if(parser.m_flags & PIMAGE_CEE_CS_CALLCONV_HASTHIS) { args++; } // // Skip return value. // TINYCLR_CHECK_HRESULT(parser.Advance( res )); for(; parser.Available() > 0; args++) { TINYCLR_CHECK_HRESULT(parser.Advance( res )); if(res.m_levels > 0) continue; // Array, no need to fix. if(args->DataType() == DATATYPE_OBJECT) { CLR_RT_TypeDef_Instance inst; inst.InitializeFromIndex( res.m_cls ); CLR_DataType dtT = (CLR_DataType)inst.m_target->dataType; const CLR_RT_DataTypeLookup& dtl = c_CLR_RT_DataTypeLookup[ dtT ]; if(dtl.m_flags & (CLR_RT_DataTypeLookup::c_OptimizedValueType | CLR_RT_DataTypeLookup::c_ValueType)) { CLR_RT_HeapBlock* value = args->FixBoxingReference(); FAULT_ON_NULL(value); if(value->DataType() == dtT) { // It's a boxed primitive/enum type. args->Assign( *value ); } else if(args->Dereference()->ObjectCls().m_data == res.m_cls.m_data) { TINYCLR_CHECK_HRESULT(args->PerformUnboxing( inst )); } else { TINYCLR_SET_AND_LEAVE(CLR_E_WRONG_TYPE); } } } if(res.m_dt == DATATYPE_VALUETYPE && res.m_fByRef == false) { if(args->IsAReferenceOfThisType( DATATYPE_VALUETYPE )) { TINYCLR_CHECK_HRESULT(g_CLR_RT_ExecutionEngine.CloneObject( *args, *args )); } } } } TINYCLR_NOCLEANUP(); }