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

Side by Side Diff: runtime/vm/object.cc

Issue 11474056: Store canonical type argments in a hash table instead of linear list. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years 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 | Annotate | Revision Log
« runtime/vm/object.h ('K') | « runtime/vm/object.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/bigint_operations.h" 10 #include "vm/bigint_operations.h"
(...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after
566 // declared in RawArray. 566 // declared in RawArray.
567 cls.set_type_arguments_field_offset(Array::type_arguments_offset()); 567 cls.set_type_arguments_field_offset(Array::type_arguments_offset());
568 568
569 // Set up the growable object array class (Has to be done after the array 569 // Set up the growable object array class (Has to be done after the array
570 // class is setup as one of its field is an array object). 570 // class is setup as one of its field is an array object).
571 cls = Class::New<GrowableObjectArray>(); 571 cls = Class::New<GrowableObjectArray>();
572 object_store->set_growable_object_array_class(cls); 572 object_store->set_growable_object_array_class(cls);
573 cls.set_type_arguments_field_offset( 573 cls.set_type_arguments_field_offset(
574 GrowableObjectArray::type_arguments_offset()); 574 GrowableObjectArray::type_arguments_offset());
575 575
576 // canonical_type_arguments_ are NULL terminated. 576 // canonical_type_arguments_ are Smi terminated.
577 array = Array::New(4); 577 // Last element contains the count of used slots.
578 const intptr_t kInitialCanonicalTypeArgumentsSize = 4;
579 array = Array::New(kInitialCanonicalTypeArgumentsSize + 1);
580 array.SetAt(kInitialCanonicalTypeArgumentsSize, Smi::Handle(Smi::New(0)));
578 object_store->set_canonical_type_arguments(array); 581 object_store->set_canonical_type_arguments(array);
579 582
580 // Setup type class early in the process. 583 // Setup type class early in the process.
581 cls = Class::New<Type>(); 584 cls = Class::New<Type>();
582 object_store->set_type_class(cls); 585 object_store->set_type_class(cls);
583 586
584 cls = Class::New<TypeParameter>(); 587 cls = Class::New<TypeParameter>();
585 object_store->set_type_parameter_class(cls); 588 object_store->set_type_parameter_class(cls);
586 589
587 // Pre-allocate the OneByteString class needed by the symbol table. 590 // Pre-allocate the OneByteString class needed by the symbol table.
(...skipping 1905 matching lines...) Expand 10 before | Expand all | Expand 10 after
2493 } 2496 }
2494 2497
2495 2498
2496 bool AbstractTypeArguments::IsUninstantiatedIdentity() const { 2499 bool AbstractTypeArguments::IsUninstantiatedIdentity() const {
2497 // AbstractTypeArguments is an abstract class. 2500 // AbstractTypeArguments is an abstract class.
2498 UNREACHABLE(); 2501 UNREACHABLE();
2499 return false; 2502 return false;
2500 } 2503 }
2501 2504
2502 2505
2506 static uword FinalizeHash(uword hash) {
2507 hash += hash << 3;
2508 hash ^= hash >> 11;
2509 hash += hash << 15;
2510 return hash;
2511 }
2512
2513
2514 uword AbstractTypeArguments::Hash() const {
2515 if (IsNull()) return 0;
2516 uword result = 0;
2517 intptr_t num_types = Length();
2518 AbstractType& type = AbstractType::Handle();
2519 for (intptr_t i = 0; i < num_types; i++) {
2520 type = TypeAt(i);
2521 result += type.Hash();
2522 result += result << 10;
2523 result ^= result >> 6;
2524 }
2525 return FinalizeHash(result);
2526 }
2527
2528
2503 RawString* AbstractTypeArguments::SubvectorName( 2529 RawString* AbstractTypeArguments::SubvectorName(
2504 intptr_t from_index, 2530 intptr_t from_index,
2505 intptr_t len, 2531 intptr_t len,
2506 NameVisibility name_visibility) const { 2532 NameVisibility name_visibility) const {
2507 ASSERT(from_index + len <= Length()); 2533 ASSERT(from_index + len <= Length());
2508 String& name = String::Handle(); 2534 String& name = String::Handle();
2509 const intptr_t num_strings = 2*len + 1; // "<""T"", ""T"">". 2535 const intptr_t num_strings = 2*len + 1; // "<""T"", ""T"">".
2510 const Array& strings = Array::Handle(Array::New(num_strings)); 2536 const Array& strings = Array::Handle(Array::New(num_strings));
2511 intptr_t s = 0; 2537 intptr_t s = 0;
2512 strings.SetAt(s++, String::Handle(Symbols::New("<"))); 2538 strings.SetAt(s++, String::Handle(Symbols::New("<")));
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after
2702 } 2728 }
2703 2729
2704 2730
2705 const char* AbstractTypeArguments::ToCString() const { 2731 const char* AbstractTypeArguments::ToCString() const {
2706 // AbstractTypeArguments is an abstract class, valid only for representing 2732 // AbstractTypeArguments is an abstract class, valid only for representing
2707 // null. 2733 // null.
2708 if (IsNull()) { 2734 if (IsNull()) {
2709 return "NULL AbstractTypeArguments"; 2735 return "NULL AbstractTypeArguments";
2710 } 2736 }
2711 UNREACHABLE(); 2737 UNREACHABLE();
2712 return "AbstractTypeArguments"; 2738 return NULL;
Ivan Posva 2012/12/12 21:25:10 Please leave this as it was. All other abstract cl
Florian Schneider 2012/12/13 11:59:45 Fine.
2713 } 2739 }
2714 2740
2715 2741
2716 intptr_t TypeArguments::Length() const { 2742 intptr_t TypeArguments::Length() const {
2717 ASSERT(!IsNull()); 2743 ASSERT(!IsNull());
2718 return Smi::Value(raw_ptr()->length_); 2744 return Smi::Value(raw_ptr()->length_);
2719 } 2745 }
2720 2746
2721 2747
2722 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const { 2748 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const {
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
2826 2852
2827 2853
2828 void TypeArguments::SetLength(intptr_t value) const { 2854 void TypeArguments::SetLength(intptr_t value) const {
2829 ASSERT(!IsCanonical()); 2855 ASSERT(!IsCanonical());
2830 // This is only safe because we create a new Smi, which does not cause 2856 // This is only safe because we create a new Smi, which does not cause
2831 // heap allocation. 2857 // heap allocation.
2832 raw_ptr()->length_ = Smi::New(value); 2858 raw_ptr()->length_ = Smi::New(value);
2833 } 2859 }
2834 2860
2835 2861
2862 static void GrowCanonicalTypeArguments(Isolate* isolate, const Array& table) {
Ivan Posva 2012/12/12 21:25:10 Do not pass Isolate as a parameter unless it is a
2863 // Last element of the array is the number of used elements.
2864 intptr_t table_size = table.Length() - 1;
2865 intptr_t new_table_size = table_size * 2;
2866 Array& new_table = Array::Handle(isolate, Array::New(new_table_size + 1));
2867 // Copy all elements from the original table to the newly allocated
2868 // array.
2869 TypeArguments& element = TypeArguments::Handle(isolate);
2870 Object& new_element = Object::Handle(isolate);
2871 for (intptr_t i = 0; i < table_size; i++) {
2872 element ^= table.At(i);
2873 if (!element.IsNull()) {
2874 intptr_t hash = element.Hash();
2875 ASSERT(Utils::IsPowerOfTwo(new_table_size));
2876 intptr_t index = hash & (new_table_size - 1);
2877 new_element = new_table.At(index);
2878 while (!new_element.IsNull()) {
2879 index = (index + 1) & (new_table_size - 1); // Move to next element.
2880 new_element = new_table.At(index);
2881 }
2882 new_table.SetAt(index, element);
2883 }
2884 }
2885 // Copy used count.
2886 new_element = table.At(table_size);
2887 new_table.SetAt(new_table_size, new_element);
2888 // Remember the new table now.
2889 isolate->object_store()->set_canonical_type_arguments(new_table);
2890 }
2891
2892
2893 static void InsertIntoCanonicalTypeArguments(Isolate* isolate,
Ivan Posva 2012/12/12 21:25:10 ditto
2894 const Array& table,
2895 const TypeArguments& arguments,
2896 intptr_t index) {
2897 arguments.SetCanonical(); // Mark object as being canonical.
2898 table.SetAt(index, arguments); // Remember the new element.
2899 // Update used count.
2900 // Last element of the array is the number of used elements.
2901 intptr_t table_size = table.Length() - 1;
2902 Smi& used = Smi::Handle(isolate);
2903 used ^= table.At(table_size);
2904 intptr_t used_elements = used.Value() + 1;
2905 used = Smi::New(used_elements);
2906 table.SetAt(table_size, used);
2907
2908 // Rehash if table is 75% full.
2909 if (used_elements > ((table_size / 4) * 3)) {
2910 GrowCanonicalTypeArguments(isolate, table);
2911 }
2912 }
2913
2914
2915 static intptr_t FindIndexInCanonicalTypeArguments(
2916 Isolate* isolate,
Ivan Posva 2012/12/12 21:25:10 ditto
Florian Schneider 2012/12/13 11:59:45 This is frequently called in checked mode. The two
2917 const Array& table,
2918 const TypeArguments& arguments,
2919 intptr_t hash) {
2920 // Last element of the array is the number of used elements.
2921 intptr_t table_size = table.Length() - 1;
2922 ASSERT(Utils::IsPowerOfTwo(table_size));
2923 intptr_t index = hash & (table_size - 1);
2924
2925 TypeArguments& current = TypeArguments::Handle(isolate);
2926 current ^= table.At(index);
2927 while (!current.IsNull() && !current.Equals(arguments)) {
2928 index = (index + 1) & (table_size - 1); // Move to next element.
2929 current ^= table.At(index);
2930 }
2931 return index; // Index of element if found or slot into which to add it.
2932 }
2933
2934
2836 RawAbstractTypeArguments* TypeArguments::Canonicalize() const { 2935 RawAbstractTypeArguments* TypeArguments::Canonicalize() const {
2837 if (IsNull() || IsCanonical()) { 2936 if (IsNull() || IsCanonical()) {
2838 ASSERT(IsOld()); 2937 ASSERT(IsOld());
2839 return this->raw(); 2938 return this->raw();
2840 } 2939 }
2841 ObjectStore* object_store = Isolate::Current()->object_store(); 2940 Isolate* isolate = Isolate::Current();
2842 // 'table' must be null terminated. 2941 ObjectStore* object_store = isolate->object_store();
2843 Array& table = Array::Handle(object_store->canonical_type_arguments()); 2942 const Array& table = Array::Handle(isolate,
2943 object_store->canonical_type_arguments());
2844 ASSERT(table.Length() > 0); 2944 ASSERT(table.Length() > 0);
2845 intptr_t index = 0; 2945 TypeArguments& self = TypeArguments::Handle(isolate, this->raw());
Ivan Posva 2012/12/12 21:25:10 Why do you need to allocate a new handle here? thi
Florian Schneider 2012/12/13 11:59:45 Done.
2846 TypeArguments& result = TypeArguments::Handle(); 2946 intptr_t index = FindIndexInCanonicalTypeArguments(isolate,
2947 table,
2948 self,
2949 Hash());
2950 TypeArguments& result = TypeArguments::Handle(isolate);
2847 result ^= table.At(index); 2951 result ^= table.At(index);
2848 while (!result.IsNull()) { 2952 if (result.IsNull()) {
2849 if (this->Equals(result)) { 2953 // Make sure we have an old space object and add it to the table.
2850 return result.raw(); 2954 result ^= this->raw();
Ivan Posva 2012/12/12 21:25:10 if (this->IsNew()) { result ^= Object::Clone(...
Florian Schneider 2012/12/13 11:59:45 Done.
2955 if (result.IsNew()) {
2956 result ^= Object::Clone(result, Heap::kOld);
2851 } 2957 }
2852 result ^= table.At(++index); 2958 ASSERT(result.IsOld());
2959 InsertIntoCanonicalTypeArguments(isolate, table, result, index);
2853 } 2960 }
2854 // Not found. Add 'this' to table. 2961 ASSERT(result.Equals(self));
2855 result ^= this->raw(); 2962 ASSERT(!result.IsNull());
2856 if (result.IsNew()) { 2963 ASSERT(result.IsTypeArguments());
2857 result ^= Object::Clone(result, Heap::kOld);
2858 }
2859 ASSERT(result.IsOld());
2860 if (index == table.Length() - 1) {
2861 table = Array::Grow(table, table.Length() + 4, Heap::kOld);
2862 object_store->set_canonical_type_arguments(table);
2863 }
2864 table.SetAt(index, result);
2865 result.SetCanonical();
2866 return result.raw(); 2964 return result.raw();
2867 } 2965 }
2868 2966
2869 2967
2870 const char* TypeArguments::ToCString() const { 2968 const char* TypeArguments::ToCString() const {
2871 if (IsNull()) { 2969 if (IsNull()) {
2872 return "NULL TypeArguments"; 2970 return "NULL TypeArguments";
2873 } 2971 }
2874 const char* format = "%s [%s]"; 2972 const char* format = "%s [%s]";
2875 const char* prev_cstr = "TypeArguments:"; 2973 const char* prev_cstr = "TypeArguments:";
(...skipping 5831 matching lines...) Expand 10 before | Expand all | Expand 10 after
8707 } 8805 }
8708 const Class& cls = Class::Handle(type_class()); 8806 const Class& cls = Class::Handle(type_class());
8709 return cls.TypeTest(test_kind, 8807 return cls.TypeTest(test_kind,
8710 AbstractTypeArguments::Handle(arguments()), 8808 AbstractTypeArguments::Handle(arguments()),
8711 Class::Handle(other.type_class()), 8809 Class::Handle(other.type_class()),
8712 AbstractTypeArguments::Handle(other.arguments()), 8810 AbstractTypeArguments::Handle(other.arguments()),
8713 malformed_error); 8811 malformed_error);
8714 } 8812 }
8715 8813
8716 8814
8815 uword AbstractType::Hash() const {
8816 // AbstractType is an abstract class.
8817 UNREACHABLE();
8818 return 0;
8819 }
8820
8821
8717 const char* AbstractType::ToCString() const { 8822 const char* AbstractType::ToCString() const {
8718 // AbstractType is an abstract class. 8823 // AbstractType is an abstract class.
8719 UNREACHABLE(); 8824 UNREACHABLE();
8720 return "AbstractType"; 8825 return "AbstractType";
8721 } 8826 }
8722 8827
8723 8828
8724 RawType* Type::NullType() { 8829 RawType* Type::NullType() {
8725 return Isolate::Current()->object_store()->null_type(); 8830 return Isolate::Current()->object_store()->null_type();
8726 } 8831 }
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after
8981 new_canonical_types.SetAt(index, *this); 9086 new_canonical_types.SetAt(index, *this);
8982 } else { 9087 } else {
8983 canonical_types.SetAt(index, *this); 9088 canonical_types.SetAt(index, *this);
8984 } 9089 }
8985 ASSERT(IsOld()); 9090 ASSERT(IsOld());
8986 SetCanonical(); 9091 SetCanonical();
8987 return this->raw(); 9092 return this->raw();
8988 } 9093 }
8989 9094
8990 9095
9096 uword Type::Hash() const {
9097 ASSERT(IsFinalized());
9098 uword result = 1;
9099 if (IsMalformed()) return result;
9100 result += Class::Handle(type_class()).id();
9101 result += AbstractTypeArguments::Handle(arguments()).Hash();
9102 return FinalizeHash(result);
9103 }
9104
9105
8991 void Type::set_type_class(const Object& value) const { 9106 void Type::set_type_class(const Object& value) const {
8992 ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass())); 9107 ASSERT(!value.IsNull() && (value.IsClass() || value.IsUnresolvedClass()));
8993 StorePointer(&raw_ptr()->type_class_, value.raw()); 9108 StorePointer(&raw_ptr()->type_class_, value.raw());
8994 } 9109 }
8995 9110
8996 9111
8997 void Type::set_arguments(const AbstractTypeArguments& value) const { 9112 void Type::set_arguments(const AbstractTypeArguments& value) const {
8998 StorePointer(&raw_ptr()->arguments_, value.raw()); 9113 StorePointer(&raw_ptr()->arguments_, value.raw());
8999 } 9114 }
9000 9115
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
9084 const TypeParameter& other_type_param = TypeParameter::Cast(other); 9199 const TypeParameter& other_type_param = TypeParameter::Cast(other);
9085 if (IsFinalized() != other_type_param.IsFinalized()) { 9200 if (IsFinalized() != other_type_param.IsFinalized()) {
9086 return false; 9201 return false;
9087 } 9202 }
9088 if (parameterized_class() != other_type_param.parameterized_class()) { 9203 if (parameterized_class() != other_type_param.parameterized_class()) {
9089 return false; 9204 return false;
9090 } 9205 }
9091 if (index() != other_type_param.index()) { 9206 if (index() != other_type_param.index()) {
9092 return false; 9207 return false;
9093 } 9208 }
9094 const String& type_param_name = String::Handle(name()); 9209 return true;
Ivan Posva 2012/12/12 21:25:10 Thanks for simplifying this.
9095 const String& other_type_param_name = String::Handle(other_type_param.name());
9096 return type_param_name.Equals(other_type_param_name);
9097 } 9210 }
9098 9211
9099 9212
9100 void TypeParameter::set_parameterized_class(const Class& value) const { 9213 void TypeParameter::set_parameterized_class(const Class& value) const {
9101 // Set value may be null. 9214 // Set value may be null.
9102 StorePointer(&raw_ptr()->parameterized_class_, value.raw()); 9215 StorePointer(&raw_ptr()->parameterized_class_, value.raw());
9103 } 9216 }
9104 9217
9105 9218
9106 void TypeParameter::set_index(intptr_t value) const { 9219 void TypeParameter::set_index(intptr_t value) const {
(...skipping 15 matching lines...) Expand all
9122 RawAbstractType* TypeParameter::InstantiateFrom( 9235 RawAbstractType* TypeParameter::InstantiateFrom(
9123 const AbstractTypeArguments& instantiator_type_arguments) const { 9236 const AbstractTypeArguments& instantiator_type_arguments) const {
9124 ASSERT(IsFinalized()); 9237 ASSERT(IsFinalized());
9125 if (instantiator_type_arguments.IsNull()) { 9238 if (instantiator_type_arguments.IsNull()) {
9126 return Type::DynamicType(); 9239 return Type::DynamicType();
9127 } 9240 }
9128 return instantiator_type_arguments.TypeAt(index()); 9241 return instantiator_type_arguments.TypeAt(index());
9129 } 9242 }
9130 9243
9131 9244
9245 uword TypeParameter::Hash() const {
9246 ASSERT(IsFinalized());
9247 uword result = 0;
9248 result += Class::Handle(parameterized_class()).id();
9249 result <<= index();
9250 return FinalizeHash(result);
9251 }
9252
9253
9132 RawTypeParameter* TypeParameter::New() { 9254 RawTypeParameter* TypeParameter::New() {
9133 ASSERT(Isolate::Current()->object_store()->type_parameter_class() != 9255 ASSERT(Isolate::Current()->object_store()->type_parameter_class() !=
9134 Class::null()); 9256 Class::null());
9135 RawObject* raw = Object::Allocate(TypeParameter::kClassId, 9257 RawObject* raw = Object::Allocate(TypeParameter::kClassId,
9136 TypeParameter::InstanceSize(), 9258 TypeParameter::InstanceSize(),
9137 Heap::kOld); 9259 Heap::kOld);
9138 return reinterpret_cast<RawTypeParameter*>(raw); 9260 return reinterpret_cast<RawTypeParameter*>(raw);
9139 } 9261 }
9140 9262
9141 9263
(...skipping 3157 matching lines...) Expand 10 before | Expand all | Expand 10 after
12299 } 12421 }
12300 return result.raw(); 12422 return result.raw();
12301 } 12423 }
12302 12424
12303 12425
12304 const char* WeakProperty::ToCString() const { 12426 const char* WeakProperty::ToCString() const {
12305 return "_WeakProperty"; 12427 return "_WeakProperty";
12306 } 12428 }
12307 12429
12308 } // namespace dart 12430 } // namespace dart
OLDNEW
« runtime/vm/object.h ('K') | « runtime/vm/object.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698