} CONTRACTL_END;
INT32 hashCode = 0;
- INT32 *pObj = (INT32*)pObjRef;
+
+ GCPROTECT_BEGININTERIOR(pObjRef);
BOOL canUseFastGetHashCodeHelper = FALSE;
if (mt->HasCheckedCanCompareBitsOrUseFastGetHashCode())
// 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
{
//
// <TODO> check this approximation - we may be losing exact type information </TODO>
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] = PTR_TO_ARGHOLDER(*(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] = PTR_TO_ARGHOLDER(((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] = PTR_TO_ARGHOLDER(((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;
}
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)