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

Side by Side 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: 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/object.h" 5 #include "vm/object.h"
6 6
7 #include "include/dart_api.h" 7 #include "include/dart_api.h"
8 #include "platform/assert.h" 8 #include "platform/assert.h"
9 #include "vm/assembler.h" 9 #include "vm/assembler.h"
10 #include "vm/cpu.h" 10 #include "vm/cpu.h"
(...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 object_store->set_empty_context(context); 1077 object_store->set_empty_context(context);
1078 1078
1079 // Now that the symbol table is initialized and that the core dictionary as 1079 // Now that the symbol table is initialized and that the core dictionary as
1080 // well as the core implementation dictionary have been setup, preallocate 1080 // well as the core implementation dictionary have been setup, preallocate
1081 // remaining classes and register them by name in the dictionaries. 1081 // remaining classes and register them by name in the dictionaries.
1082 String& name = String::Handle(isolate); 1082 String& name = String::Handle(isolate);
1083 cls = object_store->array_class(); // Was allocated above. 1083 cls = object_store->array_class(); // Was allocated above.
1084 RegisterPrivateClass(cls, Symbols::_List(), core_lib); 1084 RegisterPrivateClass(cls, Symbols::_List(), core_lib);
1085 pending_classes.Add(cls); 1085 pending_classes.Add(cls);
1086 // We cannot use NewNonParameterizedType(cls), because Array is parameterized. 1086 // We cannot use NewNonParameterizedType(cls), because Array is parameterized.
1087 // Warning: class _List has not been patched yet. Its declared number of type
1088 // parameters is still 0. It will become 1 after patching. The array type
1089 // allocated below represents the raw type _List and not _List<E> as we
1090 // could expect. Use with caution.
1087 type ^= Type::New(Object::Handle(isolate, cls.raw()), 1091 type ^= Type::New(Object::Handle(isolate, cls.raw()),
1088 TypeArguments::Handle(isolate), 1092 TypeArguments::Handle(isolate),
1089 Scanner::kNoSourcePos); 1093 Scanner::kNoSourcePos);
1090 type.SetIsFinalized(); 1094 type.SetIsFinalized();
1091 type ^= type.Canonicalize(); 1095 type ^= type.Canonicalize();
1092 object_store->set_array_type(type); 1096 object_store->set_array_type(type);
1093 1097
1094 cls = object_store->growable_object_array_class(); // Was allocated above. 1098 cls = object_store->growable_object_array_class(); // Was allocated above.
1095 RegisterPrivateClass(cls, Symbols::_GrowableList(), core_lib); 1099 RegisterPrivateClass(cls, Symbols::_GrowableList(), core_lib);
1096 pending_classes.Add(cls); 1100 pending_classes.Add(cls);
(...skipping 770 matching lines...) Expand 10 before | Expand all | Expand 10 after
1867 const Function& function = Function::Handle(signature_function()); 1871 const Function& function = Function::Handle(signature_function());
1868 ASSERT(!function.IsNull()); 1872 ASSERT(!function.IsNull());
1869 if (function.signature_class() != raw()) { 1873 if (function.signature_class() != raw()) {
1870 // This class is a function type alias. Return the canonical signature type. 1874 // This class is a function type alias. Return the canonical signature type.
1871 const Class& canonical_class = Class::Handle(function.signature_class()); 1875 const Class& canonical_class = Class::Handle(function.signature_class());
1872 return canonical_class.SignatureType(); 1876 return canonical_class.SignatureType();
1873 } 1877 }
1874 // Return the first canonical signature type if already computed at class 1878 // Return the first canonical signature type if already computed at class
1875 // finalization time. The optimizer may canonicalize instantiated function 1879 // finalization time. The optimizer may canonicalize instantiated function
1876 // types of the same signature class, but these will be added after the 1880 // types of the same signature class, but these will be added after the
1877 // uninstantiated signature class at index 0. 1881 // uninstantiated signature class at index 1.
1878 Array& signature_types = Array::Handle(); 1882 Array& signature_types = Array::Handle();
1879 signature_types ^= canonical_types(); 1883 signature_types ^= canonical_types();
1880 if (signature_types.IsNull()) { 1884 if (signature_types.IsNull()) {
1881 set_canonical_types(empty_array()); 1885 set_canonical_types(empty_array());
1882 signature_types ^= canonical_types(); 1886 signature_types ^= canonical_types();
1883 } 1887 }
1884 // The canonical_types array is initialized to the empty array. 1888 // The canonical_types array is initialized to the empty array.
1885 ASSERT(!signature_types.IsNull()); 1889 ASSERT(!signature_types.IsNull());
1886 if (signature_types.Length() > 0) { 1890 if (signature_types.Length() > 0) {
1891 ASSERT(signature_types.Length() > 1);
1887 Type& signature_type = Type::Handle(); 1892 Type& signature_type = Type::Handle();
1888 signature_type ^= signature_types.At(0); 1893 signature_type ^= signature_types.At(1);
1889 ASSERT(!signature_type.IsNull()); 1894 ASSERT(!signature_type.IsNull());
1890 return signature_type.raw(); 1895 return signature_type.raw();
1891 } 1896 }
1892 // A signature class extends class Instance and is parameterized in the same 1897 // A signature class extends class Instance and is parameterized in the same
1893 // way as the owner class of its non-static signature function. 1898 // way as the owner class of its non-static signature function.
1894 // It is not type parameterized if its signature function is static. 1899 // It is not type parameterized if its signature function is static.
1895 // See Class::NewSignatureClass() for the setup of its type parameters. 1900 // See Class::NewSignatureClass() for the setup of its type parameters.
1896 // During type finalization, the type arguments of the super class of the 1901 // During type finalization, the type arguments of the super class of the
1897 // owner class of its signature function will be prepended to the type 1902 // owner class of its signature function will be prepended to the type
1898 // argument vector. Therefore, we only need to set the type arguments 1903 // argument vector. Therefore, we only need to set the type arguments
(...skipping 1697 matching lines...) Expand 10 before | Expand all | Expand 10 after
3596 return raw_ptr()->canonical_types_; 3601 return raw_ptr()->canonical_types_;
3597 } 3602 }
3598 3603
3599 3604
3600 void Class::set_canonical_types(const Object& value) const { 3605 void Class::set_canonical_types(const Object& value) const {
3601 ASSERT(!value.IsNull()); 3606 ASSERT(!value.IsNull());
3602 StorePointer(&raw_ptr()->canonical_types_, value.raw()); 3607 StorePointer(&raw_ptr()->canonical_types_, value.raw());
3603 } 3608 }
3604 3609
3605 3610
3606 intptr_t Class::NumCanonicalTypes() const { 3611 RawType* Class::CanonicalType() const {
3607 if (CanonicalType() != Type::null()) { 3612 if ((NumTypeArguments() == 0) && !IsSignatureClass()) {
3608 return 1; 3613 return reinterpret_cast<RawType*>(raw_ptr()->canonical_types_);
3609 } 3614 }
3610 const Object& types = Object::Handle(canonical_types()); 3615 Array& types = Array::Handle();
3611 if (types.IsNull()) { 3616 types ^= canonical_types();
3612 return 0; 3617 if (!types.IsNull() && types.Length() > 0) {
srdjan 2015/08/21 05:02:20 Add parenthesis.
regis 2015/08/21 15:38:21 Done.
3618 return reinterpret_cast<RawType*>(types.At(0));
3613 } 3619 }
3614 intptr_t num_types = Array::Cast(types).Length(); 3620 return reinterpret_cast<RawType*>(Object::null());
3615 while ((num_types > 0) &&
3616 (Array::Cast(types).At(num_types - 1) == Type::null())) {
3617 num_types--;
3618 }
3619 return num_types;
3620 } 3621 }
3621 3622
3622 3623
3624 void Class::SetCanonicalType(const Type& type) const {
3625 ASSERT(type.IsCanonical());
3626 if ((NumTypeArguments() == 0) && !IsSignatureClass()) {
srdjan 2015/08/21 05:02:20 Should we factor out this test? Only if we can com
regis 2015/08/21 15:38:21 I cannot think of a good name :-) In any case, I t
3627 ASSERT((canonical_types() == Object::null() ||
3628 (canonical_types() == type.raw()))); // Set during own finalization.
3629 set_canonical_types(type);
srdjan 2015/08/21 05:02:20 Can we clear it ever, i.e., type -> null ? If it i
regis 2015/08/21 15:38:21 No, we cannot clear it. However, from the time we
3630 } else {
3631 Array& types = Array::Handle();
3632 types ^= canonical_types();
3633 ASSERT(!types.IsNull() && (types.Length() > 1));
3634 ASSERT((types.At(0) == Object::null()) || (types.At(0) == type.raw()));
3635 types.SetAt(0, type);
3636 }
3637 }
3638
3639
3623 intptr_t Class::FindCanonicalTypeIndex(const Type& needle) const { 3640 intptr_t Class::FindCanonicalTypeIndex(const Type& needle) const {
3624 Isolate* isolate = Isolate::Current(); 3641 Isolate* isolate = Isolate::Current();
3625 if (EnsureIsFinalized(isolate) != Error::null()) { 3642 if (EnsureIsFinalized(isolate) != Error::null()) {
3626 return -1; 3643 return -1;
3627 } 3644 }
3628 if (needle.raw() == CanonicalType()) { 3645 if (needle.raw() == CanonicalType()) {
3646 // For a generic type or signature type, there exists another index with the
3647 // same type. It will never be returned by this function.
3629 return 0; 3648 return 0;
3630 } 3649 }
3631 REUSABLE_OBJECT_HANDLESCOPE(isolate); 3650 REUSABLE_OBJECT_HANDLESCOPE(isolate);
3632 Object& types = isolate->ObjectHandle(); 3651 Object& types = isolate->ObjectHandle();
3633 types = canonical_types(); 3652 types = canonical_types();
3634 if (types.IsNull()) { 3653 if (types.IsNull()) {
3635 return -1; 3654 return -1;
3636 } 3655 }
3637 const intptr_t len = Array::Cast(types).Length(); 3656 const intptr_t len = Array::Cast(types).Length();
3638 REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(isolate); 3657 REUSABLE_ABSTRACT_TYPE_HANDLESCOPE(isolate);
(...skipping 10745 matching lines...) Expand 10 before | Expand all | Expand 10 after
14384 result.SetCanonical(); 14403 result.SetCanonical();
14385 return result.raw(); 14404 return result.raw();
14386 } 14405 }
14387 14406
14388 14407
14389 RawType* Instance::GetType() const { 14408 RawType* Instance::GetType() const {
14390 if (IsNull()) { 14409 if (IsNull()) {
14391 return Type::NullType(); 14410 return Type::NullType();
14392 } 14411 }
14393 const Class& cls = Class::Handle(clazz()); 14412 const Class& cls = Class::Handle(clazz());
14394 Type& type = Type::Handle(cls.CanonicalType()); 14413 Type& type = Type::Handle();
14414 if (cls.NumTypeArguments() == 0) {
14415 type = cls.CanonicalType();
14416 }
14395 if (type.IsNull()) { 14417 if (type.IsNull()) {
14396 TypeArguments& type_arguments = TypeArguments::Handle(); 14418 TypeArguments& type_arguments = TypeArguments::Handle();
14397 if (cls.NumTypeArguments() > 0) { 14419 if (cls.NumTypeArguments() > 0) {
14398 type_arguments = GetTypeArguments(); 14420 type_arguments = GetTypeArguments();
14399 } 14421 }
14400 type = Type::New(cls, type_arguments, Scanner::kNoSourcePos); 14422 type = Type::New(cls, type_arguments, Scanner::kNoSourcePos);
14401 type.SetIsFinalized(); 14423 type.SetIsFinalized();
14402 type ^= type.Canonicalize(); 14424 type ^= type.Canonicalize();
14403 } 14425 }
14404 return type.raw(); 14426 return type.raw();
(...skipping 1254 matching lines...) Expand 10 before | Expand all | Expand 10 after
15659 Array& canonical_types = Array::Handle(isolate); 15681 Array& canonical_types = Array::Handle(isolate);
15660 canonical_types ^= cls.canonical_types(); 15682 canonical_types ^= cls.canonical_types();
15661 if (canonical_types.IsNull()) { 15683 if (canonical_types.IsNull()) {
15662 canonical_types = empty_array().raw(); 15684 canonical_types = empty_array().raw();
15663 } 15685 }
15664 intptr_t length = canonical_types.Length(); 15686 intptr_t length = canonical_types.Length();
15665 // Linear search to see whether this type is already present in the 15687 // Linear search to see whether this type is already present in the
15666 // list of canonicalized types. 15688 // list of canonicalized types.
15667 // TODO(asiva): Try to re-factor this lookup code to make sharing 15689 // TODO(asiva): Try to re-factor this lookup code to make sharing
15668 // easy between the 4 versions of this loop. 15690 // easy between the 4 versions of this loop.
15669 intptr_t index = 0; 15691 intptr_t index = 1; // Slot 0 is reserved for CanonicalType().
15670 while (index < length) { 15692 while (index < length) {
15671 type ^= canonical_types.At(index); 15693 type ^= canonical_types.At(index);
15672 if (type.IsNull()) { 15694 if (type.IsNull()) {
15673 break; 15695 break;
15674 } 15696 }
15675 ASSERT(type.IsFinalized()); 15697 ASSERT(type.IsFinalized());
15676 if (this->Equals(type)) { 15698 if (this->Equals(type)) {
15677 ASSERT(type.IsCanonical()); 15699 ASSERT(type.IsCanonical());
15678 return type.raw(); 15700 return type.raw();
15679 } 15701 }
(...skipping 23 matching lines...) Expand all
15703 } 15725 }
15704 ASSERT(type.IsFinalized()); 15726 ASSERT(type.IsFinalized());
15705 if (this->Equals(type)) { 15727 if (this->Equals(type)) {
15706 ASSERT(type.IsCanonical()); 15728 ASSERT(type.IsCanonical());
15707 return type.raw(); 15729 return type.raw();
15708 } 15730 }
15709 index++; 15731 index++;
15710 } 15732 }
15711 15733
15712 // The type needs to be added to the list. Grow the list if it is full. 15734 // The type needs to be added to the list. Grow the list if it is full.
15713 if (index == length) { 15735 if (index >= length) {
15736 ASSERT((index == length) || ((index == 1) && (length == 0)));
15714 const intptr_t new_length = (length > 64) ? 15737 const intptr_t new_length = (length > 64) ?
15715 (length + 64) : 15738 (length + 64) :
15716 ((length == 0) ? 1 : (length * 2)); 15739 ((length == 0) ? 2 : (length * 2));
15717 const Array& new_canonical_types = Array::Handle( 15740 const Array& new_canonical_types = Array::Handle(
15718 isolate, Array::Grow(canonical_types, new_length, Heap::kOld)); 15741 isolate, Array::Grow(canonical_types, new_length, Heap::kOld));
15719 cls.set_canonical_types(new_canonical_types); 15742 cls.set_canonical_types(new_canonical_types);
15720 new_canonical_types.SetAt(index, *this); 15743 new_canonical_types.SetAt(index, *this);
15721 } else { 15744 } else {
15722 canonical_types.SetAt(index, *this); 15745 canonical_types.SetAt(index, *this);
15723 } 15746 }
15724 #ifdef DEBUG 15747 #ifdef DEBUG
15725 if ((index == 0) && cls.IsCanonicalSignatureClass()) { 15748 if ((index == 1) && cls.IsCanonicalSignatureClass()) {
15726 // Verify that the first canonical type is the signature type by checking 15749 // Verify that the first canonical type is the signature type by checking
15727 // that the type argument vector of the canonical type ends with the 15750 // that the type argument vector of the canonical type ends with the
15728 // uninstantiated type parameters of the signature class. Note that these 15751 // uninstantiated type parameters of the signature class. Note that these
15729 // type parameters may be bounded if the super class of the owner class 15752 // type parameters may be bounded if the super class of the owner class
15730 // declares bounds. 15753 // declares bounds.
15731 // The signature type is finalized during class finalization, before the 15754 // The signature type is finalized during class finalization, before the
15732 // optimizer may canonicalize instantiated function types of the same 15755 // optimizer may canonicalize instantiated function types of the same
15733 // signature class. 15756 // signature class.
15734 // Although the signature class extends class Instance, the type arguments 15757 // Although the signature class extends class Instance, the type arguments
15735 // of the super class of the owner class of its signature function will be 15758 // of the super class of the owner class of its signature function will be
(...skipping 5679 matching lines...) Expand 10 before | Expand all | Expand 10 after
21415 return tag_label.ToCString(); 21438 return tag_label.ToCString();
21416 } 21439 }
21417 21440
21418 21441
21419 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const { 21442 void UserTag::PrintJSONImpl(JSONStream* stream, bool ref) const {
21420 Instance::PrintJSONImpl(stream, ref); 21443 Instance::PrintJSONImpl(stream, ref);
21421 } 21444 }
21422 21445
21423 21446
21424 } // namespace dart 21447 } // namespace dart
OLDNEW
« runtime/vm/object.h ('K') | « runtime/vm/object.h ('k') | runtime/vm/parser.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698