Chromium Code Reviews| Index: src/objects.cc |
| diff --git a/src/objects.cc b/src/objects.cc |
| index 075a738d2ccf742f635d60e0cb13c49d9219d9fa..7ba2f64383babcd5ccd1c2fa9efb2c56ed2f410d 100644 |
| --- a/src/objects.cc |
| +++ b/src/objects.cc |
| @@ -8776,10 +8776,94 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, |
| return keys; |
| } |
| +MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries( |
| + Isolate* isolate, Handle<JSObject> object, bool get_entries, |
| + Handle<FixedArray>* result) { |
| + Handle<Map> map(JSReceiver::cast(*object)->map(), isolate); |
| + |
| + if (!map->IsJSObjectMap()) return Just(false); |
| + if (!map->OnlyHasSimpleProperties()) return Just(false); |
| + |
| + if (object->elements() != isolate->heap()->empty_fixed_array()) { |
| + return Just(false); |
| + } |
| + |
| + Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate); |
| + int length = map->NumberOfOwnDescriptors(); |
| + int elements_length = object->NumberOfOwnElements(ENUMERABLE_STRINGS); |
| + Handle<FixedArray> values_or_entries = |
| + isolate->factory()->NewFixedArray(length + elements_length); |
| + int count = 0; |
| + |
| + bool stable = true; |
| + |
| + for (int index = 0; index < length; index++) { |
| + Handle<Name> next_key(descriptors->GetKey(index), isolate); |
| + if (!next_key->IsString()) continue; |
| + Handle<Object> prop_value; |
| + |
| + // Directly decode from the descriptor array if |from| did not change shape. |
| + if (stable) { |
| + PropertyDetails details = descriptors->GetDetails(index); |
| + if (!details.IsEnumerable()) continue; |
| + if (details.kind() == kData) { |
| + if (details.location() == kDescriptor) { |
| + prop_value = handle(descriptors->GetValue(index), isolate); |
| + } else { |
| + Representation representation = details.representation(); |
| + FieldIndex field_index = FieldIndex::ForDescriptor(*map, index); |
| + prop_value = |
| + JSObject::FastPropertyAt(object, representation, field_index); |
| + } |
| + } else { |
| + ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, prop_value, |
| + Object::GetProperty(object, next_key), |
| + Nothing<bool>()); |
| + stable = object->map() == *map; |
| + } |
| + } else { |
| + // If the map did change, do a slower lookup. We are still guaranteed that |
| + // the object has a simple shape, and that the key is a name. |
| + LookupIterator it(object, next_key, LookupIterator::OWN_SKIP_INTERCEPTOR); |
| + if (!it.IsFound()) continue; |
| + DCHECK(it.state() == LookupIterator::DATA || |
| + it.state() == LookupIterator::ACCESSOR); |
| + if (!it.IsEnumerable()) continue; |
| + ASSIGN_RETURN_ON_EXCEPTION_VALUE( |
| + isolate, prop_value, Object::GetProperty(&it), Nothing<bool>()); |
| + } |
| + |
| + if (get_entries) { |
| + Handle<FixedArray> entry_storage = |
| + isolate->factory()->NewUninitializedFixedArray(2); |
| + entry_storage->set(0, *next_key); |
| + entry_storage->set(1, *prop_value); |
| + prop_value = isolate->factory()->NewJSArrayWithElements(entry_storage, |
| + FAST_ELEMENTS, 2); |
| + } |
| + |
| + values_or_entries->set(count, *prop_value); |
| + count++; |
| + } |
| + |
| + if (count < values_or_entries->length()) values_or_entries->Shrink(count); |
| + *result = values_or_entries; |
| + return Just(true); |
| +} |
| + |
| MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate, |
| Handle<JSReceiver> object, |
| PropertyFilter filter, |
| bool get_entries) { |
| + Handle<FixedArray> values_or_entries; |
| + if (filter == ENUMERABLE_STRINGS && object->IsJSObject()) { |
|
Toon Verwaest
2016/03/07 22:39:34
You don't need object->IsJSObject since that's alr
|
| + Maybe<bool> fast_values_or_entries = |
| + FastGetOwnValuesOrEntries(isolate, Handle<JSObject>::cast(object), |
| + get_entries, &values_or_entries); |
| + if (fast_values_or_entries.IsNothing()) return MaybeHandle<FixedArray>(); |
| + if (fast_values_or_entries.FromJust()) return values_or_entries; |
| + } |
| + |
| PropertyFilter key_filter = |
| static_cast<PropertyFilter>(filter & ~ONLY_ENUMERABLE); |
| KeyAccumulator accumulator(isolate, OWN_ONLY, key_filter); |
| @@ -8789,8 +8873,7 @@ MaybeHandle<FixedArray> GetOwnValuesOrEntries(Isolate* isolate, |
| Handle<FixedArray> keys = accumulator.GetKeys(CONVERT_TO_STRING); |
| DCHECK(ContainsOnlyValidKeys(keys)); |
| - Handle<FixedArray> values_or_entries = |
| - isolate->factory()->NewFixedArray(keys->length()); |
| + values_or_entries = isolate->factory()->NewFixedArray(keys->length()); |
| int length = 0; |
| for (int i = 0; i < keys->length(); ++i) { |