From 9e655afdb42487432a0569d1856175e695f8deed Mon Sep 17 00:00:00 2001 From: "jarin@chromium.org" Date: Fri, 28 Mar 2014 06:59:20 +0000 Subject: [PATCH] Reland "Fix property enum cache creation to include only own properties" Reland r20308 (reverted by r20310). TBR=verwaest@chromium.org Review URL: https://codereview.chromium.org/216383003 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@20321 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/handles.cc | 46 +++++++++++----------- .../regress/regress-enum-prop-keys-cache-size.js | 19 +++++++++ 2 files changed, 42 insertions(+), 23 deletions(-) create mode 100644 test/mjsunit/regress/regress-enum-prop-keys-cache-size.js diff --git a/src/handles.cc b/src/handles.cc index 398a682..c301537 100644 --- a/src/handles.cc +++ b/src/handles.cc @@ -627,20 +627,21 @@ Handle GetEnumPropertyKeys(Handle object, bool cache_result) { Isolate* isolate = object->GetIsolate(); if (object->HasFastProperties()) { - if (object->map()->instance_descriptors()->HasEnumCache()) { - int own_property_count = object->map()->EnumLength(); - // If we have an enum cache, but 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); - - if (cache_result) object->map()->SetEnumLength(own_property_count); - } + 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 { + ASSERT(own_property_count == object->map()->NumberOfDescribedProperties( + OWN_DESCRIPTORS, DONT_SHOW)); + } + if (object->map()->instance_descriptors()->HasEnumCache()) { DescriptorArray* desc = object->map()->instance_descriptors(); Handle keys(desc->GetEnumCache(), isolate); @@ -649,6 +650,7 @@ Handle GetEnumPropertyKeys(Handle object, // 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); } @@ -663,23 +665,22 @@ Handle GetEnumPropertyKeys(Handle object, } isolate->counters()->enum_cache_misses()->Increment(); - int num_enum = map->NumberOfDescribedProperties(ALL_DESCRIPTORS, DONT_SHOW); - Handle storage = isolate->factory()->NewFixedArray(num_enum); - Handle indices = isolate->factory()->NewFixedArray(num_enum); + Handle storage = isolate->factory()->NewFixedArray( + own_property_count); + Handle indices = isolate->factory()->NewFixedArray( + own_property_count); Handle descs = Handle(object->map()->instance_descriptors(), isolate); - int real_size = map->NumberOfOwnDescriptors(); - int enum_size = 0; + int size = map->NumberOfOwnDescriptors(); int index = 0; - for (int i = 0; i < descs->number_of_descriptors(); i++) { + for (int i = 0; i < size; i++) { PropertyDetails details = descs->GetDetails(i); Object* key = descs->GetKey(i); if (!(details.IsDontEnum() || key->IsSymbol())) { - if (i < real_size) ++enum_size; storage->set(index, key); if (!indices.is_null()) { if (details.type() != FIELD) { @@ -706,10 +707,9 @@ Handle GetEnumPropertyKeys(Handle object, indices.is_null() ? Object::cast(Smi::FromInt(0)) : Object::cast(*indices)); if (cache_result) { - object->map()->SetEnumLength(enum_size); + object->map()->SetEnumLength(own_property_count); } - - return ReduceFixedArrayTo(storage, enum_size); + return storage; } else { Handle dictionary(object->property_dictionary()); int length = dictionary->NumberOfEnumElements(); diff --git a/test/mjsunit/regress/regress-enum-prop-keys-cache-size.js b/test/mjsunit/regress/regress-enum-prop-keys-cache-size.js new file mode 100644 index 0000000..1227500 --- /dev/null +++ b/test/mjsunit/regress/regress-enum-prop-keys-cache-size.js @@ -0,0 +1,19 @@ +// Copyright 2014 the V8 project authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Flags: --allow-natives-syntax --stress-compaction + +%SetAllocationTimeout(100000, 100000); + +var x = {}; +x.a = 1; +x.b = 2; +x = {}; + +var y = {}; +y.a = 1; + +%SetAllocationTimeout(100000, 0); + +for (var z in y) { } -- 2.7.4