blob: 2fc0dc8990cd212337bb6b76816531dcdaaa867c [file]
//-------------------------------------------------------------------------------------------------------
// 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 = JavascriptInt64Number::FromVar(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 = JavascriptString::FromVar(i);
return JsUtil::CharacterBuffer<WCHAR>::StaticGetHashCode(v->GetString(), v->GetLength());
}
default:
return RecyclerPointerComparer<Var>::GetHashCode(i);
}
}
};
}