Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 NULL terminated. |
|
Ivan Posva
2012/12/10 20:07:52
Comment out of date.
srdjan
2012/12/10 21:19:37
Fix comment: Smi terminated.
Florian Schneider
2012/12/11 12:23:04
Done.
Florian Schneider
2012/12/11 12:23:04
Done.
Florian Schneider
2012/12/11 12:23:04
Done.
| |
| 577 array = Array::New(4); | 577 const intptr_t kInitialCanonicalTypeArgumentsSize = 4; |
|
srdjan
2012/12/10 21:19:37
Seems too small as initial size.
Florian Schneider
2012/12/11 12:23:04
I don't want to wast space for programs that don't
| |
| 578 array = Array::New(kInitialCanonicalTypeArgumentsSize + 1); | |
| 579 // Last element contains the count of used slots. | |
| 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 2114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2702 } | 2705 } |
| 2703 | 2706 |
| 2704 | 2707 |
| 2705 const char* AbstractTypeArguments::ToCString() const { | 2708 const char* AbstractTypeArguments::ToCString() const { |
| 2706 // AbstractTypeArguments is an abstract class, valid only for representing | 2709 // AbstractTypeArguments is an abstract class, valid only for representing |
| 2707 // null. | 2710 // null. |
| 2708 if (IsNull()) { | 2711 if (IsNull()) { |
| 2709 return "NULL AbstractTypeArguments"; | 2712 return "NULL AbstractTypeArguments"; |
| 2710 } | 2713 } |
| 2711 UNREACHABLE(); | 2714 UNREACHABLE(); |
| 2712 return "AbstractTypeArguments"; | 2715 return NULL; |
|
Ivan Posva
2012/12/10 20:07:52
This seems very unconnected to the change at hand?
Florian Schneider
2012/12/11 12:23:04
I think it still makes sense, but I can put it int
| |
| 2713 } | 2716 } |
| 2714 | 2717 |
| 2715 | 2718 |
| 2716 intptr_t TypeArguments::Length() const { | 2719 intptr_t TypeArguments::Length() const { |
| 2717 ASSERT(!IsNull()); | 2720 ASSERT(!IsNull()); |
| 2718 return Smi::Value(raw_ptr()->length_); | 2721 return Smi::Value(raw_ptr()->length_); |
| 2719 } | 2722 } |
| 2720 | 2723 |
| 2721 | 2724 |
| 2722 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const { | 2725 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const { |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2826 | 2829 |
| 2827 | 2830 |
| 2828 void TypeArguments::SetLength(intptr_t value) const { | 2831 void TypeArguments::SetLength(intptr_t value) const { |
| 2829 ASSERT(!IsCanonical()); | 2832 ASSERT(!IsCanonical()); |
| 2830 // This is only safe because we create a new Smi, which does not cause | 2833 // This is only safe because we create a new Smi, which does not cause |
| 2831 // heap allocation. | 2834 // heap allocation. |
| 2832 raw_ptr()->length_ = Smi::New(value); | 2835 raw_ptr()->length_ = Smi::New(value); |
| 2833 } | 2836 } |
| 2834 | 2837 |
| 2835 | 2838 |
| 2839 static void GrowCanonicalTypeArguments(const Array& table, Isolate* isolate) { | |
| 2840 // Last element of the array is the number of used elements. | |
|
srdjan
2012/12/10 21:19:37
Pass isolate as first argument (as done in other p
Florian Schneider
2012/12/11 12:23:04
Done.
| |
| 2841 intptr_t table_size = table.Length() - 1; | |
| 2842 intptr_t new_table_size = table_size * 2; | |
|
srdjan
2012/12/10 21:19:37
Can you check on dart2js, checked mode, how much t
Florian Schneider
2012/12/11 12:23:04
The max table size in dart2js is 1024 with ~50% oc
| |
| 2843 Array& new_table = Array::Handle(isolate, Array::New(new_table_size + 1)); | |
| 2844 // Copy all elements from the original table to the newly allocated | |
| 2845 // array. | |
| 2846 TypeArguments& element = TypeArguments::Handle(isolate); | |
| 2847 dart::Object& new_element = Object::Handle(isolate); | |
| 2848 for (intptr_t i = 0; i < table_size; i++) { | |
| 2849 element ^= table.At(i); | |
| 2850 if (!element.IsNull()) { | |
| 2851 intptr_t hash = element.Hash(); | |
| 2852 intptr_t index = hash % new_table_size; | |
|
srdjan
2012/12/10 21:19:37
new_table_size should be power of 2 for performanc
Florian Schneider
2012/12/11 12:23:04
Done.
| |
| 2853 new_element = new_table.At(index); | |
| 2854 while (!new_element.IsNull()) { | |
| 2855 index = (index + 1) % new_table_size; // Move to next element. | |
| 2856 new_element = new_table.At(index); | |
| 2857 } | |
| 2858 new_table.SetAt(index, element); | |
| 2859 } | |
| 2860 } | |
| 2861 // Copy used count. | |
| 2862 new_element = table.At(table_size); | |
| 2863 new_table.SetAt(new_table_size, new_element); | |
| 2864 // Remember the new table now. | |
| 2865 isolate->object_store()->set_canonical_type_arguments(new_table); | |
| 2866 } | |
| 2867 | |
| 2868 | |
| 2869 static void InsertIntoCanonicalTypeArguments(const Array& table, | |
| 2870 const TypeArguments& arguments, | |
| 2871 intptr_t index, | |
| 2872 Isolate* isolate) { | |
|
srdjan
2012/12/10 21:19:37
'isolate' as first argument.
Florian Schneider
2012/12/11 12:23:04
Done.
| |
| 2873 // Last element of the array is the number of used elements. | |
| 2874 intptr_t table_size = table.Length() - 1; | |
| 2875 arguments.SetCanonical(); // Mark object as being canonical. | |
| 2876 table.SetAt(index, arguments); // Remember the new element. | |
| 2877 dart::Smi& used = Smi::Handle(isolate); | |
|
srdjan
2012/12/10 21:19:37
s/dart::Smi/Smi/ I do not think there is a conflic
Florian Schneider
2012/12/11 12:23:04
Done.
| |
| 2878 used ^= table.At(table_size); | |
| 2879 intptr_t used_elements = used.Value() + 1; // One more element added. | |
| 2880 used = Smi::New(used_elements); | |
| 2881 table.SetAt(table_size, used); // Update used count. | |
| 2882 | |
| 2883 // Rehash if table is 75% full. | |
| 2884 if (used_elements > ((table_size / 4) * 3)) { | |
| 2885 GrowCanonicalTypeArguments(table, isolate); | |
| 2886 } | |
| 2887 } | |
| 2888 | |
| 2889 | |
| 2890 intptr_t FindIndexInCanonicalTypeArguments(const Array& table, | |
| 2891 const TypeArguments& arguments, | |
| 2892 intptr_t hash, | |
| 2893 Isolate* isolate) { | |
|
srdjan
2012/12/10 21:19:37
ditto
Florian Schneider
2012/12/11 12:23:04
Done.
| |
| 2894 // Last element of the array is the number of used elements. | |
| 2895 intptr_t table_size = table.Length() - 1; | |
| 2896 intptr_t index = hash % table_size; | |
| 2897 | |
| 2898 TypeArguments& current = TypeArguments::Handle(isolate); | |
| 2899 current ^= table.At(index); | |
| 2900 while (!current.IsNull() && !current.Equals(arguments)) { | |
| 2901 index = (index + 1) % table_size; // Move to next element. | |
| 2902 current ^= table.At(index); | |
| 2903 } | |
| 2904 return index; // Index of element if found or slot into which to add it. | |
| 2905 } | |
| 2906 | |
| 2907 | |
| 2836 RawAbstractTypeArguments* TypeArguments::Canonicalize() const { | 2908 RawAbstractTypeArguments* TypeArguments::Canonicalize() const { |
| 2837 if (IsNull() || IsCanonical()) { | 2909 if (IsNull() || IsCanonical()) { |
| 2838 ASSERT(IsOld()); | 2910 ASSERT(IsOld()); |
| 2839 return this->raw(); | 2911 return this->raw(); |
| 2840 } | 2912 } |
| 2841 ObjectStore* object_store = Isolate::Current()->object_store(); | 2913 Isolate* isolate = Isolate::Current(); |
| 2842 // 'table' must be null terminated. | 2914 ObjectStore* object_store = isolate->object_store(); |
| 2843 Array& table = Array::Handle(object_store->canonical_type_arguments()); | 2915 const Array& table = Array::Handle(isolate, |
| 2916 object_store->canonical_type_arguments()); | |
| 2844 ASSERT(table.Length() > 0); | 2917 ASSERT(table.Length() > 0); |
| 2845 intptr_t index = 0; | 2918 TypeArguments& self = TypeArguments::Handle(isolate, this->raw()); |
| 2846 TypeArguments& result = TypeArguments::Handle(); | 2919 intptr_t index = FindIndexInCanonicalTypeArguments(table, |
| 2920 self, | |
| 2921 Hash(), | |
| 2922 isolate); | |
| 2923 TypeArguments& result = TypeArguments::Handle(isolate); | |
| 2847 result ^= table.At(index); | 2924 result ^= table.At(index); |
| 2848 while (!result.IsNull()) { | 2925 if (result.IsNull()) { |
| 2849 if (this->Equals(result)) { | 2926 // Make sure we have an old space object and add it to the table. |
| 2850 return result.raw(); | 2927 result ^= this->raw(); |
| 2928 if (result.IsNew()) { | |
| 2929 result ^= Object::Clone(result, Heap::kOld); | |
| 2851 } | 2930 } |
| 2852 result ^= table.At(++index); | 2931 ASSERT(result.IsOld()); |
| 2932 InsertIntoCanonicalTypeArguments(table, result, index, isolate); | |
| 2853 } | 2933 } |
| 2854 // Not found. Add 'this' to table. | 2934 ASSERT(result.Equals(self)); |
| 2855 result ^= this->raw(); | 2935 ASSERT(!result.IsNull()); |
| 2856 if (result.IsNew()) { | 2936 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(); | 2937 return result.raw(); |
| 2867 } | 2938 } |
| 2868 | 2939 |
| 2869 | 2940 |
| 2870 const char* TypeArguments::ToCString() const { | 2941 const char* TypeArguments::ToCString() const { |
| 2871 if (IsNull()) { | 2942 if (IsNull()) { |
| 2872 return "NULL TypeArguments"; | 2943 return "NULL TypeArguments"; |
| 2873 } | 2944 } |
| 2874 const char* format = "%s [%s]"; | 2945 const char* format = "%s [%s]"; |
| 2875 const char* prev_cstr = "TypeArguments:"; | 2946 const char* prev_cstr = "TypeArguments:"; |
| (...skipping 7117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 9993 static intptr_t HashImpl(const T* characters, intptr_t len) { | 10064 static intptr_t HashImpl(const T* characters, intptr_t len) { |
| 9994 ASSERT(len >= 0); | 10065 ASSERT(len >= 0); |
| 9995 StringHasher hasher; | 10066 StringHasher hasher; |
| 9996 for (intptr_t i = 0; i < len; i++) { | 10067 for (intptr_t i = 0; i < len; i++) { |
| 9997 hasher.Add(characters[i]); | 10068 hasher.Add(characters[i]); |
| 9998 } | 10069 } |
| 9999 return hasher.Finalize(String::kHashBits); | 10070 return hasher.Finalize(String::kHashBits); |
| 10000 } | 10071 } |
| 10001 | 10072 |
| 10002 | 10073 |
| 10074 intptr_t TypeArguments::Hash() const { | |
| 10075 const char* characters = ToCString(); | |
|
Ivan Posva
2012/12/10 20:07:52
This seems very fragile to me and as you are not c
regis
2012/12/11 01:37:15
Yes, for efficiency, the hash of a TypeArguments v
Florian Schneider
2012/12/11 12:23:04
Done. Added ::Hash() for Type, TypeParameter and A
| |
| 10076 return HashImpl(characters, strlen(characters)); | |
| 10077 } | |
| 10078 | |
| 10079 | |
| 10003 intptr_t String::Hash(const uint8_t* characters, intptr_t len) { | 10080 intptr_t String::Hash(const uint8_t* characters, intptr_t len) { |
| 10004 return HashImpl(characters, len); | 10081 return HashImpl(characters, len); |
| 10005 } | 10082 } |
| 10006 | 10083 |
| 10007 | 10084 |
| 10008 intptr_t String::Hash(const uint16_t* characters, intptr_t len) { | 10085 intptr_t String::Hash(const uint16_t* characters, intptr_t len) { |
| 10009 StringHasher hasher; | 10086 StringHasher hasher; |
| 10010 intptr_t i = 0; | 10087 intptr_t i = 0; |
| 10011 while (i < len) { | 10088 while (i < len) { |
| 10012 hasher.Add(Utf16::Next(characters, &i, len)); | 10089 hasher.Add(Utf16::Next(characters, &i, len)); |
| (...skipping 2286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 12299 } | 12376 } |
| 12300 return result.raw(); | 12377 return result.raw(); |
| 12301 } | 12378 } |
| 12302 | 12379 |
| 12303 | 12380 |
| 12304 const char* WeakProperty::ToCString() const { | 12381 const char* WeakProperty::ToCString() const { |
| 12305 return "_WeakProperty"; | 12382 return "_WeakProperty"; |
| 12306 } | 12383 } |
| 12307 | 12384 |
| 12308 } // namespace dart | 12385 } // namespace dart |
| OLD | NEW |