From 16484824b65b6fc4e57c45dd4e055213021fb705 Mon Sep 17 00:00:00 2001 From: verwaest Date: Thu, 21 May 2015 05:19:39 -0700 Subject: [PATCH] Start adding support for elements to the LookupIterator BUG= Review URL: https://codereview.chromium.org/1144883002 Cr-Commit-Position: refs/heads/master@{#28546} --- src/elements.cc | 107 +++++++++++++++++++++++++++++++++++++++---------------- src/elements.h | 13 +++++-- src/lookup-inl.h | 27 +++++++++----- src/lookup.cc | 14 +++++--- src/lookup.h | 55 ++++++++++++++++++++++++++-- 5 files changed, 167 insertions(+), 49 deletions(-) diff --git a/src/elements.cc b/src/elements.cc index 0237a97..a2068dc 100644 --- a/src/elements.cc +++ b/src/elements.cc @@ -616,7 +616,7 @@ class ElementsAccessorBase : public ElementsAccessor { Handle obj, uint32_t key, Handle backing_store) { - if (key < ElementsAccessorSubclass::GetCapacityImpl(obj, backing_store)) { + if (key < ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { return BackingStore::get(Handle::cast(backing_store), key); } else { return backing_store->GetIsolate()->factory()->the_hole_value(); @@ -634,7 +634,8 @@ class ElementsAccessorBase : public ElementsAccessor { Handle obj, uint32_t key, Handle backing_store) { - if (key >= ElementsAccessorSubclass::GetCapacityImpl(obj, backing_store)) { + if (key >= + ElementsAccessorSubclass::GetCapacityImpl(*obj, *backing_store)) { return ABSENT; } return @@ -749,7 +750,7 @@ class ElementsAccessorBase : public ElementsAccessor { // Optimize if 'other' is empty. // We cannot optimize if 'this' is empty, as other may have holes. - uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(receiver, from); + uint32_t len1 = ElementsAccessorSubclass::GetCapacityImpl(*receiver, *from); if (len1 == 0) return to; Isolate* isolate = from->GetIsolate(); @@ -757,7 +758,7 @@ class ElementsAccessorBase : public ElementsAccessor { // Compute how many elements are not in other. uint32_t extra = 0; for (uint32_t y = 0; y < len1; y++) { - uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(from, y); + uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y); if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) { Handle value; ASSIGN_RETURN_ON_EXCEPTION( @@ -793,8 +794,7 @@ class ElementsAccessorBase : public ElementsAccessor { // Fill in the extra values. uint32_t index = 0; for (uint32_t y = 0; y < len1; y++) { - uint32_t key = - ElementsAccessorSubclass::GetKeyForIndexImpl(from, y); + uint32_t key = ElementsAccessorSubclass::GetKeyForIndexImpl(*from, y); if (ElementsAccessorSubclass::HasElementImpl(receiver, key, from)) { Handle value; ASSIGN_RETURN_ON_EXCEPTION( @@ -815,26 +815,45 @@ class ElementsAccessorBase : public ElementsAccessor { } protected: - static uint32_t GetCapacityImpl(Handle holder, - Handle backing_store) { + static uint32_t GetCapacityImpl(JSObject* holder, + FixedArrayBase* backing_store) { return backing_store->length(); } - uint32_t GetCapacity(Handle holder, - Handle backing_store) final { + uint32_t GetCapacity(JSObject* holder, FixedArrayBase* backing_store) final { return ElementsAccessorSubclass::GetCapacityImpl(holder, backing_store); } - static uint32_t GetKeyForIndexImpl(Handle backing_store, + static uint32_t GetKeyForIndexImpl(FixedArrayBase* backing_store, uint32_t index) { return index; } - virtual uint32_t GetKeyForIndex(Handle backing_store, + virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, uint32_t index) final { return ElementsAccessorSubclass::GetKeyForIndexImpl(backing_store, index); } + static uint32_t GetIndexForKeyImpl(FixedArrayBase* backing_store, + uint32_t key) { + return key; + } + + virtual uint32_t GetIndexForKey(FixedArrayBase* backing_store, + uint32_t key) final { + return ElementsAccessorSubclass::GetIndexForKeyImpl(backing_store, key); + } + + static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, + uint32_t index) { + return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); + } + + virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, + uint32_t index) final { + return ElementsAccessorSubclass::GetDetailsImpl(backing_store, index); + } + private: DISALLOW_COPY_AND_ASSIGN(ElementsAccessorBase); }; @@ -1260,7 +1279,7 @@ class TypedElementsAccessor Handle obj, uint32_t key, Handle backing_store) { - if (key < AccessorClass::GetCapacityImpl(obj, backing_store)) { + if (key < AccessorClass::GetCapacityImpl(*obj, *backing_store)) { return BackingStore::get(Handle::cast(backing_store), key); } else { return backing_store->GetIsolate()->factory()->undefined_value(); @@ -1271,8 +1290,8 @@ class TypedElementsAccessor Handle obj, uint32_t key, Handle backing_store) { - return key < AccessorClass::GetCapacityImpl(obj, backing_store) ? NONE - : ABSENT; + return key < AccessorClass::GetCapacityImpl(*obj, *backing_store) ? NONE + : ABSENT; } MUST_USE_RESULT static MaybeHandle SetLengthImpl( @@ -1292,13 +1311,13 @@ class TypedElementsAccessor static bool HasElementImpl(Handle holder, uint32_t key, Handle backing_store) { - uint32_t capacity = AccessorClass::GetCapacityImpl(holder, backing_store); + uint32_t capacity = AccessorClass::GetCapacityImpl(*holder, *backing_store); return key < capacity; } - static uint32_t GetCapacityImpl(Handle holder, - Handle backing_store) { - Handle view = Handle::cast(holder); + static uint32_t GetCapacityImpl(JSObject* holder, + FixedArrayBase* backing_store) { + JSArrayBufferView* view = JSArrayBufferView::cast(holder); if (view->WasNeutered()) return 0; return backing_store->length(); } @@ -1500,14 +1519,27 @@ class DictionaryElementsAccessor return backing_store->FindEntry(key) != SeededNumberDictionary::kNotFound; } - static uint32_t GetKeyForIndexImpl(Handle store, - uint32_t index) { + static uint32_t GetKeyForIndexImpl(FixedArrayBase* store, uint32_t index) { DisallowHeapAllocation no_gc; - Handle dict = - Handle::cast(store); + SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); Object* key = dict->KeyAt(index); return Smi::cast(key)->value(); } + + static uint32_t GetIndexForKeyImpl(FixedArrayBase* store, uint32_t key) { + DisallowHeapAllocation no_gc; + SeededNumberDictionary* dict = SeededNumberDictionary::cast(store); + int entry = dict->FindEntry(key); + if (entry == SeededNumberDictionary::kNotFound) { + return kMaxUInt32; + } + return static_cast(entry); + } + + static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, + uint32_t index) { + return SeededNumberDictionary::cast(backing_store)->DetailsAt(index); + } }; @@ -1637,20 +1669,28 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase< UNREACHABLE(); } - static uint32_t GetCapacityImpl(Handle holder, - Handle backing_store) { - Handle parameter_map = Handle::cast(backing_store); - Handle arguments( - FixedArrayBase::cast(parameter_map->get(1))); + static uint32_t GetCapacityImpl(JSObject* holder, + FixedArrayBase* backing_store) { + FixedArray* parameter_map = FixedArray::cast(backing_store); + FixedArrayBase* arguments = FixedArrayBase::cast(parameter_map->get(1)); return Max(static_cast(parameter_map->length() - 2), ForArray(arguments)->GetCapacity(holder, arguments)); } - static uint32_t GetKeyForIndexImpl(Handle dict, - uint32_t index) { + static uint32_t GetKeyForIndexImpl(FixedArrayBase* dict, uint32_t index) { return index; } + static uint32_t GetIndexForKeyImpl(FixedArrayBase* dict, uint32_t key) { + return key; + } + + static PropertyDetails GetDetailsImpl(FixedArrayBase* backing_store, + uint32_t index) { + return PropertyDetails(NONE, DATA, 0, PropertyCellType::kNoCell); + } + + private: static Handle GetParameterMapArg(Handle holder, Handle parameter_map, @@ -1666,8 +1706,13 @@ class SloppyArgumentsElementsAccessor : public ElementsAccessorBase< }; +ElementsAccessor* ElementsAccessor::ForArray(FixedArrayBase* array) { + return elements_accessors_[ElementsKindForArray(array)]; +} + + ElementsAccessor* ElementsAccessor::ForArray(Handle array) { - return elements_accessors_[ElementsKindForArray(*array)]; + return ForArray(*array); } diff --git a/src/elements.h b/src/elements.h index 8704fff..f4d15fc 100644 --- a/src/elements.h +++ b/src/elements.h @@ -175,9 +175,12 @@ class ElementsAccessor { protected: friend class SloppyArgumentsElementsAccessor; + friend class LookupIterator; - virtual uint32_t GetCapacity(Handle holder, - Handle backing_store) = 0; + static ElementsAccessor* ForArray(FixedArrayBase* array); + + virtual uint32_t GetCapacity(JSObject* holder, + FixedArrayBase* backing_store) = 0; // Element handlers distinguish between indexes and keys when they manipulate // elements. Indexes refer to elements in terms of their location in the @@ -187,8 +190,12 @@ class ElementsAccessor { // keys are equivalent to indexes, and GetKeyForIndex returns the same value // it is passed. In the NumberDictionary ElementsAccessor, GetKeyForIndex maps // the index to a key using the KeyAt method on the NumberDictionary. - virtual uint32_t GetKeyForIndex(Handle backing_store, + virtual uint32_t GetKeyForIndex(FixedArrayBase* backing_store, uint32_t index) = 0; + virtual uint32_t GetIndexForKey(FixedArrayBase* backing_store, + uint32_t key) = 0; + virtual PropertyDetails GetDetails(FixedArrayBase* backing_store, + uint32_t index) = 0; private: static ElementsAccessor** elements_accessors_; diff --git a/src/lookup-inl.h b/src/lookup-inl.h index a801e34..50f0d3e 100644 --- a/src/lookup-inl.h +++ b/src/lookup-inl.h @@ -42,25 +42,33 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* const map, case NOT_FOUND: if (map->IsJSProxyMap()) return JSPROXY; if (map->is_access_check_needed() && - !isolate_->IsInternallyUsedPropertyName(name_)) { + (IsElement() || !isolate_->IsInternallyUsedPropertyName(name_))) { return ACCESS_CHECK; } // Fall through. case ACCESS_CHECK: - if (exotic_index_state_ != ExoticIndexState::kNoIndex && + if (exotic_index_state_ != ExoticIndexState::kNotExotic && IsIntegerIndexedExotic(holder)) { return INTEGER_INDEXED_EXOTIC; } - if (check_interceptor() && map->has_named_interceptor() && + if (check_interceptor() && HasInterceptor(map) && !SkipInterceptor(JSObject::cast(holder))) { return INTERCEPTOR; } // Fall through. case INTERCEPTOR: - if (map->is_dictionary_map()) { + if (IsElement()) { + JSObject* js_object = JSObject::cast(holder); + ElementsAccessor* accessor = js_object->GetElementsAccessor(); + FixedArrayBase* backing_store = js_object->elements(); + number_ = accessor->GetIndexForKey(backing_store, index_); + if (number_ == kMaxUInt32) return NOT_FOUND; + property_details_ = accessor->GetDetails(backing_store, number_); + } else if (map->is_dictionary_map()) { NameDictionary* dict = JSObject::cast(holder)->property_dictionary(); - number_ = dict->FindEntry(name_); - if (number_ == NameDictionary::kNotFound) return NOT_FOUND; + int number = dict->FindEntry(name_); + if (number == NameDictionary::kNotFound) return NOT_FOUND; + number_ = static_cast(number); if (holder->IsGlobalObject()) { DCHECK(dict->ValueAt(number_)->IsPropertyCell()); PropertyCell* cell = PropertyCell::cast(dict->ValueAt(number_)); @@ -69,8 +77,9 @@ LookupIterator::State LookupIterator::LookupInHolder(Map* const map, property_details_ = dict->DetailsAt(number_); } else { DescriptorArray* descriptors = map->instance_descriptors(); - number_ = descriptors->SearchWithCache(*name_, map); - if (number_ == DescriptorArray::kNotFound) return NOT_FOUND; + int number = descriptors->SearchWithCache(*name_, map); + if (number == DescriptorArray::kNotFound) return NOT_FOUND; + number_ = static_cast(number); property_details_ = descriptors->GetDetails(number_); } has_property_ = true; @@ -97,7 +106,7 @@ LookupIterator::State LookupIterator::LookupNonMaskingInterceptorInHolder( Map* const map, JSReceiver* const holder) { switch (state_) { case NOT_FOUND: - if (check_interceptor() && map->has_named_interceptor() && + if (check_interceptor() && HasInterceptor(map) && !SkipInterceptor(JSObject::cast(holder))) { return INTERCEPTOR; } diff --git a/src/lookup.cc b/src/lookup.cc index 85745ce..8eb5571 100644 --- a/src/lookup.cc +++ b/src/lookup.cc @@ -145,7 +145,7 @@ void LookupIterator::PrepareTransitionToDataProperty( DCHECK(state_ != LookupIterator::ACCESSOR || (GetAccessors()->IsAccessorInfo() && AccessorInfo::cast(*GetAccessors())->is_special_data_property())); - DCHECK_NE(LookupIterator::INTEGER_INDEXED_EXOTIC, state_); + DCHECK_NE(INTEGER_INDEXED_EXOTIC, state_); DCHECK(state_ == NOT_FOUND || !HolderIsReceiverOrHiddenPrototype()); // Can only be called when the receiver is a JSObject. JSProxy has to be // handled via a trap. Adding properties to primitive values is not @@ -355,10 +355,10 @@ void LookupIterator::WriteDataValue(Handle value) { bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) { - DCHECK(exotic_index_state_ != ExoticIndexState::kNoIndex); + DCHECK(ExoticIndexState::kNotExotic != exotic_index_state_); // Currently typed arrays are the only such objects. if (!holder->IsJSTypedArray()) return false; - if (exotic_index_state_ == ExoticIndexState::kIndex) return true; + if (exotic_index_state_ == ExoticIndexState::kExotic) return true; DCHECK(exotic_index_state_ == ExoticIndexState::kUninitialized); bool result = false; // Compute and cache result. @@ -369,7 +369,7 @@ bool LookupIterator::IsIntegerIndexedExotic(JSReceiver* holder) { } } exotic_index_state_ = - result ? ExoticIndexState::kIndex : ExoticIndexState::kNoIndex; + result ? ExoticIndexState::kExotic : ExoticIndexState::kNotExotic; return result; } @@ -380,6 +380,12 @@ void LookupIterator::InternalizeName() { } +bool LookupIterator::HasInterceptor(Map* map) const { + if (IsElement()) return map->has_indexed_interceptor(); + return map->has_named_interceptor(); +} + + bool LookupIterator::SkipInterceptor(JSObject* holder) { auto info = holder->GetNamedInterceptor(); // TODO(dcarney): check for symbol/can_intercept_symbols here as well. diff --git a/src/lookup.h b/src/lookup.h index a574980..48dce3a 100644 --- a/src/lookup.h +++ b/src/lookup.h @@ -52,6 +52,8 @@ class LookupIterator final BASE_EMBEDDED { property_details_(PropertyDetails::Empty()), isolate_(name->GetIsolate()), name_(name), + // kMaxUInt32 isn't a valid index. + index_(kMaxUInt32), receiver_(receiver), holder_(GetRoot(receiver_, isolate_)), holder_map_(holder_->map(), isolate_), @@ -70,6 +72,8 @@ class LookupIterator final BASE_EMBEDDED { property_details_(PropertyDetails::Empty()), isolate_(name->GetIsolate()), name_(name), + // kMaxUInt32 isn't a valid index. + index_(kMaxUInt32), receiver_(receiver), holder_(holder), holder_map_(holder_->map(), isolate_), @@ -78,9 +82,54 @@ class LookupIterator final BASE_EMBEDDED { Next(); } + LookupIterator(Isolate* isolate, Handle receiver, uint32_t index, + Configuration configuration = PROTOTYPE_CHAIN) + : configuration_(configuration), + state_(NOT_FOUND), + exotic_index_state_(ExoticIndexState::kNotExotic), + interceptor_state_(InterceptorState::kUninitialized), + property_details_(PropertyDetails::Empty()), + isolate_(isolate), + name_(), + index_(index), + receiver_(receiver), + holder_(GetRoot(receiver_, isolate_)), + holder_map_(holder_->map(), isolate_), + initial_holder_(holder_), + number_(DescriptorArray::kNotFound) { + // kMaxUInt32 isn't a valid index. + DCHECK_NE(kMaxUInt32, index_); + Next(); + } + + LookupIterator(Isolate* isolate, Handle receiver, uint32_t index, + Handle holder, + Configuration configuration = PROTOTYPE_CHAIN) + : configuration_(configuration), + state_(NOT_FOUND), + exotic_index_state_(ExoticIndexState::kNotExotic), + interceptor_state_(InterceptorState::kUninitialized), + property_details_(PropertyDetails::Empty()), + isolate_(isolate), + name_(), + index_(index), + receiver_(receiver), + holder_(holder), + holder_map_(holder_->map(), isolate_), + initial_holder_(holder_), + number_(DescriptorArray::kNotFound) { + // kMaxUInt32 isn't a valid index. + DCHECK_NE(kMaxUInt32, index_); + Next(); + } + Isolate* isolate() const { return isolate_; } State state() const { return state_; } + Handle name() const { return name_; } + uint32_t index() const { return index_; } + + bool IsElement() const { return index_ != kMaxUInt32; } bool IsFound() const { return state_ != NOT_FOUND; } void Next(); @@ -161,6 +210,7 @@ class LookupIterator final BASE_EMBEDDED { Handle FetchValue() const; void ReloadPropertyInformation(); bool SkipInterceptor(JSObject* holder); + bool HasInterceptor(Map* map) const; bool IsBootstrapping() const; @@ -192,7 +242,7 @@ class LookupIterator final BASE_EMBEDDED { } } - enum class ExoticIndexState { kUninitialized, kNoIndex, kIndex }; + enum class ExoticIndexState { kUninitialized, kNotExotic, kExotic }; bool IsIntegerIndexedExotic(JSReceiver* holder); // If configuration_ becomes mutable, update @@ -205,12 +255,13 @@ class LookupIterator final BASE_EMBEDDED { PropertyDetails property_details_; Isolate* const isolate_; Handle name_; + uint32_t index_; Handle transition_; const Handle receiver_; Handle holder_; Handle holder_map_; const Handle initial_holder_; - int number_; + uint32_t number_; }; -- 2.7.4