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