Chromium Code Reviews| 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 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 InternalHolderIsReceiverOrHiddenPrototype(); |
| 394 } | 394 } |
| 395 | 395 |
| 396 bool LookupIterator::InternalHolderIsReceiverOrHiddenPrototype() const { | 396 bool LookupIterator::InternalHolderIsReceiverOrHiddenPrototype() 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 Object* current = *receiver_; | 401 JSReceiver* current = JSReceiver::cast(*receiver_); |
| 402 JSReceiver* holder = *holder_; | 402 JSReceiver* holder = *holder_; |
| 403 if (current == holder) return true; | |
|
Jakob Kummerow
2016/01/26 14:21:24
Unrelated to the rest of this CL: avoid instantiat
| |
| 403 // JSProxy do not occur as hidden prototypes. | 404 // JSProxy do not occur as hidden prototypes. |
|
Toon Verwaest
2016/01/27 15:02:22
What about adding if (!holder->map()->is_hidden_pr
Jakob Kummerow
2016/01/29 14:31:26
Done.
| |
| 404 if (current->IsJSProxy()) { | 405 if (current->IsJSProxy()) return false; |
| 405 return JSReceiver::cast(current) == holder; | 406 PrototypeIterator iter(isolate(), current); |
| 407 while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)) { | |
| 408 if (iter.GetCurrent<JSReceiver>() == holder) return true; | |
| 409 iter.Advance(); | |
| 406 } | 410 } |
| 407 PrototypeIterator iter(isolate(), current, | |
| 408 PrototypeIterator::START_AT_RECEIVER); | |
| 409 do { | |
| 410 if (iter.GetCurrent<JSReceiver>() == holder) return true; | |
| 411 DCHECK(!current->IsJSProxy()); | |
| 412 iter.Advance(); | |
| 413 } while (!iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN)); | |
| 414 return false; | 411 return false; |
| 415 } | 412 } |
| 416 | 413 |
| 417 | 414 |
| 418 Handle<Object> LookupIterator::FetchValue() const { | 415 Handle<Object> LookupIterator::FetchValue() const { |
| 419 Object* result = NULL; | 416 Object* result = NULL; |
| 420 if (IsElement()) { | 417 if (IsElement()) { |
| 421 Handle<JSObject> holder = GetHolder<JSObject>(); | 418 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 422 // TODO(verwaest): Optimize. | |
| 423 if (holder->IsStringObjectWithCharacterAt(index_)) { | |
| 424 Handle<JSValue> js_value = Handle<JSValue>::cast(holder); | |
| 425 Handle<String> string(String::cast(js_value->value())); | |
| 426 return factory()->LookupSingleCharacterStringFromCode( | |
| 427 String::Flatten(string)->Get(index_)); | |
| 428 } | |
| 429 | |
| 430 ElementsAccessor* accessor = holder->GetElementsAccessor(); | 419 ElementsAccessor* accessor = holder->GetElementsAccessor(); |
| 431 return accessor->Get(handle(holder->elements()), number_); | 420 return accessor->Get(holder, number_); |
| 432 } else if (holder_map_->IsJSGlobalObjectMap()) { | 421 } else if (holder_map_->IsJSGlobalObjectMap()) { |
| 433 Handle<JSObject> holder = GetHolder<JSObject>(); | 422 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 434 result = holder->global_dictionary()->ValueAt(number_); | 423 result = holder->global_dictionary()->ValueAt(number_); |
| 435 DCHECK(result->IsPropertyCell()); | 424 DCHECK(result->IsPropertyCell()); |
| 436 result = PropertyCell::cast(result)->value(); | 425 result = PropertyCell::cast(result)->value(); |
| 437 } else if (holder_map_->is_dictionary_map()) { | 426 } else if (holder_map_->is_dictionary_map()) { |
| 438 result = holder_->property_dictionary()->ValueAt(number_); | 427 result = holder_->property_dictionary()->ValueAt(number_); |
| 439 } else if (property_details_.type() == v8::internal::DATA) { | 428 } else if (property_details_.type() == v8::internal::DATA) { |
| 440 Handle<JSObject> holder = GetHolder<JSObject>(); | 429 Handle<JSObject> holder = GetHolder<JSObject>(); |
| 441 FieldIndex field_index = FieldIndex::ForDescriptor(*holder_map_, number_); | 430 FieldIndex field_index = FieldIndex::ForDescriptor(*holder_map_, number_); |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 509 return value; | 498 return value; |
| 510 } | 499 } |
| 511 | 500 |
| 512 | 501 |
| 513 void LookupIterator::WriteDataValue(Handle<Object> value) { | 502 void LookupIterator::WriteDataValue(Handle<Object> value) { |
| 514 DCHECK_EQ(DATA, state_); | 503 DCHECK_EQ(DATA, state_); |
| 515 Handle<JSReceiver> holder = GetHolder<JSReceiver>(); | 504 Handle<JSReceiver> holder = GetHolder<JSReceiver>(); |
| 516 if (IsElement()) { | 505 if (IsElement()) { |
| 517 Handle<JSObject> object = Handle<JSObject>::cast(holder); | 506 Handle<JSObject> object = Handle<JSObject>::cast(holder); |
| 518 ElementsAccessor* accessor = object->GetElementsAccessor(); | 507 ElementsAccessor* accessor = object->GetElementsAccessor(); |
| 519 accessor->Set(object->elements(), number_, *value); | 508 accessor->Set(object, number_, *value); |
| 520 } else if (holder->IsJSGlobalObject()) { | 509 } else if (holder->IsJSGlobalObject()) { |
| 521 Handle<GlobalDictionary> property_dictionary = | 510 Handle<GlobalDictionary> property_dictionary = |
| 522 handle(JSObject::cast(*holder)->global_dictionary()); | 511 handle(JSObject::cast(*holder)->global_dictionary()); |
| 523 PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value, | 512 PropertyCell::UpdateCell(property_dictionary, dictionary_entry(), value, |
| 524 property_details_); | 513 property_details_); |
| 525 } else if (holder_map_->is_dictionary_map()) { | 514 } else if (holder_map_->is_dictionary_map()) { |
| 526 NameDictionary* property_dictionary = holder->property_dictionary(); | 515 NameDictionary* property_dictionary = holder->property_dictionary(); |
| 527 property_dictionary->ValueAtPut(dictionary_entry(), *value); | 516 property_dictionary->ValueAtPut(dictionary_entry(), *value); |
| 528 } else if (property_details_.type() == v8::internal::DATA) { | 517 } else if (property_details_.type() == v8::internal::DATA) { |
| 529 JSObject::cast(*holder)->WriteToField(descriptor_number(), *value); | 518 JSObject::cast(*holder)->WriteToField(descriptor_number(), *value); |
| (...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 619 if (map->IsJSProxyMap()) { | 608 if (map->IsJSProxyMap()) { |
| 620 // Do not leak private property names. | 609 // Do not leak private property names. |
| 621 if (IsElement() || !name_->IsPrivate()) return JSPROXY; | 610 if (IsElement() || !name_->IsPrivate()) return JSPROXY; |
| 622 } | 611 } |
| 623 if (map->is_access_check_needed() && | 612 if (map->is_access_check_needed() && |
| 624 (IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) { | 613 (IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) { |
| 625 return ACCESS_CHECK; | 614 return ACCESS_CHECK; |
| 626 } | 615 } |
| 627 // Fall through. | 616 // Fall through. |
| 628 case ACCESS_CHECK: | 617 case ACCESS_CHECK: |
| 629 if (exotic_index_state_ != ExoticIndexState::kNotExotic && | |
| 630 holder->IsJSTypedArray() && IsIntegerIndexedExotic(holder)) { | |
| 631 return INTEGER_INDEXED_EXOTIC; | |
| 632 } | |
| 633 if (check_interceptor() && HasInterceptor(map) && | 618 if (check_interceptor() && HasInterceptor(map) && |
| 634 !SkipInterceptor(JSObject::cast(holder))) { | 619 !SkipInterceptor(JSObject::cast(holder))) { |
| 635 // Do not leak private property names. | 620 // Do not leak private property names. |
| 636 if (!name_.is_null() && name_->IsPrivate()) return NOT_FOUND; | 621 if (!name_.is_null() && name_->IsPrivate()) return NOT_FOUND; |
| 637 return INTERCEPTOR; | 622 return INTERCEPTOR; |
| 638 } | 623 } |
| 639 // Fall through. | 624 // Fall through. |
| 640 case INTERCEPTOR: | 625 case INTERCEPTOR: |
| 641 if (IsElement()) { | 626 if (IsElement()) { |
| 642 // TODO(verwaest): Optimize. | 627 JSObject* js_object = JSObject::cast(holder); |
| 643 if (holder->IsStringObjectWithCharacterAt(index_)) { | 628 ElementsAccessor* accessor = js_object->GetElementsAccessor(); |
| 644 PropertyAttributes attributes = | 629 FixedArrayBase* backing_store = js_object->elements(); |
| 645 static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); | 630 number_ = accessor->GetEntryForIndex(js_object, backing_store, index_); |
| 646 property_details_ = PropertyDetails(attributes, v8::internal::DATA, 0, | 631 if (number_ == kMaxUInt32) { |
| 647 PropertyCellType::kNoCell); | 632 if (*receiver_ == Object::cast(holder) && holder->IsJSTypedArray()) { |
| 648 } else { | 633 return INTEGER_INDEXED_EXOTIC; |
| 649 JSObject* js_object = JSObject::cast(holder); | |
| 650 if (js_object->elements() == isolate()->heap()->empty_fixed_array()) { | |
| 651 return NOT_FOUND; | |
| 652 } | 634 } |
| 653 | 635 return NOT_FOUND; |
| 654 ElementsAccessor* accessor = js_object->GetElementsAccessor(); | |
| 655 FixedArrayBase* backing_store = js_object->elements(); | |
| 656 number_ = | |
| 657 accessor->GetEntryForIndex(js_object, backing_store, index_); | |
| 658 if (number_ == kMaxUInt32) return NOT_FOUND; | |
| 659 property_details_ = accessor->GetDetails(backing_store, number_); | |
| 660 } | 636 } |
| 637 property_details_ = accessor->GetDetails(js_object, number_); | |
| 638 } else if (exotic_index_state_ != ExoticIndexState::kNotExotic && | |
| 639 holder->IsJSTypedArray() && IsIntegerIndexedExotic(holder)) { | |
| 640 return INTEGER_INDEXED_EXOTIC; | |
| 661 } else if (!map->is_dictionary_map()) { | 641 } else if (!map->is_dictionary_map()) { |
| 662 DescriptorArray* descriptors = map->instance_descriptors(); | 642 DescriptorArray* descriptors = map->instance_descriptors(); |
| 663 int number = descriptors->SearchWithCache(*name_, map); | 643 int number = descriptors->SearchWithCache(*name_, map); |
| 664 if (number == DescriptorArray::kNotFound) return NOT_FOUND; | 644 if (number == DescriptorArray::kNotFound) return NOT_FOUND; |
| 665 number_ = static_cast<uint32_t>(number); | 645 number_ = static_cast<uint32_t>(number); |
| 666 property_details_ = descriptors->GetDetails(number_); | 646 property_details_ = descriptors->GetDetails(number_); |
| 667 } else if (map->IsJSGlobalObjectMap()) { | 647 } else if (map->IsJSGlobalObjectMap()) { |
| 668 GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary(); | 648 GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary(); |
| 669 int number = dict->FindEntry(name_); | 649 int number = dict->FindEntry(name_); |
| 670 if (number == GlobalDictionary::kNotFound) return NOT_FOUND; | 650 if (number == GlobalDictionary::kNotFound) return NOT_FOUND; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 711 // Fall through. | 691 // Fall through. |
| 712 default: | 692 default: |
| 713 return NOT_FOUND; | 693 return NOT_FOUND; |
| 714 } | 694 } |
| 715 UNREACHABLE(); | 695 UNREACHABLE(); |
| 716 return state_; | 696 return state_; |
| 717 } | 697 } |
| 718 | 698 |
| 719 } // namespace internal | 699 } // namespace internal |
| 720 } // namespace v8 | 700 } // namespace v8 |
| OLD | NEW |