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

Unified Diff: src/objects.cc

Issue 1612413003: Reland of [runtime] Do not use the enum-cache for non-prototype objects. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Created 4 years, 11 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/objects.h ('k') | test/mjsunit/regress/regress-705-shadowed_properties.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/objects.cc
diff --git a/src/objects.cc b/src/objects.cc
index 326b6f169ceb29b9c6364866bb21775fcbf73d3d..c0a0c08bc74d07b4e4308368fd8b543e568561d1 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -8098,8 +8098,8 @@
PropertyFilter filter = static_cast<PropertyFilter>(
ONLY_WRITABLE | ONLY_ENUMERABLE | ONLY_CONFIGURABLE);
KeyAccumulator accumulator(isolate, filter);
- accumulator.NextPrototype();
- copy->CollectOwnPropertyNames(&accumulator, filter);
+ accumulator.Prepare();
+ copy->CollectOwnPropertyKeys(&accumulator, filter);
Handle<FixedArray> names = accumulator.GetKeys();
for (int i = 0; i < names->length(); i++) {
DCHECK(names->get(i)->IsName());
@@ -8438,10 +8438,9 @@
namespace {
-Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
- Handle<JSObject> object,
+Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate, JSObject* object,
bool cache_enum_length) {
- Handle<Map> map(object->map());
+ Handle<Map> map(object->map(), isolate);
Handle<DescriptorArray> descs =
Handle<DescriptorArray>(map->instance_descriptors(), isolate);
int own_property_count = map->EnumLength();
@@ -8515,30 +8514,13 @@
} // namespace
-Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
- bool cache_enum_length) {
- Isolate* isolate = object->GetIsolate();
- if (object->HasFastProperties()) {
- return GetFastEnumPropertyKeys(isolate, object, cache_enum_length);
- } else if (object->IsJSGlobalObject()) {
- Handle<GlobalDictionary> dictionary(object->global_dictionary());
- int length = dictionary->NumberOfEnumElements();
- if (length == 0) {
- return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
- }
- Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
- dictionary->CopyEnumKeysTo(*storage);
- return storage;
- } else {
- Handle<NameDictionary> dictionary(object->property_dictionary());
- int length = dictionary->NumberOfEnumElements();
- if (length == 0) {
- return Handle<FixedArray>(isolate->heap()->empty_fixed_array());
- }
- Handle<FixedArray> storage = isolate->factory()->NewFixedArray(length);
- dictionary->CopyEnumKeysTo(*storage);
- return storage;
- }
+Handle<FixedArray> JSObject::GetOwnEnumPropertyKeys(Handle<JSObject> object,
+ bool cache_enum_length) {
+ PropertyFilter filter = PropertyFilter::ENUMERABLE_STRINGS;
+ KeyAccumulator keys(object->GetIsolate(), filter);
+ keys.Prepare();
+ object->CollectOwnPropertyKeys(&keys, filter);
+ return keys.GetKeys();
}
@@ -8622,30 +8604,7 @@
isolate, receiver, object, *filter, accumulator);
MAYBE_RETURN(success, Nothing<bool>());
- if (*filter == ENUMERABLE_STRINGS) {
- // We can cache the computed property keys if access checks are
- // not needed and no interceptors are involved.
- //
- // We do not use the cache if the object has elements and
- // therefore it does not make sense to cache the property names
- // for arguments objects. Arguments objects will always have
- // elements.
- // Wrapped strings have elements, but don't have an elements
- // array or dictionary. So the fast inline test for whether to
- // use the cache says yes, so we should not create a cache.
- Handle<JSFunction> arguments_function(
- JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
- bool cache_enum_length =
- ((object->map()->GetConstructor() != *arguments_function) &&
- !object->IsJSValue() && !object->IsAccessCheckNeeded() &&
- !object->HasNamedInterceptor() && !object->HasIndexedInterceptor());
- // Compute the property keys and cache them if possible.
- Handle<FixedArray> enum_keys =
- JSObject::GetEnumPropertyKeys(object, cache_enum_length);
- accumulator->AddKeys(enum_keys);
- } else {
- object->CollectOwnPropertyNames(accumulator, *filter);
- }
+ object->CollectOwnPropertyKeys(accumulator, *filter, type);
// Add the property keys from the interceptor.
success = GetKeysFromInterceptor<v8::GenericNamedPropertyEnumeratorCallback,
@@ -16381,24 +16340,74 @@
}
-void JSObject::CollectOwnPropertyNames(KeyAccumulator* keys,
- PropertyFilter filter) {
+namespace {
+
+void CollectEnumCacheTo(KeyAccumulator* keys, JSObject* object) {
+ // We can cache the computed property keys if access checks are
+ // not needed and no interceptors are involved.
+ //
+ // We do not use the cache if the object has elements and
+ // therefore it does not make sense to cache the property names
+ // for arguments objects. Arguments objects will always have
+ // elements.
+ // Wrapped strings have elements, but don't have an elements
+ // array or dictionary. So the fast inline test for whether to
+ // use the cache says yes, so we should not create a cache.
+ Isolate* isolate = keys->isolate();
+ Handle<JSFunction> arguments_function(
+ JSFunction::cast(isolate->sloppy_arguments_map()->GetConstructor()));
+ bool cache_enum_length =
+ ((object->map()->GetConstructor() != *arguments_function) &&
+ !object->IsJSValue() && !object->IsAccessCheckNeeded() &&
+ !object->HasNamedInterceptor() && !object->HasIndexedInterceptor());
+ // Compute the property keys and cache them if possible.
+ Handle<FixedArray> enum_keys =
+ GetFastEnumPropertyKeys(isolate, object, cache_enum_length);
+ keys->AddKeys(enum_keys);
+}
+
+} // namespace
+
+
+void JSObject::CollectFastPropertyKeysTo(KeyAccumulator* keys,
+ PropertyFilter filter,
+ JSReceiver::KeyCollectionType type) {
+ // Avoid using the enum cache if we have to walk the prototype chain due
+ // to shadowing properties.
+ if (filter == ENUMERABLE_STRINGS && type == JSReceiver::OWN_ONLY) {
+ CollectEnumCacheTo(keys, this);
+ return;
+ }
+
+ int real_size = map()->NumberOfOwnDescriptors();
+ Handle<DescriptorArray> descs(map()->instance_descriptors());
+ for (int i = 0; i < real_size; i++) {
+ PropertyDetails details = descs->GetDetails(i);
+ if ((details.attributes() & filter) != 0) {
+ if (type == JSReceiver::OWN_ONLY) continue;
+ if (details.attributes() & DONT_ENUM) {
+ keys->HideKey(descs->GetKey(i));
+ }
+ continue;
+ }
+ if (filter & ONLY_ALL_CAN_READ) {
+ if (details.kind() != kAccessor) continue;
+ Object* accessors = descs->GetValue(i);
+ if (!accessors->IsAccessorInfo()) continue;
+ if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
+ }
+ Name* key = descs->GetKey(i);
+ if (key->FilterKey(filter)) continue;
+ keys->AddKey(key);
+ }
+}
+
+
+void JSObject::CollectOwnPropertyKeys(KeyAccumulator* keys,
+ PropertyFilter filter,
+ JSReceiver::KeyCollectionType type) {
if (HasFastProperties()) {
- int real_size = map()->NumberOfOwnDescriptors();
- Handle<DescriptorArray> descs(map()->instance_descriptors());
- for (int i = 0; i < real_size; i++) {
- PropertyDetails details = descs->GetDetails(i);
- if ((details.attributes() & filter) != 0) continue;
- if (filter & ONLY_ALL_CAN_READ) {
- if (details.kind() != kAccessor) continue;
- Object* accessors = descs->GetValue(i);
- if (!accessors->IsAccessorInfo()) continue;
- if (!AccessorInfo::cast(accessors)->all_can_read()) continue;
- }
- Name* key = descs->GetKey(i);
- if (key->FilterKey(filter)) continue;
- keys->AddKey(key);
- }
+ CollectFastPropertyKeysTo(keys, filter, type);
} else if (IsJSGlobalObject()) {
GlobalDictionary::CollectKeysTo(handle(global_dictionary()), keys, filter);
} else {
@@ -18432,20 +18441,27 @@
void Dictionary<Derived, Shape, Key>::CollectKeysTo(
Handle<Dictionary<Derived, Shape, Key> > dictionary, KeyAccumulator* keys,
PropertyFilter filter) {
+ if (dictionary->NumberOfElements() == 0) return;
int capacity = dictionary->Capacity();
Handle<FixedArray> array =
keys->isolate()->factory()->NewFixedArray(dictionary->NumberOfElements());
int array_size = 0;
+ std::vector<int> hidden_key_indices;
{
DisallowHeapAllocation no_gc;
Dictionary<Derived, Shape, Key>* raw_dict = *dictionary;
for (int i = 0; i < capacity; i++) {
- Object* k = raw_dict->KeyAt(i);
- if (!raw_dict->IsKey(k) || k->FilterKey(filter)) continue;
+ Object* key = raw_dict->KeyAt(i);
+ if (!raw_dict->IsKey(key) || key->FilterKey(filter)) continue;
if (raw_dict->IsDeleted(i)) continue;
PropertyDetails details = raw_dict->DetailsAt(i);
- if ((details.attributes() & filter) != 0) continue;
+ if ((details.attributes() & filter) != 0) {
+ if (details.attributes() & DONT_ENUM) {
+ hidden_key_indices.push_back(i);
+ }
+ continue;
+ }
if (filter & ONLY_ALL_CAN_READ) {
if (details.kind() != kAccessor) continue;
Object* accessors = raw_dict->ValueAt(i);
@@ -18462,7 +18478,9 @@
Smi** start = reinterpret_cast<Smi**>(array->GetFirstElementAddress());
std::sort(start, start + array_size, cmp);
}
-
+ for (uint32_t i = 0; i < hidden_key_indices.size(); i++) {
+ keys->HideKey(dictionary->KeyAt(hidden_key_indices[i]));
+ }
for (int i = 0; i < array_size; i++) {
int index = Smi::cast(array->get(i))->value();
keys->AddKey(dictionary->KeyAt(index));
« no previous file with comments | « src/objects.h ('k') | test/mjsunit/regress/regress-705-shadowed_properties.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698