OLD | NEW |
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 <iomanip> | 5 #include <iomanip> |
6 #include <sstream> | 6 #include <sstream> |
7 | 7 |
8 #include "src/v8.h" | 8 #include "src/v8.h" |
9 | 9 |
10 #include "src/accessors.h" | 10 #include "src/accessors.h" |
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
460 if (debug->is_active()) debug->HandleStepIn(setter, false); | 460 if (debug->is_active()) debug->HandleStepIn(setter, false); |
461 | 461 |
462 Handle<Object> argv[] = { value }; | 462 Handle<Object> argv[] = { value }; |
463 RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver, | 463 RETURN_ON_EXCEPTION(isolate, Execution::Call(isolate, setter, receiver, |
464 arraysize(argv), argv, true), | 464 arraysize(argv), argv, true), |
465 Object); | 465 Object); |
466 return value; | 466 return value; |
467 } | 467 } |
468 | 468 |
469 | 469 |
470 static bool FindAllCanReadHolder(LookupIterator* it) { | 470 // static |
| 471 bool JSObject::AllCanRead(LookupIterator* it) { |
471 // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of | 472 // Skip current iteration, it's in state ACCESS_CHECK or INTERCEPTOR, both of |
472 // which have already been checked. | 473 // which have already been checked. |
473 DCHECK(it->state() == LookupIterator::ACCESS_CHECK || | 474 DCHECK(it->state() == LookupIterator::ACCESS_CHECK || |
474 it->state() == LookupIterator::INTERCEPTOR); | 475 it->state() == LookupIterator::INTERCEPTOR); |
475 for (it->Next(); it->IsFound(); it->Next()) { | 476 for (it->Next(); it->IsFound(); it->Next()) { |
476 if (it->state() == LookupIterator::ACCESSOR) { | 477 if (it->state() == LookupIterator::ACCESSOR) { |
477 auto accessors = it->GetAccessors(); | 478 auto accessors = it->GetAccessors(); |
478 if (accessors->IsAccessorInfo()) { | 479 if (accessors->IsAccessorInfo()) { |
479 if (AccessorInfo::cast(*accessors)->all_can_read()) return true; | 480 if (AccessorInfo::cast(*accessors)->all_can_read()) return true; |
480 } | 481 } |
481 } else if (it->state() == LookupIterator::INTERCEPTOR) { | 482 } else if (it->state() == LookupIterator::INTERCEPTOR) { |
482 if (it->GetInterceptor()->all_can_read()) return true; | 483 if (it->GetInterceptor()->all_can_read()) return true; |
483 } | 484 } |
484 } | 485 } |
485 return false; | 486 return false; |
486 } | 487 } |
487 | 488 |
488 | 489 |
489 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck( | 490 MaybeHandle<Object> JSObject::GetPropertyWithFailedAccessCheck( |
490 LookupIterator* it) { | 491 LookupIterator* it) { |
491 Handle<JSObject> checked = it->GetHolder<JSObject>(); | 492 Handle<JSObject> checked = it->GetHolder<JSObject>(); |
492 while (FindAllCanReadHolder(it)) { | 493 while (AllCanRead(it)) { |
493 if (it->state() == LookupIterator::ACCESSOR) { | 494 if (it->state() == LookupIterator::ACCESSOR) { |
494 return GetPropertyWithAccessor(it, SLOPPY); | 495 return GetPropertyWithAccessor(it, SLOPPY); |
495 } | 496 } |
496 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); | 497 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
497 bool done; | 498 bool done; |
498 Handle<Object> result; | 499 Handle<Object> result; |
499 ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), result, | 500 ASSIGN_RETURN_ON_EXCEPTION(it->isolate(), result, |
500 GetPropertyWithInterceptor(it, &done), Object); | 501 GetPropertyWithInterceptor(it, &done), Object); |
501 if (done) return result; | 502 if (done) return result; |
502 } | 503 } |
503 it->isolate()->ReportFailedAccessCheck(checked); | 504 it->isolate()->ReportFailedAccessCheck(checked); |
504 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 505 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); |
505 return it->factory()->undefined_value(); | 506 return it->factory()->undefined_value(); |
506 } | 507 } |
507 | 508 |
508 | 509 |
509 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck( | 510 Maybe<PropertyAttributes> JSObject::GetPropertyAttributesWithFailedAccessCheck( |
510 LookupIterator* it) { | 511 LookupIterator* it) { |
511 Handle<JSObject> checked = it->GetHolder<JSObject>(); | 512 Handle<JSObject> checked = it->GetHolder<JSObject>(); |
512 while (FindAllCanReadHolder(it)) { | 513 while (AllCanRead(it)) { |
513 if (it->state() == LookupIterator::ACCESSOR) { | 514 if (it->state() == LookupIterator::ACCESSOR) { |
514 return Just(it->property_details().attributes()); | 515 return Just(it->property_details().attributes()); |
515 } | 516 } |
516 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); | 517 DCHECK_EQ(LookupIterator::INTERCEPTOR, it->state()); |
517 auto result = GetPropertyAttributesWithInterceptor(it); | 518 auto result = GetPropertyAttributesWithInterceptor(it); |
518 if (it->isolate()->has_scheduled_exception()) break; | 519 if (it->isolate()->has_scheduled_exception()) break; |
519 if (result.IsJust() && result.FromJust() != ABSENT) return result; | 520 if (result.IsJust() && result.FromJust() != ABSENT) return result; |
520 } | 521 } |
521 it->isolate()->ReportFailedAccessCheck(checked); | 522 it->isolate()->ReportFailedAccessCheck(checked); |
522 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), | 523 RETURN_VALUE_IF_SCHEDULED_EXCEPTION(it->isolate(), |
523 Nothing<PropertyAttributes>()); | 524 Nothing<PropertyAttributes>()); |
524 return Just(ABSENT); | 525 return Just(ABSENT); |
525 } | 526 } |
526 | 527 |
527 | 528 |
528 static bool FindAllCanWriteHolder(LookupIterator* it) { | 529 // static |
| 530 bool JSObject::AllCanWrite(LookupIterator* it) { |
529 for (; it->IsFound(); it->Next()) { | 531 for (; it->IsFound(); it->Next()) { |
530 if (it->state() == LookupIterator::ACCESSOR) { | 532 if (it->state() == LookupIterator::ACCESSOR) { |
531 Handle<Object> accessors = it->GetAccessors(); | 533 Handle<Object> accessors = it->GetAccessors(); |
532 if (accessors->IsAccessorInfo()) { | 534 if (accessors->IsAccessorInfo()) { |
533 if (AccessorInfo::cast(*accessors)->all_can_write()) return true; | 535 if (AccessorInfo::cast(*accessors)->all_can_write()) return true; |
534 } | 536 } |
535 } | 537 } |
536 } | 538 } |
537 return false; | 539 return false; |
538 } | 540 } |
539 | 541 |
540 | 542 |
541 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( | 543 MaybeHandle<Object> JSObject::SetPropertyWithFailedAccessCheck( |
542 LookupIterator* it, Handle<Object> value) { | 544 LookupIterator* it, Handle<Object> value) { |
543 Handle<JSObject> checked = it->GetHolder<JSObject>(); | 545 Handle<JSObject> checked = it->GetHolder<JSObject>(); |
544 if (FindAllCanWriteHolder(it)) { | 546 if (AllCanWrite(it)) { |
545 // The supplied language-mode is ignored by SetPropertyWithAccessor. | 547 // The supplied language-mode is ignored by SetPropertyWithAccessor. |
546 return SetPropertyWithAccessor(it, value, SLOPPY); | 548 return SetPropertyWithAccessor(it, value, SLOPPY); |
547 } | 549 } |
548 | 550 |
549 it->isolate()->ReportFailedAccessCheck(checked); | 551 it->isolate()->ReportFailedAccessCheck(checked); |
550 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); | 552 RETURN_EXCEPTION_IF_SCHEDULED_EXCEPTION(it->isolate(), Object); |
551 return value; | 553 return value; |
552 } | 554 } |
553 | 555 |
554 | 556 |
(...skipping 12327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12882 } else { | 12884 } else { |
12883 HeapSortPairs(this, numbers, len); | 12885 HeapSortPairs(this, numbers, len); |
12884 return; | 12886 return; |
12885 } | 12887 } |
12886 } | 12888 } |
12887 | 12889 |
12888 | 12890 |
12889 // Fill in the names of own properties into the supplied storage. The main | 12891 // Fill in the names of own properties into the supplied storage. The main |
12890 // purpose of this function is to provide reflection information for the object | 12892 // purpose of this function is to provide reflection information for the object |
12891 // mirrors. | 12893 // mirrors. |
12892 void JSObject::GetOwnPropertyNames( | 12894 int JSObject::GetOwnPropertyNames(FixedArray* storage, int index, |
12893 FixedArray* storage, int index, PropertyAttributes filter) { | 12895 PropertyAttributes filter) { |
12894 DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index)); | 12896 DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index)); |
12895 if (HasFastProperties()) { | 12897 if (HasFastProperties()) { |
| 12898 int start_index = index; |
12896 int real_size = map()->NumberOfOwnDescriptors(); | 12899 int real_size = map()->NumberOfOwnDescriptors(); |
12897 DescriptorArray* descs = map()->instance_descriptors(); | 12900 DescriptorArray* descs = map()->instance_descriptors(); |
12898 for (int i = 0; i < real_size; i++) { | 12901 for (int i = 0; i < real_size; i++) { |
12899 if ((descs->GetDetails(i).attributes() & filter) == 0 && | 12902 if ((descs->GetDetails(i).attributes() & filter) == 0 && |
12900 !FilterKey(descs->GetKey(i), filter)) { | 12903 !FilterKey(descs->GetKey(i), filter)) { |
12901 storage->set(index++, descs->GetKey(i)); | 12904 storage->set(index++, descs->GetKey(i)); |
12902 } | 12905 } |
12903 } | 12906 } |
| 12907 return index - start_index; |
12904 } else if (IsGlobalObject()) { | 12908 } else if (IsGlobalObject()) { |
12905 global_dictionary()->CopyKeysTo(storage, index, filter, | 12909 return global_dictionary()->CopyKeysTo(storage, index, filter, |
12906 GlobalDictionary::UNSORTED); | 12910 GlobalDictionary::UNSORTED); |
12907 } else { | 12911 } else { |
12908 property_dictionary()->CopyKeysTo(storage, index, filter, | 12912 return property_dictionary()->CopyKeysTo(storage, index, filter, |
12909 NameDictionary::UNSORTED); | 12913 NameDictionary::UNSORTED); |
12910 } | 12914 } |
12911 } | 12915 } |
12912 | 12916 |
12913 | 12917 |
12914 int JSObject::NumberOfOwnElements(PropertyAttributes filter) { | 12918 int JSObject::NumberOfOwnElements(PropertyAttributes filter) { |
12915 return GetOwnElementKeys(NULL, filter); | 12919 return GetOwnElementKeys(NULL, filter); |
12916 } | 12920 } |
12917 | 12921 |
12918 | 12922 |
12919 int JSObject::NumberOfEnumElements() { | 12923 int JSObject::NumberOfEnumElements() { |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
12999 storage->set(counter, Smi::FromInt(counter)); | 13003 storage->set(counter, Smi::FromInt(counter)); |
13000 } | 13004 } |
13001 counter++; | 13005 counter++; |
13002 } | 13006 } |
13003 DCHECK(!storage || storage->length() >= counter); | 13007 DCHECK(!storage || storage->length() >= counter); |
13004 break; | 13008 break; |
13005 } | 13009 } |
13006 | 13010 |
13007 case DICTIONARY_ELEMENTS: { | 13011 case DICTIONARY_ELEMENTS: { |
13008 if (storage != NULL) { | 13012 if (storage != NULL) { |
13009 element_dictionary()->CopyKeysTo(storage, filter, | 13013 element_dictionary()->CopyKeysTo(storage, 0, filter, |
13010 SeededNumberDictionary::SORTED); | 13014 SeededNumberDictionary::SORTED); |
13011 } | 13015 } |
13012 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); | 13016 counter += element_dictionary()->NumberOfElementsFilterAttributes(filter); |
13013 break; | 13017 break; |
13014 } | 13018 } |
13015 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: | 13019 case FAST_SLOPPY_ARGUMENTS_ELEMENTS: |
13016 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { | 13020 case SLOW_SLOPPY_ARGUMENTS_ELEMENTS: { |
13017 FixedArray* parameter_map = FixedArray::cast(elements()); | 13021 FixedArray* parameter_map = FixedArray::cast(elements()); |
13018 int mapped_length = parameter_map->length() - 2; | 13022 int mapped_length = parameter_map->length() - 2; |
13019 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); | 13023 FixedArray* arguments = FixedArray::cast(parameter_map->get(1)); |
13020 if (arguments->IsDictionary()) { | 13024 if (arguments->IsDictionary()) { |
13021 // Copy the keys from arguments first, because Dictionary::CopyKeysTo | 13025 // Copy the keys from arguments first, because Dictionary::CopyKeysTo |
13022 // will insert in storage starting at index 0. | 13026 // will insert in storage starting at index 0. |
13023 SeededNumberDictionary* dictionary = | 13027 SeededNumberDictionary* dictionary = |
13024 SeededNumberDictionary::cast(arguments); | 13028 SeededNumberDictionary::cast(arguments); |
13025 if (storage != NULL) { | 13029 if (storage != NULL) { |
13026 dictionary->CopyKeysTo(storage, filter, | 13030 dictionary->CopyKeysTo(storage, 0, filter, |
13027 SeededNumberDictionary::UNSORTED); | 13031 SeededNumberDictionary::UNSORTED); |
13028 } | 13032 } |
13029 counter += dictionary->NumberOfElementsFilterAttributes(filter); | 13033 counter += dictionary->NumberOfElementsFilterAttributes(filter); |
13030 for (int i = 0; i < mapped_length; ++i) { | 13034 for (int i = 0; i < mapped_length; ++i) { |
13031 if (!parameter_map->get(i + 2)->IsTheHole()) { | 13035 if (!parameter_map->get(i + 2)->IsTheHole()) { |
13032 if (storage != NULL) storage->set(counter, Smi::FromInt(i)); | 13036 if (storage != NULL) storage->set(counter, Smi::FromInt(i)); |
13033 ++counter; | 13037 ++counter; |
13034 } | 13038 } |
13035 } | 13039 } |
13036 if (storage != NULL) storage->SortPairs(storage, counter); | 13040 if (storage != NULL) storage->SortPairs(storage, counter); |
(...skipping 1709 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
14746 PropertyDetails details = this->DetailsAt(i); | 14750 PropertyDetails details = this->DetailsAt(i); |
14747 if (details.type() == ACCESSOR_CONSTANT) return true; | 14751 if (details.type() == ACCESSOR_CONSTANT) return true; |
14748 PropertyAttributes attr = details.attributes(); | 14752 PropertyAttributes attr = details.attributes(); |
14749 if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true; | 14753 if (attr & (READ_ONLY | DONT_DELETE | DONT_ENUM)) return true; |
14750 } | 14754 } |
14751 } | 14755 } |
14752 return false; | 14756 return false; |
14753 } | 14757 } |
14754 | 14758 |
14755 | 14759 |
14756 template <typename Derived, typename Shape, typename Key> | |
14757 void Dictionary<Derived, Shape, Key>::CopyKeysTo( | |
14758 FixedArray* storage, PropertyAttributes filter, | |
14759 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { | |
14760 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); | |
14761 int capacity = this->Capacity(); | |
14762 int index = 0; | |
14763 for (int i = 0; i < capacity; i++) { | |
14764 Object* k = this->KeyAt(i); | |
14765 if (this->IsKey(k) && !FilterKey(k, filter)) { | |
14766 if (this->IsDeleted(i)) continue; | |
14767 PropertyDetails details = this->DetailsAt(i); | |
14768 PropertyAttributes attr = details.attributes(); | |
14769 if ((attr & filter) == 0) storage->set(index++, k); | |
14770 } | |
14771 } | |
14772 if (sort_mode == Dictionary::SORTED) { | |
14773 storage->SortPairs(storage, index); | |
14774 } | |
14775 DCHECK(storage->length() >= index); | |
14776 } | |
14777 | |
14778 | |
14779 template <typename Dictionary> | 14760 template <typename Dictionary> |
14780 struct EnumIndexComparator { | 14761 struct EnumIndexComparator { |
14781 explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {} | 14762 explicit EnumIndexComparator(Dictionary* dict) : dict(dict) {} |
14782 bool operator() (Smi* a, Smi* b) { | 14763 bool operator() (Smi* a, Smi* b) { |
14783 PropertyDetails da(dict->DetailsAt(a->value())); | 14764 PropertyDetails da(dict->DetailsAt(a->value())); |
14784 PropertyDetails db(dict->DetailsAt(b->value())); | 14765 PropertyDetails db(dict->DetailsAt(b->value())); |
14785 return da.dictionary_index() < db.dictionary_index(); | 14766 return da.dictionary_index() < db.dictionary_index(); |
14786 } | 14767 } |
14787 Dictionary* dict; | 14768 Dictionary* dict; |
14788 }; | 14769 }; |
(...skipping 19 matching lines...) Expand all Loading... |
14808 Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress()); | 14789 Smi** start = reinterpret_cast<Smi**>(storage->GetFirstElementAddress()); |
14809 std::sort(start, start + length, cmp); | 14790 std::sort(start, start + length, cmp); |
14810 for (int i = 0; i < length; i++) { | 14791 for (int i = 0; i < length; i++) { |
14811 int index = Smi::cast(storage->get(i))->value(); | 14792 int index = Smi::cast(storage->get(i))->value(); |
14812 storage->set(i, this->KeyAt(index)); | 14793 storage->set(i, this->KeyAt(index)); |
14813 } | 14794 } |
14814 } | 14795 } |
14815 | 14796 |
14816 | 14797 |
14817 template <typename Derived, typename Shape, typename Key> | 14798 template <typename Derived, typename Shape, typename Key> |
14818 void Dictionary<Derived, Shape, Key>::CopyKeysTo( | 14799 int Dictionary<Derived, Shape, Key>::CopyKeysTo( |
14819 FixedArray* storage, int index, PropertyAttributes filter, | 14800 FixedArray* storage, int index, PropertyAttributes filter, |
14820 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { | 14801 typename Dictionary<Derived, Shape, Key>::SortMode sort_mode) { |
14821 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); | 14802 DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); |
| 14803 int start_index = index; |
14822 int capacity = this->Capacity(); | 14804 int capacity = this->Capacity(); |
14823 for (int i = 0; i < capacity; i++) { | 14805 for (int i = 0; i < capacity; i++) { |
14824 Object* k = this->KeyAt(i); | 14806 Object* k = this->KeyAt(i); |
14825 if (this->IsKey(k) && !FilterKey(k, filter)) { | 14807 if (this->IsKey(k) && !FilterKey(k, filter)) { |
14826 if (this->IsDeleted(i)) continue; | 14808 if (this->IsDeleted(i)) continue; |
14827 PropertyDetails details = this->DetailsAt(i); | 14809 PropertyDetails details = this->DetailsAt(i); |
14828 PropertyAttributes attr = details.attributes(); | 14810 PropertyAttributes attr = details.attributes(); |
14829 if ((attr & filter) == 0) storage->set(index++, k); | 14811 if ((attr & filter) == 0) storage->set(index++, k); |
14830 } | 14812 } |
14831 } | 14813 } |
14832 if (sort_mode == Dictionary::SORTED) { | 14814 if (sort_mode == Dictionary::SORTED) { |
14833 storage->SortPairs(storage, index); | 14815 storage->SortPairs(storage, index); |
14834 } | 14816 } |
14835 DCHECK(storage->length() >= index); | 14817 DCHECK(storage->length() >= index); |
| 14818 return index - start_index; |
14836 } | 14819 } |
14837 | 14820 |
14838 | 14821 |
14839 // Backwards lookup (slow). | 14822 // Backwards lookup (slow). |
14840 template<typename Derived, typename Shape, typename Key> | 14823 template<typename Derived, typename Shape, typename Key> |
14841 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { | 14824 Object* Dictionary<Derived, Shape, Key>::SlowReverseLookup(Object* value) { |
14842 int capacity = this->Capacity(); | 14825 int capacity = this->Capacity(); |
14843 for (int i = 0; i < capacity; i++) { | 14826 for (int i = 0; i < capacity; i++) { |
14844 Object* k = this->KeyAt(i); | 14827 Object* k = this->KeyAt(i); |
14845 if (this->IsKey(k)) { | 14828 if (this->IsKey(k)) { |
(...skipping 1052 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
15898 Handle<Object> new_value) { | 15881 Handle<Object> new_value) { |
15899 if (cell->value() != *new_value) { | 15882 if (cell->value() != *new_value) { |
15900 cell->set_value(*new_value); | 15883 cell->set_value(*new_value); |
15901 Isolate* isolate = cell->GetIsolate(); | 15884 Isolate* isolate = cell->GetIsolate(); |
15902 cell->dependent_code()->DeoptimizeDependentCodeGroup( | 15885 cell->dependent_code()->DeoptimizeDependentCodeGroup( |
15903 isolate, DependentCode::kPropertyCellChangedGroup); | 15886 isolate, DependentCode::kPropertyCellChangedGroup); |
15904 } | 15887 } |
15905 } | 15888 } |
15906 } // namespace internal | 15889 } // namespace internal |
15907 } // namespace v8 | 15890 } // namespace v8 |
OLD | NEW |