Chromium Code Reviews| 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 |