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

Unified Diff: runtime/vm/object.cc

Issue 1309613002: Avoid numerous type allocations by caching the canonical type of a class, which (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: address comments Created 5 years, 4 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/parser.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 f59846deb74321e36777d443c89634c572baf535..ece71d1a49de825fc7e48a16b6596918d07b40ea 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -1084,6 +1084,10 @@ RawError* Object::Init(Isolate* isolate) {
RegisterPrivateClass(cls, Symbols::_List(), core_lib);
pending_classes.Add(cls);
// We cannot use NewNonParameterizedType(cls), because Array is parameterized.
+ // Warning: class _List has not been patched yet. Its declared number of type
+ // parameters is still 0. It will become 1 after patching. The array type
+ // allocated below represents the raw type _List and not _List<E> as we
+ // could expect. Use with caution.
type ^= Type::New(Object::Handle(isolate, cls.raw()),
TypeArguments::Handle(isolate),
Scanner::kNoSourcePos);
@@ -1874,7 +1878,7 @@ RawType* Class::SignatureType() const {
// Return the first canonical signature type if already computed at class
// finalization time. The optimizer may canonicalize instantiated function
// types of the same signature class, but these will be added after the
- // uninstantiated signature class at index 0.
+ // uninstantiated signature class at index 1.
Array& signature_types = Array::Handle();
signature_types ^= canonical_types();
if (signature_types.IsNull()) {
@@ -1884,8 +1888,9 @@ RawType* Class::SignatureType() const {
// The canonical_types array is initialized to the empty array.
ASSERT(!signature_types.IsNull());
if (signature_types.Length() > 0) {
+ ASSERT(signature_types.Length() > 1);
Type& signature_type = Type::Handle();
- signature_type ^= signature_types.At(0);
+ signature_type ^= signature_types.At(1);
ASSERT(!signature_type.IsNull());
return signature_type.raw();
}
@@ -3603,20 +3608,32 @@ void Class::set_canonical_types(const Object& value) const {
}
-intptr_t Class::NumCanonicalTypes() const {
- if (CanonicalType() != Type::null()) {
- return 1;
+RawType* Class::CanonicalType() const {
+ if ((NumTypeArguments() == 0) && !IsSignatureClass()) {
+ return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_);
}
- const Object& types = Object::Handle(canonical_types());
- if (types.IsNull()) {
- return 0;
+ Array& types = Array::Handle();
+ types ^= canonical_types();
+ if (!types.IsNull() && (types.Length() > 0)) {
+ return reinterpret_cast<RawType*>(types.At(0));
}
- intptr_t num_types = Array::Cast(types).Length();
- while ((num_types > 0) &&
- (Array::Cast(types).At(num_types - 1) == Type::null())) {
- num_types--;
+ return reinterpret_cast<RawType*>(Object::null());
+}
+
+
+void Class::SetCanonicalType(const Type& type) const {
+ ASSERT(type.IsCanonical());
+ if ((NumTypeArguments() == 0) && !IsSignatureClass()) {
+ 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);
}
- return num_types;
}
@@ -3626,6 +3643,8 @@ intptr_t Class::FindCanonicalTypeIndex(const Type& needle) const {
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(isolate);
@@ -14391,7 +14410,10 @@ RawType* Instance::GetType() const {
return Type::NullType();
}
const Class& cls = Class::Handle(clazz());
- Type& type = Type::Handle(cls.CanonicalType());
+ Type& type = Type::Handle();
+ if (cls.NumTypeArguments() == 0) {
+ type = cls.CanonicalType();
+ }
if (type.IsNull()) {
TypeArguments& type_arguments = TypeArguments::Handle();
if (cls.NumTypeArguments() > 0) {
@@ -15666,7 +15688,7 @@ RawAbstractType* Type::Canonicalize(GrowableObjectArray* trail) const {
// 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 = 0;
+ intptr_t index = 1; // Slot 0 is reserved for CanonicalType().
while (index < length) {
type ^= canonical_types.At(index);
if (type.IsNull()) {
@@ -15710,10 +15732,11 @@ RawAbstractType* Type::Canonicalize(GrowableObjectArray* trail) const {
}
// The type needs to be added to the list. Grow the list if it is full.
- if (index == length) {
+ if (index >= length) {
+ ASSERT((index == length) || ((index == 1) && (length == 0)));
const intptr_t new_length = (length > 64) ?
(length + 64) :
- ((length == 0) ? 1 : (length * 2));
+ ((length == 0) ? 2 : (length * 2));
const Array& new_canonical_types = Array::Handle(
isolate, Array::Grow(canonical_types, new_length, Heap::kOld));
cls.set_canonical_types(new_canonical_types);
@@ -15722,7 +15745,7 @@ RawAbstractType* Type::Canonicalize(GrowableObjectArray* trail) const {
canonical_types.SetAt(index, *this);
}
#ifdef DEBUG
- if ((index == 0) && cls.IsCanonicalSignatureClass()) {
+ if ((index == 1) && cls.IsCanonicalSignatureClass()) {
// Verify that the first canonical type is the signature type by checking
// that the type argument vector of the canonical type ends with the
// uninstantiated type parameters of the signature class. Note that these
« no previous file with comments | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698