blob: e5678eef3b8e68c2b687059c6fffd8f8ea1b1c0f [file] [log] [blame]
// Copyright (c) 2021, 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.
#include "platform/assert.h"
#include "vm/globals.h"
#include "vm/symbols.h"
#include "vm/unit_test.h"
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