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 |