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

Side by Side Diff: src/objects.cc

Issue 1707743002: [key-accumulator] Starting to reimplement the key-accumulator (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: WIP fast path for collecting receiver-only elements Created 4 years, 10 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 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 8318 matching lines...) Expand 10 before | Expand all | Expand 10 after
8329 if (result->IsPrimitive()) return result; 8329 if (result->IsPrimitive()) return result;
8330 } 8330 }
8331 } 8331 }
8332 THROW_NEW_ERROR(isolate, 8332 THROW_NEW_ERROR(isolate,
8333 NewTypeError(MessageTemplate::kCannotConvertToPrimitive), 8333 NewTypeError(MessageTemplate::kCannotConvertToPrimitive),
8334 Object); 8334 Object);
8335 } 8335 }
8336 8336
8337 8337
8338 // TODO(cbruni/jkummerow): Consider moving this into elements.cc. 8338 // TODO(cbruni/jkummerow): Consider moving this into elements.cc.
8339 bool HasEnumerableElements(JSObject* object) { 8339 bool JSObject::HasEnumerableElements() {
8340 // TODO(cbruni): cleanup
8341 JSObject* object = this;
8340 switch (object->GetElementsKind()) { 8342 switch (object->GetElementsKind()) {
8341 case FAST_SMI_ELEMENTS: 8343 case FAST_SMI_ELEMENTS:
8342 case FAST_ELEMENTS: 8344 case FAST_ELEMENTS:
8343 case FAST_DOUBLE_ELEMENTS: { 8345 case FAST_DOUBLE_ELEMENTS: {
8344 int length = object->IsJSArray() 8346 int length = object->IsJSArray()
8345 ? Smi::cast(JSArray::cast(object)->length())->value() 8347 ? Smi::cast(JSArray::cast(object)->length())->value()
8346 : object->elements()->length(); 8348 : object->elements()->length();
8347 return length > 0; 8349 return length > 0;
8348 } 8350 }
8349 case FAST_HOLEY_SMI_ELEMENTS: 8351 case FAST_HOLEY_SMI_ELEMENTS:
8350 case FAST_HOLEY_ELEMENTS: { 8352 case FAST_HOLEY_ELEMENTS: {
8351 FixedArray* elements = FixedArray::cast(object->elements()); 8353 FixedArray* elements = FixedArray::cast(object->elements());
8352 int length = object->IsJSArray() 8354 int length = object->IsJSArray()
8353 ? Smi::cast(JSArray::cast(object)->length())->value() 8355 ? Smi::cast(JSArray::cast(object)->length())->value()
8354 : elements->length(); 8356 : elements->length();
8355 for (int i = 0; i < length; i++) { 8357 for (int i = 0; i < length; i++) {
8356 if (!elements->is_the_hole(i)) return true; 8358 if (!elements->is_the_hole(i)) return true;
Toon Verwaest 2016/02/24 15:07:06 is it really worthwhile to find the first non-hole
8357 } 8359 }
8358 return false; 8360 return false;
8359 } 8361 }
8360 case FAST_HOLEY_DOUBLE_ELEMENTS: { 8362 case FAST_HOLEY_DOUBLE_ELEMENTS: {
8361 int length = object->IsJSArray() 8363 int length = object->IsJSArray()
8362 ? Smi::cast(JSArray::cast(object)->length())->value() 8364 ? Smi::cast(JSArray::cast(object)->length())->value()
8363 : object->elements()->length(); 8365 : object->elements()->length();
8364 // Zero-length arrays would use the empty FixedArray... 8366 // Zero-length arrays would use the empty FixedArray...
8365 if (length == 0) return false; 8367 if (length == 0) return false;
8366 // ...so only cast to FixedDoubleArray otherwise. 8368 // ...so only cast to FixedDoubleArray otherwise.
(...skipping 27 matching lines...) Expand all
8394 return true; 8396 return true;
8395 } 8397 }
8396 return object->elements()->length() > 0; 8398 return object->elements()->length() > 0;
8397 case NO_ELEMENTS: 8399 case NO_ELEMENTS:
8398 return false; 8400 return false;
8399 } 8401 }
8400 UNREACHABLE(); 8402 UNREACHABLE();
8401 return true; 8403 return true;
8402 } 8404 }
8403 8405
8404
8405 // Tests for the fast common case for property enumeration: 8406 // Tests for the fast common case for property enumeration:
8406 // - This object and all prototypes has an enum cache (which means that 8407 // - This object and all prototypes has an enum cache (which means that
8407 // it is no proxy, has no interceptors and needs no access checks). 8408 // it is no proxy, has no interceptors and needs no access checks).
8408 // - This object has no elements. 8409 // - This object has no elements.
8409 // - No prototype has enumerable properties/elements. 8410 // - No prototype has enumerable properties/elements.
8410 bool JSReceiver::IsSimpleEnum() { 8411 bool JSReceiver::IsSimpleEnum() {
8411 for (PrototypeIterator iter(GetIsolate(), this, 8412 for (PrototypeIterator iter(GetIsolate(), this,
8412 PrototypeIterator::START_AT_RECEIVER); 8413 PrototypeIterator::START_AT_RECEIVER);
8413 !iter.IsAtEnd(); iter.Advance()) { 8414 !iter.IsAtEnd(); iter.Advance()) {
8414 if (!iter.GetCurrent()->IsJSObject()) return false; 8415 if (!iter.GetCurrent()->IsJSObject()) return false;
8415 JSObject* current = iter.GetCurrent<JSObject>(); 8416 JSObject* current = iter.GetCurrent<JSObject>();
8416 int enum_length = current->map()->EnumLength(); 8417 int enum_length = current->map()->EnumLength();
8417 if (enum_length == kInvalidEnumCacheSentinel) return false; 8418 if (enum_length == kInvalidEnumCacheSentinel) return false;
8418 if (current->IsAccessCheckNeeded()) return false; 8419 if (current->IsAccessCheckNeeded()) return false;
8419 DCHECK(!current->HasNamedInterceptor()); 8420 DCHECK(!current->HasNamedInterceptor());
8420 DCHECK(!current->HasIndexedInterceptor()); 8421 DCHECK(!current->HasIndexedInterceptor());
8421 if (HasEnumerableElements(current)) return false; 8422 if (current->HasEnumerableElements()) return false;
8422 if (current != this && enum_length != 0) return false; 8423 if (current != this && enum_length != 0) return false;
8423 } 8424 }
8424 return true; 8425 return true;
8425 } 8426 }
8426 8427
8427 8428
8428 int Map::NumberOfDescribedProperties(DescriptorFlag which, 8429 int Map::NumberOfDescribedProperties(DescriptorFlag which,
8429 PropertyFilter filter) { 8430 PropertyFilter filter) {
8430 int result = 0; 8431 int result = 0;
8431 DescriptorArray* descs = instance_descriptors(); 8432 DescriptorArray* descs = instance_descriptors();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
8476 8477
8477 bool Map::OnlyHasSimpleProperties() { 8478 bool Map::OnlyHasSimpleProperties() {
8478 // Wrapped string elements aren't explicitly stored in the elements backing 8479 // Wrapped string elements aren't explicitly stored in the elements backing
8479 // store, but are loaded indirectly from the underlying string. 8480 // store, but are loaded indirectly from the underlying string.
8480 return !IsStringWrapperElementsKind(elements_kind()) && 8481 return !IsStringWrapperElementsKind(elements_kind()) &&
8481 !is_access_check_needed() && !has_named_interceptor() && 8482 !is_access_check_needed() && !has_named_interceptor() &&
8482 !has_indexed_interceptor() && !has_hidden_prototype() && 8483 !has_indexed_interceptor() && !has_hidden_prototype() &&
8483 !is_dictionary_map(); 8484 !is_dictionary_map();
8484 } 8485 }
8485 8486
8486 namespace { 8487 // stati
Toon Verwaest 2016/02/24 15:07:06 static
8487 8488 Handle<FixedArray> JSObject::GetFastEnumPropertyKeys(Isolate* isolate,
8488 Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate, 8489 Handle<JSObject> object) {
8489 Handle<JSObject> object) {
8490 Handle<Map> map(object->map()); 8490 Handle<Map> map(object->map());
8491 bool cache_enum_length = map->OnlyHasSimpleProperties(); 8491 bool cache_enum_length = map->OnlyHasSimpleProperties();
8492 8492
8493 Handle<DescriptorArray> descs = 8493 Handle<DescriptorArray> descs =
8494 Handle<DescriptorArray>(map->instance_descriptors(), isolate); 8494 Handle<DescriptorArray>(map->instance_descriptors(), isolate);
8495 int own_property_count = map->EnumLength(); 8495 int own_property_count = map->EnumLength();
8496 // If the enum length of the given map is set to kInvalidEnumCache, this 8496 // If the enum length of the given map is set to kInvalidEnumCache, this
8497 // means that the map itself has never used the present enum cache. The 8497 // means that the map itself has never used the present enum cache. The
8498 // first step to using the cache is to set the enum length of the map by 8498 // first step to using the cache is to set the enum length of the map by
8499 // counting the number of own descriptors that are ENUMERABLE_STRINGS. 8499 // counting the number of own descriptors that are ENUMERABLE_STRINGS.
(...skipping 30 matching lines...) Expand all
8530 Handle<FixedArray> storage = 8530 Handle<FixedArray> storage =
8531 isolate->factory()->NewFixedArray(own_property_count); 8531 isolate->factory()->NewFixedArray(own_property_count);
8532 Handle<FixedArray> indices = 8532 Handle<FixedArray> indices =
8533 isolate->factory()->NewFixedArray(own_property_count); 8533 isolate->factory()->NewFixedArray(own_property_count);
8534 8534
8535 int size = map->NumberOfOwnDescriptors(); 8535 int size = map->NumberOfOwnDescriptors();
8536 int index = 0; 8536 int index = 0;
8537 8537
8538 for (int i = 0; i < size; i++) { 8538 for (int i = 0; i < size; i++) {
8539 PropertyDetails details = descs->GetDetails(i); 8539 PropertyDetails details = descs->GetDetails(i);
8540 if (details.IsDontEnum()) continue;
8540 Object* key = descs->GetKey(i); 8541 Object* key = descs->GetKey(i);
8541 if (details.IsDontEnum() || key->IsSymbol()) continue; 8542 if (key->IsSymbol()) continue;
8542 storage->set(index, key); 8543 storage->set(index, key);
8543 if (!indices.is_null()) { 8544 if (!indices.is_null()) {
8544 if (details.type() != DATA) { 8545 if (details.type() != DATA) {
8545 indices = Handle<FixedArray>(); 8546 indices = Handle<FixedArray>();
8546 } else { 8547 } else {
8547 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); 8548 FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
8548 int load_by_field_index = field_index.GetLoadByFieldIndex(); 8549 int load_by_field_index = field_index.GetLoadByFieldIndex();
8549 indices->set(index, Smi::FromInt(load_by_field_index)); 8550 indices->set(index, Smi::FromInt(load_by_field_index));
8550 } 8551 }
8551 } 8552 }
8552 index++; 8553 index++;
8553 } 8554 }
8554 DCHECK(index == storage->length()); 8555 DCHECK(index == storage->length());
8555 8556
8556 DescriptorArray::SetEnumCache(descs, isolate, storage, indices); 8557 DescriptorArray::SetEnumCache(descs, isolate, storage, indices);
8557 if (cache_enum_length) { 8558 if (cache_enum_length) {
8558 map->SetEnumLength(own_property_count); 8559 map->SetEnumLength(own_property_count);
8559 } 8560 }
8560 return storage; 8561 return storage;
8561 } 8562 }
8562 8563
8563 } // namespace
8564 8564
8565 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object) { 8565 Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object) {
8566 Isolate* isolate = object->GetIsolate(); 8566 Isolate* isolate = object->GetIsolate();
8567 if (object->HasFastProperties()) { 8567 if (object->HasFastProperties()) {
8568 return GetFastEnumPropertyKeys(isolate, object); 8568 return GetFastEnumPropertyKeys(isolate, object);
8569 } else if (object->IsJSGlobalObject()) { 8569 } else if (object->IsJSGlobalObject()) {
8570 Handle<GlobalDictionary> dictionary(object->global_dictionary()); 8570 Handle<GlobalDictionary> dictionary(object->global_dictionary());
8571 int length = dictionary->NumberOfEnumElements(); 8571 int length = dictionary->NumberOfEnumElements();
8572 if (length == 0) { 8572 if (length == 0) {
8573 return Handle<FixedArray>(isolate->heap()->empty_fixed_array()); 8573 return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
(...skipping 2259 matching lines...) Expand 10 before | Expand all | Expand 10 after
10833 array = EnsureSpace(array, length + 1); 10833 array = EnsureSpace(array, length + 1);
10834 if (mode == kReloadLengthAfterAllocation) { 10834 if (mode == kReloadLengthAfterAllocation) {
10835 DCHECK(array->Length() <= length); 10835 DCHECK(array->Length() <= length);
10836 length = array->Length(); 10836 length = array->Length();
10837 } 10837 }
10838 array->Set(length, *obj); 10838 array->Set(length, *obj);
10839 array->SetLength(length + 1); 10839 array->SetLength(length + 1);
10840 return array; 10840 return array;
10841 } 10841 }
10842 10842
10843 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Smi* smi,
10844 AddMode mode) {
10845 int length = array->Length();
10846 array = EnsureSpace(array, length + 1);
10847 if (mode == kReloadLengthAfterAllocation) {
10848 DCHECK(array->Length() <= length);
10849 length = array->Length();
10850 }
10851 array->Set(length, smi);
10852 array->SetLength(length + 1);
10853 return array;
10854 }
10843 10855
10844 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1, 10856 Handle<ArrayList> ArrayList::Add(Handle<ArrayList> array, Handle<Object> obj1,
10845 Handle<Object> obj2, AddMode mode) { 10857 Handle<Object> obj2, AddMode mode) {
10846 int length = array->Length(); 10858 int length = array->Length();
10847 array = EnsureSpace(array, length + 2); 10859 array = EnsureSpace(array, length + 2);
10848 if (mode == kReloadLengthAfterAllocation) { 10860 if (mode == kReloadLengthAfterAllocation) {
10849 length = array->Length(); 10861 length = array->Length();
10850 } 10862 }
10851 array->Set(length, *obj1); 10863 array->Set(length, *obj1);
10852 array->Set(length + 1, *obj2); 10864 array->Set(length + 1, *obj2);
(...skipping 5739 matching lines...) Expand 10 before | Expand all | Expand 10 after
16592 j++ < len) { 16604 j++ < len) {
16593 SwapPairs(numbers, i, p); 16605 SwapPairs(numbers, i, p);
16594 } 16606 }
16595 } 16607 }
16596 } else { 16608 } else {
16597 HeapSortPairs(this, numbers, len); 16609 HeapSortPairs(this, numbers, len);
16598 return; 16610 return;
16599 } 16611 }
16600 } 16612 }
16601 16613
16602
16603 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys, 16614 void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys,
16604 PropertyFilter filter) { 16615 PropertyFilter filter) {
16605 if (HasFastProperties()) { 16616 if (HasFastProperties()) {
16606 int real_size = map()->NumberOfOwnDescriptors(); 16617 int real_size = map()->NumberOfOwnDescriptors();
16607 Handle<DescriptorArray> descs(map()->instance_descriptors()); 16618 Handle<DescriptorArray> descs(map()->instance_descriptors());
16608 for (int i = 0; i < real_size; i++) { 16619 for (int i = 0; i < real_size; i++) {
16609 PropertyDetails details = descs->GetDetails(i); 16620 PropertyDetails details = descs->GetDetails(i);
16610 if ((details.attributes() & filter) != 0) continue; 16621 if ((details.attributes() & filter) != 0) continue;
16611 if (filter & ONLY_ALL_CAN_READ) { 16622 if (filter & ONLY_ALL_CAN_READ) {
16612 if (details.kind() != kAccessor) continue; 16623 if (details.kind() != kAccessor) continue;
(...skipping 20 matching lines...) Expand all
16633 IsJSArray() 16644 IsJSArray()
16634 ? static_cast<uint32_t>( 16645 ? static_cast<uint32_t>(
16635 Smi::cast(JSArray::cast(this)->length())->value()) 16646 Smi::cast(JSArray::cast(this)->length())->value())
16636 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length()); 16647 : static_cast<uint32_t>(FixedArrayBase::cast(elements())->length());
16637 if (length == 0) return 0; 16648 if (length == 0) return 0;
16638 } 16649 }
16639 // Compute the number of enumerable elements. 16650 // Compute the number of enumerable elements.
16640 return GetOwnElementKeys(NULL, filter); 16651 return GetOwnElementKeys(NULL, filter);
16641 } 16652 }
16642 16653
16643
16644 void JSObject::CollectOwnElementKeys(Handle<JSObject> object, 16654 void JSObject::CollectOwnElementKeys(Handle<JSObject> object,
16645 KeyAccumulator* keys, 16655 KeyAccumulator* keys,
16646 PropertyFilter filter) { 16656 PropertyFilter filter) {
16647 if (filter & SKIP_STRINGS) return; 16657 if (filter & SKIP_STRINGS) return;
16648 ElementsAccessor* accessor = object->GetElementsAccessor(); 16658 ElementsAccessor* accessor = object->GetElementsAccessor();
16649 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0); 16659 accessor->CollectElementIndices(object, keys, kMaxUInt32, filter, 0);
16650 } 16660 }
16651 16661
16652 16662
16653 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) { 16663 int JSObject::GetOwnElementKeys(FixedArray* storage, PropertyFilter filter) {
(...skipping 1979 matching lines...) Expand 10 before | Expand all | Expand 10 after
18633 if ((attr & filter) != 0) continue; 18643 if ((attr & filter) != 0) continue;
18634 storage->set(index++, k); 18644 storage->set(index++, k);
18635 } 18645 }
18636 if (sort_mode == Dictionary::SORTED) { 18646 if (sort_mode == Dictionary::SORTED) {
18637 storage->SortPairs(storage, index); 18647 storage->SortPairs(storage, index);
18638 } 18648 }
18639 DCHECK(storage->length() >= index); 18649 DCHECK(storage->length() >= index);
18640 return index - start_index; 18650 return index - start_index;
18641 } 18651 }
18642 18652
18643
18644 template <typename Derived, typename Shape, typename Key> 18653 template <typename Derived, typename Shape, typename Key>
18645 void Dictionary<Derived, Shape, Key>::CollectKeysTo( 18654 void Dictionary<Derived, Shape, Key>::CollectKeysTo(
18646 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys, 18655 Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys,
18647 PropertyFilter filter) { 18656 PropertyFilter filter) {
18648 int capacity = dictionary->Capacity(); 18657 int capacity = dictionary->Capacity();
18649 Handle<FixedArray> array = 18658 Handle<FixedArray> array =
18650 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements()); 18659 keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements());
18651 int array_size = 0; 18660 int array_size = 0;
18652 18661
18653 { 18662 {
(...skipping 1266 matching lines...) Expand 10 before | Expand all | Expand 10 after
19920 if (cell->value() != *new_value) { 19929 if (cell->value() != *new_value) {
19921 cell->set_value(*new_value); 19930 cell->set_value(*new_value);
19922 Isolate* isolate = cell->GetIsolate(); 19931 Isolate* isolate = cell->GetIsolate();
19923 cell->dependent_code()->DeoptimizeDependentCodeGroup( 19932 cell->dependent_code()->DeoptimizeDependentCodeGroup(
19924 isolate, DependentCode::kPropertyCellChangedGroup); 19933 isolate, DependentCode::kPropertyCellChangedGroup);
19925 } 19934 }
19926 } 19935 }
19927 19936
19928 } // namespace internal 19937 } // namespace internal
19929 } // namespace v8 19938 } // namespace v8
OLDNEW
« src/key-accumulator.cc ('K') | « src/objects.h ('k') | src/objects-printer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698