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 8081 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8092 } | 8092 } |
8093 } | 8093 } |
8094 } else { | 8094 } else { |
8095 // Only deep copy fields from the object literal expression. | 8095 // Only deep copy fields from the object literal expression. |
8096 // In particular, don't try to copy the length attribute of | 8096 // In particular, don't try to copy the length attribute of |
8097 // an array. | 8097 // an array. |
8098 PropertyFilter filter = static_cast<PropertyFilter>( | 8098 PropertyFilter filter = static_cast<PropertyFilter>( |
8099 ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE); | 8099 ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE); |
8100 KeyAccumulator accumulator(isolate, filter); | 8100 KeyAccumulator accumulator(isolate, filter); |
8101 accumulator.NextPrototype(); | 8101 accumulator.NextPrototype(); |
8102 copy->CollectOwnPropertyNames(&accumulator, filter); | 8102 copy->CollectOwnPropertyKeys(&accumulator, filter); |
8103 Handle<FixedArray> names = accumulator.GetKeys(); | 8103 Handle<FixedArray> names = accumulator.GetKeys(); |
8104 for (int i = 0; i < names->length(); i++) { | 8104 for (int i = 0; i < names->length(); i++) { |
8105 DCHECK(names->get(i)->IsName()); | 8105 DCHECK(names->get(i)->IsName()); |
8106 Handle<Name> name(Name::cast(names->get(i))); | 8106 Handle<Name> name(Name::cast(names->get(i))); |
8107 Handle<Object> value = | 8107 Handle<Object> value = |
8108 Object::GetProperty(copy, name).ToHandleChecked(); | 8108 Object::GetProperty(copy, name).ToHandleChecked(); |
8109 if (value->IsJSObject()) { | 8109 if (value->IsJSObject()) { |
8110 Handle<JSObject> result; | 8110 Handle<JSObject> result; |
8111 ASSIGN_RETURN_ON_EXCEPTION( | 8111 ASSIGN_RETURN_ON_EXCEPTION( |
8112 isolate, result, | 8112 isolate, result, |
(...skipping 502 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8615 } | 8615 } |
8616 | 8616 |
8617 JSObject::CollectOwnElementKeys(object, accumulator, *filter); | 8617 JSObject::CollectOwnElementKeys(object, accumulator, *filter); |
8618 | 8618 |
8619 // Add the element keys from the interceptor. | 8619 // Add the element keys from the interceptor. |
8620 Maybe<bool> success = | 8620 Maybe<bool> success = |
8621 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( | 8621 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( |
8622 isolate, receiver, object, *filter, accumulator); | 8622 isolate, receiver, object, *filter, accumulator); |
8623 MAYBE_RETURN(success, Nothing<bool>()); | 8623 MAYBE_RETURN(success, Nothing<bool>()); |
8624 | 8624 |
8625 if (*filter == ENUMERABLE_STRINGS) { | 8625 object->CollectOwnPropertyKeys(accumulator, *filter, type); |
8626 // We can cache the computed property keys if access checks are | |
8627 // not needed and no interceptors are involved. | |
8628 // | |
8629 // We do not use the cache if the object has elements and | |
8630 // therefore it does not make sense to cache the property names | |
8631 // for arguments objects. Arguments objects will always have | |
8632 // elements. | |
8633 // Wrapped strings have elements, but don't have an elements | |
8634 // array or dictionary. So the fast inline test for whether to | |
8635 // use the cache says yes, so we should not create a cache. | |
8636 Handle<JSFunction> arguments_function( | |
8637 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); | |
8638 bool cache_enum_length = | |
8639 ((object->map()->GetConstructor() != *arguments_function) && | |
8640 !object->IsJSValue() && !object->IsAccessCheckNeeded() && | |
8641 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor()); | |
8642 // Compute the property keys and cache them if possible. | |
8643 Handle<FixedArray> enum_keys = | |
8644 JSObject::GetEnumPropertyKeys(object, cache_enum_length); | |
8645 accumulator->AddKeys(enum_keys); | |
8646 } else { | |
8647 object->CollectOwnPropertyNames(accumulator, *filter); | |
8648 } | |
8649 | 8626 |
8650 // Add the property keys from the interceptor. | 8627 // Add the property keys from the interceptor. |
8651 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, | 8628 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, |
8652 kNamed>(isolate, receiver, object, *filter, | 8629 kNamed>(isolate, receiver, object, *filter, |
8653 accumulator); | 8630 accumulator); |
8654 MAYBE_RETURN(success, Nothing<bool>()); | 8631 MAYBE_RETURN(success, Nothing<bool>()); |
8655 return Just(true); | 8632 return Just(true); |
8656 } | 8633 } |
8657 | 8634 |
8658 | 8635 |
(...skipping 7715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
16374 SwapPairs(numbers, i, p); | 16351 SwapPairs(numbers, i, p); |
16375 } | 16352 } |
16376 } | 16353 } |
16377 } else { | 16354 } else { |
16378 HeapSortPairs(this, numbers, len); | 16355 HeapSortPairs(this, numbers, len); |
16379 return; | 16356 return; |
16380 } | 16357 } |
16381 } | 16358 } |
16382 | 16359 |
16383 | 16360 |
16384 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, | 16361 void JSObject::CollectOwnPropertyKeys(KeyAccumulator* keys, |
16385 PropertyFilter filter) { | 16362 PropertyFilter filter, |
| 16363 JSReceiver::KeyCollectionType type) { |
16386 if (HasFastProperties()) { | 16364 if (HasFastProperties()) { |
16387 int real_size = map()->NumberOfOwnDescriptors(); | 16365 int real_size = map()->NumberOfOwnDescriptors(); |
16388 Handle<DescriptorArray> descs(map()->instance_descriptors()); | 16366 Handle<DescriptorArray> descs(map()->instance_descriptors()); |
16389 for (int i = 0; i < real_size; i++) { | 16367 for (int i = 0; i < real_size; i++) { |
16390 PropertyDetails details = descs->GetDetails(i); | 16368 PropertyDetails details = descs->GetDetails(i); |
16391 if ((details.attributes() & filter) != 0) continue; | 16369 if ((details.attributes() & filter) != 0) { |
| 16370 if (type == JSReceiver::OWN_ONLY) continue; |
| 16371 if (details.attributes() & DONT_ENUM) { |
| 16372 keys->HideKey(descs->GetKey(i)); |
| 16373 } |
| 16374 continue; |
| 16375 } |
16392 if (filter & ONLY_ALL_CAN_READ) { | 16376 if (filter & ONLY_ALL_CAN_READ) { |
16393 if (details.kind() != kAccessor) continue; | 16377 if (details.kind() != kAccessor) continue; |
16394 Object* accessors = descs->GetValue(i); | 16378 Object* accessors = descs->GetValue(i); |
16395 if (!accessors->IsAccessorInfo()) continue; | 16379 if (!accessors->IsAccessorInfo()) continue; |
16396 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; | 16380 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; |
16397 } | 16381 } |
16398 Name* key = descs->GetKey(i); | 16382 Name* key = descs->GetKey(i); |
16399 if (key->FilterKey(filter)) continue; | 16383 if (key->FilterKey(filter)) continue; |
16400 keys->AddKey(key); | 16384 keys->AddKey(key); |
16401 } | 16385 } |
(...skipping 2023 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
18425 } | 18409 } |
18426 DCHECK(storage->length() >= index); | 18410 DCHECK(storage->length() >= index); |
18427 return index - start_index; | 18411 return index - start_index; |
18428 } | 18412 } |
18429 | 18413 |
18430 | 18414 |
18431 template <typename Derived, typename Shape, typename Key> | 18415 template <typename Derived, typename Shape, typename Key> |
18432 void Dictionary<Derived, Shape, Key>::CollectKeysTo( | 18416 void Dictionary<Derived, Shape, Key>::CollectKeysTo( |
18433 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, | 18417 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, |
18434 PropertyFilter filter) { | 18418 PropertyFilter filter) { |
| 18419 if (dictionary->NumberOfElements() == 0) return; |
18435 int capacity = dictionary->Capacity(); | 18420 int capacity = dictionary->Capacity(); |
18436 Handle<FixedArray> array = | 18421 Handle<FixedArray> array = |
18437 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); | 18422 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); |
18438 int array_size = 0; | 18423 int array_size = 0; |
| 18424 std::vector<int> hidden_key_indices; |
18439 | 18425 |
18440 { | 18426 { |
18441 DisallowHeapAllocation no_gc; | 18427 DisallowHeapAllocation no_gc; |
18442 Dictionary<Derived, Shape, Key>* raw_dict = *dictionary; | 18428 Dictionary<Derived, Shape, Key>* raw_dict = *dictionary; |
18443 for (int i = 0; i < capacity; i++) { | 18429 for (int i = 0; i < capacity; i++) { |
18444 Object* k = raw_dict->KeyAt(i); | 18430 Object* key = raw_dict->KeyAt(i); |
18445 if (!raw_dict->IsKey(k) || k->FilterKey(filter)) continue; | 18431 if (!raw_dict->IsKey(key) || key->FilterKey(filter)) continue; |
18446 if (raw_dict->IsDeleted(i)) continue; | 18432 if (raw_dict->IsDeleted(i)) continue; |
18447 PropertyDetails details = raw_dict->DetailsAt(i); | 18433 PropertyDetails details = raw_dict->DetailsAt(i); |
18448 if ((details.attributes() & filter) != 0) continue; | 18434 if ((details.attributes() & filter) != 0) { |
| 18435 if (details.attributes() & DONT_ENUM) { |
| 18436 hidden_key_indices.push_back(i); |
| 18437 } |
| 18438 continue; |
| 18439 } |
18449 if (filter & ONLY_ALL_CAN_READ) { | 18440 if (filter & ONLY_ALL_CAN_READ) { |
18450 if (details.kind() != kAccessor) continue; | 18441 if (details.kind() != kAccessor) continue; |
18451 Object* accessors = raw_dict->ValueAt(i); | 18442 Object* accessors = raw_dict->ValueAt(i); |
18452 if (accessors->IsPropertyCell()) { | 18443 if (accessors->IsPropertyCell()) { |
18453 accessors = PropertyCell::cast(accessors)->value(); | 18444 accessors = PropertyCell::cast(accessors)->value(); |
18454 } | 18445 } |
18455 if (!accessors->IsAccessorInfo()) continue; | 18446 if (!accessors->IsAccessorInfo()) continue; |
18456 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; | 18447 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; |
18457 } | 18448 } |
18458 array->set(array_size++, Smi::FromInt(i)); | 18449 array->set(array_size++, Smi::FromInt(i)); |
18459 } | 18450 } |
18460 | 18451 |
18461 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict)); | 18452 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict)); |
18462 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress()); | 18453 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress()); |
18463 std::sort(start, start + array_size, cmp); | 18454 std::sort(start, start + array_size, cmp); |
18464 } | 18455 } |
18465 | 18456 for (int i = 0; i < hidden_key_indices.size(); i++) { |
| 18457 keys->HideKey(dictionary->KeyAt(hidden_key_indices[i])); |
| 18458 } |
18466 for (int i = 0; i < array_size; i++) { | 18459 for (int i = 0; i < array_size; i++) { |
18467 int index = Smi::cast(array->get(i))->value(); | 18460 int index = Smi::cast(array->get(i))->value(); |
18468 keys->AddKey(dictionary->KeyAt(index)); | 18461 keys->AddKey(dictionary->KeyAt(index)); |
18469 } | 18462 } |
18470 } | 18463 } |
18471 | 18464 |
18472 | 18465 |
18473 // Backwards lookup (slow). | 18466 // Backwards lookup (slow). |
18474 template<typename Derived, typename Shape, typename Key> | 18467 template<typename Derived, typename Shape, typename Key> |
18475 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { | 18468 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { |
(...skipping 1239 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
19715 if (cell->value() != *new_value) { | 19708 if (cell->value() != *new_value) { |
19716 cell->set_value(*new_value); | 19709 cell->set_value(*new_value); |
19717 Isolate* isolate = cell->GetIsolate(); | 19710 Isolate* isolate = cell->GetIsolate(); |
19718 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 19711 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
19719 isolate, DependentCode::kPropertyCellChangedGroup); | 19712 isolate, DependentCode::kPropertyCellChangedGroup); |
19720 } | 19713 } |
19721 } | 19714 } |
19722 | 19715 |
19723 } // namespace internal | 19716 } // namespace internal |
19724 } // namespace v8 | 19717 } // namespace v8 |
OLD | NEW |