OLD | NEW |
1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/lookup.h" | 5 #include "src/lookup.h" |
6 | 6 |
7 #include "src/bootstrapper.h" | 7 #include "src/bootstrapper.h" |
8 #include "src/deoptimizer.h" | 8 #include "src/deoptimizer.h" |
| 9 #include "src/elements.h" |
9 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
10 #include "src/lookup-inl.h" | |
11 | 11 |
12 namespace v8 { | 12 namespace v8 { |
13 namespace internal { | 13 namespace internal { |
14 | 14 |
15 | 15 |
16 // static | 16 // static |
17 LookupIterator LookupIterator::PropertyOrElement(Isolate* isolate, | 17 LookupIterator LookupIterator::PropertyOrElement(Isolate* isolate, |
18 Handle<Object> receiver, | 18 Handle<Object> receiver, |
19 Handle<Object> key, | 19 Handle<Object> key, |
20 bool* success, | 20 bool* success, |
(...skipping 565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 interceptor_state_ = InterceptorState::kSkipNonMasking; | 586 interceptor_state_ = InterceptorState::kSkipNonMasking; |
587 // Fall through. | 587 // Fall through. |
588 case InterceptorState::kSkipNonMasking: | 588 case InterceptorState::kSkipNonMasking: |
589 return true; | 589 return true; |
590 case InterceptorState::kProcessNonMasking: | 590 case InterceptorState::kProcessNonMasking: |
591 return false; | 591 return false; |
592 } | 592 } |
593 } | 593 } |
594 return interceptor_state_ == InterceptorState::kProcessNonMasking; | 594 return interceptor_state_ == InterceptorState::kProcessNonMasking; |
595 } | 595 } |
| 596 |
| 597 |
| 598 JSReceiver* LookupIterator::NextHolder(Map* map) { |
| 599 DisallowHeapAllocation no_gc; |
| 600 if (!map->prototype()->IsJSReceiver()) return NULL; |
| 601 |
| 602 JSReceiver* next = JSReceiver::cast(map->prototype()); |
| 603 DCHECK(!next->map()->IsGlobalObjectMap() || |
| 604 next->map()->is_hidden_prototype()); |
| 605 |
| 606 if (!check_prototype_chain() && |
| 607 !(check_hidden() && next->map()->is_hidden_prototype()) && |
| 608 // Always lookup behind the JSGlobalProxy into the JSGlobalObject, even |
| 609 // when not checking other hidden prototypes. |
| 610 !map->IsJSGlobalProxyMap()) { |
| 611 return NULL; |
| 612 } |
| 613 |
| 614 return next; |
| 615 } |
| 616 |
| 617 |
| 618 LookupIterator::State LookupIterator::LookupInHolder(Map* const map, |
| 619 JSReceiver* const holder) { |
| 620 STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY); |
| 621 DisallowHeapAllocation no_gc; |
| 622 if (interceptor_state_ == InterceptorState::kProcessNonMasking) { |
| 623 return LookupNonMaskingInterceptorInHolder(map, holder); |
| 624 } |
| 625 switch (state_) { |
| 626 case NOT_FOUND: |
| 627 if (map->IsJSProxyMap()) return JSPROXY; |
| 628 if (map->is_access_check_needed() && |
| 629 (IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) { |
| 630 return ACCESS_CHECK; |
| 631 } |
| 632 // Fall through. |
| 633 case ACCESS_CHECK: |
| 634 if (exotic_index_state_ != ExoticIndexState::kNotExotic && |
| 635 IsIntegerIndexedExotic(holder)) { |
| 636 return INTEGER_INDEXED_EXOTIC; |
| 637 } |
| 638 if (check_interceptor() && HasInterceptor(map) && |
| 639 !SkipInterceptor(JSObject::cast(holder))) { |
| 640 return INTERCEPTOR; |
| 641 } |
| 642 // Fall through. |
| 643 case INTERCEPTOR: |
| 644 if (IsElement()) { |
| 645 // TODO(verwaest): Optimize. |
| 646 if (holder->IsStringObjectWithCharacterAt(index_)) { |
| 647 PropertyAttributes attributes = |
| 648 static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); |
| 649 property_details_ = PropertyDetails(attributes, v8::internal::DATA, 0, |
| 650 PropertyCellType::kNoCell); |
| 651 } else { |
| 652 JSObject* js_object = JSObject::cast(holder); |
| 653 if (js_object->elements() == isolate()->heap()->empty_fixed_array()) { |
| 654 return NOT_FOUND; |
| 655 } |
| 656 |
| 657 ElementsAccessor* accessor = js_object->GetElementsAccessor(); |
| 658 FixedArrayBase* backing_store = js_object->elements(); |
| 659 number_ = |
| 660 accessor->GetEntryForIndex(js_object, backing_store, index_); |
| 661 if (number_ == kMaxUInt32) return NOT_FOUND; |
| 662 property_details_ = accessor->GetDetails(backing_store, number_); |
| 663 } |
| 664 } else if (!map->is_dictionary_map()) { |
| 665 DescriptorArray* descriptors = map->instance_descriptors(); |
| 666 int number = descriptors->SearchWithCache(*name_, map); |
| 667 if (number == DescriptorArray::kNotFound) return NOT_FOUND; |
| 668 number_ = static_cast<uint32_t>(number); |
| 669 property_details_ = descriptors->GetDetails(number_); |
| 670 } else if (map->IsGlobalObjectMap()) { |
| 671 GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary(); |
| 672 int number = dict->FindEntry(name_); |
| 673 if (number == GlobalDictionary::kNotFound) return NOT_FOUND; |
| 674 number_ = static_cast<uint32_t>(number); |
| 675 DCHECK(dict->ValueAt(number_)->IsPropertyCell()); |
| 676 PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_)); |
| 677 if (cell->value()->IsTheHole()) return NOT_FOUND; |
| 678 property_details_ = cell->property_details(); |
| 679 } else { |
| 680 NameDictionary* dict = JSObject::cast(holder)->property_dictionary(); |
| 681 int number = dict->FindEntry(name_); |
| 682 if (number == NameDictionary::kNotFound) return NOT_FOUND; |
| 683 number_ = static_cast<uint32_t>(number); |
| 684 property_details_ = dict->DetailsAt(number_); |
| 685 } |
| 686 has_property_ = true; |
| 687 switch (property_details_.kind()) { |
| 688 case v8::internal::kData: |
| 689 return DATA; |
| 690 case v8::internal::kAccessor: |
| 691 return ACCESSOR; |
| 692 } |
| 693 case ACCESSOR: |
| 694 case DATA: |
| 695 return NOT_FOUND; |
| 696 case INTEGER_INDEXED_EXOTIC: |
| 697 case JSPROXY: |
| 698 case TRANSITION: |
| 699 UNREACHABLE(); |
| 700 } |
| 701 UNREACHABLE(); |
| 702 return state_; |
| 703 } |
| 704 |
| 705 |
| 706 LookupIterator::State LookupIterator::LookupNonMaskingInterceptorInHolder( |
| 707 Map* const map, JSReceiver* const holder) { |
| 708 switch (state_) { |
| 709 case NOT_FOUND: |
| 710 if (check_interceptor() && HasInterceptor(map) && |
| 711 !SkipInterceptor(JSObject::cast(holder))) { |
| 712 return INTERCEPTOR; |
| 713 } |
| 714 // Fall through. |
| 715 default: |
| 716 return NOT_FOUND; |
| 717 } |
| 718 UNREACHABLE(); |
| 719 return state_; |
| 720 } |
| 721 |
596 } // namespace internal | 722 } // namespace internal |
597 } // namespace v8 | 723 } // namespace v8 |
OLD | NEW |