Commit a00d47c8 authored by cbruni's avatar cbruni Committed by Commit bot

JSObject::GetEnumProperty cleanup

BUG=

Review URL: https://codereview.chromium.org/1363293002

Cr-Commit-Position: refs/heads/master@{#30946}
parent 7e283d74
...@@ -89,8 +89,7 @@ inline int FieldIndex::GetLoadByFieldIndex() const { ...@@ -89,8 +89,7 @@ inline int FieldIndex::GetLoadByFieldIndex() const {
inline FieldIndex FieldIndex::ForDescriptor(Map* map, int descriptor_index) { inline FieldIndex FieldIndex::ForDescriptor(Map* map, int descriptor_index) {
PropertyDetails details = PropertyDetails details =
map->instance_descriptors()->GetDetails(descriptor_index); map->instance_descriptors()->GetDetails(descriptor_index);
int field_index = int field_index = details.field_index();
map->instance_descriptors()->GetFieldIndex(descriptor_index);
return ForPropertyIndex(map, field_index, return ForPropertyIndex(map, field_index,
details.representation().IsDouble()); details.representation().IsDouble());
} }
......
...@@ -6568,91 +6568,90 @@ static Handle<FixedArray> ReduceFixedArrayTo( ...@@ -6568,91 +6568,90 @@ static Handle<FixedArray> ReduceFixedArrayTo(
} }
Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object, namespace {
bool cache_result) {
Isolate* isolate = object->GetIsolate();
if (object->HasFastProperties()) {
int own_property_count = object->map()->EnumLength();
// If the enum length of the given map is set to kInvalidEnumCache, this
// means that the map itself has never used the present enum cache. The
// first step to using the cache is to set the enum length of the map by
// counting the number of own descriptors that are not DONT_ENUM or
// SYMBOLIC.
if (own_property_count == kInvalidEnumCacheSentinel) {
own_property_count = object->map()->NumberOfDescribedProperties(
OWN_DESCRIPTORS, DONT_SHOW);
} else {
DCHECK(own_property_count == object->map()->NumberOfDescribedProperties(
OWN_DESCRIPTORS, DONT_SHOW));
}
if (object->map()->instance_descriptors()->HasEnumCache()) {
DescriptorArray* desc = object->map()->instance_descriptors();
Handle<FixedArray> keys(desc->GetEnumCache(), isolate);
// In case the number of properties required in the enum are actually
// present, we can reuse the enum cache. Otherwise, this means that the
// enum cache was generated for a previous (smaller) version of the
// Descriptor Array. In that case we regenerate the enum cache.
if (own_property_count <= keys->length()) {
if (cache_result) object->map()->SetEnumLength(own_property_count);
isolate->counters()->enum_cache_hits()->Increment();
return ReduceFixedArrayTo(keys, own_property_count);
}
}
Handle<Map> map(object->map()); Handle<FixedArray> GetFastEnumPropertyKeys(Isolate* isolate,
Handle<JSObject> object,
bool cache_enum_length) {
Handle<Map> map(object->map());
Handle<DescriptorArray> descs =
Handle<DescriptorArray>(map->instance_descriptors(), isolate);
int own_property_count = map->EnumLength();
// If the enum length of the given map is set to kInvalidEnumCache, this
// means that the map itself has never used the present enum cache. The
// first step to using the cache is to set the enum length of the map by
// counting the number of own descriptors that are not DONT_ENUM or
// SYMBOLIC.
if (own_property_count == kInvalidEnumCacheSentinel) {
own_property_count =
map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_SHOW);
} else {
DCHECK(own_property_count ==
map->NumberOfDescribedProperties(OWN_DESCRIPTORS, DONT_SHOW));
}
if (map->instance_descriptors()->IsEmpty()) { if (descs->HasEnumCache()) {
Handle<FixedArray> keys(descs->GetEnumCache(), isolate);
// In case the number of properties required in the enum are actually
// present, we can reuse the enum cache. Otherwise, this means that the
// enum cache was generated for a previous (smaller) version of the
// Descriptor Array. In that case we regenerate the enum cache.
if (own_property_count <= keys->length()) {
isolate->counters()->enum_cache_hits()->Increment(); isolate->counters()->enum_cache_hits()->Increment();
if (cache_result) map->SetEnumLength(0); if (cache_enum_length) map->SetEnumLength(own_property_count);
return isolate->factory()->empty_fixed_array(); return ReduceFixedArrayTo(keys, own_property_count);
} }
}
isolate->counters()->enum_cache_misses()->Increment(); if (descs->IsEmpty()) {
isolate->counters()->enum_cache_hits()->Increment();
if (cache_enum_length) map->SetEnumLength(0);
return isolate->factory()->empty_fixed_array();
}
Handle<FixedArray> storage = isolate->factory()->NewFixedArray( isolate->counters()->enum_cache_misses()->Increment();
own_property_count);
Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
own_property_count);
Handle<DescriptorArray> descs = Handle<FixedArray> storage =
Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate); isolate->factory()->NewFixedArray(own_property_count);
Handle<FixedArray> indices =
isolate->factory()->NewFixedArray(own_property_count);
int size = map->NumberOfOwnDescriptors(); int size = map->NumberOfOwnDescriptors();
int index = 0; int index = 0;
for (int i = 0; i < size; i++) { for (int i = 0; i < size; i++) {
PropertyDetails details = descs->GetDetails(i); PropertyDetails details = descs->GetDetails(i);
Object* key = descs->GetKey(i); Object* key = descs->GetKey(i);
if (!(details.IsDontEnum() || key->IsSymbol())) { if (details.IsDontEnum() || key->IsSymbol()) continue;
storage->set(index, key); storage->set(index, key);
if (!indices.is_null()) { if (!indices.is_null()) {
if (details.type() != DATA) { if (details.type() != DATA) {
indices = Handle<FixedArray>(); indices = Handle<FixedArray>();
} else { } else {
FieldIndex field_index = FieldIndex::ForDescriptor(*map, i); FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
int load_by_field_index = field_index.GetLoadByFieldIndex(); int load_by_field_index = field_index.GetLoadByFieldIndex();
indices->set(index, Smi::FromInt(load_by_field_index)); indices->set(index, Smi::FromInt(load_by_field_index));
}
}
index++;
} }
} }
DCHECK(index == storage->length()); index++;
}
DCHECK(index == storage->length());
Handle<FixedArray> bridge_storage = descs->SetEnumCache(isolate, storage, indices);
isolate->factory()->NewFixedArray( if (cache_enum_length) {
DescriptorArray::kEnumCacheBridgeLength); map->SetEnumLength(own_property_count);
DescriptorArray* desc = object->map()->instance_descriptors(); }
desc->SetEnumCache(*bridge_storage, return storage;
*storage, }
indices.is_null() ? Object::cast(Smi::FromInt(0))
: Object::cast(*indices)); } // namespace
if (cache_result) {
object->map()->SetEnumLength(own_property_count);
} Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
return storage; bool cache_enum_length) {
Isolate* isolate = object->GetIsolate();
if (object->HasFastProperties()) {
return GetFastEnumPropertyKeys(isolate, object, cache_enum_length);
} else if (object->IsGlobalObject()) { } else if (object->IsGlobalObject()) {
Handle<GlobalDictionary> dictionary(object->global_dictionary()); Handle<GlobalDictionary> dictionary(object->global_dictionary());
int length = dictionary->NumberOfEnumElements(); int length = dictionary->NumberOfEnumElements();
...@@ -6856,14 +6855,14 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object, ...@@ -6856,14 +6855,14 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
// Wrapped strings have elements, but don't have an elements // Wrapped strings have elements, but don't have an elements
// array or dictionary. So the fast inline test for whether to // array or dictionary. So the fast inline test for whether to
// use the cache says yes, so we should not create a cache. // use the cache says yes, so we should not create a cache.
bool cache_enum_keys = bool cache_enum_length =
((current->map()->GetConstructor() != *arguments_function) && ((current->map()->GetConstructor() != *arguments_function) &&
!current->IsJSValue() && !current->IsAccessCheckNeeded() && !current->IsJSValue() && !current->IsAccessCheckNeeded() &&
!current->HasNamedInterceptor() && !current->HasIndexedInterceptor()); !current->HasNamedInterceptor() && !current->HasIndexedInterceptor());
// Compute the property keys and cache them if possible. // Compute the property keys and cache them if possible.
Handle<FixedArray> enum_keys = Handle<FixedArray> enum_keys =
JSObject::GetEnumPropertyKeys(current, cache_enum_keys); JSObject::GetEnumPropertyKeys(current, cache_enum_length);
accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS); accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS);
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys())); DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
...@@ -8616,18 +8615,25 @@ void DescriptorArray::Replace(int index, Descriptor* descriptor) { ...@@ -8616,18 +8615,25 @@ void DescriptorArray::Replace(int index, Descriptor* descriptor) {
} }
void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, void DescriptorArray::SetEnumCache(Isolate* isolate,
FixedArray* new_cache, Handle<FixedArray> new_cache,
Object* new_index_cache) { Handle<FixedArray> new_index_cache) {
DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
DCHECK(!IsEmpty()); DCHECK(!IsEmpty());
DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length()); FixedArray* bridge_storage;
FixedArray::cast(bridge_storage)-> bool needs_new_enum_cache = !HasEnumCache();
set(kEnumCacheBridgeCacheIndex, new_cache); if (needs_new_enum_cache) {
FixedArray::cast(bridge_storage)-> bridge_storage = *isolate->factory()->NewFixedArray(
set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); DescriptorArray::kEnumCacheBridgeLength);
set(kEnumCacheIndex, bridge_storage); } else {
bridge_storage = FixedArray::cast(get(kEnumCacheIndex));
}
bridge_storage->set(kEnumCacheBridgeCacheIndex, *new_cache);
bridge_storage->set(kEnumCacheBridgeIndicesCacheIndex,
new_index_cache.is_null() ? Object::cast(Smi::FromInt(0))
: *new_index_cache);
if (needs_new_enum_cache) {
set(kEnumCacheIndex, bridge_storage);
}
} }
......
...@@ -2745,9 +2745,8 @@ class DescriptorArray: public FixedArray { ...@@ -2745,9 +2745,8 @@ class DescriptorArray: public FixedArray {
// Initialize or change the enum cache, // Initialize or change the enum cache,
// using the supplied storage for the small "bridge". // using the supplied storage for the small "bridge".
void SetEnumCache(FixedArray* bridge_storage, void SetEnumCache(Isolate* isolate, Handle<FixedArray> new_cache,
FixedArray* new_cache, Handle<FixedArray> new_index_cache);
Object* new_index_cache);
bool CanHoldValue(int descriptor, Object* value); bool CanHoldValue(int descriptor, Object* value);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment