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

Unified Diff: src/keys.cc

Issue 1707743002: [key-accumulator] Starting to reimplement the key-accumulator (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: use proper type Created 4 years, 9 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/keys.h ('k') | src/objects.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/keys.cc
diff --git a/src/key-accumulator.cc b/src/keys.cc
similarity index 72%
rename from src/key-accumulator.cc
rename to src/keys.cc
index c2c49969229de3f603ea8494b4543696fef10855..dc696cf10e578ab35b11c4038ea5c274834c2294 100644
--- a/src/key-accumulator.cc
+++ b/src/keys.cc
@@ -2,26 +2,24 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "src/key-accumulator.h"
+#include "src/keys.h"
#include "src/elements.h"
#include "src/factory.h"
#include "src/isolate-inl.h"
#include "src/objects-inl.h"
#include "src/property-descriptor.h"
-
+#include "src/prototype.h"
namespace v8 {
namespace internal {
-
KeyAccumulator::~KeyAccumulator() {
for (size_t i = 0; i < elements_.size(); i++) {
delete elements_[i];
}
}
-
Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) {
if (length_ == 0) {
return isolate_->factory()->empty_fixed_array();
@@ -86,7 +84,6 @@ Handle<FixedArray> KeyAccumulator::GetKeys(GetKeysConversion convert) {
return result;
}
-
namespace {
bool AccumulatorHasKey(std::vector<uint32_t>* sub_elements, uint32_t key) {
@@ -99,7 +96,6 @@ bool KeyAccumulator::AddKey(Object* key, AddKeyConversion convert) {
return AddKey(handle(key, isolate_), convert);
}
-
bool KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) {
if (key->IsSymbol()) {
if (filter_ & SKIP_SYMBOLS) return false;
@@ -136,10 +132,8 @@ bool KeyAccumulator::AddKey(Handle<Object> key, AddKeyConversion convert) {
return AddStringKey(key, convert);
}
-
bool KeyAccumulator::AddKey(uint32_t key) { return AddIntegerKey(key); }
-
bool KeyAccumulator::AddIntegerKey(uint32_t key) {
// Make sure we do not add keys to a proxy-level (see AddKeysFromProxy).
// We mark proxy-levels with a negative length
@@ -154,7 +148,6 @@ bool KeyAccumulator::AddIntegerKey(uint32_t key) {
return true;
}
-
bool KeyAccumulator::AddStringKey(Handle<Object> key,
AddKeyConversion convert) {
if (string_properties_.is_null()) {
@@ -176,7 +169,6 @@ bool KeyAccumulator::AddStringKey(Handle<Object> key,
}
}
-
bool KeyAccumulator::AddSymbolKey(Handle<Object> key) {
if (symbol_properties_.is_null()) {
symbol_properties_ = OrderedHashSet::Allocate(isolate_, 16);
@@ -192,7 +184,6 @@ bool KeyAccumulator::AddSymbolKey(Handle<Object> key) {
}
}
-
void KeyAccumulator::AddKeys(Handle<FixedArray> array,
AddKeyConversion convert) {
int add_length = array->length();
@@ -203,7 +194,6 @@ void KeyAccumulator::AddKeys(Handle<FixedArray> array,
}
}
-
void KeyAccumulator::AddKeys(Handle<JSObject> array_like,
AddKeyConversion convert) {
DCHECK(array_like->IsJSArray() || array_like->HasSloppyArgumentsElements());
@@ -211,7 +201,6 @@ void KeyAccumulator::AddKeys(Handle<JSObject> array_like,
accessor->AddElementsToKeyAccumulator(array_like, this, convert);
}
-
void KeyAccumulator::AddKeysFromProxy(Handle<JSObject> array_like) {
// Proxies define a complete list of keys with no distinction of
// elements and properties, which breaks the normal assumption for the
@@ -223,7 +212,6 @@ void KeyAccumulator::AddKeysFromProxy(Handle<JSObject> array_like) {
level_string_length_ = -level_string_length_;
}
-
MaybeHandle<FixedArray> FilterProxyKeys(Isolate* isolate, Handle<JSProxy> owner,
Handle<FixedArray> keys,
PropertyFilter filter) {
@@ -253,7 +241,6 @@ MaybeHandle<FixedArray> FilterProxyKeys(Isolate* isolate, Handle<JSProxy> owner,
return keys;
}
-
// Returns "nothing" in case of exception, "true" on success.
Maybe<bool> KeyAccumulator::AddKeysFromProxy(Handle<JSProxy> proxy,
Handle<FixedArray> keys) {
@@ -277,7 +264,6 @@ Maybe<bool> KeyAccumulator::AddKeysFromProxy(Handle<JSProxy> proxy,
return Just(true);
}
-
void KeyAccumulator::AddElementKeysFromInterceptor(
Handle<JSObject> array_like) {
AddKeys(array_like, CONVERT_TO_ARRAY_INDEX);
@@ -286,7 +272,6 @@ void KeyAccumulator::AddElementKeysFromInterceptor(
SortCurrentElementsListRemoveDuplicates();
}
-
void KeyAccumulator::SortCurrentElementsListRemoveDuplicates() {
// Sort and remove duplicates from the current elements level and adjust.
// the lengths accordingly.
@@ -300,14 +285,12 @@ void KeyAccumulator::SortCurrentElementsListRemoveDuplicates() {
length_ -= static_cast<int>(nof_removed_keys);
}
-
void KeyAccumulator::SortCurrentElementsList() {
if (elements_.empty()) return;
auto element_keys = elements_.back();
std::sort(element_keys->begin(), element_keys->end());
}
-
void KeyAccumulator::NextPrototype() {
// Store the protoLength on the first call of this method.
if (!elements_.empty()) {
@@ -319,6 +302,125 @@ void KeyAccumulator::NextPrototype() {
level_symbol_length_ = 0;
}
+namespace {
+
+void TrySettingEmptyEnumCache(JSReceiver* object) {
+ Map* map = object->map();
+ DCHECK_EQ(kInvalidEnumCacheSentinel, map->EnumLength());
+ if (!map->OnlyHasSimpleProperties()) return;
+ if (map->IsJSProxyMap()) return;
+ if (map->NumberOfOwnDescriptors() > 0) {
+ int number_of_enumerable_own_properties =
+ map->NumberOfDescribedProperties(OWN_DESCRIPTORS, ENUMERABLE_STRINGS);
+ if (number_of_enumerable_own_properties > 0) return;
+ }
+ DCHECK(object->IsJSObject());
+ map->SetEnumLength(0);
+}
+
+bool CheckAndInitalizeSimpleEnumCache(JSReceiver* object) {
+ if (object->map()->EnumLength() == kInvalidEnumCacheSentinel) {
+ TrySettingEmptyEnumCache(object);
+ }
+ if (object->map()->EnumLength() != 0) return false;
+ DCHECK(object->IsJSObject());
+ return !JSObject::cast(object)->HasEnumerableElements();
+}
+} // namespace
+
+void FastKeyAccumulator::Prepare() {
+ DisallowHeapAllocation no_gc;
+ // Directly go for the fast path for OWN_ONLY keys.
+ if (type_ == OWN_ONLY) return;
+ // Fully walk the prototype chain and find the last prototype with keys.
+ is_receiver_simple_enum_ = false;
+ has_empty_prototype_ = true;
+ JSReceiver* first_non_empty_prototype;
+ for (PrototypeIterator iter(isolate_, *receiver_); !iter.IsAtEnd();
+ iter.Advance()) {
+ JSReceiver* current = iter.GetCurrent<JSReceiver>();
+ if (CheckAndInitalizeSimpleEnumCache(current)) continue;
+ has_empty_prototype_ = false;
+ first_non_empty_prototype = current;
+ // TODO(cbruni): use the first non-empty prototype.
+ USE(first_non_empty_prototype);
+ return;
+ }
+ DCHECK(has_empty_prototype_);
+ is_receiver_simple_enum_ =
+ receiver_->map()->EnumLength() != kInvalidEnumCacheSentinel &&
+ !JSObject::cast(*receiver_)->HasEnumerableElements();
+}
+
+namespace {
+Handle<FixedArray> GetOwnKeysWithElements(Isolate* isolate,
+ Handle<JSObject> object,
+ GetKeysConversion convert) {
+ Handle<FixedArray> keys = JSObject::GetFastEnumPropertyKeys(isolate, object);
+ ElementsAccessor* accessor = object->GetElementsAccessor();
+ return accessor->PrependElementIndices(object, keys, convert,
+ ONLY_ENUMERABLE);
+}
+
+MaybeHandle<FixedArray> GetOwnKeysWithUninitializedEnumCache(
+ Isolate* isolate, Handle<JSObject> object) {
+ // Uninitalized enum cache
+ Map* map = object->map();
+ if (object->elements() != isolate->heap()->empty_fixed_array() ||
+ object->elements() != isolate->heap()->empty_slow_element_dictionary()) {
+ // Assume that there are elements.
+ return MaybeHandle<FixedArray>();
+ }
+ int number_of_own_descriptors = map->NumberOfOwnDescriptors();
+ if (number_of_own_descriptors == 0) {
+ map->SetEnumLength(0);
+ return isolate->factory()->empty_fixed_array();
+ }
+ // We have no elements but possibly enumerable property keys, hence we can
+ // directly initialize the enum cache.
+ return JSObject::GetFastEnumPropertyKeys(isolate, object);
+}
+
+} // namespace
+
+MaybeHandle<FixedArray> FastKeyAccumulator::GetKeys(GetKeysConversion convert) {
+ Handle<FixedArray> keys;
+ if (GetKeysFast(convert).ToHandle(&keys)) {
+ return keys;
+ }
+ return GetKeysSlow(convert);
+}
+
+MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysFast(
+ GetKeysConversion convert) {
+ bool own_only = has_empty_prototype_ || type_ == OWN_ONLY;
+ if (!own_only || !receiver_->map()->OnlyHasSimpleProperties()) {
+ return MaybeHandle<FixedArray>();
+ }
+
+ Handle<FixedArray> keys;
+ DCHECK(receiver_->IsJSObject());
+ Handle<JSObject> object = Handle<JSObject>::cast(receiver_);
+
+ int enum_length = receiver_->map()->EnumLength();
+ if (enum_length == kInvalidEnumCacheSentinel) {
+ // Try initializing the enum cache and return own properties.
+ if (GetOwnKeysWithUninitializedEnumCache(isolate_, object)
+ .ToHandle(&keys)) {
+ is_receiver_simple_enum_ =
+ object->map()->EnumLength() != kInvalidEnumCacheSentinel;
+ return keys;
+ }
+ }
+ // The properties-only case failed because there were probably elements on the
+ // receiver.
+ return GetOwnKeysWithElements(isolate_, object, convert);
+}
+
+MaybeHandle<FixedArray> FastKeyAccumulator::GetKeysSlow(
+ GetKeysConversion convert) {
+ return JSReceiver::GetKeys(receiver_, type_, ENUMERABLE_STRINGS);
+}
} // namespace internal
} // namespace v8
« no previous file with comments | « src/keys.h ('k') | src/objects.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698