OLD | NEW |
---|---|
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include <iomanip> | 5 #include <iomanip> |
6 #include <sstream> | 6 #include <sstream> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 4891 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
4902 Handle<SeededNumberDictionary> new_elements = | 4902 Handle<SeededNumberDictionary> new_elements = |
4903 SeededNumberDictionary::New(isolate, 0); | 4903 SeededNumberDictionary::New(isolate, 0); |
4904 object->set_elements(*new_elements); | 4904 object->set_elements(*new_elements); |
4905 } else { | 4905 } else { |
4906 object->set_elements(object->map()->GetInitialElements()); | 4906 object->set_elements(object->map()->GetInitialElements()); |
4907 } | 4907 } |
4908 } | 4908 } |
4909 | 4909 |
4910 | 4910 |
4911 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary( | 4911 static Handle<SeededNumberDictionary> CopyFastElementsToDictionary( |
4912 Handle<FixedArrayBase> array, | 4912 Handle<FixedArrayBase> array, int length, |
4913 int length, | 4913 Handle<SeededNumberDictionary> dictionary, bool used_as_prototype) { |
4914 Handle<SeededNumberDictionary> dictionary) { | |
4915 Isolate* isolate = array->GetIsolate(); | 4914 Isolate* isolate = array->GetIsolate(); |
4916 Factory* factory = isolate->factory(); | 4915 Factory* factory = isolate->factory(); |
4917 bool has_double_elements = array->IsFixedDoubleArray(); | 4916 bool has_double_elements = array->IsFixedDoubleArray(); |
4918 for (int i = 0; i < length; i++) { | 4917 for (int i = 0; i < length; i++) { |
4919 Handle<Object> value; | 4918 Handle<Object> value; |
4920 if (has_double_elements) { | 4919 if (has_double_elements) { |
4921 Handle<FixedDoubleArray> double_array = | 4920 Handle<FixedDoubleArray> double_array = |
4922 Handle<FixedDoubleArray>::cast(array); | 4921 Handle<FixedDoubleArray>::cast(array); |
4923 if (double_array->is_the_hole(i)) { | 4922 if (double_array->is_the_hole(i)) { |
4924 value = factory->the_hole_value(); | 4923 value = factory->the_hole_value(); |
4925 } else { | 4924 } else { |
4926 value = factory->NewHeapNumber(double_array->get_scalar(i)); | 4925 value = factory->NewHeapNumber(double_array->get_scalar(i)); |
4927 } | 4926 } |
4928 } else { | 4927 } else { |
4929 value = handle(Handle<FixedArray>::cast(array)->get(i), isolate); | 4928 value = handle(Handle<FixedArray>::cast(array)->get(i), isolate); |
4930 } | 4929 } |
4931 if (!value->IsTheHole()) { | 4930 if (!value->IsTheHole()) { |
4932 PropertyDetails details = PropertyDetails::Empty(); | 4931 PropertyDetails details = PropertyDetails::Empty(); |
4933 dictionary = | 4932 dictionary = SeededNumberDictionary::AddNumberEntry( |
4934 SeededNumberDictionary::AddNumberEntry(dictionary, i, value, details); | 4933 dictionary, i, value, details, used_as_prototype); |
4935 } | 4934 } |
4936 } | 4935 } |
4937 return dictionary; | 4936 return dictionary; |
4938 } | 4937 } |
4939 | 4938 |
4940 | 4939 |
4941 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) { | 4940 void JSObject::RequireSlowElements(SeededNumberDictionary* dictionary) { |
4942 if (dictionary->requires_slow_elements()) return; | 4941 if (dictionary->requires_slow_elements()) return; |
4943 dictionary->set_requires_slow_elements(); | 4942 dictionary->set_requires_slow_elements(); |
4944 // TODO(verwaest): Remove this hack. | 4943 // TODO(verwaest): Remove this hack. |
(...skipping 10 matching lines...) Expand all Loading... | |
4955 Isolate* isolate = object->GetIsolate(); | 4954 Isolate* isolate = object->GetIsolate(); |
4956 // Ensure that notifications fire if the array or object prototypes are | 4955 // Ensure that notifications fire if the array or object prototypes are |
4957 // normalizing. | 4956 // normalizing. |
4958 isolate->UpdateArrayProtectorOnNormalizeElements(object); | 4957 isolate->UpdateArrayProtectorOnNormalizeElements(object); |
4959 int length = object->IsJSArray() | 4958 int length = object->IsJSArray() |
4960 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() | 4959 ? Smi::cast(Handle<JSArray>::cast(object)->length())->value() |
4961 : elements->length(); | 4960 : elements->length(); |
4962 int used = object->GetFastElementsUsage(); | 4961 int used = object->GetFastElementsUsage(); |
4963 Handle<SeededNumberDictionary> dictionary = | 4962 Handle<SeededNumberDictionary> dictionary = |
4964 SeededNumberDictionary::New(isolate, used); | 4963 SeededNumberDictionary::New(isolate, used); |
4965 return CopyFastElementsToDictionary(elements, length, dictionary); | 4964 return CopyFastElementsToDictionary(elements, length, dictionary, |
4965 object->map()->is_prototype_map()); | |
4966 } | 4966 } |
4967 | 4967 |
4968 | 4968 |
4969 Handle<SeededNumberDictionary> JSObject::NormalizeElements( | 4969 Handle<SeededNumberDictionary> JSObject::NormalizeElements( |
4970 Handle<JSObject> object) { | 4970 Handle<JSObject> object) { |
4971 DCHECK(!object->HasFixedTypedArrayElements()); | 4971 DCHECK(!object->HasFixedTypedArrayElements()); |
4972 Isolate* isolate = object->GetIsolate(); | 4972 Isolate* isolate = object->GetIsolate(); |
4973 | 4973 |
4974 // Find the backing store. | 4974 // Find the backing store. |
4975 Handle<FixedArrayBase> elements(object->elements(), isolate); | 4975 Handle<FixedArrayBase> elements(object->elements(), isolate); |
(...skipping 8884 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
13860 uint32_t key = NumberToUint32(k); | 13860 uint32_t key = NumberToUint32(k); |
13861 if (key < limit) { | 13861 if (key < limit) { |
13862 if (value->IsUndefined()) { | 13862 if (value->IsUndefined()) { |
13863 undefs++; | 13863 undefs++; |
13864 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 13864 } else if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
13865 // Adding an entry with the key beyond smi-range requires | 13865 // Adding an entry with the key beyond smi-range requires |
13866 // allocation. Bailout. | 13866 // allocation. Bailout. |
13867 return bailout; | 13867 return bailout; |
13868 } else { | 13868 } else { |
13869 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 13869 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
13870 new_dict, pos, value, details); | 13870 new_dict, pos, value, details, object->map()->is_prototype_map()); |
13871 DCHECK(result.is_identical_to(new_dict)); | 13871 DCHECK(result.is_identical_to(new_dict)); |
13872 USE(result); | 13872 USE(result); |
13873 pos++; | 13873 pos++; |
13874 } | 13874 } |
13875 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) { | 13875 } else if (key > static_cast<uint32_t>(Smi::kMaxValue)) { |
13876 // Adding an entry with the key beyond smi-range requires | 13876 // Adding an entry with the key beyond smi-range requires |
13877 // allocation. Bailout. | 13877 // allocation. Bailout. |
13878 return bailout; | 13878 return bailout; |
13879 } else { | 13879 } else { |
13880 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 13880 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
13881 new_dict, key, value, details); | 13881 new_dict, key, value, details, object->map()->is_prototype_map()); |
13882 DCHECK(result.is_identical_to(new_dict)); | 13882 DCHECK(result.is_identical_to(new_dict)); |
13883 USE(result); | 13883 USE(result); |
13884 } | 13884 } |
13885 } | 13885 } |
13886 | 13886 |
13887 uint32_t result = pos; | 13887 uint32_t result = pos; |
13888 PropertyDetails no_details = PropertyDetails::Empty(); | 13888 PropertyDetails no_details = PropertyDetails::Empty(); |
13889 while (undefs > 0) { | 13889 while (undefs > 0) { |
13890 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { | 13890 if (pos > static_cast<uint32_t>(Smi::kMaxValue)) { |
13891 // Adding an entry with the key beyond smi-range requires | 13891 // Adding an entry with the key beyond smi-range requires |
13892 // allocation. Bailout. | 13892 // allocation. Bailout. |
13893 return bailout; | 13893 return bailout; |
13894 } | 13894 } |
13895 HandleScope scope(isolate); | 13895 HandleScope scope(isolate); |
13896 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( | 13896 Handle<Object> result = SeededNumberDictionary::AddNumberEntry( |
13897 new_dict, pos, isolate->factory()->undefined_value(), no_details); | 13897 new_dict, pos, isolate->factory()->undefined_value(), no_details, |
13898 object->map()->is_prototype_map()); | |
13898 DCHECK(result.is_identical_to(new_dict)); | 13899 DCHECK(result.is_identical_to(new_dict)); |
13899 USE(result); | 13900 USE(result); |
13900 pos++; | 13901 pos++; |
13901 undefs--; | 13902 undefs--; |
13902 } | 13903 } |
13903 | 13904 |
13904 object->set_elements(*new_dict); | 13905 object->set_elements(*new_dict); |
13905 | 13906 |
13906 AllowHeapAllocation allocate_return_value; | 13907 AllowHeapAllocation allocate_return_value; |
13907 return isolate->factory()->NewNumberFromUint(result); | 13908 return isolate->factory()->NewNumberFromUint(result); |
(...skipping 718 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
14626 details = details.set_index(index); | 14627 details = details.set_index(index); |
14627 dictionary->SetNextEnumerationIndex(index + 1); | 14628 dictionary->SetNextEnumerationIndex(index + 1); |
14628 } | 14629 } |
14629 dictionary->SetEntry(entry, k, value, details); | 14630 dictionary->SetEntry(entry, k, value, details); |
14630 DCHECK((dictionary->KeyAt(entry)->IsNumber() || | 14631 DCHECK((dictionary->KeyAt(entry)->IsNumber() || |
14631 dictionary->KeyAt(entry)->IsName())); | 14632 dictionary->KeyAt(entry)->IsName())); |
14632 dictionary->ElementAdded(); | 14633 dictionary->ElementAdded(); |
14633 } | 14634 } |
14634 | 14635 |
14635 | 14636 |
14636 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key) { | 14637 void SeededNumberDictionary::UpdateMaxNumberKey(uint32_t key, |
14638 bool used_as_prototype) { | |
14637 DisallowHeapAllocation no_allocation; | 14639 DisallowHeapAllocation no_allocation; |
14638 // If the dictionary requires slow elements an element has already | 14640 // If the dictionary requires slow elements an element has already |
14639 // been added at a high index. | 14641 // been added at a high index. |
14640 if (requires_slow_elements()) return; | 14642 if (requires_slow_elements()) return; |
14641 // Check if this index is high enough that we should require slow | 14643 // Check if this index is high enough that we should require slow |
14642 // elements. | 14644 // elements. |
14643 if (key > kRequiresSlowElementsLimit) { | 14645 if (key > kRequiresSlowElementsLimit) { |
14644 // TODO(verwaest): Remove this hack. | 14646 if (used_as_prototype) { |
14645 GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); | 14647 // TODO(verwaest): Remove this hack. |
Yang
2015/08/07 21:28:50
Indeed!
| |
14648 GetHeap()->ClearAllICsByKind(Code::KEYED_STORE_IC); | |
14649 } | |
14646 set_requires_slow_elements(); | 14650 set_requires_slow_elements(); |
14647 return; | 14651 return; |
14648 } | 14652 } |
14649 // Update max key value. | 14653 // Update max key value. |
14650 Object* max_index_object = get(kMaxNumberKeyIndex); | 14654 Object* max_index_object = get(kMaxNumberKeyIndex); |
14651 if (!max_index_object->IsSmi() || max_number_key() < key) { | 14655 if (!max_index_object->IsSmi() || max_number_key() < key) { |
14652 FixedArray::set(kMaxNumberKeyIndex, | 14656 FixedArray::set(kMaxNumberKeyIndex, |
14653 Smi::FromInt(key << kRequiresSlowElementsTagSize)); | 14657 Smi::FromInt(key << kRequiresSlowElementsTagSize)); |
14654 } | 14658 } |
14655 } | 14659 } |
14656 | 14660 |
14657 | 14661 |
14658 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry( | 14662 Handle<SeededNumberDictionary> SeededNumberDictionary::AddNumberEntry( |
14659 Handle<SeededNumberDictionary> dictionary, | 14663 Handle<SeededNumberDictionary> dictionary, uint32_t key, |
14660 uint32_t key, | 14664 Handle<Object> value, PropertyDetails details, bool used_as_prototype) { |
14661 Handle<Object> value, | 14665 dictionary->UpdateMaxNumberKey(key, used_as_prototype); |
14662 PropertyDetails details) { | |
14663 dictionary->UpdateMaxNumberKey(key); | |
14664 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); | 14666 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); |
14665 return Add(dictionary, key, value, details); | 14667 return Add(dictionary, key, value, details); |
14666 } | 14668 } |
14667 | 14669 |
14668 | 14670 |
14669 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( | 14671 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AddNumberEntry( |
14670 Handle<UnseededNumberDictionary> dictionary, | 14672 Handle<UnseededNumberDictionary> dictionary, |
14671 uint32_t key, | 14673 uint32_t key, |
14672 Handle<Object> value) { | 14674 Handle<Object> value) { |
14673 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); | 14675 SLOW_DCHECK(dictionary->FindEntry(key) == kNotFound); |
14674 return Add(dictionary, key, value, PropertyDetails::Empty()); | 14676 return Add(dictionary, key, value, PropertyDetails::Empty()); |
14675 } | 14677 } |
14676 | 14678 |
14677 | 14679 |
14678 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( | 14680 Handle<SeededNumberDictionary> SeededNumberDictionary::AtNumberPut( |
14679 Handle<SeededNumberDictionary> dictionary, | 14681 Handle<SeededNumberDictionary> dictionary, uint32_t key, |
14680 uint32_t key, | 14682 Handle<Object> value, bool used_as_prototype) { |
14681 Handle<Object> value) { | 14683 dictionary->UpdateMaxNumberKey(key, used_as_prototype); |
14682 dictionary->UpdateMaxNumberKey(key); | |
14683 return AtPut(dictionary, key, value); | 14684 return AtPut(dictionary, key, value); |
14684 } | 14685 } |
14685 | 14686 |
14686 | 14687 |
14687 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut( | 14688 Handle<UnseededNumberDictionary> UnseededNumberDictionary::AtNumberPut( |
14688 Handle<UnseededNumberDictionary> dictionary, | 14689 Handle<UnseededNumberDictionary> dictionary, |
14689 uint32_t key, | 14690 uint32_t key, |
14690 Handle<Object> value) { | 14691 Handle<Object> value) { |
14691 return AtPut(dictionary, key, value); | 14692 return AtPut(dictionary, key, value); |
14692 } | 14693 } |
14693 | 14694 |
14694 | 14695 |
14695 Handle<SeededNumberDictionary> SeededNumberDictionary::Set( | 14696 Handle<SeededNumberDictionary> SeededNumberDictionary::Set( |
14696 Handle<SeededNumberDictionary> dictionary, | 14697 Handle<SeededNumberDictionary> dictionary, uint32_t key, |
14697 uint32_t key, | 14698 Handle<Object> value, PropertyDetails details, bool used_as_prototype) { |
14698 Handle<Object> value, | |
14699 PropertyDetails details) { | |
14700 int entry = dictionary->FindEntry(key); | 14699 int entry = dictionary->FindEntry(key); |
14701 if (entry == kNotFound) { | 14700 if (entry == kNotFound) { |
14702 return AddNumberEntry(dictionary, key, value, details); | 14701 return AddNumberEntry(dictionary, key, value, details, used_as_prototype); |
14703 } | 14702 } |
14704 // Preserve enumeration index. | 14703 // Preserve enumeration index. |
14705 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index()); | 14704 details = details.set_index(dictionary->DetailsAt(entry).dictionary_index()); |
14706 Handle<Object> object_key = | 14705 Handle<Object> object_key = |
14707 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); | 14706 SeededNumberDictionaryShape::AsHandle(dictionary->GetIsolate(), key); |
14708 dictionary->SetEntry(entry, object_key, value, details); | 14707 dictionary->SetEntry(entry, object_key, value, details); |
14709 return dictionary; | 14708 return dictionary; |
14710 } | 14709 } |
14711 | 14710 |
14712 | 14711 |
(...skipping 1156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
15869 if (cell->value() != *new_value) { | 15868 if (cell->value() != *new_value) { |
15870 cell->set_value(*new_value); | 15869 cell->set_value(*new_value); |
15871 Isolate* isolate = cell->GetIsolate(); | 15870 Isolate* isolate = cell->GetIsolate(); |
15872 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 15871 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
15873 isolate, DependentCode::kPropertyCellChangedGroup); | 15872 isolate, DependentCode::kPropertyCellChangedGroup); |
15874 } | 15873 } |
15875 } | 15874 } |
15876 | 15875 |
15877 } // namespace internal | 15876 } // namespace internal |
15878 } // namespace v8 | 15877 } // namespace v8 |
OLD | NEW |