| 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 |