Index: src/lookup.cc |
diff --git a/src/lookup.cc b/src/lookup.cc |
index 5dcc04586e65e045e0a553b3061c57a9f35f6471..a404cd9cd468404254eb67ac9daef4f76871c7ee 100644 |
--- a/src/lookup.cc |
+++ b/src/lookup.cc |
@@ -6,8 +6,8 @@ |
#include "src/bootstrapper.h" |
#include "src/deoptimizer.h" |
+#include "src/elements.h" |
#include "src/isolate-inl.h" |
-#include "src/lookup-inl.h" |
namespace v8 { |
namespace internal { |
@@ -593,5 +593,131 @@ bool LookupIterator::SkipInterceptor(JSObject* holder) { |
} |
return interceptor_state_ == InterceptorState::kProcessNonMasking; |
} |
+ |
+ |
+JSReceiver* LookupIterator::NextHolder(Map* map) { |
+ DisallowHeapAllocation no_gc; |
+ if (!map->prototype()->IsJSReceiver()) return NULL; |
+ |
+ JSReceiver* next = JSReceiver::cast(map->prototype()); |
+ DCHECK(!next->map()->IsGlobalObjectMap() || |
+ next->map()->is_hidden_prototype()); |
+ |
+ if (!check_prototype_chain() && |
+ !(check_hidden() && next->map()->is_hidden_prototype()) && |
+ // Always lookup behind the JSGlobalProxy into the JSGlobalObject, even |
+ // when not checking other hidden prototypes. |
+ !map->IsJSGlobalProxyMap()) { |
+ return NULL; |
+ } |
+ |
+ return next; |
+} |
+ |
+ |
+LookupIterator::State LookupIterator::LookupInHolder(Map* const map, |
+ JSReceiver* const holder) { |
+ STATIC_ASSERT(INTERCEPTOR == BEFORE_PROPERTY); |
+ DisallowHeapAllocation no_gc; |
+ if (interceptor_state_ == InterceptorState::kProcessNonMasking) { |
+ return LookupNonMaskingInterceptorInHolder(map, holder); |
+ } |
+ switch (state_) { |
+ case NOT_FOUND: |
+ if (map->IsJSProxyMap()) return JSPROXY; |
+ if (map->is_access_check_needed() && |
+ (IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) { |
+ return ACCESS_CHECK; |
+ } |
+ // Fall through. |
+ case ACCESS_CHECK: |
+ if (exotic_index_state_ != ExoticIndexState::kNotExotic && |
+ IsIntegerIndexedExotic(holder)) { |
+ return INTEGER_INDEXED_EXOTIC; |
+ } |
+ if (check_interceptor() && HasInterceptor(map) && |
+ !SkipInterceptor(JSObject::cast(holder))) { |
+ return INTERCEPTOR; |
+ } |
+ // Fall through. |
+ case INTERCEPTOR: |
+ if (IsElement()) { |
+ // TODO(verwaest): Optimize. |
+ if (holder->IsStringObjectWithCharacterAt(index_)) { |
+ PropertyAttributes attributes = |
+ static_cast<PropertyAttributes>(READ_ONLY | DONT_DELETE); |
+ property_details_ = PropertyDetails(attributes, v8::internal::DATA, 0, |
+ PropertyCellType::kNoCell); |
+ } else { |
+ JSObject* js_object = JSObject::cast(holder); |
+ if (js_object->elements() == isolate()->heap()->empty_fixed_array()) { |
+ return NOT_FOUND; |
+ } |
+ |
+ ElementsAccessor* accessor = js_object->GetElementsAccessor(); |
+ FixedArrayBase* backing_store = js_object->elements(); |
+ number_ = |
+ accessor->GetEntryForIndex(js_object, backing_store, index_); |
+ if (number_ == kMaxUInt32) return NOT_FOUND; |
+ property_details_ = accessor->GetDetails(backing_store, number_); |
+ } |
+ } else if (!map->is_dictionary_map()) { |
+ DescriptorArray* descriptors = map->instance_descriptors(); |
+ int number = descriptors->SearchWithCache(*name_, map); |
+ if (number == DescriptorArray::kNotFound) return NOT_FOUND; |
+ number_ = static_cast<uint32_t>(number); |
+ property_details_ = descriptors->GetDetails(number_); |
+ } else if (map->IsGlobalObjectMap()) { |
+ GlobalDictionary* dict = JSObject::cast(holder)->global_dictionary(); |
+ int number = dict->FindEntry(name_); |
+ if (number == GlobalDictionary::kNotFound) return NOT_FOUND; |
+ number_ = static_cast<uint32_t>(number); |
+ DCHECK(dict->ValueAt(number_)->IsPropertyCell()); |
+ PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_)); |
+ if (cell->value()->IsTheHole()) return NOT_FOUND; |
+ property_details_ = cell->property_details(); |
+ } else { |
+ NameDictionary* dict = JSObject::cast(holder)->property_dictionary(); |
+ int number = dict->FindEntry(name_); |
+ if (number == NameDictionary::kNotFound) return NOT_FOUND; |
+ number_ = static_cast<uint32_t>(number); |
+ property_details_ = dict->DetailsAt(number_); |
+ } |
+ has_property_ = true; |
+ switch (property_details_.kind()) { |
+ case v8::internal::kData: |
+ return DATA; |
+ case v8::internal::kAccessor: |
+ return ACCESSOR; |
+ } |
+ case ACCESSOR: |
+ case DATA: |
+ return NOT_FOUND; |
+ case INTEGER_INDEXED_EXOTIC: |
+ case JSPROXY: |
+ case TRANSITION: |
+ UNREACHABLE(); |
+ } |
+ UNREACHABLE(); |
+ return state_; |
+} |
+ |
+ |
+LookupIterator::State LookupIterator::LookupNonMaskingInterceptorInHolder( |
+ Map* const map, JSReceiver* const holder) { |
+ switch (state_) { |
+ case NOT_FOUND: |
+ if (check_interceptor() && HasInterceptor(map) && |
+ !SkipInterceptor(JSObject::cast(holder))) { |
+ return INTERCEPTOR; |
+ } |
+ // Fall through. |
+ default: |
+ return NOT_FOUND; |
+ } |
+ UNREACHABLE(); |
+ return state_; |
+} |
+ |
} // namespace internal |
} // namespace v8 |