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 8318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 |
OLD | NEW |