/* This is not the same functionality as System.Array.IndexOf. CLR_RT_HeapBlock_Array::IndexOf does the search analogous to calling Object.ReferenceEquals, not Object.Equals, as System.Array.IndexOf demands. This function is used by TrySzIndexOf */ HRESULT CLR_RT_HeapBlock_Array::IndexOf( CLR_RT_HeapBlock_Array* array, CLR_RT_HeapBlock& match, int start, int stop, bool fForward, int& index ) { NATIVE_PROFILE_CLR_CORE(); TINYCLR_HEADER(); int numElem = array->m_numOfElements; int count; if(stop == -1) stop = numElem; count = stop - start; if(CheckRange( start, count, numElem ) == false) TINYCLR_SET_AND_LEAVE(CLR_E_OUT_OF_RANGE); if(count > 0) { CLR_UINT8* data = array->GetFirstElement(); CLR_UINT8 sizeElem = array->m_sizeOfElement; int pos; int incr; if(fForward) { pos = start ; incr = 1; } else { pos = stop-1; incr = -1; } data += pos * sizeElem; if(!array->m_fReference) { CLR_RT_HeapBlock* matchPtr = match.FixBoxingReference(); FAULT_ON_NULL(matchPtr); if(matchPtr->DataType() <= DATATYPE_LAST_PRIMITIVE) { int incrElem = incr * sizeElem; while(true) { #if !defined(BIG_ENDIAN) if(memcmp( data, &matchPtr->NumericByRef(), sizeElem ) == 0) { index = pos; TINYCLR_SET_AND_LEAVE(S_OK); } #else CLR_UINT64 refNum; switch(sizeElem) { case 1: refNum = matchPtr->NumericByRef().u1; break; case 2: refNum = matchPtr->NumericByRef().u2; break; case 4: refNum = matchPtr->NumericByRef().u4; break; case 8: refNum = matchPtr->NumericByRef().u8; break; } if(memcmp( data, &refNum, sizeElem ) == 0) { index = pos; TINYCLR_SET_AND_LEAVE(S_OK); } #endif if(--count == 0) break; pos += incr; data += incrElem; } } } else { CLR_RT_HeapBlock* dataPtr = (CLR_RT_HeapBlock*)data; while(true) { if(CLR_RT_HeapBlock::Compare_Unsigned_Values( *dataPtr, match ) == 0) { index = pos; TINYCLR_SET_AND_LEAVE(S_OK); } if(--count == 0) break; pos += incr; dataPtr += incr; } } } index = -1; TINYCLR_NOCLEANUP(); }
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(); }