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

Side by Side Diff: src/objects.cc

Issue 1397063002: [runtime] Fancify KeyAccumulator (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: adding KeyAccumulator destructor 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
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
11 #include "src/accessors.h" 11 #include "src/accessors.h"
12 #include "src/allocation-site-scopes.h" 12 #include "src/allocation-site-scopes.h"
13 #include "src/api.h" 13 #include "src/api.h"
14 #include "src/arguments.h" 14 #include "src/arguments.h"
15 #include "src/base/bits.h" 15 #include "src/base/bits.h"
16 #include "src/base/utils/random-number-generator.h" 16 #include "src/base/utils/random-number-generator.h"
17 #include "src/bootstrapper.h" 17 #include "src/bootstrapper.h"
18 #include "src/code-stubs.h" 18 #include "src/code-stubs.h"
19 #include "src/codegen.h" 19 #include "src/codegen.h"
20 #include "src/compilation-dependencies.h" 20 #include "src/compilation-dependencies.h"
21 #include "src/compiler.h" 21 #include "src/compiler.h"
22 #include "src/date.h" 22 #include "src/date.h"
23 #include "src/debug/debug.h" 23 #include "src/debug/debug.h"
24 #include "src/deoptimizer.h" 24 #include "src/deoptimizer.h"
25 #include "src/elements.h" 25 #include "src/elements.h"
26 #include "src/execution.h" 26 #include "src/execution.h"
27 #include "src/field-index.h"
27 #include "src/field-index-inl.h" 28 #include "src/field-index-inl.h"
28 #include "src/field-index.h"
29 #include "src/full-codegen/full-codegen.h" 29 #include "src/full-codegen/full-codegen.h"
30 #include "src/hydrogen.h" 30 #include "src/hydrogen.h"
31 #include "src/ic/ic.h" 31 #include "src/ic/ic.h"
32 #include "src/interpreter/bytecodes.h" 32 #include "src/interpreter/bytecodes.h"
33 #include "src/isolate-inl.h" 33 #include "src/isolate-inl.h"
34 #include "src/list.h"
34 #include "src/log.h" 35 #include "src/log.h"
35 #include "src/lookup.h" 36 #include "src/lookup.h"
36 #include "src/macro-assembler.h" 37 #include "src/macro-assembler.h"
37 #include "src/messages.h" 38 #include "src/messages.h"
38 #include "src/objects-inl.h" 39 #include "src/objects-inl.h"
39 #include "src/profiler/cpu-profiler.h" 40 #include "src/profiler/cpu-profiler.h"
40 #include "src/prototype.h" 41 #include "src/prototype.h"
41 #include "src/safepoint-table.h" 42 #include "src/safepoint-table.h"
42 #include "src/string-builder.h" 43 #include "src/string-builder.h"
43 #include "src/string-search.h" 44 #include "src/string-search.h"
(...skipping 6726 matching lines...) Expand 10 before | Expand all | Expand 10 after
6770 if (length == 0) { 6771 if (length == 0) {
6771 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); 6772 return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
6772 } 6773 }
6773 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length); 6774 Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
6774 dictionary->CopyEnumKeysTo(*storage); 6775 dictionary->CopyEnumKeysTo(*storage);
6775 return storage; 6776 return storage;
6776 } 6777 }
6777 } 6778 }
6778 6779
6779 6780
6780 Handle<FixedArray> KeyAccumulator::GetKeys() { 6781 KeyAccumulator::~KeyAccumulator() {
6782 for (int i = 0; i < elements_.length(); i++) {
6783 delete elements_[i];
6784 }
6785 }
6786
6787
6788 Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) {
6781 if (length_ == 0) { 6789 if (length_ == 0) {
6782 return isolate_->factory()->empty_fixed_array(); 6790 return isolate_->factory()->empty_fixed_array();
6783 } 6791 }
6784 if (set_.is_null()) { 6792 // make sure we have all the lengths collected
6785 keys_->Shrink(length_); 6793 NextPrototype();
6786 return keys_; 6794
6787 } 6795 // Assemble the result array by first adding the element keys and then
6788 // copy over results from set_ 6796 // the property keys. We use the total number of keys per level in
6797 // |protoLengths_| and the available element keys in the corresponding bucket
6798 // in |elements_| to deduce the number of keys to take from the |properties_|
6799 // set.
6789 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_); 6800 Handle<FixedArray> result = isolate_->factory()->NewFixedArray(length_);
6790 for (int i = 0; i < length_; i++) { 6801 int index = 0;
6791 result->set(i, set_->KeyAt(i)); 6802 int properties_index = 0;
6803 for (int level = 0; level < levelLengths_.length(); level++) {
6804 int num_total = levelLengths_[level];
6805 int num_elements = 0;
6806 if (num_total < 0) {
6807 // If the total is negative, the current level contains properties from a
6808 // proxy, hence we skip the integer keys in |elements_| since procies
Igor Sheludko 2015/10/15 09:51:44 s/procies/proxies/
6809 // define the complete ordering.
6810 num_total = -num_total;
6811 } else if (level < elements_.length()) {
6812 List<uint32_t>* elements = elements_[level];
6813 num_elements = elements->length();
6814 for (int i = 0; i < num_elements; i++) {
6815 Handle<Object> key;
6816 if (convert == KEEP_NUMBERS) {
6817 key = isolate_->factory()->NewNumberFromUint(elements->at(i));
6818 } else {
6819 key = isolate_->factory()->Uint32ToString(elements->at(i));
6820 }
6821 result->set(index, *key);
6822 index++;
6823 }
6824 }
6825 // Add the property keys for this prototype level.
6826 int num_properties = num_total - num_elements;
6827 for (int i = 0; i < num_properties; i++) {
6828 Object* key = properties_->KeyAt(properties_index);
6829 result->set(index, key);
6830 index++;
6831 properties_index++;
6832 }
6792 } 6833 }
Igor Sheludko 2015/10/15 09:51:44 DCHECK_EQ(index, length_);
6793 return result; 6834 return result;
6794 } 6835 }
6795 6836
6796 6837
6797 void KeyAccumulator::AddKey(Handle<Object> key, int check_limit) { 6838 namespace {
6798 #ifdef ENABLE_SLOW_DCHECKS 6839
6799 if (FLAG_enable_slow_asserts) { 6840 class FindKey {
6800 DCHECK(key->IsNumber() || key->IsName()); 6841 public:
6801 } 6842 explicit FindKey(uint32_t key) : key_(key) {}
6802 #endif 6843 int operator()(uint32_t* entry) {
6803 if (!set_.is_null()) { 6844 if (*entry == key_) return 0;
6804 set_ = OrderedHashSet::Add(set_, key); 6845 return *entry < key_ ? -1 : 1;
6805 length_ = set_->NumberOfElements(); 6846 }
6806 return; 6847
6807 } 6848 private:
6808 // check if we already have the key in the case we are still using 6849 uint32_t key_;
6809 // the keys_ FixedArray 6850 };
6810 check_limit = Min(check_limit, length_); 6851
6811 for (int i = 0; i < check_limit; i++) { 6852
6812 Object* current = keys_->get(i); 6853 bool AccumulatorHasKey(List<uint32_t>* sub_elements, uint32_t key) {
6813 if (current->KeyEquals(*key)) return; 6854 int index = SortedListBSearch(*sub_elements, FindKey(key));
6814 } 6855 return index != -1;
6815 EnsureCapacity(length_); 6856 }
6816 keys_->set(length_, *key); 6857
6858 } // namespace
6859
6860
6861 bool KeyAccumulator::AddKey(uint32_t key) {
6862 int lookup_limit = elements_.length();
6863 for (int i = 0; i < lookup_limit; i++) {
6864 if (AccumulatorHasKey(elements_[i], key)) return false;
6865 }
6866 elements_[lookup_limit - 1]->Add(key);
6817 length_++; 6867 length_++;
6818 } 6868 levelLength_++;
6819 6869 return true;
6820 6870 }
6821 void KeyAccumulator::AddKeys(Handle<FixedArray> array, KeyFilter filter) { 6871
6872
6873 bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) {
6874 return AddKey(handle(key, isolate_), convert);
6875 }
6876
6877
6878 bool KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) {
6879 if (filter_ == SKIP_SYMBOLS && key->IsSymbol()) {
6880 return false;
6881 }
Igor Sheludko 2015/10/15 09:51:43 Just to be sure we are not trying to add to the pr
6882 // In some cases (e.g. proxies) we might get in String-converted ints which
6883 // should be added to the elements list instead of the properties. For
6884 // proxies we have to convert as well but also respect the original order.
6885 // Therefore we add a converted key to both sides
6886 if (convert == CONVERT_TO_ARRAY_INDEX || convert == PROXY_MAGIC) {
6887 uint32_t index = 0;
6888 int prev_length = length_;
6889 int prev_proto = levelLength_;
6890 bool was_array_index = false;
6891 bool key_was_added = false;
6892 if ((key->IsString() && Handle<String>::cast(key)->AsArrayIndex(&index)) ||
6893 key->ToArrayIndex(&index)) {
6894 key_was_added = AddKey(index);
6895 was_array_index = true;
6896 if (convert == CONVERT_TO_ARRAY_INDEX) return key_was_added;
6897 }
6898 if (was_array_index && convert == PROXY_MAGIC) {
6899 // If we had an array index (number) and it wasn't added, the key
6900 // already existed before, hence we cannot add it to the properties
6901 // keys as it would lead to duplicate entries.
6902 if (!key_was_added) {
6903 return false;
6904 }
6905 length_ = prev_length;
6906 levelLength_ = prev_proto;
6907 }
6908 }
6909 if (properties_.is_null()) {
6910 properties_ = OrderedHashSet::Allocate(isolate_, 16);
6911 }
6912 // TODO(cbruni): remove this conversion once we throw the correct TypeError
6913 // for non-string/symbol elements returned by proxies
6914 if (convert == PROXY_MAGIC && key->IsNumber()) {
6915 key = isolate_->factory()->NumberToString(key);
6916 }
6917 int prev_size = properties_->NumberOfElements();
6918 properties_ = OrderedHashSet::Add(properties_, key);
6919 if (prev_size < properties_->NumberOfElements()) {
6920 length_++;
6921 levelLength_++;
6922 }
6923 return true;
6924 }
6925
6926
6927 void KeyAccumulator::AddKeys(Handle<FixedArray> array,
6928 AddKeyConversion convert) {
6822 int add_length = array->length(); 6929 int add_length = array->length();
6823 if (add_length == 0) return; 6930 if (add_length == 0) return;
6824 if (keys_.is_null() && filter == INCLUDE_SYMBOLS) {
6825 keys_ = array;
6826 length_ = keys_->length();
6827 return;
6828 }
6829 PrepareForComparisons(add_length);
6830 int previous_key_count = length_;
6831 for (int i = 0; i < add_length; i++) { 6931 for (int i = 0; i < add_length; i++) {
6832 Handle<Object> current(array->get(i), isolate_); 6932 Handle<Object> current(array->get(i), isolate_);
6833 if (filter == SKIP_SYMBOLS && current->IsSymbol()) continue; 6933 AddKey(current);
6834 AddKey(current, previous_key_count); 6934 }
6835 } 6935 }
6836 } 6936
6837 6937
6838 6938 void KeyAccumulator::AddKeys(Handle<JSObject> array_like,
6839 void KeyAccumulator::AddKeys(Handle<JSObject> array_like, KeyFilter filter) { 6939 AddKeyConversion convert) {
6840 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements()); 6940 DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements());
6841 ElementsAccessor* accessor = array_like->GetElementsAccessor(); 6941 ElementsAccessor* accessor = array_like->GetElementsAccessor();
6842 accessor->AddElementsToKeyAccumulator(array_like, this, filter); 6942 accessor->AddElementsToKeyAccumulator(array_like, this, convert);
6843 } 6943 }
6844 6944
6845 6945
6846 void KeyAccumulator::PrepareForComparisons(int count) { 6946 void KeyAccumulator::AddKeysFromProxy(Handle<JSObject> array_like) {
6847 // Depending on how many comparisons we do we should switch to the 6947 // Proxies define a complete list of keys with no distinction of
6848 // hash-table-based checks which have a one-time overhead for 6948 // elements and properties, which breaks the normal assumption for the
6849 // initializing but O(1) for HasKey checks. 6949 // KeyAccumulator.
6850 if (!set_.is_null()) return; 6950 AddKeys(array_like, PROXY_MAGIC);
6851 // These limits were obtained through evaluation of several microbenchmarks. 6951 // Invert the current length to indicate a present proxy, so we can ignore
6852 if (length_ * count < 100) return; 6952 // element keys for this level. Otherwise we would not fully respect the order
6853 // Don't use a set for few elements 6953 // given by the proxy.
6854 if (length_ < 100 && count < 20) return; 6954 levelLength_ = -levelLength_;
6855 set_ = OrderedHashSet::Allocate(isolate_, length_); 6955 }
6856 for (int i = 0; i < length_; i++) { 6956
6857 Handle<Object> value(keys_->get(i), isolate_); 6957
6858 set_ = OrderedHashSet::Add(set_, value); 6958 namespace {
6859 } 6959
6860 } 6960 // Used for sorting indices in a List<uint32_t>.
6861 6961 int compareUInt32(const uint32_t* ap, const uint32_t* bp) {
6862 6962 uint32_t a = *ap;
6863 void KeyAccumulator::EnsureCapacity(int capacity) { 6963 uint32_t b = *bp;
6864 if (keys_.is_null() || keys_->length() <= capacity) { 6964 return (a == b) ? 0 : (a < b) ? -1 : 1;
6865 Grow(); 6965 }
6866 } 6966
6867 } 6967
6868 6968 } // namespace
6869 6969
6870 void KeyAccumulator::Grow() { 6970
6871 // The OrderedHashSet handles growing by itself. 6971 void KeyAccumulator::SortCurrentElementsList() {
6872 if (!set_.is_null()) return; 6972 if (elements_.length() == 0) return;
6873 // Otherwise, grow the internal keys_ FixedArray 6973 List<uint32_t>* element_keys = elements_[elements_.length() - 1];
6874 int capacity = keys_.is_null() ? 16 : keys_->length() * 2 + 16; 6974 element_keys->Sort(&compareUInt32);
6875 Handle<FixedArray> new_keys = isolate_->factory()->NewFixedArray(capacity); 6975 }
6876 if (keys_.is_null()) { 6976
6877 keys_ = new_keys; 6977
6878 return; 6978 void KeyAccumulator::NextPrototype() {
6879 } 6979 // Store the protoLength on the first call of this method.
6880 int buffer_length = keys_->length(); 6980 if (!elements_.is_empty()) {
6881 { 6981 levelLengths_.Add(levelLength_);
6882 DisallowHeapAllocation no_gc; 6982 }
6883 WriteBarrierMode mode = new_keys->GetWriteBarrierMode(no_gc); 6983 elements_.Add(new List<uint32_t>());
6884 for (int i = 0; i < buffer_length; i++) { 6984 levelLength_ = 0;
6885 new_keys->set(i, keys_->get(i), mode); 6985 }
6886 } 6986
6887 } 6987
6888 keys_ = new_keys;
6889 }
6890
6891
6892 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, 6988 MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
6893 KeyCollectionType type, 6989 KeyCollectionType type,
6894 KeyFilter filter) { 6990 KeyFilter filter) {
6895 USE(ContainsOnlyValidKeys); 6991 USE(ContainsOnlyValidKeys);
6896 Isolate* isolate = object->GetIsolate(); 6992 Isolate* isolate = object->GetIsolate();
6897 KeyAccumulator accumulator(isolate); 6993 KeyAccumulator accumulator(isolate, filter);
6898 Handle<JSFunction> arguments_function( 6994 Handle<JSFunction> arguments_function(
6899 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor())); 6995 JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
6900 6996
6901 PrototypeIterator::WhereToEnd end = type == OWN_ONLY 6997 PrototypeIterator::WhereToEnd end = type == OWN_ONLY
6902 ? PrototypeIterator::END_AT_NON_HIDDEN 6998 ? PrototypeIterator::END_AT_NON_HIDDEN
6903 : PrototypeIterator::END_AT_NULL; 6999 : PrototypeIterator::END_AT_NULL;
6904 // Only collect keys if access is permitted. 7000 // Only collect keys if access is permitted.
6905 for (PrototypeIterator iter(isolate, object, 7001 for (PrototypeIterator iter(isolate, object,
6906 PrototypeIterator::START_AT_RECEIVER); 7002 PrototypeIterator::START_AT_RECEIVER);
6907 !iter.IsAtEnd(end); iter.Advance()) { 7003 !iter.IsAtEnd(end); iter.Advance()) {
7004 accumulator.NextPrototype();
6908 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) { 7005 if (PrototypeIterator::GetCurrent(iter)->IsJSProxy()) {
6909 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter); 7006 Handle<JSProxy> proxy = PrototypeIterator::GetCurrent<JSProxy>(iter);
6910 Handle<Object> args[] = { proxy }; 7007 Handle<Object> args[] = { proxy };
6911 Handle<Object> names; 7008 Handle<Object> names;
6912 ASSIGN_RETURN_ON_EXCEPTION( 7009 ASSIGN_RETURN_ON_EXCEPTION(
6913 isolate, names, 7010 isolate, names,
6914 Execution::Call(isolate, 7011 Execution::Call(isolate,
6915 isolate->proxy_enumerate(), 7012 isolate->proxy_enumerate(),
6916 object, 7013 object,
6917 arraysize(args), 7014 arraysize(args),
6918 args), 7015 args),
6919 FixedArray); 7016 FixedArray);
6920 accumulator.AddKeys(Handle<JSObject>::cast(names), filter); 7017 accumulator.AddKeysFromProxy(Handle<JSObject>::cast(names));
6921 break; 7018 break;
6922 } 7019 }
6923 7020
6924 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter); 7021 Handle<JSObject> current = PrototypeIterator::GetCurrent<JSObject>(iter);
6925 7022
6926 // Check access rights if required. 7023 // Check access rights if required.
6927 if (current->IsAccessCheckNeeded() && 7024 if (current->IsAccessCheckNeeded() &&
6928 !isolate->MayAccess(handle(isolate->context()), current)) { 7025 !isolate->MayAccess(handle(isolate->context()), current)) {
6929 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { 7026 if (iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) {
6930 isolate->ReportFailedAccessCheck(current); 7027 isolate->ReportFailedAccessCheck(current);
6931 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray); 7028 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(isolate, FixedArray);
6932 } 7029 }
6933 break; 7030 break;
6934 } 7031 }
6935 7032
6936 // Compute the element keys. 7033 JSObject::CollectOwnElementKeys(current, &accumulator,
6937 Handle<FixedArray> element_keys = 7034 static_cast<PropertyAttributes>(DONT_ENUM));
6938 isolate->factory()->NewFixedArray(current->NumberOfEnumElements());
6939 current->GetEnumElementKeys(*element_keys);
6940 accumulator.AddKeys(element_keys, filter);
6941 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6942 7035
6943 // Add the element keys from the interceptor. 7036 // Add the element keys from the interceptor.
6944 if (current->HasIndexedInterceptor()) { 7037 if (current->HasIndexedInterceptor()) {
6945 Handle<JSObject> result; 7038 Handle<JSObject> result;
6946 if (JSObject::GetKeysForIndexedInterceptor( 7039 if (JSObject::GetKeysForIndexedInterceptor(current, object)
6947 current, object).ToHandle(&result)) { 7040 .ToHandle(&result)) {
6948 accumulator.AddKeys(result, filter); 7041 accumulator.AddKeys(result, CONVERT_TO_ARRAY_INDEX);
6949 } 7042 }
6950 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6951 } 7043 }
6952 7044
6953 if (filter == SKIP_SYMBOLS) { 7045 if (filter == SKIP_SYMBOLS) {
6954 // We can cache the computed property keys if access checks are 7046 // We can cache the computed property keys if access checks are
6955 // not needed and no interceptors are involved. 7047 // not needed and no interceptors are involved.
6956 // 7048 //
6957 // We do not use the cache if the object has elements and 7049 // We do not use the cache if the object has elements and
6958 // therefore it does not make sense to cache the property names 7050 // therefore it does not make sense to cache the property names
6959 // for arguments objects. Arguments objects will always have 7051 // for arguments objects. Arguments objects will always have
6960 // elements. 7052 // elements.
6961 // Wrapped strings have elements, but don't have an elements 7053 // Wrapped strings have elements, but don't have an elements
6962 // array or dictionary. So the fast inline test for whether to 7054 // array or dictionary. So the fast inline test for whether to
6963 // use the cache says yes, so we should not create a cache. 7055 // use the cache says yes, so we should not create a cache.
6964 bool cache_enum_length = 7056 bool cache_enum_length =
6965 ((current->map()->GetConstructor() != *arguments_function) && 7057 ((current->map()->GetConstructor() != *arguments_function) &&
6966 !current->IsJSValue() && !current->IsAccessCheckNeeded() && 7058 !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
6967 !current->HasNamedInterceptor() && 7059 !current->HasNamedInterceptor() &&
6968 !current->HasIndexedInterceptor()); 7060 !current->HasIndexedInterceptor());
6969 // Compute the property keys and cache them if possible. 7061 // Compute the property keys and cache them if possible.
6970
6971 Handle<FixedArray> enum_keys = 7062 Handle<FixedArray> enum_keys =
6972 JSObject::GetEnumPropertyKeys(current, cache_enum_length); 7063 JSObject::GetEnumPropertyKeys(current, cache_enum_length);
6973 accumulator.AddKeys(enum_keys, filter); 7064 accumulator.AddKeys(enum_keys);
6974 } else { 7065 } else {
6975 DCHECK(filter == INCLUDE_SYMBOLS); 7066 DCHECK(filter == INCLUDE_SYMBOLS);
6976 PropertyAttributes attr_filter = 7067 PropertyAttributes attr_filter =
6977 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL); 7068 static_cast<PropertyAttributes>(DONT_ENUM | PRIVATE_SYMBOL);
6978 Handle<FixedArray> property_keys = isolate->factory()->NewFixedArray( 7069 JSObject::CollectOwnElementKeys(current, &accumulator, attr_filter);
6979 current->NumberOfOwnProperties(attr_filter));
6980 current->GetOwnPropertyNames(*property_keys, 0, attr_filter);
6981 accumulator.AddKeys(property_keys, filter);
6982 } 7070 }
6983 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6984 7071
6985 // Add the property keys from the interceptor. 7072 // Add the property keys from the interceptor.
6986 if (current->HasNamedInterceptor()) { 7073 if (current->HasNamedInterceptor()) {
6987 Handle<JSObject> result; 7074 Handle<JSObject> result;
6988 if (JSObject::GetKeysForNamedInterceptor( 7075 if (JSObject::GetKeysForNamedInterceptor(current, object)
6989 current, object).ToHandle(&result)) { 7076 .ToHandle(&result)) {
6990 accumulator.AddKeys(result, filter); 7077 accumulator.AddKeys(result);
6991 } 7078 }
6992 DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
6993 } 7079 }
6994 } 7080 }
6995 7081
6996 Handle<FixedArray> keys = accumulator.GetKeys(); 7082 Handle<FixedArray> keys = accumulator.GetKeys();
6997 DCHECK(ContainsOnlyValidKeys(keys)); 7083 DCHECK(ContainsOnlyValidKeys(keys));
6998 return keys; 7084 return keys;
6999 } 7085 }
7000 7086
7001 7087
7002 bool Map::DictionaryElementsInPrototypeChainOnly() { 7088 bool Map::DictionaryElementsInPrototypeChainOnly() {
(...skipping 6964 matching lines...) Expand 10 before | Expand all | Expand 10 after
13967 // Compute the number of enumerable elements. 14053 // Compute the number of enumerable elements.
13968 return GetOwnElementKeys(NULL, filter); 14054 return GetOwnElementKeys(NULL, filter);
13969 } 14055 }
13970 14056
13971 14057
13972 int JSObject::NumberOfEnumElements() { 14058 int JSObject::NumberOfEnumElements() {
13973 return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM)); 14059 return NumberOfOwnElements(static_cast<PropertyAttributes>(DONT_ENUM));
13974 } 14060 }
13975 14061
13976 14062
14063 namespace {
14064
14065 // TODO(cbruni): unify with the version in builtins.cc
14066 void CollectElementIndices(Handle<JSObject> object, uint32_t range,
14067 KeyAccumulator* keys, PropertyAttributes filter,
14068 uint32_t offset) {
14069 ElementsKind kind = object->GetElementsKind();
14070 switch (kind) {
14071 case FAST_SMI_ELEMENTS:
14072 case FAST_ELEMENTS:
14073 case FAST_HOLEY_SMI_ELEMENTS:
14074 case FAST_HOLEY_ELEMENTS: {
14075 Handle<FixedArray> elements(FixedArray::cast(object->elements()));
14076 uint32_t length = static_cast<uint32_t>(elements->length());
14077 if (range < length) length = range;
14078 for (uint32_t i = offset; i < length; i++) {
14079 if (!elements->get(i)->IsTheHole()) {
14080 keys->AddKey(i);
14081 }
14082 }
14083 break;
14084 }
14085 case FAST_HOLEY_DOUBLE_ELEMENTS:
14086 case FAST_DOUBLE_ELEMENTS: {
14087 if (object->elements()->IsFixedArray()) {
14088 DCHECK(object->elements()->length() == 0);
14089 return;
14090 }
14091 Handle<FixedDoubleArray> elements(
14092 FixedDoubleArray::cast(object->elements()));
14093 uint32_t length = static_cast<uint32_t>(elements->length());
14094 if (range < length) length = range;
14095 for (uint32_t i = offset; i < length; i++) {
14096 if (!elements->is_the_hole(i)) {
14097 keys->AddKey(i);
14098 }
14099 }
14100 break;
14101 }
14102 case DICTIONARY_ELEMENTS: {
14103 Handle<SeededNumberDictionary> dict(object->element_dictionary());
14104 SeededNumberDictionary::CopyElementKeysTo(dict, keys, filter, offset);
14105 keys->SortCurrentElementsList();
14106 break;
14107 }
14108 #define TYPED_ARRAY_CASE(Type, type, TYPE, ctype, size) case TYPE##_ELEMENTS:
14109
14110 TYPED_ARRAYS(TYPED_ARRAY_CASE)
14111 #undef TYPED_ARRAY_CASE
14112 {
14113 uint32_t length = static_cast<uint32_t>(
14114 FixedArrayBase::cast(object->elements())->length());
14115 for (uint32_t i = offset; i < length; i++) {
14116 keys->AddKey(i);
14117 }
14118 break;
14119 }
14120 case FAST_SLOPPY_ARGUMENTS_ELEMENTS:
14121 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: {
14122 ElementsAccessor* accessor = object->GetElementsAccessor();
14123 uint32_t length = accessor->GetCapacity(*object, object->elements());
Igor Sheludko 2015/10/15 09:51:43 I don't like exposing ElementsAccessor::GetCapacit
Camillo Bruni 2015/10/16 09:38:02 Indeed, I postponed it since I had so many other b
14124 range = Min(range, length);
14125 for (uint32_t i = offset; i < range; i++) {
14126 // Check for filter
14127 if (accessor->HasElement(object, i, filter)) {
14128 keys->AddKey(i);
14129 }
14130 }
14131 break;
14132 }
14133 }
14134 }
14135
14136 } // namespace
14137
14138 void JSObject::CollectOwnElementKeys(Handle<JSObject> object,
14139 KeyAccumulator* keys,
14140 PropertyAttributes filter) {
14141 uint32_t string_keys = 0;
14142
14143 // If this is a String wrapper, add the string indices first,
14144 // as they're guaranteed to precede the elements in numerical order
14145 // and ascending order is required by ECMA-262, 6th, 9.1.12.
14146 if (object->IsJSValue()) {
14147 Object* val = JSValue::cast(*object)->value();
14148 if (val->IsString()) {
14149 String* str = String::cast(val);
14150 string_keys = str->length();
14151 for (uint32_t i = 0; i < string_keys; i++) {
14152 keys->AddKey(i);
14153 }
14154 }
14155 }
14156 CollectElementIndices(object, kMaxUInt32, keys, filter, string_keys);
14157 }
14158
14159
13977 int JSObject::GetOwnElementKeys(FixedArray* storage, 14160 int JSObject::GetOwnElementKeys(FixedArray* storage,
13978 PropertyAttributes filter) { 14161 PropertyAttributes filter) {
13979 int counter = 0; 14162 int counter = 0;
13980 14163
13981 // If this is a String wrapper, add the string indices first, 14164 // If this is a String wrapper, add the string indices first,
13982 // as they're guaranteed to preced the elements in numerical order 14165 // as they're guaranteed to precede the elements in numerical order
13983 // and ascending order is required by ECMA-262, 6th, 9.1.12. 14166 // and ascending order is required by ECMA-262, 6th, 9.1.12.
13984 if (IsJSValue()) { 14167 if (IsJSValue()) {
13985 Object* val = JSValue::cast(this)->value(); 14168 Object* val = JSValue::cast(this)->value();
13986 if (val->IsString()) { 14169 if (val->IsString()) {
13987 String* str = String::cast(val); 14170 String* str = String::cast(val);
13988 if (storage) { 14171 if (storage) {
13989 for (int i = 0; i < str->length(); i++) { 14172 for (int i = 0; i < str->length(); i++) {
13990 storage->set(counter + i, Smi::FromInt(i)); 14173 storage->set(counter + i, Smi::FromInt(i));
13991 } 14174 }
13992 } 14175 }
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
14097 } 14280 }
14098 break; 14281 break;
14099 } 14282 }
14100 } 14283 }
14101 14284
14102 DCHECK(!storage || storage->length() == counter); 14285 DCHECK(!storage || storage->length() == counter);
14103 return counter; 14286 return counter;
14104 } 14287 }
14105 14288
14106 14289
14107 int JSObject::GetEnumElementKeys(FixedArray* storage) {
14108 return GetOwnElementKeys(storage, static_cast<PropertyAttributes>(DONT_ENUM));
14109 }
14110
14111
14112 const char* Symbol::PrivateSymbolToName() const { 14290 const char* Symbol::PrivateSymbolToName() const {
14113 Heap* heap = GetIsolate()->heap(); 14291 Heap* heap = GetIsolate()->heap();
14114 #define SYMBOL_CHECK_AND_PRINT(name) \ 14292 #define SYMBOL_CHECK_AND_PRINT(name) \
14115 if (this == heap->name()) return #name; 14293 if (this == heap->name()) return #name;
14116 PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT) 14294 PRIVATE_SYMBOL_LIST(SYMBOL_CHECK_AND_PRINT)
14117 #undef SYMBOL_CHECK_AND_PRINT 14295 #undef SYMBOL_CHECK_AND_PRINT
14118 return "UNKNOWN"; 14296 return "UNKNOWN";
14119 } 14297 }
14120 14298
14121 14299
(...skipping 1593 matching lines...) Expand 10 before | Expand all | Expand 10 after
15715 } 15893 }
15716 } 15894 }
15717 if (sort_mode == Dictionary::SORTED) { 15895 if (sort_mode == Dictionary::SORTED) {
15718 storage->SortPairs(storage, index); 15896 storage->SortPairs(storage, index);
15719 } 15897 }
15720 DCHECK(storage->length() >= index); 15898 DCHECK(storage->length() >= index);
15721 return index - start_index; 15899 return index - start_index;
15722 } 15900 }
15723 15901
15724 15902
15903 template <typename Derived, typename Shape, typename Key>
15904 void Dictionary<Derived, Shape, Key>::CopyElementKeysTo(
15905 Handle<Derived> dictionary, KeyAccumulator* keys, PropertyAttributes filter,
15906 uint32_t start) {
15907 int capacity = dictionary->Capacity();
15908 for (int i = 0; i < capacity; i++) {
15909 Object* k = dictionary->KeyAt(i);
15910 if (!dictionary->IsKey(k) || FilterKey(k, filter)) continue;
15911 if (dictionary->IsDeleted(i)) continue;
15912 DCHECK(k->IsNumber());
15913 PropertyDetails details = dictionary->DetailsAt(i);
15914 PropertyAttributes attr = details.attributes();
15915 if ((attr & filter) != 0) continue;
15916 uint32_t index = static_cast<uint32_t>(k->Number());
15917 if (start <= index) {
15918 keys->AddKey(index);
15919 }
15920 }
15921 }
15922
15923
15725 // Backwards lookup (slow). 15924 // Backwards lookup (slow).
15726 template<typename Derived, typename Shape, typename Key> 15925 template<typename Derived, typename Shape, typename Key>
15727 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { 15926 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) {
15728 int capacity = this->Capacity(); 15927 int capacity = this->Capacity();
15729 for (int i = 0; i < capacity; i++) { 15928 for (int i = 0; i < capacity; i++) {
15730 Object* k = this->KeyAt(i); 15929 Object* k = this->KeyAt(i);
15731 if (this->IsKey(k)) { 15930 if (this->IsKey(k)) {
15732 Object* e = this->ValueAt(i); 15931 Object* e = this->ValueAt(i);
15733 // TODO(dcarney): this should be templatized. 15932 // TODO(dcarney): this should be templatized.
15734 if (e->IsPropertyCell()) { 15933 if (e->IsPropertyCell()) {
(...skipping 1190 matching lines...) Expand 10 before | Expand all | Expand 10 after
16925 if (cell->value() != *new_value) { 17124 if (cell->value() != *new_value) {
16926 cell->set_value(*new_value); 17125 cell->set_value(*new_value);
16927 Isolate* isolate = cell->GetIsolate(); 17126 Isolate* isolate = cell->GetIsolate();
16928 cell->dependent_code()->DeoptimizeDependentCodeGroup( 17127 cell->dependent_code()->DeoptimizeDependentCodeGroup(
16929 isolate, DependentCode::kPropertyCellChangedGroup); 17128 isolate, DependentCode::kPropertyCellChangedGroup);
16930 } 17129 }
16931 } 17130 }
16932 17131
16933 } // namespace internal 17132 } // namespace internal
16934 } // namespace v8 17133 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698