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/elements.h" |
10 #include "src/isolate-inl.h" | 10 #include "src/isolate-inl.h" |
(...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
383 JSObject::ReoptimizeIfPrototype(receiver); | 383 JSObject::ReoptimizeIfPrototype(receiver); |
384 } | 384 } |
385 | 385 |
386 holder_map_ = handle(receiver->map(), isolate_); | 386 holder_map_ = handle(receiver->map(), isolate_); |
387 ReloadPropertyInformation(); | 387 ReloadPropertyInformation(); |
388 } | 388 } |
389 | 389 |
390 | 390 |
391 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { | 391 bool LookupIterator::HolderIsReceiverOrHiddenPrototype() const { |
392 DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); | 392 DCHECK(has_property_ || state_ == INTERCEPTOR || state_ == JSPROXY); |
393 return InternalHolderIsReceiverOrHiddenPrototype(); | |
394 } | |
395 | |
396 bool LookupIterator::InternalHolderIsReceiverOrHiddenPrototype() const { | |
397 // Optimization that only works if configuration_ is not mutable. | 393 // Optimization that only works if configuration_ is not mutable. |
398 if (!check_prototype_chain()) return true; | 394 if (!check_prototype_chain()) return true; |
399 DisallowHeapAllocation no_gc; | 395 DisallowHeapAllocation no_gc; |
400 if (!receiver_->IsJSReceiver()) return false; | 396 if (!receiver_->IsJSReceiver()) return false; |
401 JSReceiver* current = JSReceiver::cast(*receiver_); | 397 JSReceiver* current = JSReceiver::cast(*receiver_); |
402 JSReceiver* holder = *holder_; | 398 JSReceiver* object = *holder_; |
403 if (current == holder) return true; | 399 if (current == object) return true; |
404 if (!holder->map()->is_hidden_prototype()) return false; | 400 if (!object->map()->is_hidden_prototype()) return false; |
405 // JSProxy do not occur as hidden prototypes. | 401 // JSProxy do not occur as hidden prototypes. |
406 if (current->IsJSProxy()) return false; | 402 if (current->IsJSProxy()) return false; |
407 PrototypeIterator iter(isolate(), current); | 403 PrototypeIterator iter(isolate(), current); |
408 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | 404 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { |
409 if (iter.GetCurrent<JSReceiver>() == holder) return true; | 405 if (iter.GetCurrent<JSReceiver>() == object) return true; |
410 iter.Advance(); | 406 iter.Advance(); |
411 } | 407 } |
412 return false; | 408 return false; |
413 } | 409 } |
414 | 410 |
415 | 411 |
416 Handle<Object> LookupIterator::FetchValue() const { | 412 Handle<Object> LookupIterator::FetchValue() const { |
417 Object* result = NULL; | 413 Object* result = NULL; |
418 if (IsElement()) { | 414 if (IsElement()) { |
419 Handle<JSObject> holder = GetHolder<JSObject>(); | 415 Handle<JSObject> holder = GetHolder<JSObject>(); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
516 property_dictionary->ValueAtPut(dictionary_entry(), *value); | 512 property_dictionary->ValueAtPut(dictionary_entry(), *value); |
517 } else if (property_details_.type() == v8::internal::DATA) { | 513 } else if (property_details_.type() == v8::internal::DATA) { |
518 JSObject::cast(*holder)->WriteToField(descriptor_number(), *value); | 514 JSObject::cast(*holder)->WriteToField(descriptor_number(), *value); |
519 } else { | 515 } else { |
520 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); | 516 DCHECK_EQ(v8::internal::DATA_CONSTANT, property_details_.type()); |
521 } | 517 } |
522 } | 518 } |
523 | 519 |
524 | 520 |
525 bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) { | 521 bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) { |
526 DCHECK(exotic_index_state_ != ExoticIndexState::kNotExotic); | 522 DCHECK(!IsElement()); |
527 if (exotic_index_state_ == ExoticIndexState::kExotic) return true; | 523 if (!name_->IsString()) return false; |
528 if (!InternalHolderIsReceiverOrHiddenPrototype()) { | 524 if (*receiver_ != holder) return false; |
529 exotic_index_state_ = ExoticIndexState::kNotExotic; | 525 |
530 return false; | 526 Handle<String> name_string = Handle<String>::cast(name_); |
531 } | 527 if (name_string->length() == 0) return false; |
532 DCHECK(exotic_index_state_ == ExoticIndexState::kUninitialized); | 528 |
533 bool result = false; | 529 return IsSpecialIndex(isolate_->unicode_cache(), *name_string); |
534 // Compute and cache result. | |
535 if (IsElement()) { | |
536 result = index_ >= JSTypedArray::cast(holder)->length_value(); | |
537 } else if (name()->IsString()) { | |
538 Handle<String> name_string = Handle<String>::cast(name()); | |
539 if (name_string->length() != 0) { | |
540 result = IsSpecialIndex(isolate_->unicode_cache(), *name_string); | |
541 } | |
542 } | |
543 exotic_index_state_ = | |
544 result ? ExoticIndexState::kExotic : ExoticIndexState::kNotExotic; | |
545 return result; | |
546 } | 530 } |
547 | 531 |
548 | 532 |
549 void LookupIterator::InternalizeName() { | 533 void LookupIterator::InternalizeName() { |
550 if (name_->IsUniqueName()) return; | 534 if (name_->IsUniqueName()) return; |
551 name_ = factory()->InternalizeString(Handle<String>::cast(name_)); | 535 name_ = factory()->InternalizeString(Handle<String>::cast(name_)); |
552 } | 536 } |
553 | 537 |
554 | 538 |
555 bool LookupIterator::HasInterceptor(Map* map) const { | 539 bool LookupIterator::HasInterceptor(Map* map) const { |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
622 return INTERCEPTOR; | 606 return INTERCEPTOR; |
623 } | 607 } |
624 // Fall through. | 608 // Fall through. |
625 case INTERCEPTOR: | 609 case INTERCEPTOR: |
626 if (IsElement()) { | 610 if (IsElement()) { |
627 JSObject* js_object = JSObject::cast(holder); | 611 JSObject* js_object = JSObject::cast(holder); |
628 ElementsAccessor* accessor = js_object->GetElementsAccessor(); | 612 ElementsAccessor* accessor = js_object->GetElementsAccessor(); |
629 FixedArrayBase* backing_store = js_object->elements(); | 613 FixedArrayBase* backing_store = js_object->elements(); |
630 number_ = accessor->GetEntryForIndex(js_object, backing_store, index_); | 614 number_ = accessor->GetEntryForIndex(js_object, backing_store, index_); |
631 if (number_ == kMaxUInt32) { | 615 if (number_ == kMaxUInt32) { |
632 if (*receiver_ == Object::cast(holder) && holder->IsJSTypedArray()) { | 616 if (*receiver_ == holder && holder->IsJSTypedArray()) { |
633 return INTEGER_INDEXED_EXOTIC; | 617 return INTEGER_INDEXED_EXOTIC; |
634 } | 618 } |
635 return NOT_FOUND; | 619 return NOT_FOUND; |
636 } | 620 } |
637 property_details_ = accessor->GetDetails(js_object, number_); | 621 property_details_ = accessor->GetDetails(js_object, number_); |
638 } else if (exotic_index_state_ != ExoticIndexState::kNotExotic && | 622 } else if (holder->IsJSTypedArray() && IsIntegerIndexedExotic(holder)) { |
639 holder->IsJSTypedArray() && IsIntegerIndexedExotic(holder)) { | |
640 return INTEGER_INDEXED_EXOTIC; | 623 return INTEGER_INDEXED_EXOTIC; |
641 } else if (!map->is_dictionary_map()) { | 624 } else if (!map->is_dictionary_map()) { |
642 DescriptorArray* descriptors = map->instance_descriptors(); | 625 DescriptorArray* descriptors = map->instance_descriptors(); |
643 int number = descriptors->SearchWithCache(*name_, map); | 626 int number = descriptors->SearchWithCache(*name_, map); |
644 if (number == DescriptorArray::kNotFound) return NOT_FOUND; | 627 if (number == DescriptorArray::kNotFound) return NOT_FOUND; |
645 number_ = static_cast<uint32_t>(number); | 628 number_ = static_cast<uint32_t>(number); |
646 property_details_ = descriptors->GetDetails(number_); | 629 property_details_ = descriptors->GetDetails(number_); |
647 } else if (map->IsJSGlobalObjectMap()) { | 630 } else if (map->IsJSGlobalObjectMap()) { |
648 GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary(); | 631 GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary(); |
649 int number = dict->FindEntry(name_); | 632 int number = dict->FindEntry(name_); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
691 // Fall through. | 674 // Fall through. |
692 default: | 675 default: |
693 return NOT_FOUND; | 676 return NOT_FOUND; |
694 } | 677 } |
695 UNREACHABLE(); | 678 UNREACHABLE(); |
696 return state_; | 679 return state_; |
697 } | 680 } |
698 | 681 |
699 } // namespace internal | 682 } // namespace internal |
700 } // namespace v8 | 683 } // namespace v8 |
OLD | NEW |