Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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 "src/objects.h" | 5 #include "src/objects.h" |
| 6 | 6 |
| 7 #include <cmath> | 7 #include <cmath> |
| 8 #include <iomanip> | 8 #include <iomanip> |
| 9 #include <sstream> | 9 #include <sstream> |
| 10 | 10 |
| (...skipping 8817 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 8828 Isolate* isolate = object->GetIsolate(); | 8828 Isolate* isolate = object->GetIsolate(); |
| 8829 KeyAccumulator accumulator(isolate, type, filter); | 8829 KeyAccumulator accumulator(isolate, type, filter); |
| 8830 MAYBE_RETURN( | 8830 MAYBE_RETURN( |
| 8831 GetKeys_Internal(isolate, object, object, type, filter, &accumulator), | 8831 GetKeys_Internal(isolate, object, object, type, filter, &accumulator), |
| 8832 MaybeHandle<FixedArray>()); | 8832 MaybeHandle<FixedArray>()); |
| 8833 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); | 8833 Handle<FixedArray> keys = accumulator.GetKeys(keys_conversion); |
| 8834 DCHECK(ContainsOnlyValidKeys(keys)); | 8834 DCHECK(ContainsOnlyValidKeys(keys)); |
| 8835 return keys; | 8835 return keys; |
| 8836 } | 8836 } |
| 8837 | 8837 |
| 8838 MUST_USE_RESULT Maybe<bool> GetOwnElementValuesOrEntries( | |
| 8839 Isolate* isolate, Handle<JSObject> object, bool get_entries, | |
| 8840 Handle<FixedArray> values_or_entries, int num_elements, int* count) { | |
| 8841 Handle<FixedArray> keys = isolate->factory()->NewFixedArray(num_elements); | |
| 8842 object->GetOwnElementKeys(*keys, ENUMERABLE_STRINGS); | |
| 8843 | |
| 8844 int elements = 0; | |
| 8845 | |
| 8846 for (int i = 0; i < num_elements; ++i) { | |
| 8847 Handle<Object> next_key(keys->get(i), isolate); | |
| 8848 Handle<Object> prop_value; | |
| 8849 | |
| 8850 bool success; | |
| 8851 LookupIterator it = | |
| 8852 LookupIterator::PropertyOrElement(isolate, object, next_key, &success, | |
| 8853 LookupIterator::OWN_SKIP_INTERCEPTOR); | |
|
Camillo Bruni
2016/03/04 09:40:25
I think you will only have the full benefits when
caitp (gmail)
2016/03/04 16:34:33
Acknowledged.
| |
| 8854 USE(success); | |
| 8855 | |
| 8856 if (!it.IsFound()) continue; | |
| 8857 DCHECK(it.state() == LookupIterator::DATA || | |
| 8858 it.state() == LookupIterator::ACCESSOR); | |
| 8859 if (!it.IsEnumerable()) continue; | |
|
Camillo Bruni
2016/03/04 09:40:25
For instance the enumerability check would only be
caitp (gmail)
2016/03/04 16:34:33
Acknowledged.
| |
| 8860 | |
| 8861 PropertyDetails details = it.property_details(); | |
| 8862 if (details.kind() == kData) { | |
| 8863 prop_value = it.GetDataValue(); | |
| 8864 } else { | |
| 8865 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 8866 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>()); | |
|
Camillo Bruni
2016/03/04 09:40:25
Same here, you can only have a getter with DICTION
caitp (gmail)
2016/03/04 16:34:33
Acknowledged.
| |
| 8867 } | |
| 8868 | |
| 8869 if (get_entries) { | |
| 8870 Handle<FixedArray> entry_storage = | |
| 8871 isolate->factory()->NewUninitializedFixedArray(2); | |
| 8872 | |
| 8873 if (!next_key->IsName()) { | |
|
Camillo Bruni
2016/03/04 09:40:25
element keys should always be Numbers.
DCHECK(next
caitp (gmail)
2016/03/04 16:34:33
Dictionary gave me the impression that they could
Camillo Bruni
2016/03/04 17:23:26
Sure :).
DICTIONARY_ELEMENTS is used for elements
| |
| 8874 DCHECK(next_key->IsNumber()); | |
| 8875 Handle<String> property_name; | |
| 8876 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, property_name, | |
| 8877 Object::ToString(isolate, next_key), | |
| 8878 Nothing<bool>()); | |
| 8879 next_key = property_name; | |
| 8880 } | |
| 8881 entry_storage->set(0, *next_key); | |
| 8882 entry_storage->set(1, *prop_value); | |
| 8883 prop_value = isolate->factory()->NewJSArrayWithElements(entry_storage, | |
| 8884 FAST_ELEMENTS, 2); | |
| 8885 } | |
| 8886 | |
| 8887 values_or_entries->set(elements, *prop_value); | |
| 8888 elements++; | |
| 8889 } | |
| 8890 | |
| 8891 *count = elements; | |
| 8892 return Just(true); | |
| 8893 } | |
| 8894 | |
| 8895 MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries( | |
| 8896 Isolate* isolate, Handle<JSObject> object, bool get_entries, | |
| 8897 Handle<FixedArray>* result) { | |
| 8898 Handle<Map> map(JSReceiver::cast(*object)->map(), isolate); | |
| 8899 | |
| 8900 if (!map->IsJSObjectMap()) return Just(false); | |
| 8901 if (!map->OnlyHasSimpleProperties()) return Just(false); | |
| 8902 | |
| 8903 Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate); | |
| 8904 int length = map->NumberOfOwnDescriptors(); | |
| 8905 int elements_length = object->NumberOfOwnElements(ENUMERABLE_STRINGS); | |
| 8906 Handle<FixedArray> values_or_entries = | |
| 8907 isolate->factory()->NewFixedArray(length + elements_length); | |
| 8908 int count = 0; | |
| 8909 | |
| 8910 bool stable = true; | |
| 8911 | |
| 8912 if (object->elements() != isolate->heap()->empty_fixed_array()) { | |
| 8913 MAYBE_RETURN(GetOwnElementValuesOrEntries(isolate, object, get_entries, | |
| 8914 values_or_entries, | |
| 8915 elements_length, &count), | |
| 8916 Nothing<bool>()); | |
| 8917 stable = object->map() == *map; | |
| 8918 } | |
| 8919 | |
| 8920 for (int index = 0; index < length; index++) { | |
| 8921 Handle<Name> next_key(descriptors->GetKey(index), isolate); | |
| 8922 if (!next_key->IsString()) continue; | |
| 8923 Handle<Object> prop_value; | |
| 8924 | |
| 8925 // Directly decode from the descriptor array if |from| did not change shape. | |
| 8926 if (stable) { | |
| 8927 PropertyDetails details = descriptors->GetDetails(index); | |
| 8928 if (!details.IsEnumerable()) continue; | |
| 8929 if (details.kind() == kData) { | |
| 8930 if (details.location() == kDescriptor) { | |
| 8931 prop_value = handle(descriptors->GetValue(index), isolate); | |
| 8932 } else { | |
| 8933 Representation representation = details.representation(); | |
| 8934 FieldIndex field_index = FieldIndex::ForDescriptor(*map, index); | |
| 8935 prop_value = | |
| 8936 JSObject::FastPropertyAt(object, representation, field_index); | |
| 8937 } | |
| 8938 } else { | |
| 8939 ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, prop_value, | |
| 8940 Object::GetProperty(object, next_key), | |
| 8941 Nothing<bool>()); | |
| 8942 stable = object->map() == *map; | |
| 8943 } | |
| 8944 } else { | |
| 8945 // If the map did change, do a slower lookup. We are still guaranteed that | |
| 8946 // the object has a simple shape, and that the key is a name. | |
| 8947 LookupIterator it(object, next_key, LookupIterator::OWN_SKIP_INTERCEPTOR); | |
| 8948 if (!it.IsFound()) continue; | |
| 8949 DCHECK(it.state() == LookupIterator::DATA || | |
| 8950 it.state() == LookupIterator::ACCESSOR); | |
| 8951 if (!it.IsEnumerable()) continue; | |
| 8952 ASSIGN_RETURN_ON_EXCEPTION_VALUE( | |
| 8953 isolate, prop_value, Object::GetProperty(&it), Nothing<bool>()); | |
| 8954 } | |
| 8955 | |
| 8956 if (get_entries) { | |
| 8957 Handle<FixedArray> entry_storage = | |
| 8958 isolate->factory()->NewUninitializedFixedArray(2); | |
| 8959 entry_storage->set(0, *next_key); | |
| 8960 entry_storage->set(1, *prop_value); | |
| 8961 prop_value = isolate->factory()->NewJSArrayWithElements(entry_storage, | |
| 8962 FAST_ELEMENTS, 2); | |
| 8963 } | |
| 8964 | |
| 8965 values_or_entries->set(count, *prop_value); | |
| 8966 count++; | |
| 8967 } | |
| 8968 | |
| 8969 if (count < values_or_entries->length()) values_or_entries->Shrink(count); | |
| 8970 *result = values_or_entries; | |
| 8971 return Just(true); | |
| 8972 } | |
| 8973 | |
| 8838 MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate, | 8974 MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate, |
| 8839 Handle<JSReceiver> object, | 8975 Handle<JSReceiver> object, |
| 8840 PropertyFilter filter, | 8976 PropertyFilter filter, |
| 8841 bool get_entries) { | 8977 bool get_entries) { |
| 8978 Handle<FixedArray> values_or_entries; | |
| 8979 if (filter == ENUMERABLE_STRINGS && object->IsJSObject()) { | |
| 8980 Maybe<bool> fast_values_or_entries = | |
| 8981 FastGetOwnValuesOrEntries(isolate, Handle<JSObject>::cast(object), | |
| 8982 get_entries, &values_or_entries); | |
| 8983 if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>(); | |
| 8984 if (fast_values_or_entries.FromJust()) return values_or_entries; | |
| 8985 } | |
| 8986 | |
| 8842 PropertyFilter key_filter = | 8987 PropertyFilter key_filter = |
| 8843 static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE); | 8988 static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE); |
| 8844 KeyAccumulator accumulator(isolate, OWN_ONLY, key_filter); | 8989 KeyAccumulator accumulator(isolate, OWN_ONLY, key_filter); |
| 8845 MAYBE_RETURN(GetKeys_Internal(isolate, object, object, OWN_ONLY, key_filter, | 8990 MAYBE_RETURN(GetKeys_Internal(isolate, object, object, OWN_ONLY, key_filter, |
| 8846 &accumulator), | 8991 &accumulator), |
| 8847 MaybeHandle<FixedArray>()); | 8992 MaybeHandle<FixedArray>()); |
| 8848 Handle<FixedArray> keys = accumulator.GetKeys(CONVERT_TO_STRING); | 8993 Handle<FixedArray> keys = accumulator.GetKeys(CONVERT_TO_STRING); |
| 8849 DCHECK(ContainsOnlyValidKeys(keys)); | 8994 DCHECK(ContainsOnlyValidKeys(keys)); |
| 8850 | 8995 |
| 8851 Handle<FixedArray> values_or_entries = | 8996 values_or_entries = isolate->factory()->NewFixedArray(keys->length()); |
| 8852 isolate->factory()->NewFixedArray(keys->length()); | |
| 8853 int length = 0; | 8997 int length = 0; |
| 8854 | 8998 |
| 8855 for (int i = 0; i < keys->length(); ++i) { | 8999 for (int i = 0; i < keys->length(); ++i) { |
| 8856 Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate)); | 9000 Handle<Name> key = Handle<Name>::cast(handle(keys->get(i), isolate)); |
| 8857 | 9001 |
| 8858 if (filter & ONLY_ENUMERABLE) { | 9002 if (filter & ONLY_ENUMERABLE) { |
| 8859 PropertyDescriptor descriptor; | 9003 PropertyDescriptor descriptor; |
| 8860 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor( | 9004 Maybe<bool> did_get_descriptor = JSReceiver::GetOwnPropertyDescriptor( |
| 8861 isolate, object, key, &descriptor); | 9005 isolate, object, key, &descriptor); |
| 8862 MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>()); | 9006 MAYBE_RETURN(did_get_descriptor, MaybeHandle<FixedArray>()); |
| (...skipping 10961 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 19824 if (cell->value() != *new_value) { | 19968 if (cell->value() != *new_value) { |
| 19825 cell->set_value(*new_value); | 19969 cell->set_value(*new_value); |
| 19826 Isolate* isolate = cell->GetIsolate(); | 19970 Isolate* isolate = cell->GetIsolate(); |
| 19827 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19971 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
| 19828 isolate, DependentCode::kPropertyCellChangedGroup); | 19972 isolate, DependentCode::kPropertyCellChangedGroup); |
| 19829 } | 19973 } |
| 19830 } | 19974 } |
| 19831 | 19975 |
| 19832 } // namespace internal | 19976 } // namespace internal |
| 19833 } // namespace v8 | 19977 } // namespace v8 |
| OLD | NEW |