[vm] Fix Instance::IdentityHashCode for strings
This method should return the same value as `String::Hash` to not be misaligned with how `identityHashCode()` is implemented. On 64bit platforms we also use the same location in the object header to store identity hash and string hash so these two can't be misaligned. Fixes https://github.com/dart-lang/sdk/issues/56749 TEST=vm/cc/String,vm/dart/regress_56749 R=rmacnak@google.com Change-Id: I221cc8ad85f7ffb7f7d2bcdd0f4341c3ecf25663 Fixed: 56749 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/385860 Commit-Queue: Slava Egorov <vegorov@google.com> Reviewed-by: Ryan Macnak <rmacnak@google.com>
This commit is contained in:
committed by
Commit Queue
parent
bf36861cb3
commit
bb59b5c72c
@@ -0,0 +1,19 @@
|
||||
// Copyright (c) 2024, the Dart project authors. Please see the AUTHORS file
|
||||
// for details. All rights reserved. Use of this source code is governed by a
|
||||
// BSD-style license that can be found in the LICENSE file.
|
||||
|
||||
import "package:expect/expect.dart";
|
||||
|
||||
void main() {
|
||||
String a = "Hello, world!";
|
||||
String b = a.substring(0, 5) + a.substring(5);
|
||||
|
||||
// `Closure::ComputeHash` will invoke `Instance::IdentityHashCode` on
|
||||
// the receiver (b). Previously this function did not handle String
|
||||
// specially and used a random hash code instead of the expected
|
||||
// content-based hash code.
|
||||
print(b.toString.hashCode);
|
||||
|
||||
Expect.equals(a.hashCode, b.hashCode);
|
||||
Expect.equals(a, b);
|
||||
}
|
||||
@@ -20727,6 +20727,9 @@ ObjectPtr Instance::HashCode() const {
|
||||
// Keep in sync with AsmIntrinsifier::Object_getHash.
|
||||
IntegerPtr Instance::IdentityHashCode(Thread* thread) const {
|
||||
if (IsInteger()) return Integer::Cast(*this).ptr();
|
||||
if (IsString()) {
|
||||
return Smi::New(String::Cast(*this).Hash());
|
||||
}
|
||||
|
||||
#if defined(HASH_IN_OBJECT_HEADER)
|
||||
intptr_t hash = Object::GetCachedHash(ptr());
|
||||
|
||||
@@ -824,6 +824,17 @@ ISOLATE_UNIT_TEST_CASE(String) {
|
||||
EXPECT_EQ(0x7FFF, str16.CharAt(1));
|
||||
EXPECT_EQ(0xFFFF, str16.CharAt(2));
|
||||
}
|
||||
|
||||
// Check that String's identity hash and hashCode are the same.
|
||||
{
|
||||
for (auto str : {"Hello", "Hell\xC3\x98"}) {
|
||||
const String& s = String::Handle(String::New(str));
|
||||
const String& s2 = String::Handle(String::New(str));
|
||||
EXPECT_EQ(s.Hash(),
|
||||
static_cast<uword>(
|
||||
Integer::Handle(s2.IdentityHashCode(thread)).Value()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ISOLATE_UNIT_TEST_CASE(StringFormat) {
|
||||
|
||||
Reference in New Issue
Block a user