Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(630)

Unified Diff: runtime/vm/object.cc

Issue 1965493004: Canonicalize generic types in an isolate specific hash table (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: address-merge-conflicts Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_reload.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: runtime/vm/object.cc
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index ad7b37ae34434626c45ade692961e4d8114c090a..aff8c27b7190f99c7f0094bd05b33f405c5da505 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -42,6 +42,7 @@
#include "vm/thread_registry.h"
#include "vm/timeline.h"
#include "vm/timer.h"
+#include "vm/type_table.h"
#include "vm/unicode.h"
#include "vm/verified_memory.h"
#include "vm/weak_code.h"
@@ -1146,12 +1147,16 @@ NOT_IN_PRODUCT(
GrowableObjectArray::type_arguments_offset());
cls.set_num_type_arguments(1);
- // canonical_type_arguments_ are Smi terminated.
- // Last element contains the count of used slots.
+ // Initialize hash set for canonical_type_.
+ const intptr_t kInitialCanonicalTypeSize = 16;
+ array = HashTables::New<CanonicalTypeSet>(
+ kInitialCanonicalTypeSize, Heap::kOld);
+ object_store->set_canonical_types(array);
+
+ // Initialize hash set for canonical_type_arguments_.
const intptr_t kInitialCanonicalTypeArgumentsSize = 4;
- array = Array::New(kInitialCanonicalTypeArgumentsSize + 1);
- array.SetAt(kInitialCanonicalTypeArgumentsSize,
- Smi::Handle(zone, Smi::New(0)));
+ array = HashTables::New<CanonicalTypeArgumentsSet>(
+ kInitialCanonicalTypeArgumentsSize, Heap::kOld);
object_store->set_canonical_type_arguments(array);
// Setup type class early in the process.
@@ -3632,96 +3637,26 @@ void Class::set_constants(const Array& value) const {
}
-RawObject* Class::canonical_types() const {
- return raw_ptr()->canonical_types_;
+RawType* Class::canonical_type() const {
+ return raw_ptr()->canonical_type_;
}
-void Class::set_canonical_types(const Object& value) const {
+void Class::set_canonical_type(const Type& value) const {
ASSERT(!value.IsNull());
- StorePointer(&raw_ptr()->canonical_types_, value.raw());
+ StorePointer(&raw_ptr()->canonical_type_, value.raw());
}
RawType* Class::CanonicalType() const {
- if (!IsGeneric() && !IsClosureClass()) {
- return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_);
- }
- Array& types = Array::Handle();
- types ^= canonical_types();
- if (!types.IsNull() && (types.Length() > 0)) {
- return reinterpret_cast<RawType*>(types.At(0));
- }
- return reinterpret_cast<RawType*>(Object::null());
+ return raw_ptr()->canonical_type_;
}
void Class::SetCanonicalType(const Type& type) const {
- ASSERT(type.IsCanonical());
- if (!IsGeneric() && !IsClosureClass()) {
- ASSERT((canonical_types() == Object::null()) ||
- (canonical_types() == type.raw())); // Set during own finalization.
- set_canonical_types(type);
- } else {
- Array& types = Array::Handle();
- types ^= canonical_types();
- ASSERT(!types.IsNull() && (types.Length() > 1));
- ASSERT((types.At(0) == Object::null()) || (types.At(0) == type.raw()));
- types.SetAt(0, type);
- // Makes sure that 'canonical_types' has not changed.
- ASSERT(types.raw() == canonical_types());
- }
-}
-
-
-intptr_t Class::FindCanonicalTypeIndex(const AbstractType& needle) const {
- Thread* thread = Thread::Current();
- if (EnsureIsFinalized(thread) != Error::null()) {
- return -1;
- }
- if (needle.raw() == CanonicalType()) {
- // For a generic type or signature type, there exists another index with the
- // same type. It will never be returned by this function.
- return 0;
- }
- REUSABLE_OBJECT_HANDLESCOPE(thread);
- Object& types = thread->ObjectHandle();
- types = canonical_types();
- if (types.IsNull()) {
- return -1;
- }
- const intptr_t len = Array::Cast(types).Length();
- REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(thread);
- AbstractType& type = thread->AbstractTypeHandle();
- for (intptr_t i = 0; i < len; i++) {
- type ^= Array::Cast(types).At(i);
- if (needle.raw() == type.raw()) {
- return i;
- }
- }
- // No type found.
- return -1;
-}
-
-
-RawAbstractType* Class::CanonicalTypeFromIndex(intptr_t idx) const {
- AbstractType& type = AbstractType::Handle();
- if (idx == 0) {
- type = CanonicalType();
- if (!type.IsNull()) {
- return type.raw();
- }
- }
- Object& types = Object::Handle(canonical_types());
- if (types.IsNull() || !types.IsArray()) {
- return Type::null();
- }
- if ((idx < 0) || (idx >= Array::Cast(types).Length())) {
- return Type::null();
- }
- type ^= Array::Cast(types).At(idx);
- ASSERT(!type.IsNull());
- return type.raw();
+ ASSERT((canonical_type() == Object::null()) ||
+ (canonical_type() == type.raw())); // Set during own finalization.
+ set_canonical_type(type);
}
@@ -4293,84 +4228,6 @@ RawLibraryPrefix* Class::LookupLibraryPrefix(const String& name) const {
}
-// Returns AbstractType::null() if type not found. Modifies index to the last
-// position looked up.
-RawAbstractType* Class::LookupCanonicalType(
- Zone* zone, const AbstractType& lookup_type, intptr_t* index) const {
- Array& canonical_types = Array::Handle(zone);
- canonical_types ^= this->canonical_types();
- if (canonical_types.IsNull()) {
- return AbstractType::null();
- }
- AbstractType& type = Type::Handle(zone);
- const intptr_t length = canonical_types.Length();
- while (*index < length) {
- type ^= canonical_types.At(*index);
- if (type.IsNull()) {
- break;
- }
- ASSERT(type.IsFinalized());
- if (lookup_type.Equals(type)) {
- ASSERT(type.IsCanonical());
- return type.raw();
- }
- *index = *index + 1;
- }
- return AbstractType::null();
-}
-
-
-// Canonicalizing the type arguments may have changed the index, may have
-// grown the table, or may even have canonicalized this type. Therefore
-// conrtinue search for canonical type at the last index visited.
-RawAbstractType* Class::LookupOrAddCanonicalType(
- const AbstractType& lookup_type, intptr_t start_index) const {
- Thread* thread = Thread::Current();
- Zone* zone = thread->zone();
- Isolate* isolate = thread->isolate();
- AbstractType& type = Type::Handle(zone);
- intptr_t index = start_index;
- type ^= LookupCanonicalType(zone, lookup_type, &index);
-
- if (!type.IsNull()) {
- return type.raw();
- }
- {
- SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
- // Lookup again, in case the canonicalization array changed.
- Array& canonical_types = Array::Handle(zone);
- canonical_types ^= this->canonical_types();
- if (canonical_types.IsNull()) {
- canonical_types = empty_array().raw();
- }
- const intptr_t length = canonical_types.Length();
- // Start looking after previously looked up last position ('length').
- type ^= LookupCanonicalType(zone, lookup_type, &index);
- if (!type.IsNull()) {
- return type.raw();
- }
-
- // 'lookup_type' is not canonicalized yet.
- lookup_type.SetCanonical();
-
- // The type needs to be added to the list. Grow the list if it is full.
- if (index >= length) {
- ASSERT((index == length) || ((index == 1) && (length == 0)));
- const intptr_t new_length = (length > 64) ?
- (length + 64) :
- ((length == 0) ? 2 : (length * 2));
- const Array& new_canonical_types = Array::Handle(
- zone, Array::Grow(canonical_types, new_length, Heap::kOld));
- new_canonical_types.SetAt(index, lookup_type);
- this->set_canonical_types(new_canonical_types);
- } else {
- canonical_types.SetAt(index, lookup_type);
- }
- }
- return lookup_type.raw();
-}
-
-
const char* Class::ToCString() const {
const Library& lib = Library::Handle(library());
const char* library_name = lib.IsNull() ? "" : lib.ToCString();
@@ -4648,15 +4505,16 @@ static uint32_t CombineHashes(uint32_t hash, uint32_t other_hash) {
}
-static uint32_t FinalizeHash(uint32_t hash) {
+static uint32_t FinalizeHash(uint32_t hash, intptr_t hashbits) {
hash += hash << 3;
hash ^= hash >> 11; // Logical shift, unsigned hash.
hash += hash << 15;
- return hash;
+ hash &= ((static_cast<intptr_t>(1) << hashbits) - 1);
+ return (hash == 0) ? 1 : hash;
}
-intptr_t TypeArguments::Hash() const {
+intptr_t TypeArguments::ComputeHash() const {
if (IsNull()) return 0;
const intptr_t num_types = Length();
if (IsRaw(0, num_types)) return 0;
@@ -4668,7 +4526,9 @@ intptr_t TypeArguments::Hash() const {
// purposes only) while a type argument is still temporarily null.
result = CombineHashes(result, type.IsNull() ? 0 : type.Hash());
}
- return FinalizeHash(result);
+ result = FinalizeHash(result, kHashBits);
+ SetHash(result);
+ return result;
}
@@ -5119,6 +4979,7 @@ RawTypeArguments* TypeArguments::New(intptr_t len, Heap::Space space) {
result ^= raw;
// Length must be set before we start storing into the array.
result.SetLength(len);
+ result.SetHash(0);
}
// The zero array should have been initialized.
ASSERT(Object::zero_array().raw() != Array::null());
@@ -5144,99 +5005,6 @@ void TypeArguments::SetLength(intptr_t value) const {
}
-static void GrowCanonicalTypeArguments(Thread* thread, const Array& table) {
- Isolate* isolate = thread->isolate();
- Zone* zone = thread->zone();
- // Last element of the array is the number of used elements.
- const intptr_t table_size = table.Length() - 1;
- const intptr_t new_table_size = table_size * 2;
- Array& new_table = Array::Handle(zone, Array::New(new_table_size + 1));
- // Copy all elements from the original table to the newly allocated
- // array.
- TypeArguments& element = TypeArguments::Handle(zone);
- Object& new_element = Object::Handle(zone);
- for (intptr_t i = 0; i < table_size; i++) {
- element ^= table.At(i);
- if (!element.IsNull()) {
- const intptr_t hash = element.Hash();
- ASSERT(Utils::IsPowerOfTwo(new_table_size));
- intptr_t index = hash & (new_table_size - 1);
- new_element = new_table.At(index);
- while (!new_element.IsNull()) {
- index = (index + 1) & (new_table_size - 1); // Move to next element.
- new_element = new_table.At(index);
- }
- new_table.SetAt(index, element);
- }
- }
- // Copy used count.
- new_element = table.At(table_size);
- new_table.SetAt(new_table_size, new_element);
- // Remember the new table now.
- isolate->object_store()->set_canonical_type_arguments(new_table);
-}
-
-
-static void InsertIntoCanonicalTypeArguments(Thread* thread,
- const Array& table,
- const TypeArguments& arguments,
- intptr_t index) {
- Zone* zone = thread->zone();
- arguments.SetCanonical(); // Mark object as being canonical.
- table.SetAt(index, arguments); // Remember the new element.
- // Update used count.
- // Last element of the array is the number of used elements.
- const intptr_t table_size = table.Length() - 1;
- const intptr_t used_elements =
- Smi::Value(Smi::RawCast(table.At(table_size))) + 1;
- const Smi& used = Smi::Handle(zone, Smi::New(used_elements));
- table.SetAt(table_size, used);
-
-#ifdef DEBUG
- // Verify that there are no duplicates.
- // Duplicates could appear if hash values are not kept constant across
- // snapshots, e.g. if class ids are not preserved by the snapshots.
- TypeArguments& other_arguments = TypeArguments::Handle();
- for (intptr_t i = 0; i < table_size; i++) {
- if ((i != index) && (table.At(i) != TypeArguments::null())) {
- other_arguments ^= table.At(i);
- if (arguments.Equals(other_arguments)) {
- // Recursive types may be equal, but have different hashes.
- ASSERT(arguments.IsRecursive());
- ASSERT(other_arguments.IsRecursive());
- ASSERT(arguments.Hash() != other_arguments.Hash());
- }
- }
- }
-#endif
-
- // Rehash if table is 75% full.
- if (used_elements > ((table_size / 4) * 3)) {
- GrowCanonicalTypeArguments(thread, table);
- }
-}
-
-
-static intptr_t FindIndexInCanonicalTypeArguments(
- Zone* zone,
- const Array& table,
- const TypeArguments& arguments,
- intptr_t hash) {
- // Last element of the array is the number of used elements.
- const intptr_t table_size = table.Length() - 1;
- ASSERT(Utils::IsPowerOfTwo(table_size));
- intptr_t index = hash & (table_size - 1);
-
- TypeArguments& current = TypeArguments::Handle(zone);
- current ^= table.At(index);
- while (!current.IsNull() && !current.Equals(arguments)) {
- index = (index + 1) & (table_size - 1); // Move to next element.
- current ^= table.At(index);
- }
- return index; // Index of element if found or slot into which to add it.
-}
-
-
RawTypeArguments* TypeArguments::CloneUnfinalized() const {
if (IsNull() || IsFinalized()) {
return raw();
@@ -5291,15 +5059,14 @@ RawTypeArguments* TypeArguments::Canonicalize(TrailPtr trail) const {
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
ObjectStore* object_store = isolate->object_store();
- Array& table = Array::Handle(zone,
- object_store->canonical_type_arguments());
- // Last element of the array is the number of used elements.
- const intptr_t num_used =
- Smi::Value(Smi::RawCast(table.At(table.Length() - 1)));
- const intptr_t hash = Hash();
- intptr_t index = FindIndexInCanonicalTypeArguments(zone, table, *this, hash);
TypeArguments& result = TypeArguments::Handle(zone);
- result ^= table.At(index);
+ {
+ SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
+ CanonicalTypeArgumentsSet table(zone,
+ object_store->canonical_type_arguments());
+ result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this));
+ object_store->set_canonical_type_arguments(table.Release());
+ }
if (result.IsNull()) {
// Canonicalize each type argument.
AbstractType& type_arg = AbstractType::Handle(zone);
@@ -5313,21 +5080,18 @@ RawTypeArguments* TypeArguments::Canonicalize(TrailPtr trail) const {
}
SetTypeAt(i, type_arg);
}
- // Canonicalization of a recursive type may change its hash.
- intptr_t canonical_hash = hash;
+ // Canonicalization of a type argument of a recursive type argument vector
+ // may change the hash of the vector, so recompute.
if (IsRecursive()) {
- canonical_hash = Hash();
- }
- // Canonicalization of the type argument's own type arguments may add an
- // entry to the table, or even grow the table, and thereby change the
- // previously calculated index.
- table = object_store->canonical_type_arguments();
- if ((canonical_hash != hash) ||
- (Smi::Value(Smi::RawCast(table.At(table.Length() - 1))) != num_used)) {
- index = FindIndexInCanonicalTypeArguments(
- zone, table, *this, canonical_hash);
- result ^= table.At(index);
+ ComputeHash();
}
+ SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
+ CanonicalTypeArgumentsSet table(
+ zone, object_store->canonical_type_arguments());
+ // Since we canonicalized some type arguments above we need to lookup
+ // in the table again to make sure we don't already have an equivalent
+ // canonical entry.
+ result ^= table.GetOrNull(CanonicalTypeArgumentsKey(*this));
if (result.IsNull()) {
// Make sure we have an old space object and add it to the table.
if (this->IsNew()) {
@@ -5336,8 +5100,12 @@ RawTypeArguments* TypeArguments::Canonicalize(TrailPtr trail) const {
result ^= this->raw();
}
ASSERT(result.IsOld());
- InsertIntoCanonicalTypeArguments(thread, table, result, index);
+ result.SetCanonical(); // Mark object as being canonical.
+ // Now add this TypeArgument into the canonical list of type arguments.
+ bool present = table.Insert(result);
+ ASSERT(!present);
}
+ object_store->set_canonical_type_arguments(table.Release());
}
ASSERT(result.Equals(*this));
ASSERT(!result.IsNull());
@@ -5368,12 +5136,13 @@ const char* TypeArguments::ToCString() const {
if (IsNull()) {
return "NULL TypeArguments";
}
- const char* prev_cstr = "TypeArguments:";
+ Zone* zone = Thread::Current()->zone();
+ const char* prev_cstr = OS::SCreate(
+ zone, "TypeArguments: (%" Pd ")", Smi::Value(raw_ptr()->hash_));
for (int i = 0; i < Length(); i++) {
- const AbstractType& type_at = AbstractType::Handle(TypeAt(i));
+ const AbstractType& type_at = AbstractType::Handle(zone, TypeAt(i));
const char* type_cstr = type_at.IsNull() ? "null" : type_at.ToCString();
- char* chars = OS::SCreate(Thread::Current()->zone(),
- "%s [%s]", prev_cstr, type_cstr);
+ char* chars = OS::SCreate(zone, "%s [%s]", prev_cstr, type_cstr);
prev_cstr = chars;
}
return prev_cstr;
@@ -9475,8 +9244,6 @@ class LibraryUrlTraits {
return Library::Cast(key).UrlHash();
}
};
-
-
typedef UnorderedHashSet<LibraryUrlTraits> LibraryLoadErrorSet;
@@ -15444,7 +15211,7 @@ uword Instance::ComputeCanonicalTableHash() const {
*reinterpret_cast<RawObject**>(this_addr + offset));
hash = CombineHashes(hash, value);
}
- return FinalizeHash(hash);
+ return FinalizeHash(hash, (kBitsPerWord - 1));
}
@@ -17224,19 +16991,23 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
- AbstractType& type = Type::Handle(zone);
- const Class& cls = Class::Handle(zone, type_class());
+
// Since void is a keyword, we never have to canonicalize the void type after
// it is canonicalized once by the vm isolate. The parser does the mapping.
- ASSERT((cls.raw() != Object::void_class()) ||
+ ASSERT((type_class() != Object::void_class()) ||
(isolate == Dart::vm_isolate()));
+
// Since dynamic is not a keyword, the parser builds a type that requires
// canonicalization.
- if ((cls.raw() == Object::dynamic_class()) &&
+ if ((type_class() == Object::dynamic_class()) &&
(isolate != Dart::vm_isolate())) {
ASSERT(Object::dynamic_type().IsCanonical());
return Object::dynamic_type().raw();
}
+
+ AbstractType& type = Type::Handle(zone);
+ const Class& cls = Class::Handle(zone, type_class());
+
// Fast canonical lookup/registry for simple types.
if (!cls.IsGeneric() && !cls.IsClosureClass() && !cls.IsTypedefClass()) {
ASSERT(!IsFunctionType());
@@ -17254,12 +17025,13 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
set_arguments(type_args);
type = cls.CanonicalType(); // May be set while canonicalizing type args.
if (type.IsNull()) {
- MutexLocker ml(isolate->type_canonicalization_mutex());
+ SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
// Recheck if type exists.
type = cls.CanonicalType();
if (type.IsNull()) {
+ ComputeHash();
SetCanonical();
- cls.set_canonical_types(*this);
+ cls.set_canonical_type(*this);
return this->raw();
}
}
@@ -17269,73 +17041,76 @@ RawAbstractType* Type::Canonicalize(TrailPtr trail) const {
return type.raw();
}
- Array& canonical_types = Array::Handle(zone);
- canonical_types ^= cls.canonical_types();
- if (canonical_types.IsNull()) {
- canonical_types = empty_array().raw();
- }
- intptr_t length = canonical_types.Length();
- // Linear search to see whether this type is already present in the
- // list of canonicalized types.
- // TODO(asiva): Try to re-factor this lookup code to make sharing
- // easy between the 4 versions of this loop.
- intptr_t index = 1; // Slot 0 is reserved for CanonicalType().
- while (index < length) {
- type ^= canonical_types.At(index);
- if (type.IsNull()) {
- break;
- }
- ASSERT(type.IsFinalized());
- if (this->Equals(type)) {
- ASSERT(type.IsCanonical());
- return type.raw();
- }
- index++;
- }
- // The type was not found in the table. It is not canonical yet.
-
- // Canonicalize the type arguments.
- TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
- // In case the type is first canonicalized at runtime, its type argument
- // vector may be longer than necessary. This is not an issue.
- ASSERT(type_args.IsNull() || (type_args.Length() >= cls.NumTypeArguments()));
- type_args = type_args.Canonicalize(trail);
- if (IsCanonical()) {
- // Canonicalizing type_args canonicalized this type as a side effect.
- ASSERT(IsRecursive());
- // Cycles via typedefs are detected and disallowed, but a function type can
- // be recursive due to a cycle in its type arguments.
- return this->raw();
+ ObjectStore* object_store = isolate->object_store();
+ {
+ SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
+ CanonicalTypeSet table(zone, object_store->canonical_types());
+ type ^= table.GetOrNull(CanonicalTypeKey(*this));
+ object_store->set_canonical_types(table.Release());
}
- set_arguments(type_args);
- ASSERT(type_args.IsNull() || type_args.IsOld());
-
- // In case of a function type, replace the actual function by a signature
- // function.
- if (IsFunctionType()) {
- const Function& fun = Function::Handle(zone, signature());
- if (!fun.IsSignatureFunction()) {
- Function& sig_fun = Function::Handle(zone,
- Function::NewSignatureFunction(cls, TokenPosition::kNoSource));
- type = fun.result_type();
- type = type.Canonicalize(trail);
- sig_fun.set_result_type(type);
- const intptr_t num_params = fun.NumParameters();
- sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
- sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
- fun.HasOptionalPositionalParameters());
- sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
- Heap::kOld)));
- for (intptr_t i = 0; i < num_params; i++) {
- type = fun.ParameterTypeAt(i);
+ if (type.IsNull()) {
+ // The type was not found in the table. It is not canonical yet.
+
+ // Canonicalize the type arguments.
+ TypeArguments& type_args = TypeArguments::Handle(zone, arguments());
+ // In case the type is first canonicalized at runtime, its type argument
+ // vector may be longer than necessary. This is not an issue.
+ ASSERT(type_args.IsNull() ||
+ (type_args.Length() >= cls.NumTypeArguments()));
+ type_args = type_args.Canonicalize(trail);
+ if (IsCanonical()) {
+ // Canonicalizing type_args canonicalized this type as a side effect.
+ ASSERT(IsRecursive());
+ // Cycles via typedefs are detected and disallowed, but a function type
+ // can be recursive due to a cycle in its type arguments.
+ return this->raw();
+ }
+ set_arguments(type_args);
+ ASSERT(type_args.IsNull() || type_args.IsOld());
+
+ // In case of a function type, replace the actual function by a signature
+ // function.
+ if (IsFunctionType()) {
+ const Function& fun = Function::Handle(zone, signature());
+ if (!fun.IsSignatureFunction()) {
+ Function& sig_fun = Function::Handle(
+ zone,
+ Function::NewSignatureFunction(cls, TokenPosition::kNoSource));
+ type = fun.result_type();
type = type.Canonicalize(trail);
- sig_fun.SetParameterTypeAt(i, type);
+ sig_fun.set_result_type(type);
+ const intptr_t num_params = fun.NumParameters();
+ sig_fun.set_num_fixed_parameters(fun.num_fixed_parameters());
+ sig_fun.SetNumOptionalParameters(fun.NumOptionalParameters(),
+ fun.HasOptionalPositionalParameters());
+ sig_fun.set_parameter_types(Array::Handle(Array::New(num_params,
+ Heap::kOld)));
+ for (intptr_t i = 0; i < num_params; i++) {
+ type = fun.ParameterTypeAt(i);
+ type = type.Canonicalize(trail);
+ sig_fun.SetParameterTypeAt(i, type);
+ }
+ sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
+ set_signature(sig_fun);
}
- sig_fun.set_parameter_names(Array::Handle(zone, fun.parameter_names()));
- set_signature(sig_fun);
}
+
+ // Check to see if the type got added to canonical list as part of the
+ // type arguments canonicalization.
+ SafepointMutexLocker ml(isolate->type_canonicalization_mutex());
+ CanonicalTypeSet table(zone, object_store->canonical_types());
+ type ^= table.GetOrNull(CanonicalTypeKey(*this));
+ if (type.IsNull()) {
+ // Add this Type into the canonical list of types.
+ type ^= raw();
+ ASSERT(type.IsOld());
+ type.SetCanonical(); // Mark object as being canonical.
+ bool present = table.Insert(type);
+ ASSERT(!present);
+ }
+ object_store->set_canonical_types(table.Release());
}
- return cls.LookupOrAddCanonicalType(*this, index);
+ return type.raw();
}
@@ -17376,7 +17151,7 @@ RawString* Type::EnumerateURIs() const {
}
-intptr_t Type::Hash() const {
+intptr_t Type::ComputeHash() const {
ASSERT(IsFinalized());
uint32_t result = 1;
if (IsMalformed()) return result;
@@ -17400,7 +17175,9 @@ intptr_t Type::Hash() const {
}
}
}
- return FinalizeHash(result);
+ result = FinalizeHash(result, kHashBits);
+ SetHash(result);
+ return result;
}
@@ -17442,6 +17219,7 @@ RawType* Type::New(const Object& clazz,
result.set_unresolved_class(clazz);
}
result.set_arguments(arguments);
+ result.SetHash(0);
result.set_token_pos(token_pos);
result.StoreNonPointer(&result.raw_ptr()->type_state_, RawType::kAllocated);
return result.raw();
@@ -17621,7 +17399,7 @@ intptr_t TypeRef::Hash() const {
// Do not calculate the hash of the referenced type to avoid divergence.
const uint32_t result =
Class::Handle(AbstractType::Handle(type()).type_class()).id();
- return FinalizeHash(result);
+ return FinalizeHash(result, kHashBits);
}
@@ -17869,13 +17647,15 @@ RawString* TypeParameter::EnumerateURIs() const {
}
-intptr_t TypeParameter::Hash() const {
+intptr_t TypeParameter::ComputeHash() const {
ASSERT(IsFinalized());
uint32_t result = Class::Handle(parameterized_class()).id();
// No need to include the hash of the bound, since the type parameter is fully
// identified by its class and index.
result = CombineHashes(result, index());
- return FinalizeHash(result);
+ result = FinalizeHash(result, kHashBits);
+ SetHash(result);
+ return result;
}
@@ -17897,6 +17677,7 @@ RawTypeParameter* TypeParameter::New(const Class& parameterized_class,
result.set_index(index);
result.set_name(name);
result.set_bound(bound);
+ result.SetHash(0);
result.set_token_pos(token_pos);
result.StoreNonPointer(&result.raw_ptr()->type_state_,
RawTypeParameter::kAllocated);
@@ -18133,13 +17914,15 @@ RawString* BoundedType::EnumerateURIs() const {
}
-intptr_t BoundedType::Hash() const {
+intptr_t BoundedType::ComputeHash() const {
uint32_t result = AbstractType::Handle(type()).Hash();
// No need to include the hash of the bound, since the bound is defined by the
// type parameter (modulo instantiation state).
result = CombineHashes(result,
TypeParameter::Handle(type_parameter()).Hash());
- return FinalizeHash(result);
+ result = FinalizeHash(result, kHashBits);
+ SetHash(result);
+ return result;
}
@@ -18157,6 +17940,7 @@ RawBoundedType* BoundedType::New(const AbstractType& type,
const BoundedType& result = BoundedType::Handle(BoundedType::New());
result.set_type(type);
result.set_bound(bound);
+ result.SetHash(0);
result.set_type_parameter(type_parameter);
return result.raw();
}
@@ -19694,10 +19478,9 @@ class StringHasher : ValueObject {
// Return a non-zero hash of at most 'bits' bits.
intptr_t Finalize(int bits) {
ASSERT(1 <= bits && bits <= (kBitsPerWord - 1));
- hash_ = FinalizeHash(hash_);
- hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
+ hash_ = FinalizeHash(hash_, bits);
ASSERT(hash_ <= static_cast<uint32_t>(kMaxInt32));
- return hash_ == 0 ? 1 : hash_;
+ return hash_;
}
private:
uint32_t hash_;
@@ -19730,7 +19513,7 @@ void StringHasher::Add(const String& str, intptr_t begin_index, intptr_t len) {
intptr_t String::Hash(const String& str, intptr_t begin_index, intptr_t len) {
StringHasher hasher;
hasher.Add(str, begin_index, len);
- return hasher.Finalize(String::kHashBits);
+ return hasher.Finalize(kHashBits);
}
@@ -19745,7 +19528,7 @@ intptr_t String::HashConcat(const String& str1, const String& str2) {
StringHasher hasher;
hasher.Add(str1, 0, len1);
hasher.Add(str2, 0, str2.Length());
- return hasher.Finalize(String::kHashBits);
+ return hasher.Finalize(kHashBits);
}
}
@@ -19777,7 +19560,7 @@ intptr_t String::Hash(const uint16_t* characters, intptr_t len) {
while (i < len) {
hasher.Add(Utf16::Next(characters, &i, len));
}
- return hasher.Finalize(String::kHashBits);
+ return hasher.Finalize(kHashBits);
}
@@ -21474,7 +21257,7 @@ uword Array::ComputeCanonicalTableHash() const {
value = reinterpret_cast<uword>(At(i));
hash = CombineHashes(hash, value);
}
- return FinalizeHash(hash);
+ return FinalizeHash(hash, kHashBits);
}
@@ -22131,7 +21914,7 @@ uword TypedData::ComputeCanonicalTableHash() const {
for (intptr_t i = 0; i < len; i++) {
hash = CombineHashes(len, GetUint8(i));
}
- return FinalizeHash(hash);
+ return FinalizeHash(hash, kHashBits);
}
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/object_reload.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698