diff options
author | Bill Rassieur <rassb@google.com> | 2018-10-10 17:33:16 +0000 |
---|---|---|
committer | Bill Rassieur <rassb@google.com> | 2018-10-10 17:33:16 +0000 |
commit | 05edf2eb4ef2e8fc8d0f5e73448f7e3338b42588 (patch) | |
tree | 76e408ade56f04e6da9b483cab9b5885333f8f79 | |
parent | 6579fbf033a3cf2957c0319028dc02b7fe684500 (diff) | |
parent | afbf44e2252cb7ffd05989348074470612ebda0b (diff) | |
download | v8-android-wear-9.0.0_r24.tar.gz |
Merge PPR2.181005.003 from pi-release-2 into pi-platform-release.android-wear-9.0.0_r9android-wear-9.0.0_r8android-wear-9.0.0_r7android-wear-9.0.0_r6android-wear-9.0.0_r5android-wear-9.0.0_r4android-wear-9.0.0_r34android-wear-9.0.0_r33android-wear-9.0.0_r32android-wear-9.0.0_r31android-wear-9.0.0_r30android-wear-9.0.0_r3android-wear-9.0.0_r29android-wear-9.0.0_r28android-wear-9.0.0_r27android-wear-9.0.0_r26android-wear-9.0.0_r25android-wear-9.0.0_r24android-wear-9.0.0_r23android-wear-9.0.0_r22android-wear-9.0.0_r21android-wear-9.0.0_r20android-wear-9.0.0_r2android-wear-9.0.0_r19android-wear-9.0.0_r18android-wear-9.0.0_r17android-wear-9.0.0_r16android-wear-9.0.0_r15android-wear-9.0.0_r14android-wear-9.0.0_r13android-wear-9.0.0_r12android-wear-9.0.0_r11android-wear-9.0.0_r10android-wear-9.0.0_r1
Change-Id: I3182ac2a53db57975e8792555b1d10113312cdfd
BUG: 117431430
-rw-r--r-- | src/elements.cc | 71 | ||||
-rw-r--r-- | src/elements.h | 18 |
2 files changed, 70 insertions, 19 deletions
diff --git a/src/elements.cc b/src/elements.cc index d5acb667..501cff7c 100644 --- a/src/elements.cc +++ b/src/elements.cc @@ -511,6 +511,21 @@ static Maybe<int64_t> IndexOfValueSlowPath(Isolate* isolate, return Just<int64_t>(-1); } +// The InternalElementsAccessor is a helper class to expose otherwise protected +// methods to its subclasses. Namely, we don't want to publicly expose methods +// that take an entry (instead of an index) as an argument. +class InternalElementsAccessor : public ElementsAccessor { + public: + explicit InternalElementsAccessor(const char* name) + : ElementsAccessor(name) {} + + virtual uint32_t GetEntryForIndex(Isolate* isolate, JSObject* holder, + FixedArrayBase* backing_store, + uint32_t index) = 0; + + virtual PropertyDetails GetDetails(JSObject* holder, uint32_t entry) = 0; +}; + // Base class for element handler implementations. Contains the // the common logic for objects with different ElementsKinds. // Subclasses must specialize method for which the element @@ -529,10 +544,10 @@ static Maybe<int64_t> IndexOfValueSlowPath(Isolate* isolate, // CRTP to guarantee aggressive compile time optimizations (i.e. inlining and // specialization of SomeElementsAccessor methods). template <typename Subclass, typename ElementsTraitsParam> -class ElementsAccessorBase : public ElementsAccessor { +class ElementsAccessorBase : public InternalElementsAccessor { public: explicit ElementsAccessorBase(const char* name) - : ElementsAccessor(name) { } + : InternalElementsAccessor(name) {} typedef ElementsTraitsParam ElementsTraits; typedef typename ElementsTraitsParam::BackingStore BackingStore; @@ -1014,35 +1029,66 @@ class ElementsAccessorBase : public ElementsAccessor { Isolate* isolate, Handle<JSObject> object, Handle<FixedArray> values_or_entries, bool get_entries, int* nof_items, PropertyFilter filter) { - int count = 0; + DCHECK_EQ(*nof_items, 0); KeyAccumulator accumulator(isolate, KeyCollectionMode::kOwnOnly, ALL_PROPERTIES); Subclass::CollectElementIndicesImpl( object, handle(object->elements(), isolate), &accumulator); Handle<FixedArray> keys = accumulator.GetKeys(); - for (int i = 0; i < keys->length(); ++i) { + int count = 0; + int i = 0; + Handle<Map> original_map(object->map(), isolate); + + for (; i < keys->length(); ++i) { Handle<Object> key(keys->get(i), isolate); - Handle<Object> value; uint32_t index; if (!key->ToUint32(&index)) continue; + DCHECK_EQ(object->map(), *original_map); uint32_t entry = Subclass::GetEntryForIndexImpl( isolate, *object, object->elements(), index, filter); if (entry == kMaxUInt32) continue; PropertyDetails details = Subclass::GetDetailsImpl(*object, entry); + Handle<Object> value; if (details.kind() == kData) { value = Subclass::GetImpl(isolate, object->elements(), entry); } else { + // This might modify the elements and/or change the elements kind. LookupIterator it(isolate, object, index, LookupIterator::OWN); ASSIGN_RETURN_ON_EXCEPTION_VALUE( isolate, value, Object::GetProperty(&it), Nothing<bool>()); } - if (get_entries) { - value = MakeEntryPair(isolate, index, value); + if (get_entries) value = MakeEntryPair(isolate, index, value); + values_or_entries->set(count++, *value); + if (object->map() != *original_map) break; + } + + // Slow path caused by changes in elements kind during iteration. + for (; i < keys->length(); i++) { + Handle<Object> key(keys->get(i), isolate); + uint32_t index; + if (!key->ToUint32(&index)) continue; + + if (filter & ONLY_ENUMERABLE) { + InternalElementsAccessor* accessor = + reinterpret_cast<InternalElementsAccessor*>( + object->GetElementsAccessor()); + uint32_t entry = accessor->GetEntryForIndex(isolate, *object, + object->elements(), index); + if (entry == kMaxUInt32) continue; + PropertyDetails details = accessor->GetDetails(*object, entry); + if (!details.IsEnumerable()) continue; } + + Handle<Object> value; + LookupIterator it(isolate, object, index, LookupIterator::OWN); + ASSIGN_RETURN_ON_EXCEPTION_VALUE(isolate, value, Object::GetProperty(&it), + Nothing<bool>()); + + if (get_entries) value = MakeEntryPair(isolate, index, value); values_or_entries->set(count++, *value); } @@ -1623,12 +1669,13 @@ class DictionaryElementsAccessor return result; } } - + Handle<Map> original_map(receiver->map(), isolate); Handle<SeededNumberDictionary> dictionary( SeededNumberDictionary::cast(receiver->elements()), isolate); // Iterate through entire range, as accessing elements out of order is // observable for (uint32_t k = start_from; k < length; ++k) { + DCHECK_EQ(receiver->map(), *original_map); int entry = dictionary->FindEntry(isolate, k); if (entry == SeededNumberDictionary::kNotFound) { if (search_for_hole) return Just(true); @@ -1690,11 +1737,13 @@ class DictionaryElementsAccessor uint32_t start_from, uint32_t length) { DCHECK(JSObject::PrototypeHasNoElements(isolate, *receiver)); + Handle<Map> original_map(receiver->map(), isolate); Handle<SeededNumberDictionary> dictionary( SeededNumberDictionary::cast(receiver->elements()), isolate); // Iterate through entire range, as accessing elements out of order is // observable. for (uint32_t k = start_from; k < length; ++k) { + DCHECK_EQ(receiver->map(), *original_map); int entry = dictionary->FindEntry(isolate, k); if (entry == SeededNumberDictionary::kNotFound) { continue; @@ -3170,12 +3219,13 @@ class SloppyArgumentsElementsAccessor Handle<Object> value, uint32_t start_from, uint32_t length) { DCHECK(JSObject::PrototypeHasNoElements(isolate, *object)); - Handle<Map> original_map = handle(object->map(), isolate); + Handle<Map> original_map(object->map(), isolate); Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()), isolate); bool search_for_hole = value->IsUndefined(isolate); for (uint32_t k = start_from; k < length; ++k) { + DCHECK_EQ(object->map(), *original_map); uint32_t entry = GetEntryForIndexImpl(isolate, *object, *parameter_map, k, ALL_PROPERTIES); if (entry == kMaxUInt32) { @@ -3212,11 +3262,12 @@ class SloppyArgumentsElementsAccessor Handle<Object> value, uint32_t start_from, uint32_t length) { DCHECK(JSObject::PrototypeHasNoElements(isolate, *object)); - Handle<Map> original_map = handle(object->map(), isolate); + Handle<Map> original_map(object->map(), isolate); Handle<FixedArray> parameter_map(FixedArray::cast(object->elements()), isolate); for (uint32_t k = start_from; k < length; ++k) { + DCHECK_EQ(object->map(), *original_map); uint32_t entry = GetEntryForIndexImpl(isolate, *object, *parameter_map, k, ALL_PROPERTIES); if (entry == kMaxUInt32) { diff --git a/src/elements.h b/src/elements.h index 28635d5b..376bcbe8 100644 --- a/src/elements.h +++ b/src/elements.h @@ -54,7 +54,6 @@ class ElementsAccessor { virtual Handle<Object> Get(Handle<JSObject> holder, uint32_t entry) = 0; - virtual PropertyDetails GetDetails(JSObject* holder, uint32_t entry) = 0; virtual bool HasAccessors(JSObject* holder) = 0; virtual uint32_t NumberOfElements(JSObject* holder) = 0; @@ -65,9 +64,6 @@ class ElementsAccessor { // element that is non-deletable. virtual void SetLength(Handle<JSArray> holder, uint32_t new_length) = 0; - // Deletes an element in an object. - virtual void Delete(Handle<JSObject> holder, uint32_t entry) = 0; - // If kCopyToEnd is specified as the copy_size to CopyElements, it copies all // of elements from source after source_start to the destination array. static const int kCopyToEnd = -1; @@ -124,11 +120,6 @@ class ElementsAccessor { virtual void Set(Handle<JSObject> holder, uint32_t entry, Object* value) = 0; - virtual void Reconfigure(Handle<JSObject> object, - Handle<FixedArrayBase> backing_store, uint32_t entry, - Handle<Object> value, - PropertyAttributes attributes) = 0; - virtual void Add(Handle<JSObject> object, uint32_t index, Handle<Object> value, PropertyAttributes attributes, uint32_t new_capacity) = 0; @@ -193,6 +184,15 @@ class ElementsAccessor { FixedArrayBase* backing_store, uint32_t index) = 0; + virtual PropertyDetails GetDetails(JSObject* holder, uint32_t entry) = 0; + virtual void Reconfigure(Handle<JSObject> object, + Handle<FixedArrayBase> backing_store, uint32_t entry, + Handle<Object> value, + PropertyAttributes attributes) = 0; + + // Deletes an element in an object. + virtual void Delete(Handle<JSObject> holder, uint32_t entry) = 0; + // NOTE: this method violates the handlified function signature convention: // raw pointer parameter |source_holder| in the function that allocates. // This is done intentionally to avoid ArrayConcat() builtin performance |