diff --git a/src/vm/comutilnative.cpp b/src/vm/comutilnative.cpp index c4563992b728..0b2d8d896811 100644 --- a/src/vm/comutilnative.cpp +++ b/src/vm/comutilnative.cpp @@ -2058,7 +2058,8 @@ static INT32 RegularGetValueTypeHashCode(MethodTable *mt, void *pObjRef) } CONTRACTL_END; INT32 hashCode = 0; - INT32 *pObj = (INT32*)pObjRef; + + GCPROTECT_BEGININTERIOR(pObjRef); BOOL canUseFastGetHashCodeHelper = FALSE; if (mt->HasCheckedCanCompareBitsOrUseFastGetHashCode()) @@ -2074,7 +2075,7 @@ static INT32 RegularGetValueTypeHashCode(MethodTable *mt, void *pObjRef) // be able to handle getting the hashcode for an embedded structure whose hashcode is computed by the fast path. if (canUseFastGetHashCodeHelper) { - return FastGetValueTypeHashCodeHelper(mt, pObjRef); + hashCode = FastGetValueTypeHashCodeHelper(mt, pObjRef); } else { @@ -2087,60 +2088,65 @@ static INT32 RegularGetValueTypeHashCode(MethodTable *mt, void *pObjRef) // // check this approximation - we may be losing exact type information ApproxFieldDescIterator fdIterator(mt, ApproxFieldDescIterator::INSTANCE_FIELDS); - INT32 count = (INT32)fdIterator.Count(); - if (count != 0) + FieldDesc *field; + while ((field = fdIterator.Next()) != NULL) { - for (INT32 i = 0; i < count; i++) + _ASSERTE(!field->IsRVA()); + if (field->IsObjRef()) { - FieldDesc *field = fdIterator.Next(); - _ASSERTE(!field->IsRVA()); - void *pFieldValue = (BYTE *)pObj + field->GetOffsetUnsafe(); - if (field->IsObjRef()) + // if we get an object reference we get the hash code out of that + if (*(Object**)((BYTE *)pObjRef + field->GetOffsetUnsafe()) != NULL) { - // if we get an object reference we get the hash code out of that - if (*(Object**)pFieldValue != NULL) - { - - OBJECTREF fieldObjRef = ObjectToOBJECTREF(*(Object **) pFieldValue); - GCPROTECT_BEGIN(fieldObjRef); - - MethodDescCallSite getHashCode(METHOD__OBJECT__GET_HASH_CODE, &fieldObjRef); - - // Make the call. - ARG_SLOT arg[1] = {ObjToArgSlot(fieldObjRef)}; - hashCode = getHashCode.Call_RetI4(arg); - - GCPROTECT_END(); - } - else - { - // null object reference, try next - continue; - } + PREPARE_SIMPLE_VIRTUAL_CALLSITE(METHOD__OBJECT__GET_HASH_CODE, (*(Object**)((BYTE *)pObjRef + field->GetOffsetUnsafe()))); + DECLARE_ARGHOLDER_ARRAY(args, 1); + args[ARGNUM_0] = *(Object**)((BYTE *)pObjRef + field->GetOffsetUnsafe()); + CALL_MANAGED_METHOD(hashCode, INT32, args); } else + { + // null object reference, try next + continue; + } + } + else + { + CorElementType fieldType = field->GetFieldType(); + if (fieldType == ELEMENT_TYPE_R8) + { + PREPARE_NONVIRTUAL_CALLSITE(METHOD__DOUBLE__GET_HASH_CODE); + DECLARE_ARGHOLDER_ARRAY(args, 1); + args[ARGNUM_0] = (BYTE *)pObjRef + field->GetOffsetUnsafe(); + CALL_MANAGED_METHOD(hashCode, INT32, args); + } + else if (fieldType == ELEMENT_TYPE_R4) + { + PREPARE_NONVIRTUAL_CALLSITE(METHOD__SINGLE__GET_HASH_CODE); + DECLARE_ARGHOLDER_ARRAY(args, 1); + args[ARGNUM_0] = (BYTE *)pObjRef + field->GetOffsetUnsafe(); + CALL_MANAGED_METHOD(hashCode, INT32, args); + } + else if (fieldType != ELEMENT_TYPE_VALUETYPE) { UINT fieldSize = field->LoadSize(); - INT32 *pValue = (INT32*)pFieldValue; - CorElementType fieldType = field->GetFieldType(); - if (fieldType != ELEMENT_TYPE_VALUETYPE) - { - for (INT32 j = 0; j < (INT32)(fieldSize / sizeof(INT32)); j++) - hashCode ^= *pValue++; - } - else - { - // got another value type. Get the type - TypeHandle fieldTH = field->LookupFieldTypeHandle(); // the type was loaded already - _ASSERTE(!fieldTH.IsNull()); - hashCode = RegularGetValueTypeHashCode(fieldTH.GetMethodTable(), pValue); - } + INT32 *pValue = (INT32*)((BYTE *)pObjRef + field->GetOffsetUnsafe()); + for (INT32 j = 0; j < (INT32)(fieldSize / sizeof(INT32)); j++) + hashCode ^= *pValue++; + } + else + { + // got another value type. Get the type + TypeHandle fieldTH = field->GetFieldTypeHandleThrowing(); + _ASSERTE(!fieldTH.IsNull()); + hashCode = RegularGetValueTypeHashCode(fieldTH.GetMethodTable(), (BYTE *)pObjRef + field->GetOffsetUnsafe()); } - break; } + break; } } + + GCPROTECT_END(); + return hashCode; } diff --git a/src/vm/mscorlib.h b/src/vm/mscorlib.h index d58e6aa7b548..528f2d9b4124 100644 --- a/src/vm/mscorlib.h +++ b/src/vm/mscorlib.h @@ -661,6 +661,12 @@ DEFINE_METHOD(OBJECT, EQUALS, Equals, DEFINE_METHOD(OBJECT, FIELD_SETTER, FieldSetter, IM_Str_Str_Obj_RetVoid) DEFINE_METHOD(OBJECT, FIELD_GETTER, FieldGetter, IM_Str_Str_RefObj_RetVoid) +// DEFINE_CLASS(DOUBLE, System, Double) +DEFINE_METHOD(DOUBLE, GET_HASH_CODE, GetHashCode, IM_RetInt) + +// DEFINE_CLASS(SINGLE, System, Single) +DEFINE_METHOD(SINGLE, GET_HASH_CODE, GetHashCode, IM_RetInt) + DEFINE_CLASS(__CANON, System, __Canon)