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

Unified Diff: src/objects.cc

Issue 1363293002: JSObject::GetEnumProperty cleanup (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: handlifying method Created 5 years, 3 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') | no next file » | 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 ca941ce4e21a0c6c0a6b6eb9cc54e8ffd3441054..172538c061601b64d8fbec4f4c3d80b52ec19d22 100644
--- a/src/objects.cc
+++ b/src/objects.cc
@@ -6612,91 +6612,90 @@ static Handle<FixedArray> ReduceFixedArrayTo(
}
-Handle<FixedArray> JSObject::GetEnumPropertyKeys(Handle<JSObject> object,
- 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);
- }
- }
+namespace {
- 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();
- if (cache_result) map->SetEnumLength(0);
- return isolate->factory()->empty_fixed_array();
+ if (cache_enum_length) map->SetEnumLength(own_property_count);
+ 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(
- own_property_count);
- Handle<FixedArray> indices = isolate->factory()->NewFixedArray(
- own_property_count);
+ isolate->counters()->enum_cache_misses()->Increment();
- Handle<DescriptorArray> descs =
- Handle<DescriptorArray>(object->map()->instance_descriptors(), isolate);
+ Handle<FixedArray> storage =
+ isolate->factory()->NewFixedArray(own_property_count);
+ Handle<FixedArray> indices =
+ isolate->factory()->NewFixedArray(own_property_count);
- int size = map->NumberOfOwnDescriptors();
- int index = 0;
+ int size = map->NumberOfOwnDescriptors();
+ int index = 0;
- for (int i = 0; i < size; i++) {
- PropertyDetails details = descs->GetDetails(i);
- Object* key = descs->GetKey(i);
- if (!(details.IsDontEnum() || key->IsSymbol())) {
- storage->set(index, key);
- if (!indices.is_null()) {
- if (details.type() != DATA) {
- indices = Handle<FixedArray>();
- } else {
- FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
- int load_by_field_index = field_index.GetLoadByFieldIndex();
- indices->set(index, Smi::FromInt(load_by_field_index));
- }
- }
- index++;
+ for (int i = 0; i < size; i++) {
+ PropertyDetails details = descs->GetDetails(i);
+ Object* key = descs->GetKey(i);
+ if (details.IsDontEnum() || key->IsSymbol()) continue;
+ storage->set(index, key);
+ if (!indices.is_null()) {
+ if (details.type() != DATA) {
+ indices = Handle<FixedArray>();
+ } else {
+ FieldIndex field_index = FieldIndex::ForDescriptor(*map, i);
+ int load_by_field_index = field_index.GetLoadByFieldIndex();
+ indices->set(index, Smi::FromInt(load_by_field_index));
}
}
- DCHECK(index == storage->length());
+ index++;
+ }
+ DCHECK(index == storage->length());
- Handle<FixedArray> bridge_storage =
- isolate->factory()->NewFixedArray(
- DescriptorArray::kEnumCacheBridgeLength);
- DescriptorArray* desc = object->map()->instance_descriptors();
- desc->SetEnumCache(*bridge_storage,
- *storage,
- indices.is_null() ? Object::cast(Smi::FromInt(0))
- : Object::cast(*indices));
- if (cache_result) {
- object->map()->SetEnumLength(own_property_count);
- }
- return storage;
+ DescriptorArray::SetEnumCache(descs, isolate, storage, indices);
+ if (cache_enum_length) {
+ map->SetEnumLength(own_property_count);
+ }
+ return storage;
+}
+
+} // 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->IsGlobalObject()) {
Handle<GlobalDictionary> dictionary(object->global_dictionary());
int length = dictionary->NumberOfEnumElements();
@@ -6900,14 +6899,14 @@ MaybeHandle<FixedArray> JSReceiver::GetKeys(Handle<JSReceiver> object,
// 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.
- bool cache_enum_keys =
+ bool cache_enum_length =
((current->map()->GetConstructor() != *arguments_function) &&
!current->IsJSValue() && !current->IsAccessCheckNeeded() &&
!current->HasNamedInterceptor() && !current->HasIndexedInterceptor());
// Compute the property keys and cache them if possible.
Handle<FixedArray> enum_keys =
- JSObject::GetEnumPropertyKeys(current, cache_enum_keys);
+ JSObject::GetEnumPropertyKeys(current, cache_enum_length);
accumulator.AddKeys(enum_keys, FixedArray::ALL_KEYS);
DCHECK(ContainsOnlyValidKeys(accumulator.GetKeys()));
@@ -8660,18 +8659,27 @@ void DescriptorArray::Replace(int index, Descriptor* descriptor) {
}
-void DescriptorArray::SetEnumCache(FixedArray* bridge_storage,
- FixedArray* new_cache,
- Object* new_index_cache) {
- DCHECK(bridge_storage->length() >= kEnumCacheBridgeLength);
- DCHECK(new_index_cache->IsSmi() || new_index_cache->IsFixedArray());
- DCHECK(!IsEmpty());
- DCHECK(!HasEnumCache() || new_cache->length() > GetEnumCache()->length());
- FixedArray::cast(bridge_storage)->
- set(kEnumCacheBridgeCacheIndex, new_cache);
- FixedArray::cast(bridge_storage)->
- set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache);
- set(kEnumCacheIndex, bridge_storage);
+// static
+void DescriptorArray::SetEnumCache(Handle<DescriptorArray> descriptors,
+ Isolate* isolate,
+ Handle<FixedArray> new_cache,
+ Handle<FixedArray> new_index_cache) {
+ DCHECK(!descriptors->IsEmpty());
+ FixedArray* bridge_storage;
+ bool needs_new_enum_cache = !descriptors->HasEnumCache();
+ if (needs_new_enum_cache) {
+ bridge_storage = *isolate->factory()->NewFixedArray(
+ DescriptorArray::kEnumCacheBridgeLength);
+ } else {
+ bridge_storage = FixedArray::cast(descriptors->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) {
+ descriptors->set(kEnumCacheIndex, bridge_storage);
+ }
}
« no previous file with comments | « src/objects.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698