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

Side by Side Diff: src/objects.cc

Issue 1363293002: JSObject::GetEnumProperty cleanup (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: handlifying method Created 5 years, 2 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') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2013 the V8 project authors. All rights reserved. 1 // Copyright 2013 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 6594 matching lines...) Expand 10 before | Expand all | Expand 10 after
6605 DCHECK(array->length() >= length); 6605 DCHECK(array->length() >= length);
6606 if (array->length() == length) return array; 6606 if (array->length() == length) return array;
6607 6607
6608 Handle<FixedArray> new_array = 6608 Handle<FixedArray> new_array =
6609 array->GetIsolate()->factory()->NewFixedArray(length); 6609 array->GetIsolate()->factory()->NewFixedArray(length);
6610 for (int i = 0; i < length; ++i) new_array->set(i, array->get(i)); 6610 for (int i = 0; i < length; ++i) new_array->set(i, array->get(i));
6611 return new_array; 6611 return new_array;
6612 } 6612 }
6613 6613
6614 6614
6615 namespace {
6616
6617 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
6618 Handle<JSObject> object,
6619 bool cache_enum_length) {
6620 Handle<Map> map(object->map());
6621 Handle<DescriptorArray> descs =
6622 Handle<DescriptorArray>(map->instance_descriptors(), isolate);
6623 int own_property_count = map->EnumLength();
6624 // If the enum length of the given map is set to kInvalidEnumCache, this
6625 // means that the map itself has never used the present enum cache. The
6626 // first step to using the cache is to set the enum length of the map by
6627 // counting the number of own descriptors that are not DONT_ENUM or
6628 // SYMBOLIC.
6629 if (own_property_count == kInvalidEnumCacheSentinel) {
6630 own_property_count =
6631 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_SHOW);
6632 } else {
6633 DCHECK(own_property_count ==
6634 map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_SHOW));
6635 }
6636
6637 if (descs->HasEnumCache()) {
6638 Handle<FixedArray> keys(descs->GetEnumCache(), isolate);
6639 // In case the number of properties required in the enum are actually
6640 // present, we can reuse the enum cache. Otherwise, this means that the
6641 // enum cache was generated for a previous (smaller) version of the
6642 // Descriptor Array. In that case we regenerate the enum cache.
6643 if (own_property_count <= keys->length()) {
6644 isolate->counters()->enum_cache_hits()->Increment();
6645 if (cache_enum_length) map->SetEnumLength(own_property_count);
6646 return ReduceFixedArrayTo(keys, own_property_count);
6647 }
6648 }
6649
6650 if (descs->IsEmpty()) {
6651 isolate->counters()->enum_cache_hits()->Increment();
6652 if (cache_enum_length) map->SetEnumLength(0);
6653 return isolate->factory()->empty_fixed_array();
6654 }
6655
6656 isolate->counters()->enum_cache_misses()->Increment();
6657
6658 Handle<FixedArray> storage =
6659 isolate->factory()->NewFixedArray(own_property_count);
6660 Handle<FixedArray> indices =
6661 isolate->factory()->NewFixedArray(own_property_count);
6662
6663 int size = map->NumberOfOwnDescriptors();
6664 int index = 0;
6665
6666 for (int i = 0; i < size; i++) {
6667 PropertyDetails details = descs->GetDetails(i);
6668 Object* key = descs->GetKey(i);
6669 if (details.IsDontEnum() || key->IsSymbol()) continue;
6670 storage->set(index, key);
6671 if (!indices.is_null()) {
6672 if (details.type() != DATA) {
6673 indices = Handle<FixedArray>();
6674 } else {
6675 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
6676 int load_by_field_index = field_index.GetLoadByFieldIndex();
6677 indices->set(index, Smi::FromInt(load_by_field_index));
6678 }
6679 }
6680 index++;
6681 }
6682 DCHECK(index == storage->length());
6683
6684 DescriptorArray::SetEnumCache(descs, isolate, storage, indices);
6685 if (cache_enum_length) {
6686 map->SetEnumLength(own_property_count);
6687 }
6688 return storage;
6689 }
6690
6691 } // namespace
6692
6693
6615 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object, 6694 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
6616 bool cache_result) { 6695 bool cache_enum_length) {
6617 Isolate* isolate = object->GetIsolate(); 6696 Isolate* isolate = object->GetIsolate();
6618 if (object->HasFastProperties()) { 6697 if (object->HasFastProperties()) {
6619 int own_property_count = object->map()->EnumLength(); 6698 return GetFastEnumPropertyKeys(isolate, object, cache_enum_length);
6620 // If the enum length of the given map is set to kInvalidEnumCache, this
6621 // means that the map itself has never used the present enum cache. The
6622 // first step to using the cache is to set the enum length of the map by
6623 // counting the number of own descriptors that are not DONT_ENUM or
6624 // SYMBOLIC.
6625 if (own_property_count == kInvalidEnumCacheSentinel) {
6626 own_property_count = object->map()->NumberOfDescribedProperties(
6627 OWN_DESCRIPTORS, DONT_SHOW);
6628 } else {
6629 DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
6630 OWN_DESCRIPTORS, DONT_SHOW));
6631 }
6632
6633 if (object->map()->instance_descriptors()->HasEnumCache()) {
6634 DescriptorArray* desc = object->map()->instance_descriptors();
6635 Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
6636
6637 // In case the number of properties required in the enum are actually
6638 // present, we can reuse the enum cache. Otherwise, this means that the
6639 // enum cache was generated for a previous (smaller) version of the
6640 // Descriptor Array. In that case we regenerate the enum cache.
6641 if (own_property_count <= keys->length()) {
6642 if (cache_result) object->map()->SetEnumLength(own_property_count);
6643 isolate->counters()->enum_cache_hits()->Increment();
6644 return ReduceFixedArrayTo(keys, own_property_count);
6645 }
6646 }
6647
6648 Handle<Map> map(object->map());
6649
6650 if (map->instance_descriptors()->IsEmpty()) {
6651 isolate->counters()->enum_cache_hits()->Increment();
6652 if (cache_result) map->SetEnumLength(0);
6653 return isolate->factory()->empty_fixed_array();
6654 }
6655
6656 isolate->counters()->enum_cache_misses()->Increment();
6657
6658 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(
6659 own_property_count);
6660 Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
6661 own_property_count);
6662
6663 Handle<DescriptorArray> descs =
6664 Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
6665
6666 int size = map->NumberOfOwnDescriptors();
6667 int index = 0;
6668
6669 for (int i = 0; i < size; i++) {
6670 PropertyDetails details = descs->GetDetails(i);
6671 Object* key = descs->GetKey(i);
6672 if (!(details.IsDontEnum() || key->IsSymbol())) {
6673 storage->set(index, key);
6674 if (!indices.is_null()) {
6675 if (details.type() != DATA) {
6676 indices = Handle<FixedArray>();
6677 } else {
6678 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
6679 int load_by_field_index = field_index.GetLoadByFieldIndex();
6680 indices->set(index, Smi::FromInt(load_by_field_index));
6681 }
6682 }
6683 index++;
6684 }
6685 }
6686 DCHECK(index == storage->length());
6687
6688 Handle<FixedArray> bridge_storage =
6689 isolate->factory()->NewFixedArray(
6690 DescriptorArray::kEnumCacheBridgeLength);
6691 DescriptorArray* desc = object->map()->instance_descriptors();
6692 desc->SetEnumCache(*bridge_storage,
6693 *storage,
6694 indices.is_null() ? Object::cast(Smi::FromInt(0))
6695 : Object::cast(*indices));
6696 if (cache_result) {
6697 object->map()->SetEnumLength(own_property_count);
6698 }
6699 return storage;
6700 } else if (object->IsGlobalObject()) { 6699 } else if (object->IsGlobalObject()) {
6701 Handle<GlobalDictionary> dictionary(object->global_dictionary()); 6700 Handle<GlobalDictionary> dictionary(object->global_dictionary());
6702 int length = dictionary->NumberOfEnumElements(); 6701 int length = dictionary->NumberOfEnumElements();
6703 if (length == 0) { 6702 if (length == 0) {
6704 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); 6703 return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6705 } 6704 }
6706 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); 6705 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6707 dictionary->CopyEnumKeysTo(*storage); 6706 dictionary->CopyEnumKeysTo(*storage);
6708 return storage; 6707 return storage;
6709 } else { 6708 } else {
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
6893 // We can cache the computed property keys if access checks are 6892 // We can cache the computed property keys if access checks are
6894 // not needed and no interceptors are involved. 6893 // not needed and no interceptors are involved.
6895 // 6894 //
6896 // We do not use the cache if the object has elements and 6895 // We do not use the cache if the object has elements and
6897 // therefore it does not make sense to cache the property names 6896 // therefore it does not make sense to cache the property names
6898 // for arguments objects. Arguments objects will always have 6897 // for arguments objects. Arguments objects will always have
6899 // elements. 6898 // elements.
6900 // Wrapped strings have elements, but don't have an elements 6899 // Wrapped strings have elements, but don't have an elements
6901 // array or dictionary. So the fast inline test for whether to 6900 // array or dictionary. So the fast inline test for whether to
6902 // use the cache says yes, so we should not create a cache. 6901 // use the cache says yes, so we should not create a cache.
6903 bool cache_enum_keys = 6902 bool cache_enum_length =
6904 ((current->map()->GetConstructor() != *arguments_function) && 6903 ((current->map()->GetConstructor() != *arguments_function) &&
6905 !current->IsJSValue() && !current->IsAccessCheckNeeded() && 6904 !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
6906 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); 6905 !current->HasNamedInterceptor() && !current->HasIndexedInterceptor());
6907 // Compute the property keys and cache them if possible. 6906 // Compute the property keys and cache them if possible.
6908 6907
6909 Handle<FixedArray> enum_keys = 6908 Handle<FixedArray> enum_keys =
6910 JSObject::GetEnumPropertyKeys(current, cache_enum_keys); 6909 JSObject::GetEnumPropertyKeys(current, cache_enum_length);
6911 accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS); 6910 accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS);
6912 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); 6911 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6913 6912
6914 // Add the non-symbol property keys from the interceptor. 6913 // Add the non-symbol property keys from the interceptor.
6915 if (current->HasNamedInterceptor()) { 6914 if (current->HasNamedInterceptor()) {
6916 Handle<JSObject> result; 6915 Handle<JSObject> result;
6917 if (JSObject::GetKeysForNamedInterceptor( 6916 if (JSObject::GetKeysForNamedInterceptor(
6918 current, object).ToHandle(&result)) { 6917 current, object).ToHandle(&result)) {
6919 accumulator.AddKeys(result, FixedArray::NON_SYMBOL_KEYS); 6918 accumulator.AddKeys(result, FixedArray::NON_SYMBOL_KEYS);
6920 } 6919 }
(...skipping 1732 matching lines...) Expand 10 before | Expand all | Expand 10 after
8653 set(kEnumCacheIndex, Smi::FromInt(0)); 8652 set(kEnumCacheIndex, Smi::FromInt(0));
8654 } 8653 }
8655 8654
8656 8655
8657 void DescriptorArray::Replace(int index, Descriptor* descriptor) { 8656 void DescriptorArray::Replace(int index, Descriptor* descriptor) {
8658 descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index)); 8657 descriptor->SetSortedKeyIndex(GetSortedKeyIndex(index));
8659 Set(index, descriptor); 8658 Set(index, descriptor);
8660 } 8659 }
8661 8660
8662 8661
8663 void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, 8662 // static
8664 FixedArray* new_cache, 8663 void DescriptorArray::SetEnumCache(Handle<DescriptorArray> descriptors,
8665 Object* new_index_cache) { 8664 Isolate* isolate,
8666 DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength); 8665 Handle<FixedArray> new_cache,
8667 DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); 8666 Handle<FixedArray> new_index_cache) {
8668 DCHECK(!IsEmpty()); 8667 DCHECK(!descriptors->IsEmpty());
8669 DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length()); 8668 FixedArray* bridge_storage;
8670 FixedArray::cast(bridge_storage)-> 8669 bool needs_new_enum_cache = !descriptors->HasEnumCache();
8671 set(kEnumCacheBridgeCacheIndex, new_cache); 8670 if (needs_new_enum_cache) {
8672 FixedArray::cast(bridge_storage)-> 8671 bridge_storage = *isolate->factory()->NewFixedArray(
8673 set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); 8672 DescriptorArray::kEnumCacheBridgeLength);
8674 set(kEnumCacheIndex, bridge_storage); 8673 } else {
8674 bridge_storage = FixedArray::cast(descriptors->get(kEnumCacheIndex));
8675 }
8676 bridge_storage->set(kEnumCacheBridgeCacheIndex, *new_cache);
8677 bridge_storage->set(kEnumCacheBridgeIndicesCacheIndex,
8678 new_index_cache.is_null() ? Object::cast(Smi::FromInt(0))
8679 : *new_index_cache);
8680 if (needs_new_enum_cache) {
8681 descriptors->set(kEnumCacheIndex, bridge_storage);
8682 }
8675 } 8683 }
8676 8684
8677 8685
8678 void DescriptorArray::CopyFrom(int index, DescriptorArray* src, 8686 void DescriptorArray::CopyFrom(int index, DescriptorArray* src,
8679 const WhitenessWitness& witness) { 8687 const WhitenessWitness& witness) {
8680 Object* value = src->GetValue(index); 8688 Object* value = src->GetValue(index);
8681 PropertyDetails details = src->GetDetails(index); 8689 PropertyDetails details = src->GetDetails(index);
8682 Descriptor desc(handle(src->GetKey(index)), 8690 Descriptor desc(handle(src->GetKey(index)),
8683 handle(value, src->GetIsolate()), 8691 handle(value, src->GetIsolate()),
8684 details); 8692 details);
(...skipping 8103 matching lines...) Expand 10 before | Expand all | Expand 10 after
16788 if (cell->value() != *new_value) { 16796 if (cell->value() != *new_value) {
16789 cell->set_value(*new_value); 16797 cell->set_value(*new_value);
16790 Isolate* isolate = cell->GetIsolate(); 16798 Isolate* isolate = cell->GetIsolate();
16791 cell->dependent_code()->DeoptimizeDependentCodeGroup( 16799 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16792 isolate, DependentCode::kPropertyCellChangedGroup); 16800 isolate, DependentCode::kPropertyCellChangedGroup);
16793 } 16801 }
16794 } 16802 }
16795 16803
16796 } // namespace internal 16804 } // namespace internal
16797 } // namespace v8 16805 } // namespace v8
OLDNEW
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698