Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(345)

Unified Diff: src/elements.cc

Issue 1707743002: [key-accumulator] Starting to reimplement the key-accumulator (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: WIP fast path for collecting receiver-only elements Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « src/elements.h ('k') | src/key-accumulator.h » ('j') | src/key-accumulator.cc » ('J')
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/elements.cc
diff --git a/src/elements.cc b/src/elements.cc
index e6d3f84f9ce8eec80bec76695220f6ff392c2787..409fc9cf9194a57c41b32b3aef474c3ea4b2d735 100644
--- a/src/elements.cc
+++ b/src/elements.cc
@@ -428,6 +428,14 @@ static void CopyDictionaryToDoubleElements(FixedArrayBase* from_base,
}
}
+Handle<FixedArray> EnsureSize(Isolate* isolate, Handle<FixedArray> array,
+ int size) {
+ int length = array->length();
+ if (size < length) return array;
+ int new_capacity = length + length / 2;
+ int grow_by = new_capacity - length;
+ return isolate->factory()->CopyFixedArrayAndGrow(array, grow_by);
+}
static void TraceTopFrame(Isolate* isolate) {
StackFrameIterator it(isolate);
@@ -727,6 +735,16 @@ class ElementsAccessorBase : public ElementsAccessor {
JSObject::ValidateElements(array);
}
+ static uint32_t GetIterationLength(JSObject* receiver,
+ FixedArrayBase* elements) {
+ if (receiver->IsJSArray()) {
+ return static_cast<uint32_t>(
+ Smi::cast(JSArray::cast(receiver)->length())->value());
+ } else {
+ return ElementsAccessorSubclass::GetCapacityImpl(receiver, elements);
+ }
+ }
+
static Handle<FixedArrayBase> ConvertElementsWithCapacity(
Handle<JSObject> object, Handle<FixedArrayBase> old_elements,
ElementsKind from_kind, uint32_t capacity) {
@@ -843,6 +861,14 @@ class ElementsAccessorBase : public ElementsAccessor {
from, from_start, *to, from_kind, to_start, packed_size, copy_size);
}
+ void CollectElementIndices(Handle<JSObject> object,
+ Handle<FixedArrayBase> backing_store,
+ KeyAccumulator* keys, uint32_t range,
+ PropertyFilter filter, uint32_t offset) final {
+ ElementsAccessorSubclass::CollectElementIndicesImpl(
+ object, backing_store, keys, range, filter, offset);
+ }
+
static void CollectElementIndicesImpl(Handle<JSObject> object,
Handle<FixedArrayBase> backing_store,
KeyAccumulator* keys, uint32_t range,
@@ -853,30 +879,115 @@ class ElementsAccessorBase : public ElementsAccessor {
// Non-dictionary elements can't have all-can-read accessors.
return;
}
- uint32_t length = 0;
- if (object->IsJSArray()) {
- length = Smi::cast(JSArray::cast(*object)->length())->value();
- } else {
- length =
- ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store);
- }
+ uint32_t length = GetIterationLength(*object, *backing_store);
if (range < length) length = range;
for (uint32_t i = offset; i < length; i++) {
- if (!ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
- filter)) {
- continue;
+ if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
+ filter)) {
+ keys->AddKey(i);
}
- keys->AddKey(i);
}
}
- void CollectElementIndices(Handle<JSObject> object,
- Handle<FixedArrayBase> backing_store,
- KeyAccumulator* keys, uint32_t range,
- PropertyFilter filter, uint32_t offset) final {
- ElementsAccessorSubclass::CollectElementIndicesImpl(
- object, backing_store, keys, range, filter, offset);
- };
+ static Handle<FixedArray> FastCollectElementIndicesImpl(
+ Isolate* isolate, Handle<JSObject> object,
+ Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
+ PropertyFilter filter, Handle<FixedArray> list, int* nof_indices) {
+ uint32_t length =
+ ElementsAccessorSubclass::GetIterationLength(*object, *backing_store);
+ int insertion_index = 0;
+ for (uint32_t i = 0; i < length; i++) {
+ if (IsFastPackedElementsKind(kind())) {
Toon Verwaest 2016/02/24 15:07:06 HasElementImpl should just return true for packed
+ if (convert == CONVERT_TO_STRING) {
+ list->set(insertion_index++, *isolate->factory()->Uint32ToString(i));
+ } else {
+ list->set(insertion_index++, Smi::FromInt(i), SKIP_WRITE_BARRIER);
+ }
+ } else {
+ if (ElementsAccessorSubclass::HasElementImpl(object, i, backing_store,
+ filter)) {
+ list = EnsureSize(isolate, list, insertion_index);
+ if (convert == CONVERT_TO_STRING) {
+ list->set(insertion_index++,
+ *isolate->factory()->Uint32ToString(i));
+ } else {
+ list->set(insertion_index++, Smi::FromInt(i), SKIP_WRITE_BARRIER);
+ }
+ }
+ }
+ }
+ *nof_indices = insertion_index;
+ return list;
+ }
+
+ Handle<FixedArray> PrependElementIndices(Handle<JSObject> object,
+ Handle<FixedArrayBase> backing_store,
+ Handle<FixedArray> keys,
+ GetKeysConversion convert,
+ PropertyFilter filter) final {
+ return ElementsAccessorSubclass::PrependElementIndicesImpl(
+ object, backing_store, keys, convert, filter);
+ }
+
+ Handle<FixedArray> PrependElementIndicesImpl(
+ Handle<JSObject> object, Handle<FixedArrayBase> backing_store,
+ Handle<FixedArray> keys, GetKeysConversion convert,
+ PropertyFilter filter) {
+ if (!IsDictionaryElementsKind(kind()) && filter & ONLY_ALL_CAN_READ) {
Toon Verwaest 2016/02/24 15:07:06 There are no ALL_CAN_READ indexed properties that
+ // Non-dictionary elements can't have all-can-read accessors.
+ return keys;
+ }
+
+ Isolate* isolate = object->GetIsolate();
+ int nof_property_keys = keys->length();
+
+ // Calculate the initial list size depending on the object at hand.
+ int initial_list_length = 10;
Toon Verwaest 2016/02/24 15:07:06 Why not immediately use Capacity + nof_property_ke
+ if (IsFastPackedElementsKind(kind())) {
+ initial_list_length =
+ ElementsAccessorSubclass::GetCapacityImpl(*object, *backing_store);
+ initial_list_length += nof_property_keys;
+ }
+
+ // Collect the element indices into a new list.
+ int nof_indices = 0;
+ Handle<FixedArray> combined_keys =
+ isolate->factory()->NewFixedArray(initial_list_length);
+ combined_keys = ElementsAccessorSubclass::FastCollectElementIndicesImpl(
+ isolate, object, backing_store, convert, filter, combined_keys,
+ &nof_indices);
+
+ // Sort the indices list if necessary.
+ if (kind() == DICTIONARY_ELEMENTS) {
+ struct {
+ bool operator()(Object* a, Object* b) {
Toon Verwaest 2016/02/24 15:07:06 return a->Number() < b->Number()? Seems like doub
+ if (a->IsSmi()) {
+ if (!b->IsSmi()) return true;
+ return Smi::cast(a)->value() < Smi::cast(b)->value();
+ }
+ return !b->IsSmi();
+ }
+ } cmp;
+ Object** start =
+ reinterpret_cast<Object**>(combined_keys->GetFirstElementAddress());
+ std::sort(start, start + nof_indices, cmp);
+ }
+
+ // Shrink/Grow the combined_keys to the final size.
+ int final_size = nof_indices + nof_property_keys;
+ if (combined_keys->length() < final_size) {
+ combined_keys = isolate->factory()->CopyFixedArrayAndGrow(
+ combined_keys, final_size - combined_keys->length());
+ } else {
+ combined_keys->Shrink(final_size);
+ }
+
+ // Copy over the property keys.
+ ElementsKind kind = FAST_HOLEY_ELEMENTS;
Toon Verwaest 2016/02/24 15:07:06 I guess it doesn't change anything, but this shoul
+ CopyObjectToObjectElements(*keys, kind, 0, *combined_keys, kind,
+ nof_indices, nof_property_keys);
+ return combined_keys;
+ }
void AddElementsToKeyAccumulator(Handle<JSObject> receiver,
KeyAccumulator* accumulator,
@@ -909,12 +1020,7 @@ class ElementsAccessorBase : public ElementsAccessor {
? index
: kMaxUInt32;
} else {
- uint32_t length =
- holder->IsJSArray()
- ? static_cast<uint32_t>(
- Smi::cast(JSArray::cast(holder)->length())->value())
- : ElementsAccessorSubclass::GetCapacityImpl(holder,
- backing_store);
+ uint32_t length = GetIterationLength(holder, backing_store);
return index < length ? index : kMaxUInt32;
}
}
@@ -1116,6 +1222,27 @@ class DictionaryElementsAccessor
return SeededNumberDictionary::cast(backing_store)->DetailsAt(entry);
}
+ static uint32_t GetKeyForEntryImpl(Handle<SeededNumberDictionary> dictionary,
+ int entry, PropertyFilter filter) {
+ Object* raw_key = dictionary->KeyAt(entry);
+ if (!dictionary->IsKey(raw_key)) return kMaxUInt32;
+ if (raw_key->FilterKey(filter)) return kMaxUInt32;
+ if (dictionary->IsDeleted(entry)) return kMaxUInt32;
+ DCHECK(raw_key->IsNumber());
+ DCHECK_LE(raw_key->Number(), kMaxUInt32);
+ uint32_t key = static_cast<uint32_t>(raw_key->Number());
+ PropertyDetails details = dictionary->DetailsAt(entry);
+ if (filter & ONLY_ALL_CAN_READ) {
+ if (details.kind() != kAccessor) return kMaxUInt32;
+ Object* accessors = dictionary->ValueAt(entry);
+ if (!accessors->IsAccessorInfo()) return kMaxUInt32;
+ if (!AccessorInfo::cast(accessors)->all_can_read()) return kMaxUInt32;
+ }
+ PropertyAttributes attr = details.attributes();
+ if ((attr & filter) != 0) return kMaxUInt32;
+ return key;
+ }
+
static void CollectElementIndicesImpl(Handle<JSObject> object,
Handle<FixedArrayBase> backing_store,
KeyAccumulator* keys, uint32_t range,
@@ -1125,29 +1252,37 @@ class DictionaryElementsAccessor
Handle<SeededNumberDictionary>::cast(backing_store);
int capacity = dictionary->Capacity();
for (int i = 0; i < capacity; i++) {
- Object* k = dictionary->KeyAt(i);
- if (!dictionary->IsKey(k)) continue;
- if (k->FilterKey(filter)) continue;
- if (dictionary->IsDeleted(i)) continue;
- DCHECK(k->IsNumber());
- DCHECK_LE(k->Number(), kMaxUInt32);
- uint32_t index = static_cast<uint32_t>(k->Number());
- if (index < offset) continue;
- PropertyDetails details = dictionary->DetailsAt(i);
- if (filter & ONLY_ALL_CAN_READ) {
- if (details.kind() != kAccessor) continue;
- Object* accessors = dictionary->ValueAt(i);
- if (!accessors->IsAccessorInfo()) continue;
- if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
- }
- PropertyAttributes attr = details.attributes();
- if ((attr & filter) != 0) continue;
- keys->AddKey(index);
+ uint32_t key = GetKeyForEntryImpl(dictionary, i, filter);
+ if (key == kMaxUInt32) continue;
+ keys->AddKey(key);
}
keys->SortCurrentElementsList();
}
+ static Handle<FixedArray> FastCollectElementIndicesImpl(
+ Isolate* isolate, Handle<JSObject> object,
+ Handle<FixedArrayBase> backing_store, GetKeysConversion convert,
+ PropertyFilter filter, Handle<FixedArray> list, int* nof_indices) {
+ Handle<SeededNumberDictionary> dictionary =
+ Handle<SeededNumberDictionary>::cast(backing_store);
+
+ int capacity = dictionary->Capacity();
+ int insertion_index = 0;
+ for (uint32_t i = 0; i < capacity; i++) {
+ uint32_t key = GetKeyForEntryImpl(dictionary, i, filter);
+ if (key == kMaxUInt32) continue;
+ list = EnsureSize(isolate, list, insertion_index);
+ if (convert == CONVERT_TO_STRING) {
+ list->set(insertion_index++, *isolate->factory()->Uint32ToString(key));
+ } else {
+ list->set(insertion_index++, Smi::FromInt(key), SKIP_WRITE_BARRIER);
+ }
+ }
+ *nof_indices = insertion_index;
+ return list;
+ }
+
static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
KeyAccumulator* accumulator,
AddKeyConversion convert) {
@@ -1312,15 +1447,10 @@ class FastElementsAccessor
static void AddElementsToKeyAccumulatorImpl(Handle<JSObject> receiver,
KeyAccumulator* accumulator,
AddKeyConversion convert) {
- uint32_t length = 0;
Handle<FixedArrayBase> elements(receiver->elements(),
receiver->GetIsolate());
- if (receiver->IsJSArray()) {
- length = Smi::cast(JSArray::cast(*receiver)->length())->value();
- } else {
- length =
- FastElementsAccessorSubclass::GetCapacityImpl(*receiver, *elements);
- }
+ uint32_t length =
+ FastElementsAccessorSubclass::GetIterationLength(*receiver, *elements);
for (uint32_t i = 0; i < length; i++) {
if (IsFastPackedElementsKind(KindTraits::Kind) ||
HasEntryImpl(*elements, i)) {
« no previous file with comments | « src/elements.h ('k') | src/key-accumulator.h » ('j') | src/key-accumulator.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698