| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697 |
- //-------------------------------------------------------------------------------------------------------
- // Copyright (C) Microsoft. All rights reserved.
- // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
- //-------------------------------------------------------------------------------------------------------
- #pragma once
- namespace Js
- {
- template <typename Key, bool zero>
- struct SameValueComparerCommon
- {
- static bool Equals(Key, Key) { static_assert(false, "Can only use SameValueComparer with Var as the key type"); }
- static hash_t GetHashCode(Key) { static_assert(false, "Can only use SameValueComparer with Var as the key type"); }
- };
- template <typename Key> using SameValueComparer = SameValueComparerCommon<Key, false>;
- template <typename Key> using SameValueZeroComparer = SameValueComparerCommon<Key, true>;
- template <bool zero>
- struct SameValueComparerCommon<Var, zero>
- {
- static bool Equals(Var x, Var y)
- {
- if (zero)
- {
- return JavascriptConversion::SameValueZero(x, y);
- }
- else
- {
- return JavascriptConversion::SameValue(x, y);
- }
- }
- static hash_t HashDouble(double d)
- {
- if (JavascriptNumber::IsNan(d))
- {
- return 0;
- }
- if (zero)
- {
- // SameValueZero treats -0 and +0 the same, so normalize to get same hash code
- if (JavascriptNumber::IsNegZero(d))
- {
- d = 0.0;
- }
- }
- __int64 v = *(__int64*)&d;
- return (uint)v ^ (uint)(v >> 32);
- }
- static hash_t GetHashCode(Var i)
- {
- switch (JavascriptOperators::GetTypeId(i))
- {
- case TypeIds_Integer:
- // int32 can be fully represented in a double, so hash it as a double
- // to ensure that tagged ints hash to the same value as JavascriptNumbers.
- return HashDouble((double)TaggedInt::ToInt32(i));
- case TypeIds_Int64Number:
- case TypeIds_UInt64Number:
- {
- __int64 v = VarTo<JavascriptInt64Number>(i)->GetValue();
- double d = (double) v;
- if (v != (__int64) d)
- {
- // this int64 is too large to represent in a double
- // and thus will never be equal to a double so hash it
- // as an int64
- return (uint)v ^ (uint)(v >> 32);
- }
- // otherwise hash it as a double
- return HashDouble(d);
- }
- case TypeIds_Number:
- {
- double d = JavascriptNumber::GetValue(i);
- return HashDouble(d);
- }
- case TypeIds_String:
- {
- JavascriptString* v = UnsafeVarTo<JavascriptString>(i);
- return JsUtil::CharacterBuffer<WCHAR>::StaticGetHashCode(v->GetString(), v->GetLength());
- }
- default:
- return RecyclerPointerComparer<Var>::GetHashCode(i);
- }
- }
- };
- }
|