| OLD | NEW |
| (Empty) |
| 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 | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #ifndef V8_LOOKUP_INL_H_ | |
| 6 #define V8_LOOKUP_INL_H_ | |
| 7 | |
| 8 #include "src/lookup.h" | |
| 9 | |
| 10 #include "src/elements.h" | |
| 11 | |
| 12 namespace v8 { | |
| 13 namespace internal { | |
| 14 | |
| 15 | |
| 16 JSReceiver* LookupIterator::NextHolder(Map* map) { | |
| 17 DisallowHeapAllocation no_gc; | |
| 18 if (!map->prototype()->IsJSReceiver()) return NULL; | |
| 19 | |
| 20 JSReceiver* next = JSReceiver::cast(map->prototype()); | |
| 21 DCHECK(!next->map()->IsGlobalObjectMap() || | |
| 22 next->map()->is_hidden_prototype()); | |
| 23 | |
| 24 if (!check_prototype_chain() && | |
| 25 !(check_hidden() && next->map()->is_hidden_prototype()) && | |
| 26 // Always lookup behind the JSGlobalProxy into the JSGlobalObject, even | |
| 27 // when not checking other hidden prototypes. | |
| 28 !map->IsJSGlobalProxyMap()) { | |
| 29 return NULL; | |
| 30 } | |
| 31 | |
| 32 return next; | |
| 33 } | |
| 34 | |
| 35 | |
| 36 LookupIterator::State LookupIterator::LookupInHolder(Map* const map, | |
| 37 JSReceiver* const holder) { | |
| 38 STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY); | |
| 39 DisallowHeapAllocation no_gc; | |
| 40 if (interceptor_state_ == InterceptorState::kProcessNonMasking) { | |
| 41 return LookupNonMaskingInterceptorInHolder(map, holder); | |
| 42 } | |
| 43 switch (state_) { | |
| 44 case NOT_FOUND: | |
| 45 if (map->IsJSProxyMap()) return JSPROXY; | |
| 46 if (map->is_access_check_needed() && | |
| 47 (IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) { | |
| 48 return ACCESS_CHECK; | |
| 49 } | |
| 50 // Fall through. | |
| 51 case ACCESS_CHECK: | |
| 52 if (exotic_index_state_ != ExoticIndexState::kNotExotic && | |
| 53 IsIntegerIndexedExotic(holder)) { | |
| 54 return INTEGER_INDEXED_EXOTIC; | |
| 55 } | |
| 56 if (check_interceptor() && HasInterceptor(map) && | |
| 57 !SkipInterceptor(JSObject::cast(holder))) { | |
| 58 return INTERCEPTOR; | |
| 59 } | |
| 60 // Fall through. | |
| 61 case INTERCEPTOR: | |
| 62 if (IsElement()) { | |
| 63 // TODO(verwaest): Optimize. | |
| 64 if (holder->IsStringObjectWithCharacterAt(index_)) { | |
| 65 PropertyAttributes attributes = | |
| 66 static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); | |
| 67 property_details_ = PropertyDetails(attributes, v8::internal::DATA, 0, | |
| 68 PropertyCellType::kNoCell); | |
| 69 } else { | |
| 70 JSObject* js_object = JSObject::cast(holder); | |
| 71 if (js_object->elements() == isolate()->heap()->empty_fixed_array()) { | |
| 72 return NOT_FOUND; | |
| 73 } | |
| 74 | |
| 75 ElementsAccessor* accessor = js_object->GetElementsAccessor(); | |
| 76 FixedArrayBase* backing_store = js_object->elements(); | |
| 77 number_ = | |
| 78 accessor->GetEntryForIndex(js_object, backing_store, index_); | |
| 79 if (number_ == kMaxUInt32) return NOT_FOUND; | |
| 80 property_details_ = accessor->GetDetails(backing_store, number_); | |
| 81 } | |
| 82 } else if (!map->is_dictionary_map()) { | |
| 83 DescriptorArray* descriptors = map->instance_descriptors(); | |
| 84 int number = descriptors->SearchWithCache(*name_, map); | |
| 85 if (number == DescriptorArray::kNotFound) return NOT_FOUND; | |
| 86 number_ = static_cast<uint32_t>(number); | |
| 87 property_details_ = descriptors->GetDetails(number_); | |
| 88 } else if (map->IsGlobalObjectMap()) { | |
| 89 GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary(); | |
| 90 int number = dict->FindEntry(name_); | |
| 91 if (number == GlobalDictionary::kNotFound) return NOT_FOUND; | |
| 92 number_ = static_cast<uint32_t>(number); | |
| 93 DCHECK(dict->ValueAt(number_)->IsPropertyCell()); | |
| 94 PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_)); | |
| 95 if (cell->value()->IsTheHole()) return NOT_FOUND; | |
| 96 property_details_ = cell->property_details(); | |
| 97 } else { | |
| 98 NameDictionary* dict = JSObject::cast(holder)->property_dictionary(); | |
| 99 int number = dict->FindEntry(name_); | |
| 100 if (number == NameDictionary::kNotFound) return NOT_FOUND; | |
| 101 number_ = static_cast<uint32_t>(number); | |
| 102 property_details_ = dict->DetailsAt(number_); | |
| 103 } | |
| 104 has_property_ = true; | |
| 105 switch (property_details_.kind()) { | |
| 106 case v8::internal::kData: | |
| 107 return DATA; | |
| 108 case v8::internal::kAccessor: | |
| 109 return ACCESSOR; | |
| 110 } | |
| 111 case ACCESSOR: | |
| 112 case DATA: | |
| 113 return NOT_FOUND; | |
| 114 case INTEGER_INDEXED_EXOTIC: | |
| 115 case JSPROXY: | |
| 116 case TRANSITION: | |
| 117 UNREACHABLE(); | |
| 118 } | |
| 119 UNREACHABLE(); | |
| 120 return state_; | |
| 121 } | |
| 122 | |
| 123 | |
| 124 LookupIterator::State LookupIterator::LookupNonMaskingInterceptorInHolder( | |
| 125 Map* const map, JSReceiver* const holder) { | |
| 126 switch (state_) { | |
| 127 case NOT_FOUND: | |
| 128 if (check_interceptor() && HasInterceptor(map) && | |
| 129 !SkipInterceptor(JSObject::cast(holder))) { | |
| 130 return INTERCEPTOR; | |
| 131 } | |
| 132 // Fall through. | |
| 133 default: | |
| 134 return NOT_FOUND; | |
| 135 } | |
| 136 UNREACHABLE(); | |
| 137 return state_; | |
| 138 } | |
| 139 } // namespace internal | |
| 140 } // namespace v8 | |
| 141 | |
| 142 #endif // V8_LOOKUP_INL_H_ | |
| OLD | NEW |