Revert "[VM/nnbd] Canonicalize TypeParameter objects in the VM."

This reverts commit 6a98e2719e.

Reason for revert: Unexpected test failures

Original change's description:
> [VM/nnbd] Canonicalize TypeParameter objects in the VM.
> 
> Prior to this CL, type parameters were all assumed canonical, even duplicate ones.
> 
> Per a new convention introduced in this CL, the type parameter array in generic classes and generic functions contains canonical type parameters. As these type parameters get cloned with a different nullability, they are inserted in a new hash table of canonical type parameters.
> 
> This fixes performance issue https://github.com/dart-lang/sdk/issues/41421
> 
> Change-Id: I9086158fa6b6261e9997bb50edec6d7c54abbfa1
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/148223
> Commit-Queue: Régis Crelier <regis@google.com>
> Reviewed-by: Ryan Macnak <rmacnak@google.com>

TBR=rmacnak@google.com,alexmarkov@google.com,asiva@google.com,regis@google.com

Change-Id: I0ca3b6b66e2281c285eba6b564f78c0e6b2f2217
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/150265
Reviewed-by: Régis Crelier <regis@google.com>
Commit-Queue: Régis Crelier <regis@google.com>
This commit is contained in:
Régis Crelier
2020-06-05 23:36:45 +00:00
committed by commit-bot@chromium.org
parent 6a98e2719e
commit c48263e901
12 changed files with 35 additions and 365 deletions
+11 -47
View File
@@ -300,13 +300,13 @@ void ClassFinalizer::VerifyBootstrapClasses() {
}
#endif // !defined(DART_PRECOMPILED_RUNTIME)
void ClassFinalizer::FinalizeTypeParameters(const Class& cls) {
void ClassFinalizer::FinalizeTypeParameters(const Class& cls,
PendingTypes* pending_types) {
if (FLAG_trace_type_finalization) {
THR_Print("Finalizing type parameters of '%s'\n",
String::Handle(cls.Name()).ToCString());
}
// The type parameter bounds are not finalized here.
const intptr_t offset = cls.NumTypeArguments() - cls.NumTypeParameters();
const TypeArguments& type_parameters =
TypeArguments::Handle(cls.type_parameters());
if (!type_parameters.IsNull()) {
@@ -314,14 +314,9 @@ void ClassFinalizer::FinalizeTypeParameters(const Class& cls) {
const intptr_t num_types = type_parameters.Length();
for (intptr_t i = 0; i < num_types; i++) {
type_parameter ^= type_parameters.TypeAt(i);
if (!type_parameter.IsFinalized()) {
type_parameter.set_index(type_parameter.index() + offset);
type_parameter.SetIsFinalized();
}
if (!type_parameter.IsCanonical()) {
// The declaration of a type parameter is canonical.
type_parameter.SetCanonical();
}
type_parameter ^=
FinalizeType(cls, type_parameter, kFinalize, pending_types);
type_parameters.SetTypeAt(i, type_parameter);
}
}
}
@@ -430,7 +425,7 @@ intptr_t ClassFinalizer::ExpandAndFinalizeTypeArguments(
Class& type_class = Class::Handle(zone, type.type_class());
type_class.EnsureDeclarationLoaded();
if (!type_class.is_type_finalized()) {
FinalizeTypeParameters(type_class);
FinalizeTypeParameters(type_class, pending_types);
}
// The finalized type argument vector needs num_type_arguments types.
@@ -564,7 +559,7 @@ void ClassFinalizer::FinalizeTypeArguments(const Class& cls,
TrailPtr trail) {
ASSERT(arguments.Length() >= cls.NumTypeArguments());
if (!cls.is_type_finalized()) {
FinalizeTypeParameters(cls);
FinalizeTypeParameters(cls, pending_types);
}
AbstractType& super_type = AbstractType::Handle(cls.super_type());
if (!super_type.IsNull()) {
@@ -682,7 +677,8 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const Class& cls,
ASSERT((pending_types == NULL) || (finalization < kCanonicalize));
if (type.IsFinalized()) {
// Ensure type is canonical if canonicalization is requested.
if ((finalization >= kCanonicalize) && !type.IsCanonical()) {
if ((finalization >= kCanonicalize) && !type.IsCanonical() &&
type.IsType()) {
return type.Canonicalize();
}
return type.raw();
@@ -735,7 +731,8 @@ AbstractTypePtr ClassFinalizer::FinalizeType(const Class& cls,
type_parameter.index());
}
return type_parameter.Canonicalize();
// We do not canonicalize type parameters.
return type_parameter.raw();
}
// At this point, we can only have a Type.
@@ -848,12 +845,7 @@ void ClassFinalizer::FinalizeSignature(const Class& cls,
if (!type_param.IsFinalized()) {
type_param.set_index(num_parent_type_params + i);
type_param.SetIsFinalized();
// The declaration of a type parameter is canonical.
type_param.SetCanonical();
}
}
for (intptr_t i = 0; i < num_type_params; i++) {
type_param ^= type_params.TypeAt(i);
type = type_param.bound();
finalized_type = FinalizeType(cls, type, finalization);
if (finalized_type.raw() != type.raw()) {
@@ -1594,7 +1586,6 @@ void ClassFinalizer::RemapClassIds(intptr_t* old_to_new_cid) {
// Usages of canonical hash codes are:
//
// * ObjectStore::canonical_types()
// * ObjectStore::canonical_type_parameters()
// * ObjectStore::canonical_type_arguments()
// * Class::constants()
//
@@ -1663,33 +1654,6 @@ void ClassFinalizer::RehashTypes() {
}
object_store->set_canonical_types(types_table.Release());
// Rehash the canonical TypeParameters table.
Array& typeparams_array = Array::Handle(Z);
GrowableObjectArray& typeparams =
GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
TypeParameter& typeparam = TypeParameter::Handle(Z);
{
CanonicalTypeParameterSet typeparams_table(
Z, object_store->canonical_type_parameters());
typeparams_array = HashTables::ToArray(typeparams_table, false);
for (intptr_t i = 0; i < typeparams_array.Length(); i++) {
typeparam ^= typeparams_array.At(i);
typeparams.Add(typeparam);
}
typeparams_table.Release();
}
dict_size = Utils::RoundUpToPowerOfTwo(typeparams.Length() * 4 / 3);
typeparams_array =
HashTables::New<CanonicalTypeParameterSet>(dict_size, Heap::kOld);
CanonicalTypeParameterSet typeparams_table(Z, typeparams_array.raw());
for (intptr_t i = 0; i < typeparams.Length(); i++) {
typeparam ^= typeparams.At(i);
bool present = typeparams_table.Insert(typeparam);
ASSERT(!present);
}
object_store->set_canonical_type_parameters(typeparams_table.Release());
// Rehash the canonical TypeArguments table.
Array& typeargs_array = Array::Handle(Z);
GrowableObjectArray& typeargs =
+2 -1
View File
@@ -79,7 +79,8 @@ class ClassFinalizer : public AllStatic {
private:
static void AllocateEnumValues(const Class& enum_cls);
static void FinalizeTypeParameters(const Class& cls);
static void FinalizeTypeParameters(const Class& cls,
PendingTypes* pending_types = NULL);
static intptr_t ExpandAndFinalizeTypeArguments(const Class& cls,
const AbstractType& type,
PendingTypes* pending_types);
+9 -74
View File
@@ -3498,28 +3498,19 @@ class TypeRefDeserializationCluster : public DeserializationCluster {
class TypeParameterSerializationCluster : public SerializationCluster {
public:
TypeParameterSerializationCluster() : SerializationCluster("TypeParameter") {}
~TypeParameterSerializationCluster() {}
void Trace(Serializer* s, ObjectPtr object) {
TypeParameterPtr type = TypeParameter::RawCast(object);
if (type->ptr()->IsCanonical()) {
canonical_objects_.Add(type);
} else {
objects_.Add(type);
}
objects_.Add(type);
ASSERT(!type->ptr()->IsCanonical());
PushFromTo(type);
}
void WriteAlloc(Serializer* s) {
s->WriteCid(kTypeParameterCid);
intptr_t count = canonical_objects_.length();
s->WriteUnsigned(count);
for (intptr_t i = 0; i < count; i++) {
TypeParameterPtr type = canonical_objects_[i];
s->AssignRef(type);
}
count = objects_.length();
const intptr_t count = objects_.length();
s->WriteUnsigned(count);
for (intptr_t i = 0; i < count; i++) {
TypeParameterPtr type = objects_[i];
@@ -3528,21 +3519,7 @@ class TypeParameterSerializationCluster : public SerializationCluster {
}
void WriteFill(Serializer* s) {
intptr_t count = canonical_objects_.length();
for (intptr_t i = 0; i < count; i++) {
TypeParameterPtr type = canonical_objects_[i];
AutoTraceObject(type);
WriteFromTo(type);
s->Write<int32_t>(type->ptr()->parameterized_class_id_);
s->WriteTokenPosition(type->ptr()->token_pos_);
s->Write<int16_t>(type->ptr()->index_);
const uint8_t combined =
(type->ptr()->flags_ << 4) | type->ptr()->nullability_;
ASSERT(type->ptr()->flags_ == (combined >> 4));
ASSERT(type->ptr()->nullability_ == (combined & 0xf));
s->Write<uint8_t>(combined);
}
count = objects_.length();
const intptr_t count = objects_.length();
for (intptr_t i = 0; i < count; i++) {
TypeParameterPtr type = objects_[i];
AutoTraceObject(type);
@@ -3559,7 +3536,6 @@ class TypeParameterSerializationCluster : public SerializationCluster {
}
private:
GrowableArray<TypeParameterPtr> canonical_objects_;
GrowableArray<TypeParameterPtr> objects_;
};
#endif // !DART_PRECOMPILED_RUNTIME
@@ -3570,17 +3546,9 @@ class TypeParameterDeserializationCluster : public DeserializationCluster {
~TypeParameterDeserializationCluster() {}
void ReadAlloc(Deserializer* d) {
canonical_start_index_ = d->next_index();
PageSpace* old_space = d->heap()->old_space();
intptr_t count = d->ReadUnsigned();
for (intptr_t i = 0; i < count; i++) {
d->AssignRef(
AllocateUninitialized(old_space, TypeParameter::InstanceSize()));
}
canonical_stop_index_ = d->next_index();
start_index_ = d->next_index();
count = d->ReadUnsigned();
PageSpace* old_space = d->heap()->old_space();
const intptr_t count = d->ReadUnsigned();
for (intptr_t i = 0; i < count; i++) {
d->AssignRef(
AllocateUninitialized(old_space, TypeParameter::InstanceSize()));
@@ -3589,26 +3557,10 @@ class TypeParameterDeserializationCluster : public DeserializationCluster {
}
void ReadFill(Deserializer* d) {
for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
id++) {
TypeParameterPtr type = static_cast<TypeParameterPtr>(d->Ref(id));
bool is_canonical = true;
Deserializer::InitializeHeader(
type, kTypeParameterCid, TypeParameter::InstanceSize(), is_canonical);
ReadFromTo(type);
type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
type->ptr()->token_pos_ = d->ReadTokenPosition();
type->ptr()->index_ = d->Read<int16_t>();
const uint8_t combined = d->Read<uint8_t>();
type->ptr()->flags_ = combined >> 4;
type->ptr()->nullability_ = combined & 0xf;
}
for (intptr_t id = start_index_; id < stop_index_; id++) {
TypeParameterPtr type = static_cast<TypeParameterPtr>(d->Ref(id));
bool is_canonical = false;
Deserializer::InitializeHeader(
type, kTypeParameterCid, TypeParameter::InstanceSize(), is_canonical);
Deserializer::InitializeHeader(type, kTypeParameterCid,
TypeParameter::InstanceSize());
ReadFromTo(type);
type->ptr()->parameterized_class_id_ = d->Read<int32_t>();
type->ptr()->token_pos_ = d->ReadTokenPosition();
@@ -3624,13 +3576,6 @@ class TypeParameterDeserializationCluster : public DeserializationCluster {
Code& stub = Code::Handle(zone);
if (Snapshot::IncludesCode(kind)) {
for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
id++) {
type_param ^= refs.At(id);
stub = type_param.type_test_stub();
type_param.SetTypeTestingStub(
stub); // Update type_test_stub_entry_point_
}
for (intptr_t id = start_index_; id < stop_index_; id++) {
type_param ^= refs.At(id);
stub = type_param.type_test_stub();
@@ -3638,12 +3583,6 @@ class TypeParameterDeserializationCluster : public DeserializationCluster {
stub); // Update type_test_stub_entry_point_
}
} else {
for (intptr_t id = canonical_start_index_; id < canonical_stop_index_;
id++) {
type_param ^= refs.At(id);
stub = TypeTestingStubGenerator::DefaultCodeForType(type_param);
type_param.SetTypeTestingStub(stub);
}
for (intptr_t id = start_index_; id < stop_index_; id++) {
type_param ^= refs.At(id);
stub = TypeTestingStubGenerator::DefaultCodeForType(type_param);
@@ -3651,10 +3590,6 @@ class TypeParameterDeserializationCluster : public DeserializationCluster {
}
}
}
private:
intptr_t canonical_start_index_;
intptr_t canonical_stop_index_;
};
#if !defined(DART_PRECOMPILED_RUNTIME)
-40
View File
@@ -384,7 +384,6 @@ void Precompiler::DoCompileAll() {
DropFields();
TraceTypesFromRetainedClasses();
DropTypes();
DropTypeParameters();
DropTypeArguments();
// Clear these before dropping classes as they may hold onto otherwise
@@ -1784,45 +1783,6 @@ void Precompiler::DropTypes() {
object_store->set_canonical_types(types_table.Release());
}
void Precompiler::DropTypeParameters() {
ObjectStore* object_store = I->object_store();
GrowableObjectArray& retained_typeparams =
GrowableObjectArray::Handle(Z, GrowableObjectArray::New());
Array& typeparams_array = Array::Handle(Z);
TypeParameter& typeparam = TypeParameter::Handle(Z);
// First drop all the type parameters that are not referenced.
{
CanonicalTypeParameterSet typeparams_table(
Z, object_store->canonical_type_parameters());
typeparams_array = HashTables::ToArray(typeparams_table, false);
for (intptr_t i = 0; i < typeparams_array.Length(); i++) {
typeparam ^= typeparams_array.At(i);
bool retain = typeparams_to_retain_.HasKey(&typeparam);
if (retain) {
retained_typeparams.Add(typeparam);
} else {
typeparam.ClearCanonical();
dropped_typeparam_count_++;
}
}
typeparams_table.Release();
}
// Now construct a new type parameter table and save in the object store.
const intptr_t dict_size =
Utils::RoundUpToPowerOfTwo(retained_typeparams.Length() * 4 / 3);
typeparams_array =
HashTables::New<CanonicalTypeParameterSet>(dict_size, Heap::kOld);
CanonicalTypeParameterSet typeparams_table(Z, typeparams_array.raw());
bool present;
for (intptr_t i = 0; i < retained_typeparams.Length(); i++) {
typeparam ^= retained_typeparams.At(i);
present = typeparams_table.Insert(typeparam);
ASSERT(!present);
}
object_store->set_canonical_type_parameters(typeparams_table.Release());
}
void Precompiler::DropTypeArguments() {
ObjectStore* object_store = I->object_store();
Array& typeargs_array = Array::Handle(Z);
-23
View File
@@ -149,26 +149,6 @@ class AbstractTypeKeyValueTrait {
typedef DirectChainedHashMap<AbstractTypeKeyValueTrait> AbstractTypeSet;
class TypeParameterKeyValueTrait {
public:
// Typedefs needed for the DirectChainedHashMap template.
typedef const TypeParameter* Key;
typedef const TypeParameter* Value;
typedef const TypeParameter* Pair;
static Key KeyOf(Pair kv) { return kv; }
static Value ValueOf(Pair kv) { return kv; }
static inline intptr_t Hashcode(Key key) { return key->Hash(); }
static inline bool IsKeyEqual(Pair pair, Key key) {
return pair->raw() == key->raw();
}
};
typedef DirectChainedHashMap<TypeParameterKeyValueTrait> TypeParameterSet;
class TypeArgumentsKeyValueTrait {
public:
// Typedefs needed for the DirectChainedHashMap template.
@@ -290,7 +270,6 @@ class Precompiler : public ValueObject {
void DropFields();
void TraceTypesFromRetainedClasses();
void DropTypes();
void DropTypeParameters();
void DropTypeArguments();
void DropMetadata();
void DropLibraryEntries();
@@ -330,7 +309,6 @@ class Precompiler : public ValueObject {
intptr_t dropped_class_count_;
intptr_t dropped_typearg_count_;
intptr_t dropped_type_count_;
intptr_t dropped_typeparam_count_;
intptr_t dropped_library_count_;
compiler::ObjectPoolBuilder global_object_pool_builder_;
@@ -344,7 +322,6 @@ class Precompiler : public ValueObject {
ClassSet classes_to_retain_;
TypeArgumentsSet typeargs_to_retain_;
AbstractTypeSet types_to_retain_;
TypeParameterSet typeparams_to_retain_;
InstanceSet consts_to_retain_;
TableSelectorSet seen_table_selectors_;
Error& error_;
@@ -671,7 +671,6 @@ void BytecodeReaderHelper::ReadTypeParametersDeclaration(
nullability, TokenPosition::kNoSource);
parameter.set_index(offset + i);
parameter.SetIsFinalized();
parameter.SetCanonical();
type_parameters.SetTypeAt(i, parameter);
}
+5 -107
View File
@@ -1661,12 +1661,6 @@ ErrorPtr Object::Init(Isolate* isolate,
Heap::kOld);
object_store->set_canonical_types(array);
// Initialize hash set for canonical type parameters.
const intptr_t kInitialCanonicalTypeParameterSize = 4;
array = HashTables::New<CanonicalTypeParameterSet>(
kInitialCanonicalTypeParameterSize, Heap::kOld);
object_store->set_canonical_type_parameters(array);
// Initialize hash set for canonical_type_arguments_.
const intptr_t kInitialCanonicalTypeArgumentsSize = 4;
array = HashTables::New<CanonicalTypeArgumentsSet>(
@@ -4894,8 +4888,9 @@ TypePtr Class::DeclarationType() const {
}
// For efficiency, the runtimeType intrinsic returns the type cached by
// DeclarationType without checking its nullability. Therefore, we
// consistently cache the kNonNullable version of the type.
// The exception is type Null which is stored as kNullable.
// consistently cache the kLegacy version of a type, unless the non-nullable
// experiment is enabled, in which case we store the kNonNullable version.
// In either cases, the exception is type Null which is stored as kNullable.
Type& type =
Type::Handle(Type::New(*this, TypeArguments::Handle(type_parameters()),
token_pos(), Nullability::kNonNullable));
@@ -7934,13 +7929,11 @@ FunctionPtr Function::InstantiateSignatureFrom(
cls = type_param.parameterized_class();
param_name = type_param.name();
ASSERT(type_param.IsFinalized());
ASSERT(type_param.IsCanonical());
type_param = TypeParameter::New(
cls, sig, type_param.index(), param_name, type,
type_param.IsGenericCovariantImpl(), type_param.nullability(),
type_param.token_pos());
type_param.SetIsFinalized();
type_param.SetCanonical();
if (instantiated_type_params.IsNull()) {
instantiated_type_params = TypeArguments::New(type_params.Length());
for (intptr_t j = 0; j < i; ++j) {
@@ -19268,6 +19261,7 @@ TypePtr Type::ToNullability(Nullability value, Heap::Space space) const {
ASSERT(!type.IsCanonical());
type ^= type.Canonicalize();
}
// TODO(regis): Should we link canonical types of different nullability?
return type.raw();
}
@@ -20116,11 +20110,7 @@ TypeParameterPtr TypeParameter::ToNullability(Nullability value,
type_parameter.SetHash(0);
type_parameter.SetTypeTestingStub(Code::Handle(
TypeTestingStubGenerator::DefaultCodeForType(type_parameter)));
if (IsCanonical()) {
// Object::Clone does not clone canonical bit.
ASSERT(!type_parameter.IsCanonical());
type_parameter ^= type_parameter.Canonicalize();
}
// TODO(regis): Should we link type parameters of different nullability?
return type_parameter.raw();
}
@@ -20306,90 +20296,6 @@ AbstractTypePtr TypeParameter::InstantiateFrom(
// not only happens at run time, but also during type finalization.
}
AbstractTypePtr TypeParameter::Canonicalize(TrailPtr trail) const {
ASSERT(IsFinalized());
if (IsCanonical()) {
return this->raw();
}
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
const Class& cls = Class::Handle(zone, parameterized_class());
const Function& function = Function::Handle(
zone, cls.IsNull() ? parameterized_function() : Function::null());
const TypeArguments& type_params = TypeArguments::Handle(
zone, cls.IsNull() ? function.type_parameters() : cls.type_parameters());
const intptr_t offset =
cls.IsNull() ? function.NumParentTypeParameters()
: (cls.NumTypeArguments() - cls.NumTypeParameters());
TypeParameter& type_parameter = TypeParameter::Handle(zone);
type_parameter ^= type_params.TypeAt(index() - offset);
ASSERT(!type_parameter.IsNull());
if (type_parameter.nullability() == nullability()) {
ASSERT(this->Equals(type_parameter));
ASSERT(type_parameter.IsCanonical());
ASSERT(type_parameter.IsOld());
return type_parameter.raw();
}
ObjectStore* object_store = isolate->object_store();
{
SafepointMutexLocker ml(isolate->group()->type_canonicalization_mutex());
CanonicalTypeParameterSet table(zone,
object_store->canonical_type_parameters());
type_parameter ^= table.GetOrNull(CanonicalTypeParameterKey(*this));
if (type_parameter.IsNull()) {
// The type parameter was not found in the table. It is not canonical yet.
// Add this type parameter into the canonical list of type parameters.
if (this->IsNew()) {
type_parameter ^= Object::Clone(*this, Heap::kOld);
} else {
type_parameter = this->raw();
}
ASSERT(type_parameter.IsOld());
type_parameter.SetCanonical(); // Mark object as being canonical.
bool present = table.Insert(type_parameter);
ASSERT(!present);
}
object_store->set_canonical_type_parameters(table.Release());
}
return type_parameter.raw();
}
#if defined(DEBUG)
bool TypeParameter::CheckIsCanonical(Thread* thread) const {
Zone* zone = thread->zone();
Isolate* isolate = thread->isolate();
const Class& cls = Class::Handle(zone, parameterized_class());
const Function& function = Function::Handle(
zone, cls.IsNull() ? parameterized_function() : Function::null());
const TypeArguments& type_params = TypeArguments::Handle(
zone, cls.IsNull() ? function.type_parameters() : cls.type_parameters());
const intptr_t offset =
cls.IsNull() ? function.NumParentTypeParameters()
: (cls.NumTypeArguments() - cls.NumTypeParameters());
TypeParameter& type_parameter = TypeParameter::Handle(zone);
type_parameter ^= type_params.TypeAt(index() - offset);
ASSERT(!type_parameter.IsNull());
if (type_parameter.nullability() == nullability()) {
ASSERT(type_parameter.IsCanonical());
return (raw() == type_parameter.raw());
}
ObjectStore* object_store = isolate->object_store();
{
SafepointMutexLocker ml(isolate->group()->type_canonicalization_mutex());
CanonicalTypeParameterSet table(zone,
object_store->canonical_type_parameters());
type_parameter ^= table.GetOrNull(CanonicalTypeParameterKey(*this));
object_store->set_canonical_type_parameters(table.Release());
}
return (raw() == type_parameter.raw());
}
#endif // DEBUG
void TypeParameter::EnumerateURIs(URIs* uris) const {
Thread* thread = Thread::Current();
Zone* zone = thread->zone();
@@ -24366,14 +24272,6 @@ void DumpTypeTable(Isolate* isolate) {
table.Release();
}
void DumpTypeParameterTable(Isolate* isolate) {
OS::PrintErr("canonical type parameters (cloned from declarations):\n");
CanonicalTypeParameterSet table(
isolate->object_store()->canonical_type_parameters());
table.Dump();
table.Release();
}
void DumpTypeArgumentsTable(Isolate* isolate) {
OS::PrintErr("canonical type arguments:\n");
CanonicalTypeArgumentsSet table(
+7 -2
View File
@@ -1097,6 +1097,9 @@ class Class : public Object {
intptr_t NumTypeParameters() const {
return NumTypeParameters(Thread::Current());
}
static intptr_t type_parameters_offset() {
return OFFSET_OF(ClassLayout, type_parameters_);
}
// Return a TypeParameter if the type_name is a type parameter of this class.
// Return null otherwise.
@@ -8173,10 +8176,12 @@ class TypeParameter : public AbstractType {
intptr_t num_free_fun_type_params,
Heap::Space space,
TrailPtr trail = nullptr) const;
virtual AbstractTypePtr Canonicalize(TrailPtr trail = nullptr) const;
virtual AbstractTypePtr Canonicalize(TrailPtr trail = nullptr) const {
return raw();
}
#if defined(DEBUG)
// Check if type parameter is canonical.
virtual bool CheckIsCanonical(Thread* thread) const;
virtual bool CheckIsCanonical(Thread* thread) const { return true; }
#endif // DEBUG
virtual void EnumerateURIs(URIs* uris) const;
-1
View File
@@ -130,7 +130,6 @@ class ObjectPointerVisitor;
RW(Class, weak_property_class) \
RW(Array, symbol_table) \
RW(Array, canonical_types) \
RW(Array, canonical_type_parameters) \
RW(Array, canonical_type_arguments) \
RW(Library, async_library) \
RW(Library, builtin_library) \
-5
View File
@@ -229,7 +229,6 @@ TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
// Allocate type parameter object.
TypeParameter& type_parameter =
TypeParameter::ZoneHandle(reader->zone(), TypeParameter::New());
bool is_canonical = ObjectLayout::IsCanonical(tags);
reader->AddBackRef(object_id, &type_parameter, kIsDeserialized);
// Set all non object fields.
@@ -257,10 +256,6 @@ TypeParameterPtr TypeParameter::ReadFrom(SnapshotReader* reader,
code = TypeTestingStubGenerator::DefaultCodeForType(type_parameter);
type_parameter.SetTypeTestingStub(code);
if (is_canonical) {
type_parameter ^= type_parameter.Canonicalize();
}
return type_parameter.raw();
}
+1 -24
View File
@@ -312,25 +312,21 @@ void Symbols::Compact() {
// 1. Drop the tables and do a full garbage collection.
object_store->set_symbol_table(Object::empty_array());
object_store->set_canonical_types(Object::empty_array());
object_store->set_canonical_type_parameters(Object::empty_array());
object_store->set_canonical_type_arguments(Object::empty_array());
thread->heap()->CollectAllGarbage();
// 2. Walk the heap to find surviving canonical objects.
GrowableArray<String*> symbols;
GrowableArray<class Type*> types;
GrowableArray<class TypeParameter*> type_params;
GrowableArray<class TypeArguments*> type_args;
class SymbolCollector : public ObjectVisitor {
public:
SymbolCollector(Thread* thread,
GrowableArray<String*>* symbols,
GrowableArray<class Type*>* types,
GrowableArray<class TypeParameter*>* type_params,
GrowableArray<class TypeArguments*>* type_args)
: symbols_(symbols),
types_(types),
type_params_(type_params),
type_args_(type_args),
zone_(thread->zone()) {}
@@ -340,9 +336,6 @@ void Symbols::Compact() {
symbols_->Add(&String::Handle(zone_, String::RawCast(obj)));
} else if (obj->IsType()) {
types_->Add(&Type::Handle(zone_, Type::RawCast(obj)));
} else if (obj->IsTypeParameter()) {
type_params_->Add(
&TypeParameter::Handle(zone_, TypeParameter::RawCast(obj)));
} else if (obj->IsTypeArguments()) {
type_args_->Add(
&TypeArguments::Handle(zone_, TypeArguments::RawCast(obj)));
@@ -353,14 +346,13 @@ void Symbols::Compact() {
private:
GrowableArray<String*>* symbols_;
GrowableArray<class Type*>* types_;
GrowableArray<class TypeParameter*>* type_params_;
GrowableArray<class TypeArguments*>* type_args_;
Zone* zone_;
};
{
HeapIterationScope iteration(thread);
SymbolCollector visitor(thread, &symbols, &types, &type_params, &type_args);
SymbolCollector visitor(thread, &symbols, &types, &type_args);
iteration.IterateObjects(&visitor);
}
@@ -395,21 +387,6 @@ void Symbols::Compact() {
object_store->set_canonical_types(table.Release());
}
{
Array& array =
Array::Handle(zone, HashTables::New<CanonicalTypeParameterSet>(
type_params.length() * 4 / 3, Heap::kOld));
CanonicalTypeParameterSet table(zone, array.raw());
for (intptr_t i = 0; i < type_params.length(); i++) {
class TypeParameter& type_param = *type_params[i];
ASSERT(type_param.IsTypeParameter());
ASSERT(type_param.IsCanonical());
bool present = table.Insert(type_param);
ASSERT(!present);
}
object_store->set_canonical_type_parameters(table.Release());
}
{
Array& array =
Array::Handle(zone, HashTables::New<CanonicalTypeArgumentsSet>(
-40
View File
@@ -50,46 +50,6 @@ class CanonicalTypeTraits {
};
typedef UnorderedHashSet<CanonicalTypeTraits> CanonicalTypeSet;
class CanonicalTypeParameterKey {
public:
explicit CanonicalTypeParameterKey(const TypeParameter& key) : key_(key) {}
bool Matches(const TypeParameter& arg) const { return key_.Equals(arg); }
uword Hash() const { return key_.Hash(); }
const TypeParameter& key_;
private:
DISALLOW_ALLOCATION();
};
// Traits for looking up Canonical TypeParameter based on its hash.
class CanonicalTypeParameterTraits {
public:
static const char* Name() { return "CanonicalTypeParameterTraits"; }
static bool ReportStats() { return false; }
// Called when growing the table.
static bool IsMatch(const Object& a, const Object& b) {
ASSERT(a.IsTypeParameter() && b.IsTypeParameter());
const TypeParameter& arg1 = TypeParameter::Cast(a);
const TypeParameter& arg2 = TypeParameter::Cast(b);
return arg1.Equals(arg2) && (arg1.Hash() == arg2.Hash());
}
static bool IsMatch(const CanonicalTypeParameterKey& a, const Object& b) {
ASSERT(b.IsTypeParameter());
return a.Matches(TypeParameter::Cast(b));
}
static uword Hash(const Object& key) {
ASSERT(key.IsTypeParameter());
return TypeParameter::Cast(key).Hash();
}
static uword Hash(const CanonicalTypeParameterKey& key) { return key.Hash(); }
static ObjectPtr NewKey(const CanonicalTypeParameterKey& obj) {
return obj.key_.raw();
}
};
typedef UnorderedHashSet<CanonicalTypeParameterTraits>
CanonicalTypeParameterSet;
class CanonicalTypeArgumentsKey {
public:
explicit CanonicalTypeArgumentsKey(const TypeArguments& key) : key_(key) {}