| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 075a738d2ccf742f635d60e0cb13c49d9219d9fa..540bbb34a13748a4216ceeedfe541106cc0846d9 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -8776,10 +8776,93 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
|
| return keys;
|
| }
|
|
|
| +MUST_USE_RESULT Maybe<bool> FastGetOwnValuesOrEntries(
|
| + Isolate* isolate, Handle<JSReceiver> receiver, bool get_entries,
|
| + Handle<FixedArray>* result) {
|
| + Handle<Map> map(JSReceiver::cast(*receiver)->map(), isolate);
|
| +
|
| + if (!map->IsJSObjectMap()) return Just(false);
|
| + if (!map->OnlyHasSimpleProperties()) return Just(false);
|
| +
|
| + Handle<JSObject> object(JSObject::cast(*receiver));
|
| + if (object->elements() != isolate->heap()->empty_fixed_array()) {
|
| + return Just(false);
|
| + }
|
| +
|
| + Handle<DescriptorArray> descriptors(map->instance_descriptors(), isolate);
|
| + int number_of_own_descriptors = map->NumberOfOwnDescriptors();
|
| + Handle<FixedArray> values_or_entries =
|
| + isolate->factory()->NewFixedArray(number_of_own_descriptors);
|
| + int count = 0;
|
| +
|
| + bool stable = true;
|
| +
|
| + for (int index = 0; index < number_of_own_descriptors; 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) {
|
| + Maybe<bool> fast_values_or_entries = FastGetOwnValuesOrEntries(
|
| + isolate, 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 +8872,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) {
|
|
|