Index: runtime/lib/function.cc |
diff --git a/runtime/lib/function.cc b/runtime/lib/function.cc |
index cf6e29813f2795baaafb582b6969b5f1d8f29bae..e87914aac7174d882f4afce7ba6bc18151ee9068 100644 |
--- a/runtime/lib/function.cc |
+++ b/runtime/lib/function.cc |
@@ -68,11 +68,30 @@ DEFINE_NATIVE_ENTRY(Closure_equals, 2) { |
return Bool::False().raw(); |
} |
-DEFINE_NATIVE_ENTRY(Closure_hashCode, 1) { |
+DEFINE_NATIVE_ENTRY(Closure_calculateHashCode, 1) { |
rmacnak
2017/07/19 01:00:24
computeHash
(Compare String and Type)
alexmarkov
2017/07/19 17:54:19
Done.
|
const Closure& receiver = |
Closure::CheckedHandle(zone, arguments->NativeArgAt(0)); |
const Function& func = Function::Handle(zone, receiver.function()); |
- return func.GetClosureHashCode(); |
+ intptr_t result = func.GetClosureHashCode(); |
+ if (func.IsImplicitInstanceClosureFunction()) { |
+ // Calculate identityHashCode of cached closure receiver and |
+ // combine it with function's hash code. |
+ const Context& context = Context::Handle(zone, receiver.context()); |
+ const Object& recv = Object::Handle(zone, context.At(0)); |
+ ASSERT(recv.IsInstance()); |
+ const Object& recvHash = |
+ Object::Handle(zone, Instance::Cast(recv).IdentityHashCode()); |
+ if (recvHash.IsInteger()) { |
+ result = result ^ static_cast<intptr_t>( |
rmacnak
2017/07/19 01:00:24
Please use CombineHashes and FinalizeHash
alexmarkov
2017/07/19 17:54:19
Done.
|
+ Integer::Cast(recvHash).AsTruncatedInt64Value()); |
+ } |
+ } |
+ // Finalize hash value like for strings so that it fits into a smi. |
+ result += result << 3; |
+ result ^= result >> 11; |
+ result += result << 15; |
+ result &= ((static_cast<intptr_t>(1) << String::kHashBits) - 1); |
+ return Smi::New(result); |
} |
DEFINE_NATIVE_ENTRY(Closure_clone, 1) { |