Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(407)

Side by Side Diff: src/objects.cc

Issue 1614313003: Revert of [runtime] Do not use the enum-cache for non-prototype objects. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/regress/regress-705-shadowed_properties.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 8080 matching lines...) Expand 10 before | Expand all | Expand 10 after
8091 } 8091 }
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.Prepare(); 8101 accumulator.NextPrototype();
8102 copy->CollectOwnPropertyKeys(&accumulator, filter); 8102 copy->CollectOwnPropertyNames(&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 318 matching lines...) Expand 10 before | Expand all | Expand 10 after
8431 8431
8432 Handle<FixedArray> new_array = 8432 Handle<FixedArray> new_array =
8433 array->GetIsolate()->factory()->NewFixedArray(length); 8433 array->GetIsolate()->factory()->NewFixedArray(length);
8434 for (int i = 0; i < length; ++i) new_array->set(i, array->get(i)); 8434 for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
8435 return new_array; 8435 return new_array;
8436 } 8436 }
8437 8437
8438 8438
8439 namespace { 8439 namespace {
8440 8440
8441 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate, JSObject* object, 8441 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
8442 Handle<JSObject> object,
8442 bool cache_enum_length) { 8443 bool cache_enum_length) {
8443 Handle<Map> map(object->map(), isolate); 8444 Handle<Map> map(object->map());
8444 Handle<DescriptorArray> descs = 8445 Handle<DescriptorArray> descs =
8445 Handle<DescriptorArray>(map->instance_descriptors(), isolate); 8446 Handle<DescriptorArray>(map->instance_descriptors(), isolate);
8446 int own_property_count = map->EnumLength(); 8447 int own_property_count = map->EnumLength();
8447 // If the enum length of the given map is set to kInvalidEnumCache, this 8448 // If the enum length of the given map is set to kInvalidEnumCache, this
8448 // means that the map itself has never used the present enum cache. The 8449 // means that the map itself has never used the present enum cache. The
8449 // first step to using the cache is to set the enum length of the map by 8450 // first step to using the cache is to set the enum length of the map by
8450 // counting the number of own descriptors that are ENUMERABLE_STRINGS. 8451 // counting the number of own descriptors that are ENUMERABLE_STRINGS.
8451 if (own_property_count == kInvalidEnumCacheSentinel) { 8452 if (own_property_count == kInvalidEnumCacheSentinel) {
8452 own_property_count = 8453 own_property_count =
8453 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS); 8454 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS);
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
8507 DescriptorArray::SetEnumCache(descs, isolate, storage, indices); 8508 DescriptorArray::SetEnumCache(descs, isolate, storage, indices);
8508 if (cache_enum_length) { 8509 if (cache_enum_length) {
8509 map->SetEnumLength(own_property_count); 8510 map->SetEnumLength(own_property_count);
8510 } 8511 }
8511 return storage; 8512 return storage;
8512 } 8513 }
8513 8514
8514 } // namespace 8515 } // namespace
8515 8516
8516 8517
8517 Handle<FixedArray> JSObject::GetOwnEnumPropertyKeys(Handle<JSObject> object, 8518 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
8518 bool cache_enum_length) { 8519 bool cache_enum_length) {
8519 PropertyFilter filter = PropertyFilter::ENUMERABLE_STRINGS; 8520 Isolate* isolate = object->GetIsolate();
8520 KeyAccumulator keys(object->GetIsolate(), filter); 8521 if (object->HasFastProperties()) {
8521 keys.Prepare(); 8522 return GetFastEnumPropertyKeys(isolate, object, cache_enum_length);
8522 object->CollectOwnPropertyKeys(&keys, filter); 8523 } else if (object->IsJSGlobalObject()) {
8523 return keys.GetKeys(); 8524 Handle<GlobalDictionary> dictionary(object->global_dictionary());
8525 int length = dictionary->NumberOfEnumElements();
8526 if (length == 0) {
8527 return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
8528 }
8529 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
8530 dictionary->CopyEnumKeysTo(*storage);
8531 return storage;
8532 } else {
8533 Handle<NameDictionary> dictionary(object->property_dictionary());
8534 int length = dictionary->NumberOfEnumElements();
8535 if (length == 0) {
8536 return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
8537 }
8538 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
8539 dictionary->CopyEnumKeysTo(*storage);
8540 return storage;
8541 }
8524 } 8542 }
8525 8543
8526 8544
8527 enum IndexedOrNamed { kIndexed, kNamed }; 8545 enum IndexedOrNamed { kIndexed, kNamed };
8528 8546
8529 8547
8530 // Returns |true| on success, |nothing| on exception. 8548 // Returns |true| on success, |nothing| on exception.
8531 template <class Callback, IndexedOrNamed type> 8549 template <class Callback, IndexedOrNamed type>
8532 static Maybe<bool> GetKeysFromInterceptor(Isolate* isolate, 8550 static Maybe<bool> GetKeysFromInterceptor(Isolate* isolate,
8533 Handle<JSReceiver> receiver, 8551 Handle<JSReceiver> receiver,
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
8597 } 8615 }
8598 8616
8599 JSObject::CollectOwnElementKeys(object, accumulator, *filter); 8617 JSObject::CollectOwnElementKeys(object, accumulator, *filter);
8600 8618
8601 // Add the element keys from the interceptor. 8619 // Add the element keys from the interceptor.
8602 Maybe<bool> success = 8620 Maybe<bool> success =
8603 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>( 8621 GetKeysFromInterceptor<v8::IndexedPropertyEnumeratorCallback, kIndexed>(
8604 isolate, receiver, object, *filter, accumulator); 8622 isolate, receiver, object, *filter, accumulator);
8605 MAYBE_RETURN(success, Nothing<bool>()); 8623 MAYBE_RETURN(success, Nothing<bool>());
8606 8624
8607 object->CollectOwnPropertyKeys(accumulator, *filter, type); 8625 if (*filter == ENUMERABLE_STRINGS) {
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 }
8608 8649
8609 // Add the property keys from the interceptor. 8650 // Add the property keys from the interceptor.
8610 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback, 8651 success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback,
8611 kNamed>(isolate, receiver, object, *filter, 8652 kNamed>(isolate, receiver, object, *filter,
8612 accumulator); 8653 accumulator);
8613 MAYBE_RETURN(success, Nothing<bool>()); 8654 MAYBE_RETURN(success, Nothing<bool>());
8614 return Just(true); 8655 return Just(true);
8615 } 8656 }
8616 8657
8617 8658
(...skipping 7715 matching lines...) Expand 10 before | Expand all | Expand 10 after
16333 SwapPairs(numbers, i, p); 16374 SwapPairs(numbers, i, p);
16334 } 16375 }
16335 } 16376 }
16336 } else { 16377 } else {
16337 HeapSortPairs(this, numbers, len); 16378 HeapSortPairs(this, numbers, len);
16338 return; 16379 return;
16339 } 16380 }
16340 } 16381 }
16341 16382
16342 16383
16343 namespace { 16384 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys,
16344 16385 PropertyFilter filter) {
16345 void CollectEnumCacheTo(KeyAccumulator* keys, JSObject* object) { 16386 if (HasFastProperties()) {
16346 // We can cache the computed property keys if access checks are 16387 int real_size = map()->NumberOfOwnDescriptors();
16347 // not needed and no interceptors are involved. 16388 Handle<DescriptorArray> descs(map()->instance_descriptors());
16348 // 16389 for (int i = 0; i < real_size; i++) {
16349 // We do not use the cache if the object has elements and 16390 PropertyDetails details = descs->GetDetails(i);
16350 // therefore it does not make sense to cache the property names 16391 if ((details.attributes() & filter) != 0) continue;
16351 // for arguments objects. Arguments objects will always have 16392 if (filter & ONLY_ALL_CAN_READ) {
16352 // elements. 16393 if (details.kind() != kAccessor) continue;
16353 // Wrapped strings have elements, but don't have an elements 16394 Object* accessors = descs->GetValue(i);
16354 // array or dictionary. So the fast inline test for whether to 16395 if (!accessors->IsAccessorInfo()) continue;
16355 // use the cache says yes, so we should not create a cache. 16396 if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
16356 Isolate* isolate = keys->isolate();
16357 Handle<JSFunction> arguments_function(
16358 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
16359 bool cache_enum_length =
16360 ((object->map()->GetConstructor() != *arguments_function) &&
16361 !object->IsJSValue() && !object->IsAccessCheckNeeded() &&
16362 !object->HasNamedInterceptor() && !object->HasIndexedInterceptor());
16363 // Compute the property keys and cache them if possible.
16364 Handle<FixedArray> enum_keys =
16365 GetFastEnumPropertyKeys(isolate, object, cache_enum_length);
16366 keys->AddKeys(enum_keys);
16367 }
16368
16369 } // namespace
16370
16371
16372 void JSObject::CollectFastPropertyKeysTo(KeyAccumulator* keys,
16373 PropertyFilter filter,
16374 JSReceiver::KeyCollectionType type) {
16375 // Avoid using the enum cache if we have to walk the prototype chain due
16376 // to shadowing properties.
16377 if (filter == ENUMERABLE_STRINGS && type == JSReceiver::OWN_ONLY) {
16378 CollectEnumCacheTo(keys, this);
16379 return;
16380 }
16381
16382 int real_size = map()->NumberOfOwnDescriptors();
16383 Handle<DescriptorArray> descs(map()->instance_descriptors());
16384 for (int i = 0; i < real_size; i++) {
16385 PropertyDetails details = descs->GetDetails(i);
16386 if ((details.attributes() & filter) != 0) {
16387 if (type == JSReceiver::OWN_ONLY) continue;
16388 if (details.attributes() & DONT_ENUM) {
16389 keys->HideKey(descs->GetKey(i));
16390 } 16397 }
16391 continue; 16398 Name* key = descs->GetKey(i);
16399 if (key->FilterKey(filter)) continue;
16400 keys->AddKey(key);
16392 } 16401 }
16393 if (filter & ONLY_ALL_CAN_READ) {
16394 if (details.kind() != kAccessor) continue;
16395 Object* accessors = descs->GetValue(i);
16396 if (!accessors->IsAccessorInfo()) continue;
16397 if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
16398 }
16399 Name* key = descs->GetKey(i);
16400 if (key->FilterKey(filter)) continue;
16401 keys->AddKey(key);
16402 }
16403 }
16404
16405
16406 void JSObject::CollectOwnPropertyKeys(KeyAccumulator* keys,
16407 PropertyFilter filter,
16408 JSReceiver::KeyCollectionType type) {
16409 if (HasFastProperties()) {
16410 CollectFastPropertyKeysTo(keys, filter, type);
16411 } else if (IsJSGlobalObject()) { 16402 } else if (IsJSGlobalObject()) {
16412 GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter); 16403 GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter);
16413 } else { 16404 } else {
16414 NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter); 16405 NameDictionary::CollectKeysTo(handle(property_dictionary()), keys, filter);
16415 } 16406 }
16416 } 16407 }
16417 16408
16418 16409
16419 int JSObject::NumberOfOwnElements(PropertyFilter filter) { 16410 int JSObject::NumberOfOwnElements(PropertyFilter filter) {
16420 // Fast case for objects with no elements. 16411 // Fast case for objects with no elements.
(...skipping 2013 matching lines...) Expand 10 before | Expand all | Expand 10 after
18434 } 18425 }
18435 DCHECK(storage->length() >= index); 18426 DCHECK(storage->length() >= index);
18436 return index - start_index; 18427 return index - start_index;
18437 } 18428 }
18438 18429
18439 18430
18440 template <typename Derived, typename Shape, typename Key> 18431 template <typename Derived, typename Shape, typename Key>
18441 void Dictionary<Derived, Shape, Key>::CollectKeysTo( 18432 void Dictionary<Derived, Shape, Key>::CollectKeysTo(
18442 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, 18433 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys,
18443 PropertyFilter filter) { 18434 PropertyFilter filter) {
18444 if (dictionary->NumberOfElements() == 0) return;
18445 int capacity = dictionary->Capacity(); 18435 int capacity = dictionary->Capacity();
18446 Handle<FixedArray> array = 18436 Handle<FixedArray> array =
18447 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); 18437 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements());
18448 int array_size = 0; 18438 int array_size = 0;
18449 std::vector<int> hidden_key_indices;
18450 18439
18451 { 18440 {
18452 DisallowHeapAllocation no_gc; 18441 DisallowHeapAllocation no_gc;
18453 Dictionary<Derived, Shape, Key>* raw_dict = *dictionary; 18442 Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
18454 for (int i = 0; i < capacity; i++) { 18443 for (int i = 0; i < capacity; i++) {
18455 Object* key = raw_dict->KeyAt(i); 18444 Object* k = raw_dict->KeyAt(i);
18456 if (!raw_dict->IsKey(key) || key->FilterKey(filter)) continue; 18445 if (!raw_dict->IsKey(k) || k->FilterKey(filter)) continue;
18457 if (raw_dict->IsDeleted(i)) continue; 18446 if (raw_dict->IsDeleted(i)) continue;
18458 PropertyDetails details = raw_dict->DetailsAt(i); 18447 PropertyDetails details = raw_dict->DetailsAt(i);
18459 if ((details.attributes() & filter) != 0) { 18448 if ((details.attributes() & filter) != 0) continue;
18460 if (details.attributes() & DONT_ENUM) {
18461 hidden_key_indices.push_back(i);
18462 }
18463 continue;
18464 }
18465 if (filter & ONLY_ALL_CAN_READ) { 18449 if (filter & ONLY_ALL_CAN_READ) {
18466 if (details.kind() != kAccessor) continue; 18450 if (details.kind() != kAccessor) continue;
18467 Object* accessors = raw_dict->ValueAt(i); 18451 Object* accessors = raw_dict->ValueAt(i);
18468 if (accessors->IsPropertyCell()) { 18452 if (accessors->IsPropertyCell()) {
18469 accessors = PropertyCell::cast(accessors)->value(); 18453 accessors = PropertyCell::cast(accessors)->value();
18470 } 18454 }
18471 if (!accessors->IsAccessorInfo()) continue; 18455 if (!accessors->IsAccessorInfo()) continue;
18472 if (!AccessorInfo::cast(accessors)->all_can_read()) continue; 18456 if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
18473 } 18457 }
18474 array->set(array_size++, Smi::FromInt(i)); 18458 array->set(array_size++, Smi::FromInt(i));
18475 } 18459 }
18476 18460
18477 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict)); 18461 EnumIndexComparator<Derived> cmp(static_cast<Derived*>(raw_dict));
18478 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress()); 18462 Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress());
18479 std::sort(start, start + array_size, cmp); 18463 std::sort(start, start + array_size, cmp);
18480 } 18464 }
18481 for (uint32_t i = 0; i < hidden_key_indices.size(); i++) { 18465
18482 keys->HideKey(dictionary->KeyAt(hidden_key_indices[i]));
18483 }
18484 for (int i = 0; i < array_size; i++) { 18466 for (int i = 0; i < array_size; i++) {
18485 int index = Smi::cast(array->get(i))->value(); 18467 int index = Smi::cast(array->get(i))->value();
18486 keys->AddKey(dictionary->KeyAt(index)); 18468 keys->AddKey(dictionary->KeyAt(index));
18487 } 18469 }
18488 } 18470 }
18489 18471
18490 18472
18491 // Backwards lookup (slow). 18473 // Backwards lookup (slow).
18492 template<typename Derived, typename Shape, typename Key> 18474 template<typename Derived, typename Shape, typename Key>
18493 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { 18475 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
(...skipping 1239 matching lines...) Expand 10 before | Expand all | Expand 10 after
19733 if (cell->value() != *new_value) { 19715 if (cell->value() != *new_value) {
19734 cell->set_value(*new_value); 19716 cell->set_value(*new_value);
19735 Isolate* isolate = cell->GetIsolate(); 19717 Isolate* isolate = cell->GetIsolate();
19736 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19718 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19737 isolate, DependentCode::kPropertyCellChangedGroup); 19719 isolate, DependentCode::kPropertyCellChangedGroup);
19738 } 19720 }
19739 } 19721 }
19740 19722
19741 } // namespace internal 19723 } // namespace internal
19742 } // namespace v8 19724 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/regress/regress-705-shadowed_properties.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698