[vm] Refactor generation of identity hashes.
Generating identity hashes from the runtime no longer calls into Dart. On 32-bit systems, generating identity hashes from Dart now does only one runtime transition.
TEST=ci
Bug: https://github.com/dart-lang/sdk/issues/47873
Change-Id: Ib21156cb05706f81744eb4e5ccb644f40aa84c96
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/222326
Reviewed-by: Alexander Markov <alexmarkov@google.com>
diff --git a/pkg/front_end/testcases/general/invalid_operator.dart.weak.expect b/pkg/front_end/testcases/general/invalid_operator.dart.weak.expect
index c3f1e06..1bababf 100644
--- a/pkg/front_end/testcases/general/invalid_operator.dart.weak.expect
+++ b/pkg/front_end/testcases/general/invalid_operator.dart.weak.expect
@@ -564,35 +564,35 @@
// Try adding explicit types.
// operator ==<T>(a) => true;
// ^^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is one of the overridden members.
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is one of the overridden members.
// external bool operator ==(Object other);
// ^^
//
// pkg/front_end/testcases/general/invalid_operator.dart:6:12: Error: The method 'Operators1.==' has fewer positional arguments than those of overridden method 'Object.=='.
// operator ==() => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
// pkg/front_end/testcases/general/invalid_operator.dart:27:12: Error: The method 'Operators2.==' has more required arguments than those of overridden method 'Object.=='.
// operator ==(a, b) => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
// pkg/front_end/testcases/general/invalid_operator.dart:71:12: Error: The method 'Operators4.==' has fewer positional arguments than those of overridden method 'Object.=='.
// operator ==({a}) => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
// pkg/front_end/testcases/general/invalid_operator.dart:137:12: Error: Declared type variables of 'Operators7.==' doesn't match those on overridden method 'Object.=='.
// operator ==<T>(a) => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
diff --git a/pkg/front_end/testcases/general/invalid_operator.dart.weak.modular.expect b/pkg/front_end/testcases/general/invalid_operator.dart.weak.modular.expect
index c3f1e06..1bababf 100644
--- a/pkg/front_end/testcases/general/invalid_operator.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/general/invalid_operator.dart.weak.modular.expect
@@ -564,35 +564,35 @@
// Try adding explicit types.
// operator ==<T>(a) => true;
// ^^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is one of the overridden members.
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is one of the overridden members.
// external bool operator ==(Object other);
// ^^
//
// pkg/front_end/testcases/general/invalid_operator.dart:6:12: Error: The method 'Operators1.==' has fewer positional arguments than those of overridden method 'Object.=='.
// operator ==() => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
// pkg/front_end/testcases/general/invalid_operator.dart:27:12: Error: The method 'Operators2.==' has more required arguments than those of overridden method 'Object.=='.
// operator ==(a, b) => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
// pkg/front_end/testcases/general/invalid_operator.dart:71:12: Error: The method 'Operators4.==' has fewer positional arguments than those of overridden method 'Object.=='.
// operator ==({a}) => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
// pkg/front_end/testcases/general/invalid_operator.dart:137:12: Error: Declared type variables of 'Operators7.==' doesn't match those on overridden method 'Object.=='.
// operator ==<T>(a) => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
diff --git a/pkg/front_end/testcases/general/invalid_operator.dart.weak.outline.expect b/pkg/front_end/testcases/general/invalid_operator.dart.weak.outline.expect
index c1ee228..c9f7e40 100644
--- a/pkg/front_end/testcases/general/invalid_operator.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/general/invalid_operator.dart.weak.outline.expect
@@ -564,35 +564,35 @@
// Try adding explicit types.
// operator ==<T>(a) => true;
// ^^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is one of the overridden members.
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is one of the overridden members.
// external bool operator ==(Object other);
// ^^
//
// pkg/front_end/testcases/general/invalid_operator.dart:6:12: Error: The method 'Operators1.==' has fewer positional arguments than those of overridden method 'Object.=='.
// operator ==() => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
// pkg/front_end/testcases/general/invalid_operator.dart:27:12: Error: The method 'Operators2.==' has more required arguments than those of overridden method 'Object.=='.
// operator ==(a, b) => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
// pkg/front_end/testcases/general/invalid_operator.dart:71:12: Error: The method 'Operators4.==' has fewer positional arguments than those of overridden method 'Object.=='.
// operator ==({a}) => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
// pkg/front_end/testcases/general/invalid_operator.dart:137:12: Error: Declared type variables of 'Operators7.==' doesn't match those on overridden method 'Object.=='.
// operator ==<T>(a) => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
diff --git a/pkg/front_end/testcases/nnbd/issue42603.dart.strong.expect b/pkg/front_end/testcases/nnbd/issue42603.dart.strong.expect
index 1717f29..7d802ac 100644
--- a/pkg/front_end/testcases/nnbd/issue42603.dart.strong.expect
+++ b/pkg/front_end/testcases/nnbd/issue42603.dart.strong.expect
@@ -9,7 +9,7 @@
// pkg/front_end/testcases/nnbd/issue42603.dart:18:17: Error: The method 'E.==' has fewer positional arguments than those of overridden method 'Object.=='.
// bool operator ==() => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
diff --git a/pkg/front_end/testcases/nnbd/issue42603.dart.weak.expect b/pkg/front_end/testcases/nnbd/issue42603.dart.weak.expect
index 1717f29..7d802ac 100644
--- a/pkg/front_end/testcases/nnbd/issue42603.dart.weak.expect
+++ b/pkg/front_end/testcases/nnbd/issue42603.dart.weak.expect
@@ -9,7 +9,7 @@
// pkg/front_end/testcases/nnbd/issue42603.dart:18:17: Error: The method 'E.==' has fewer positional arguments than those of overridden method 'Object.=='.
// bool operator ==() => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
diff --git a/pkg/front_end/testcases/nnbd/issue42603.dart.weak.modular.expect b/pkg/front_end/testcases/nnbd/issue42603.dart.weak.modular.expect
index 1717f29..7d802ac 100644
--- a/pkg/front_end/testcases/nnbd/issue42603.dart.weak.modular.expect
+++ b/pkg/front_end/testcases/nnbd/issue42603.dart.weak.modular.expect
@@ -9,7 +9,7 @@
// pkg/front_end/testcases/nnbd/issue42603.dart:18:17: Error: The method 'E.==' has fewer positional arguments than those of overridden method 'Object.=='.
// bool operator ==() => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
diff --git a/pkg/front_end/testcases/nnbd/issue42603.dart.weak.outline.expect b/pkg/front_end/testcases/nnbd/issue42603.dart.weak.outline.expect
index f1a33e9..390818a 100644
--- a/pkg/front_end/testcases/nnbd/issue42603.dart.weak.outline.expect
+++ b/pkg/front_end/testcases/nnbd/issue42603.dart.weak.outline.expect
@@ -9,7 +9,7 @@
// pkg/front_end/testcases/nnbd/issue42603.dart:18:17: Error: The method 'E.==' has fewer positional arguments than those of overridden method 'Object.=='.
// bool operator ==() => true;
// ^
-// sdk/lib/_internal/vm/lib/object_patch.dart:29:26: Context: This is the overridden method ('==').
+// sdk/lib/_internal/vm/lib/object_patch.dart:21:26: Context: This is the overridden method ('==').
// external bool operator ==(Object other);
// ^
//
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
index 8964972..ebc13da 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/enum_from_lib_used_as_type.dart.expect
@@ -22,6 +22,6 @@
synthetic constructor •() → self::Class
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3305,getterSelectorId:3306] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3303,getterSelectorId:3304] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::Enum e) → core::int
return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
}
diff --git a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
index 7251a55..d0ed61e 100644
--- a/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
+++ b/pkg/vm/testcases/transformations/type_flow/transformer/tree_shake_enum_from_lib.dart.expect
@@ -51,6 +51,6 @@
synthetic constructor •() → self::ConstClass
: super core::Object::•()
;
-[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3309,getterSelectorId:3310] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
+[@vm.procedure-attributes.metadata=methodOrSetterCalledDynamically:false,getterCalledDynamically:false,hasThisUses:false,hasTearOffUses:false,methodOrSetterSelectorId:3307,getterSelectorId:3308] method method([@vm.inferred-type.metadata=dart.core::Null? (value: null)] self::ConstEnum e) → core::int
return [@vm.inferred-type.metadata=!] e.{core::_Enum::index}{core::int};
}
diff --git a/runtime/lib/object.cc b/runtime/lib/object.cc
index f8e903e..2b7a470 100644
--- a/runtime/lib/object.cc
+++ b/runtime/lib/object.cc
@@ -48,20 +48,14 @@
// Please note that no handle is created for the argument.
// This is safe since the argument is only used in a tail call.
// The performance benefit is more than 5% when using hashCode.
- return Smi::New(GetHash(isolate, arguments->NativeArgAt(0)));
-}
+ intptr_t hash = GetHash(isolate, arguments->NativeArgAt(0));
+ if (LIKELY(hash != 0)) {
+ return Smi::New(hash);
+ }
-DEFINE_NATIVE_ENTRY(Object_setHashIfNotSetYet, 0, 2) {
- GET_NON_NULL_NATIVE_ARGUMENT(Smi, hash, arguments->NativeArgAt(1));
-#if defined(HASH_IN_OBJECT_HEADER)
- return Smi::New(
- Object::SetCachedHashIfNotSet(arguments->NativeArgAt(0), hash.Value()));
-#else
const Instance& instance =
Instance::CheckedHandle(zone, arguments->NativeArgAt(0));
- Heap* heap = thread->heap();
- return Smi::New(heap->SetHashIfNotSet(instance.ptr(), hash.Value()));
-#endif
+ return instance.IdentityHashCode(arguments->thread());
}
DEFINE_NATIVE_ENTRY(Object_toString, 0, 1) {
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index adade03..50e587f 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -18,7 +18,6 @@
V(DartAsync_fatal, 1) \
V(Object_equals, 2) \
V(Object_getHash, 1) \
- V(Object_setHashIfNotSetYet, 2) \
V(Object_toString, 1) \
V(Object_runtimeType, 1) \
V(Object_haveSameRuntimeType, 2) \
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
index b61046d..e811039 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -1548,11 +1548,6 @@
UNREACHABLE();
}
-void AsmIntrinsifier::Object_setHashIfNotSetYet(Assembler* assembler,
- Label* normal_ir_body) {
- UNREACHABLE();
-}
-
void AsmIntrinsifier::StringBaseCharAt(Assembler* assembler,
Label* normal_ir_body) {
Label try_two_byte_string;
diff --git a/runtime/vm/compiler/asm_intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
index b6796b5..f9c178a 100644
--- a/runtime/vm/compiler/asm_intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -1578,21 +1578,37 @@
__ Bind(normal_ir_body);
}
+// Keep in sync with Instance::IdentityHashCode.
+// Note int and double never reach here because they override _identityHashCode.
+// Special cases are also not needed for null or bool because they were pre-set
+// during VM isolate finalization.
void AsmIntrinsifier::Object_getHash(Assembler* assembler,
Label* normal_ir_body) {
- __ ldr(R0, Address(SP, 0 * target::kWordSize));
- __ ldr(R0, FieldAddress(R0, target::String::hash_offset(), kFourBytes),
+ Label not_yet_computed;
+ __ ldr(R0, Address(SP, 0 * target::kWordSize)); // Object.
+ __ ldr(R0,
+ FieldAddress(R0,
+ target::Object::tags_offset() +
+ target::UntaggedObject::kHashTagPos / kBitsPerByte,
+ kFourBytes),
kUnsignedFourBytes);
+ __ cbz(¬_yet_computed, R0);
__ SmiTag(R0);
__ ret();
-}
-void AsmIntrinsifier::Object_setHashIfNotSetYet(Assembler* assembler,
- Label* normal_ir_body) {
- __ ldp(/*Value=*/R1, /*Object=*/R0, Address(SP, 0, Address::PairOffset));
- // R0: Untagged address of header word (ldxr/stxr do not support offsets).
+ __ Bind(¬_yet_computed);
+ __ LoadFromOffset(R1, THR, target::Thread::random_offset());
+ __ AndImmediate(R2, R1, 0xffffffff); // state_lo
+ __ LsrImmediate(R3, R1, 32); // state_hi
+ __ LoadImmediate(R1, 0xffffda61); // A
+ __ mul(R1, R1, R2);
+ __ add(R1, R1, Operand(R3)); // new_state = (A * state_lo) + state_hi
+ __ StoreToOffset(R1, THR, target::Thread::random_offset());
+ __ AndImmediate(R1, R1, 0x3fffffff);
+ __ cbz(¬_yet_computed, R1);
+
+ __ ldr(R0, Address(SP, 0 * target::kWordSize)); // Object.
__ sub(R0, R0, Operand(kHeapObjectTag));
- __ SmiUntag(R1);
__ LslImmediate(R3, R1, target::UntaggedObject::kHashTagPos);
Label retry, already_set_in_r4;
diff --git a/runtime/vm/compiler/asm_intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
index 0c58ca7..341c285 100644
--- a/runtime/vm/compiler/asm_intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -1555,11 +1555,6 @@
UNREACHABLE();
}
-void AsmIntrinsifier::Object_setHashIfNotSetYet(Assembler* assembler,
- Label* normal_ir_body) {
- UNREACHABLE();
-}
-
void AsmIntrinsifier::StringBaseCharAt(Assembler* assembler,
Label* normal_ir_body) {
Label try_two_byte_string;
diff --git a/runtime/vm/compiler/asm_intrinsifier_test.cc b/runtime/vm/compiler/asm_intrinsifier_test.cc
index e5678ee..fb112f1 100644
--- a/runtime/vm/compiler/asm_intrinsifier_test.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_test.cc
@@ -10,78 +10,4 @@
namespace dart {
-static intptr_t GetHash(Isolate* isolate, const ObjectPtr obj) {
-#if defined(HASH_IN_OBJECT_HEADER)
- return Object::GetCachedHash(obj);
-#else
- Heap* heap = isolate->group()->heap();
- ASSERT(obj->IsDartInstance());
- return heap->GetHash(obj);
-#endif
-}
-
-ISOLATE_UNIT_TEST_CASE(AsmIntrinsifier_SetHashIfNotSetYet) {
- auto I = Isolate::Current();
- const auto& corelib = Library::Handle(Library::CoreLibrary());
- const auto& name = String::Handle(String::New("_setHashIfNotSetYet"));
- const auto& symbol = String::Handle(Symbols::New(thread, name));
-
- const auto& function =
- Function::Handle(corelib.LookupFunctionAllowPrivate(symbol));
- const auto& object_class =
- Class::Handle(corelib.LookupClass(Symbols::Object()));
-
- auto& smi0 = Smi::Handle(Smi::New(0));
- auto& smi21 = Smi::Handle(Smi::New(21));
- auto& smi42 = Smi::Handle(Smi::New(42));
- const auto& obj = Object::Handle(Instance::New(object_class));
- const auto& args = Array::Handle(Array::New(2));
-
- const auto& args_descriptor_array =
- Array::Handle(ArgumentsDescriptor::NewBoxed(0, 2, Array::empty_array()));
-
- // Initialized to 0
- EXPECT_EQ(smi0.ptr(), Smi::New(GetHash(I, obj.ptr())));
-
- // Lazily set to 42 on first call.
- args.SetAt(0, obj);
- args.SetAt(1, smi42);
- EXPECT_EQ(smi42.ptr(),
- DartEntry::InvokeFunction(function, args, args_descriptor_array));
- EXPECT_EQ(smi42.ptr(), Smi::New(GetHash(I, obj.ptr())));
-
- // Stays at 42 on subsequent calls.
- args.SetAt(0, obj);
- args.SetAt(1, smi21);
- EXPECT_EQ(smi42.ptr(),
- DartEntry::InvokeFunction(function, args, args_descriptor_array));
- EXPECT_EQ(smi42.ptr(), Smi::New(GetHash(I, obj.ptr())));
-
- // We test setting the maximum value our core libraries would use when
- // installing an identity hash code (see
- // sdk/lib/_internal/vm/lib/object_patch.dart:Object._objectHashCode)
- //
- // This value is representable as a positive Smi on all architectures (even
- // compressed pointers).
- const auto& smiMax = Smi::Handle(Smi::New(0x40000000 - 1));
- const auto& obj2 = Object::Handle(Instance::New(object_class));
-
- // Initialized to 0
- EXPECT_EQ(smi0.ptr(), Smi::New(GetHash(I, obj2.ptr())));
-
- // Lazily set to smiMax first call.
- args.SetAt(0, obj2);
- args.SetAt(1, smiMax);
- EXPECT_EQ(smiMax.ptr(),
- DartEntry::InvokeFunction(function, args, args_descriptor_array));
- EXPECT_EQ(smiMax.ptr(), Smi::New(GetHash(I, obj2.ptr())));
-
- // Stays at smiMax on subsequent calls.
- args.SetAt(0, obj2);
- args.SetAt(1, smi21);
- EXPECT_EQ(smiMax.ptr(),
- DartEntry::InvokeFunction(function, args, args_descriptor_array));
- EXPECT_EQ(smiMax.ptr(), Smi::New(GetHash(I, obj2.ptr())));
-}
-
} // namespace dart
diff --git a/runtime/vm/compiler/asm_intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
index c4e02a9..e2f7b24 100644
--- a/runtime/vm/compiler/asm_intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -1452,21 +1452,35 @@
__ Bind(normal_ir_body);
}
+// Keep in sync with Instance::IdentityHashCode.
+// Note int and double never reach here because they override _identityHashCode.
+// Special cases are also not needed for null or bool because they were pre-set
+// during VM isolate finalization.
void AsmIntrinsifier::Object_getHash(Assembler* assembler,
Label* normal_ir_body) {
+ Label not_yet_computed;
__ movq(RAX, Address(RSP, +1 * target::kWordSize)); // Object.
- __ movl(RAX, FieldAddress(RAX, target::String::hash_offset()));
+ __ movl(RAX, FieldAddress(RAX, target::Object::tags_offset() +
+ target::UntaggedObject::kHashTagPos /
+ kBitsPerByte));
+ __ cmpl(RAX, Immediate(0));
+ __ j(EQUAL, ¬_yet_computed, Assembler::kNearJump);
__ SmiTag(RAX);
__ ret();
-}
-void AsmIntrinsifier::Object_setHashIfNotSetYet(Assembler* assembler,
- Label* normal_ir_body) {
- ASSERT(target::String::hash_offset() == 4);
+ __ Bind(¬_yet_computed);
+ __ movq(RCX, Address(THR, target::Thread::random_offset()));
+ __ movq(RBX, RCX);
+ __ andq(RCX, Immediate(0xffffffff)); // state_lo
+ __ shrq(RBX, Immediate(32)); // state_hi
+ __ imulq(RCX, Immediate(0xffffda61)); // A
+ __ addq(RCX, RBX); // new_state = (A* state_lo) + state_hi
+ __ movq(Address(THR, target::Thread::random_offset()), RCX);
+ __ andq(RCX, Immediate(0x3fffffff));
+ __ cmpl(RCX, Immediate(0));
+ __ j(EQUAL, ¬_yet_computed);
- __ movq(RBX, Address(RSP, +2 * target::kWordSize)); // Object.
- __ movq(RCX, Address(RSP, +1 * target::kWordSize)); // Value.
- __ SmiUntag(RCX);
+ __ movq(RBX, Address(RSP, +1 * target::kWordSize)); // Object.
__ MoveRegister(RDX, RCX);
__ shlq(RDX, Immediate(32));
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index 4ba80d9f..072e8ca 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -275,9 +275,7 @@
// identity hash is not stored in the header of the object. We
// therefore don't intrinsify them, falling back on the native C++
// implementations.
- if (function.recognized_kind() == MethodRecognizer::kObject_getHash ||
- function.recognized_kind() ==
- MethodRecognizer::kObject_setHashIfNotSetYet) {
+ if (function.recognized_kind() == MethodRecognizer::kObject_getHash) {
return false;
}
#endif
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
index 2d60271..e2f2083 100644
--- a/runtime/vm/compiler/recognized_methods_list.h
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -290,7 +290,6 @@
V(_FunctionType, get:hashCode, FunctionType_getHashCode, 0x75e0d454) \
V(_FunctionType, ==, FunctionType_equality, 0x465868ae) \
V(::, _getHash, Object_getHash, 0xc60ff758) \
- V(::, _setHashIfNotSetYet, Object_setHashIfNotSetYet, 0x4e17c2f5) \
#define CORE_INTEGER_LIB_INTRINSIC_LIST(V) \
V(_IntegerImplementation, >, Integer_greaterThan, 0xf741693b) \
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index abb824d..bc2daf8 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -99,7 +99,7 @@
intptr_t ObjectHash(const Object& obj) {
if (obj.IsNull()) {
- return 2011;
+ return kNullIdentityHash;
}
if (obj.IsInstance()) {
return Instance::Cast(obj).CanonicalizeHash();
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 8d9a7a1..1cdca3d 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -1192,6 +1192,8 @@
THREAD_XMM_CONSTANT_LIST(DECLARE_CONSTANT_OFFSET_GETTER)
#undef DECLARE_CONSTANT_OFFSET_GETTER
+ static word random_offset();
+
static word OffsetFromThread(const dart::Object& object);
static intptr_t OffsetFromThread(const dart::RuntimeEntry* runtime_entry);
};
diff --git a/runtime/vm/compiler/runtime_offsets_extracted.h b/runtime/vm/compiler/runtime_offsets_extracted.h
index 2a33ea5..5c98bc9 100644
--- a/runtime/vm/compiler/runtime_offsets_extracted.h
+++ b/runtime/vm/compiler/runtime_offsets_extracted.h
@@ -286,7 +286,7 @@
Thread_call_to_runtime_entry_point_offset = 276;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 144;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 808;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 816;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 44;
static constexpr dart::compiler::target::word
@@ -332,7 +332,7 @@
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
788;
static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 812;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 820;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
64;
static constexpr dart::compiler::target::word
@@ -417,9 +417,10 @@
static constexpr dart::compiler::target::word Thread_callback_code_offset = 780;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 784;
+static constexpr dart::compiler::target::word Thread_random_offset = 800;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 328;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 800;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 808;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -851,7 +852,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -898,7 +899,7 @@
1576;
static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1624;
+ 1632;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
128;
static constexpr dart::compiler::target::word
@@ -984,9 +985,10 @@
1560;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 1568;
+static constexpr dart::compiler::target::word Thread_random_offset = 1600;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1600;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1608;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -1416,7 +1418,7 @@
Thread_call_to_runtime_entry_point_offset = 276;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 144;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 776;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 784;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 44;
static constexpr dart::compiler::target::word
@@ -1462,7 +1464,7 @@
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
756;
static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 780;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 788;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
64;
static constexpr dart::compiler::target::word
@@ -1547,9 +1549,10 @@
static constexpr dart::compiler::target::word Thread_callback_code_offset = 748;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 752;
+static constexpr dart::compiler::target::word Thread_random_offset = 768;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 328;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 768;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 776;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -1978,7 +1981,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1680;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1688;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -2025,7 +2028,7 @@
1640;
static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1688;
+ 1696;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
128;
static constexpr dart::compiler::target::word
@@ -2111,9 +2114,10 @@
1624;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 1632;
+static constexpr dart::compiler::target::word Thread_random_offset = 1664;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1664;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1672;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -2547,7 +2551,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -2594,7 +2598,7 @@
1576;
static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1624;
+ 1632;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
128;
static constexpr dart::compiler::target::word
@@ -2680,9 +2684,10 @@
1560;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 1568;
+static constexpr dart::compiler::target::word Thread_random_offset = 1600;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1600;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1608;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -3115,7 +3120,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1680;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1688;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -3162,7 +3167,7 @@
1640;
static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1688;
+ 1696;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
128;
static constexpr dart::compiler::target::word
@@ -3248,9 +3253,10 @@
1624;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 1632;
+static constexpr dart::compiler::target::word Thread_random_offset = 1664;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1664;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1672;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -3677,7 +3683,7 @@
Thread_call_to_runtime_entry_point_offset = 276;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 144;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 808;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 816;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 44;
static constexpr dart::compiler::target::word
@@ -3723,7 +3729,7 @@
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
788;
static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 812;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 820;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
64;
static constexpr dart::compiler::target::word
@@ -3808,9 +3814,10 @@
static constexpr dart::compiler::target::word Thread_callback_code_offset = 780;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 784;
+static constexpr dart::compiler::target::word Thread_random_offset = 800;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 328;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 800;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 808;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -4236,7 +4243,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -4283,7 +4290,7 @@
1576;
static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1624;
+ 1632;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
128;
static constexpr dart::compiler::target::word
@@ -4369,9 +4376,10 @@
1560;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 1568;
+static constexpr dart::compiler::target::word Thread_random_offset = 1600;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1600;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1608;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -4795,7 +4803,7 @@
Thread_call_to_runtime_entry_point_offset = 276;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 144;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 776;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 784;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 44;
static constexpr dart::compiler::target::word
@@ -4841,7 +4849,7 @@
static constexpr dart::compiler::target::word Thread_exit_through_ffi_offset =
756;
static constexpr dart::compiler::target::word Thread_isolate_offset = 40;
-static constexpr dart::compiler::target::word Thread_isolate_group_offset = 780;
+static constexpr dart::compiler::target::word Thread_isolate_group_offset = 788;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
64;
static constexpr dart::compiler::target::word
@@ -4926,9 +4934,10 @@
static constexpr dart::compiler::target::word Thread_callback_code_offset = 748;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 752;
+static constexpr dart::compiler::target::word Thread_random_offset = 768;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 328;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 768;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 776;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -5351,7 +5360,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1680;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1688;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -5398,7 +5407,7 @@
1640;
static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1688;
+ 1696;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
128;
static constexpr dart::compiler::target::word
@@ -5484,9 +5493,10 @@
1624;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 1632;
+static constexpr dart::compiler::target::word Thread_random_offset = 1664;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1664;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1672;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -5914,7 +5924,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1616;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1624;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -5961,7 +5971,7 @@
1576;
static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1624;
+ 1632;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
128;
static constexpr dart::compiler::target::word
@@ -6047,9 +6057,10 @@
1560;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 1568;
+static constexpr dart::compiler::target::word Thread_random_offset = 1600;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1600;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1608;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -6476,7 +6487,7 @@
Thread_call_to_runtime_entry_point_offset = 528;
static constexpr dart::compiler::target::word
Thread_call_to_runtime_stub_offset = 264;
-static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1680;
+static constexpr dart::compiler::target::word Thread_dart_stream_offset = 1688;
static constexpr dart::compiler::target::word
Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -6523,7 +6534,7 @@
1640;
static constexpr dart::compiler::target::word Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word Thread_isolate_group_offset =
- 1688;
+ 1696;
static constexpr dart::compiler::target::word Thread_field_table_values_offset =
128;
static constexpr dart::compiler::target::word
@@ -6609,9 +6620,10 @@
1624;
static constexpr dart::compiler::target::word
Thread_callback_stack_return_offset = 1632;
+static constexpr dart::compiler::target::word Thread_random_offset = 1664;
static constexpr dart::compiler::target::word
Thread_jump_to_frame_entry_point_offset = 632;
-static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1664;
+static constexpr dart::compiler::target::word Thread_tsan_utils_offset = 1672;
static constexpr dart::compiler::target::word TsanUtils_setjmp_function_offset =
0;
static constexpr dart::compiler::target::word TsanUtils_setjmp_buffer_offset =
@@ -7078,7 +7090,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 144;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 808;
+ 816;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 44;
static constexpr dart::compiler::target::word
@@ -7126,7 +7138,7 @@
AOT_Thread_exit_through_ffi_offset = 788;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 812;
+ 820;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 64;
static constexpr dart::compiler::target::word
@@ -7216,10 +7228,11 @@
780;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 784;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 800;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 328;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 800;
+ 808;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
@@ -7707,7 +7720,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1616;
+ 1624;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -7755,7 +7768,7 @@
AOT_Thread_exit_through_ffi_offset = 1576;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1624;
+ 1632;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 128;
static constexpr dart::compiler::target::word
@@ -7846,10 +7859,11 @@
1560;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 1568;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1600;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 632;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 1600;
+ 1608;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
@@ -8342,7 +8356,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1680;
+ 1688;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -8390,7 +8404,7 @@
AOT_Thread_exit_through_ffi_offset = 1640;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1688;
+ 1696;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 128;
static constexpr dart::compiler::target::word
@@ -8481,10 +8495,11 @@
1624;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 1632;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1664;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 632;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 1664;
+ 1672;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
@@ -8974,7 +8989,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1616;
+ 1624;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -9022,7 +9037,7 @@
AOT_Thread_exit_through_ffi_offset = 1576;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1624;
+ 1632;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 128;
static constexpr dart::compiler::target::word
@@ -9113,10 +9128,11 @@
1560;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 1568;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1600;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 632;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 1600;
+ 1608;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
@@ -9605,7 +9621,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1680;
+ 1688;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -9653,7 +9669,7 @@
AOT_Thread_exit_through_ffi_offset = 1640;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1688;
+ 1696;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 128;
static constexpr dart::compiler::target::word
@@ -9744,10 +9760,11 @@
1624;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 1632;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1664;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 632;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 1664;
+ 1672;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
@@ -10232,7 +10249,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 144;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 808;
+ 816;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 44;
static constexpr dart::compiler::target::word
@@ -10280,7 +10297,7 @@
AOT_Thread_exit_through_ffi_offset = 788;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 40;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 812;
+ 820;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 64;
static constexpr dart::compiler::target::word
@@ -10370,10 +10387,11 @@
780;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 784;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 800;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 328;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 800;
+ 808;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
@@ -10854,7 +10872,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1616;
+ 1624;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -10902,7 +10920,7 @@
AOT_Thread_exit_through_ffi_offset = 1576;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1624;
+ 1632;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 128;
static constexpr dart::compiler::target::word
@@ -10993,10 +11011,11 @@
1560;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 1568;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1600;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 632;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 1600;
+ 1608;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
@@ -11482,7 +11501,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1680;
+ 1688;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -11530,7 +11549,7 @@
AOT_Thread_exit_through_ffi_offset = 1640;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1688;
+ 1696;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 128;
static constexpr dart::compiler::target::word
@@ -11621,10 +11640,11 @@
1624;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 1632;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1664;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 632;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 1664;
+ 1672;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
@@ -12107,7 +12127,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1616;
+ 1624;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -12155,7 +12175,7 @@
AOT_Thread_exit_through_ffi_offset = 1576;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1624;
+ 1632;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 128;
static constexpr dart::compiler::target::word
@@ -12246,10 +12266,11 @@
1560;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 1568;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1600;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 632;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 1600;
+ 1608;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
@@ -12731,7 +12752,7 @@
static constexpr dart::compiler::target::word
AOT_Thread_call_to_runtime_stub_offset = 264;
static constexpr dart::compiler::target::word AOT_Thread_dart_stream_offset =
- 1680;
+ 1688;
static constexpr dart::compiler::target::word
AOT_Thread_dispatch_table_array_offset = 88;
static constexpr dart::compiler::target::word
@@ -12779,7 +12800,7 @@
AOT_Thread_exit_through_ffi_offset = 1640;
static constexpr dart::compiler::target::word AOT_Thread_isolate_offset = 80;
static constexpr dart::compiler::target::word AOT_Thread_isolate_group_offset =
- 1688;
+ 1696;
static constexpr dart::compiler::target::word
AOT_Thread_field_table_values_offset = 128;
static constexpr dart::compiler::target::word
@@ -12870,10 +12891,11 @@
1624;
static constexpr dart::compiler::target::word
AOT_Thread_callback_stack_return_offset = 1632;
+static constexpr dart::compiler::target::word AOT_Thread_random_offset = 1664;
static constexpr dart::compiler::target::word
AOT_Thread_jump_to_frame_entry_point_offset = 632;
static constexpr dart::compiler::target::word AOT_Thread_tsan_utils_offset =
- 1664;
+ 1672;
static constexpr dart::compiler::target::word
AOT_TsanUtils_setjmp_function_offset = 0;
static constexpr dart::compiler::target::word
diff --git a/runtime/vm/compiler/runtime_offsets_list.h b/runtime/vm/compiler/runtime_offsets_list.h
index d0264eb..71cc428 100644
--- a/runtime/vm/compiler/runtime_offsets_list.h
+++ b/runtime/vm/compiler/runtime_offsets_list.h
@@ -286,6 +286,7 @@
FIELD(Thread, heap_base_offset) \
FIELD(Thread, callback_code_offset) \
FIELD(Thread, callback_stack_return_offset) \
+ FIELD(Thread, random_offset) \
FIELD(Thread, jump_to_frame_entry_point_offset) \
FIELD(Thread, tsan_utils_offset) \
FIELD(TsanUtils, setjmp_function_offset) \
diff --git a/runtime/vm/dart_entry.cc b/runtime/vm/dart_entry.cc
index 7041084..46df59f 100644
--- a/runtime/vm/dart_entry.cc
+++ b/runtime/vm/dart_entry.cc
@@ -676,24 +676,6 @@
return result.ptr();
}
-// On success, returns an InstancePtr. On failure, an ErrorPtr.
-ObjectPtr DartLibraryCalls::IdentityHashCode(const Instance& object) {
- const int kNumArguments = 1;
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- const Library& libcore = Library::Handle(zone, Library::CoreLibrary());
- ASSERT(!libcore.IsNull());
- const Function& function = Function::Handle(
- zone, libcore.LookupFunctionAllowPrivate(Symbols::identityHashCode()));
- ASSERT(!function.IsNull());
- const Array& args = Array::Handle(zone, Array::New(kNumArguments));
- args.SetAt(0, object);
- const Object& result =
- Object::Handle(zone, DartEntry::InvokeFunction(function, args));
- ASSERT(result.IsInstance() || result.IsError());
- return result.ptr();
-}
-
ObjectPtr DartLibraryCalls::LookupHandler(Dart_Port port_id) {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
diff --git a/runtime/vm/dart_entry.h b/runtime/vm/dart_entry.h
index 6ec9067..4f650a8 100644
--- a/runtime/vm/dart_entry.h
+++ b/runtime/vm/dart_entry.h
@@ -285,9 +285,6 @@
// On success, returns an InstancePtr. On failure, an ErrorPtr.
static ObjectPtr Equals(const Instance& left, const Instance& right);
- // On success, returns an InstancePtr. On failure, an ErrorPtr.
- static ObjectPtr IdentityHashCode(const Instance& object);
-
// Returns the handler if one has been registered for this port id.
static ObjectPtr LookupHandler(Dart_Port port_id);
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index df10c58..b37de90 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1344,8 +1344,13 @@
// Some classes have identity hash codes that depend on their contents,
// not per object.
ASSERT(!obj->IsStringInstance());
- if (!obj->IsMint() && !obj->IsDouble() && !obj->IsRawNull() &&
- !obj->IsBool()) {
+ if (obj == Object::null()) {
+ Object::SetCachedHashIfNotSet(obj, kNullIdentityHash);
+ } else if (obj == Object::bool_true().ptr()) {
+ Object::SetCachedHashIfNotSet(obj, kTrueIdentityHash);
+ } else if (obj == Object::bool_false().ptr()) {
+ Object::SetCachedHashIfNotSet(obj, kFalseIdentityHash);
+ } else if (!obj->IsMint() && !obj->IsDouble()) {
counter_ += 2011; // The year Dart was announced and a prime.
counter_ &= 0x3fffffff;
if (counter_ == 0) counter_++;
@@ -9522,15 +9527,6 @@
return target.ptr();
}
-intptr_t Function::ComputeClosureHash() const {
- ASSERT(IsClosureFunction());
- const Class& cls = Class::Handle(Owner());
- uintptr_t result = String::Handle(name()).Hash();
- result += String::Handle(InternalSignature()).Hash();
- result += String::Handle(cls.Name()).Hash();
- return result;
-}
-
void FunctionType::Print(NameVisibility name_visibility,
BaseTextBuffer* printer) const {
if (IsNull()) {
@@ -18995,8 +18991,45 @@
return DartLibraryCalls::HashCode(*this);
}
-ObjectPtr Instance::IdentityHashCode() const {
- return DartLibraryCalls::IdentityHashCode(*this);
+// Keep in sync with AsmIntrinsifier::Object_getHash.
+IntegerPtr Instance::IdentityHashCode(Thread* thread) const {
+ if (IsInteger()) return Integer::Cast(*this).ptr();
+
+#if defined(HASH_IN_OBJECT_HEADER)
+ intptr_t hash = Object::GetCachedHash(ptr());
+#else
+ intptr_t hash = thread->heap()->GetHash(ptr());
+#endif
+ if (hash == 0) {
+ if (IsNull()) {
+ hash = kNullIdentityHash;
+ } else if (IsBool()) {
+ hash = Bool::Cast(*this).value() ? kTrueIdentityHash : kFalseIdentityHash;
+ } else if (IsDouble()) {
+ double val = Double::Cast(*this).value();
+ if ((val >= kMinInt64RepresentableAsDouble) &&
+ (val <= kMaxInt64RepresentableAsDouble)) {
+ int64_t ival = static_cast<int64_t>(val);
+ if (static_cast<double>(ival) == val) {
+ return Integer::New(ival);
+ }
+ }
+
+ uint64_t uval = bit_cast<uint64_t>(val);
+ hash = ((uval >> 32) ^ (uval)) & kSmiMax;
+ } else {
+ do {
+ hash = thread->random()->NextUInt32() & 0x3FFFFFFF;
+ } while (hash == 0);
+ }
+
+#if defined(HASH_IN_OBJECT_HEADER)
+ hash = Object::SetCachedHashIfNotSet(ptr(), hash);
+#else
+ hash = thread->heap()->SetHashIfNotSet(ptr(), hash);
+#endif
+ }
+ return Smi::New(hash);
}
bool Instance::CanonicalizeEquals(const Instance& other) const {
@@ -19058,7 +19091,7 @@
uint32_t Instance::CanonicalizeHash() const {
if (GetClassId() == kNullCid) {
- return 2011; // Matches null_patch.dart.
+ return kNullIdentityHash;
}
Thread* thread = Thread::Current();
uint32_t hash = thread->heap()->GetCanonicalHash(ptr());
@@ -25457,7 +25490,7 @@
// Implicit instance closures are not unique, so combine function's hash
// code, delayed type arguments hash code (if generic), and identityHashCode
// of cached receiver.
- result = static_cast<uint32_t>(func.ComputeClosureHash());
+ result = static_cast<uint32_t>(func.Hash());
if (func.IsGeneric()) {
const TypeArguments& delayed_type_args =
TypeArguments::Handle(zone, delayed_type_arguments());
@@ -25466,23 +25499,15 @@
const Context& context = Context::Handle(zone, this->context());
const Instance& receiver =
Instance::Handle(zone, Instance::RawCast(context.At(0)));
- const Object& receiverHash =
- Object::Handle(zone, receiver.IdentityHashCode());
- if (receiverHash.IsError()) {
- Exceptions::PropagateError(Error::Cast(receiverHash));
- UNREACHABLE();
- }
- result = CombineHashes(
- result, Integer::Cast(receiverHash).AsTruncatedUint32Value());
+ const Integer& receiverHash =
+ Integer::Handle(zone, receiver.IdentityHashCode(thread));
+ result = CombineHashes(result, receiverHash.AsTruncatedUint32Value());
} else {
// Explicit closures and implicit static closures are unique,
// so identityHashCode of closure object is good enough.
- const Object& identityHash = Object::Handle(zone, this->IdentityHashCode());
- if (identityHash.IsError()) {
- Exceptions::PropagateError(Error::Cast(identityHash));
- UNREACHABLE();
- }
- result = Integer::Cast(identityHash).AsTruncatedUint32Value();
+ const Integer& identityHash =
+ Integer::Handle(zone, this->IdentityHashCode(thread));
+ result = identityHash.AsTruncatedUint32Value();
}
return FinalizeHash(result, String::kHashBits);
}
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index ba6e15d..591c5a1 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -2947,8 +2947,6 @@
// invalid (e.g., mismatched argument shapes after a reload).
FunctionPtr ImplicitClosureTarget(Zone* zone) const;
- intptr_t ComputeClosureHash() const;
-
FunctionPtr ForwardingTarget() const;
void SetForwardingTarget(const Function& target) const;
@@ -7517,7 +7515,7 @@
virtual ObjectPtr HashCode() const;
// Equivalent to invoking identityHashCode with this instance.
- ObjectPtr IdentityHashCode() const;
+ IntegerPtr IdentityHashCode(Thread* thread) const;
static intptr_t InstanceSize() {
return RoundedAllocationSize(sizeof(UntaggedInstance));
@@ -10065,6 +10063,11 @@
friend class Symbols;
};
+// Matches null_patch.dart / bool_patch.dart.
+static constexpr intptr_t kNullIdentityHash = 2011;
+static constexpr intptr_t kTrueIdentityHash = 1231;
+static constexpr intptr_t kFalseIdentityHash = 1237;
+
// Class Bool implements Dart core class bool.
class Bool : public Instance {
public:
@@ -10083,7 +10086,7 @@
}
virtual uint32_t CanonicalizeHash() const {
- return ptr() == True().ptr() ? 1231 : 1237;
+ return ptr() == True().ptr() ? kTrueIdentityHash : kFalseIdentityHash;
}
private:
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index 50640ad..880bdde 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -441,7 +441,6 @@
V(current_position, ":current_position") \
V(dynamic_assert_assignable_stc_check, \
":dynamic_assert_assignable_stc_check") \
- V(identityHashCode, "identityHashCode") \
V(index_temp, ":index_temp") \
V(is_sync, ":is_sync") \
V(isPaused, "isPaused") \
diff --git a/runtime/vm/thread.h b/runtime/vm/thread.h
index 66faed4..ed9e9b7 100644
--- a/runtime/vm/thread.h
+++ b/runtime/vm/thread.h
@@ -1030,6 +1030,7 @@
void InitVMConstants();
Random* random() { return &thread_random_; }
+ static intptr_t random_offset() { return OFFSET_OF(Thread, thread_random_); }
uint64_t* GetFfiMarshalledArguments(intptr_t size) {
if (ffi_marshalled_arguments_size_ < size) {
@@ -1138,6 +1139,7 @@
uword exit_through_ffi_ = 0;
ApiLocalScope* api_top_scope_;
uint8_t double_truncate_round_supported_;
+ ALIGN8 Random thread_random_;
TsanUtils* tsan_utils_ = nullptr;
@@ -1177,8 +1179,6 @@
ErrorPtr sticky_error_;
- Random thread_random_;
-
intptr_t ffi_marshalled_arguments_size_ = 0;
uint64_t* ffi_marshalled_arguments_;
diff --git a/sdk/lib/_internal/vm/lib/core_patch.dart b/sdk/lib/_internal/vm/lib/core_patch.dart
index 3118350..0d1d4a8 100644
--- a/sdk/lib/_internal/vm/lib/core_patch.dart
+++ b/sdk/lib/_internal/vm/lib/core_patch.dart
@@ -53,8 +53,6 @@
import "dart:isolate" show Isolate;
-import "dart:math" show Random;
-
import "dart:typed_data"
show Endian, Uint8List, Int64List, Uint16List, Uint32List;
diff --git a/sdk/lib/_internal/vm/lib/object_patch.dart b/sdk/lib/_internal/vm/lib/object_patch.dart
index 3a7b6bb..d0398a2 100644
--- a/sdk/lib/_internal/vm/lib/object_patch.dart
+++ b/sdk/lib/_internal/vm/lib/object_patch.dart
@@ -9,14 +9,6 @@
@pragma("vm:external-name", "Object_getHash")
external int _getHash(obj);
-/// Set hash code associated with the object if it is not set yet
-/// and return the current hash code. See [Object._objectHashCode]
-/// for why this function needs to check for already set hash code.
-@pragma("vm:recognized", "asm-intrinsic")
-@pragma("vm:exact-result-type", "dart:core#_Smi")
-@pragma("vm:external-name", "Object_setHashIfNotSetYet")
-external int _setHashIfNotSetYet(obj, int hash);
-
@patch
@pragma("vm:entry-point")
class Object {
@@ -28,31 +20,9 @@
@pragma("vm:external-name", "Object_equals")
external bool operator ==(Object other);
- // Helpers used to implement hashCode. If a hashCode is used, we remember it
- // in a weak table in the VM (32 bit) or in the header of the object (64
- // bit). A new hashCode value is calculated using a random number generator.
- static final _hashCodeRnd = new Random();
-
- static int _objectHashCode(obj) {
- var result = _getHash(obj);
- if (result == 0) {
- // We want the hash to be a Smi value greater than 0.
- do {
- result = _hashCodeRnd.nextInt(0x40000000);
- } while (result == 0);
-
- // Caveat: we might be interrupted by vm-service which then
- // can initialize [this] object's hash code, that is why we need to
- // return the return value of [_setHashIfNotSetYet] rather than
- // returning [result] itself.
- return _setHashIfNotSetYet(obj, result);
- }
- return result;
- }
-
@patch
- int get hashCode => _objectHashCode(this);
- int get _identityHashCode => _objectHashCode(this);
+ int get hashCode => _getHash(this);
+ int get _identityHashCode => _getHash(this);
@patch
@pragma("vm:external-name", "Object_toString")