From 0fce2201b99f49c3e80c0f5d6e376493a3fe8936 Mon Sep 17 00:00:00 2001 From: "machenbach@chromium.org" Date: Thu, 18 Sep 2014 06:57:12 +0000 Subject: [PATCH] Revert "Don't use OwnPrototypeChainLength in GetOwnPropertyNames" This reverts commit r23997 for causing check failures in layout tests: http://build.chromium.org/p/client.v8/builders/V8-Blink%20Linux%2064%20%28dbg%29/builds/498 TBR=verwaest@chromium.org Review URL: https://codereview.chromium.org/581013003 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24018 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/objects.cc | 44 ++++++++++++++++++++++---------------------- src/objects.h | 12 +++++++----- src/runtime.cc | 53 +++++++++++++++++++++++++++++++++++++++++++---------- 3 files changed, 72 insertions(+), 37 deletions(-) diff --git a/src/objects.cc b/src/objects.cc index eb428aa..38b56d2 100644 --- a/src/objects.cc +++ b/src/objects.cc @@ -13346,24 +13346,23 @@ void FixedArray::SortPairs(FixedArray* numbers, uint32_t len) { // Fill in the names of own properties into the supplied storage. The main // purpose of this function is to provide reflection information for the object // mirrors. -int JSObject::GetOwnPropertyNames(FixedArray* storage, int index, - PropertyAttributes filter) { +void JSObject::GetOwnPropertyNames( + FixedArray* storage, int index, PropertyAttributes filter) { DCHECK(storage->length() >= (NumberOfOwnProperties(filter) - index)); if (HasFastProperties()) { - int offset = 0; int real_size = map()->NumberOfOwnDescriptors(); DescriptorArray* descs = map()->instance_descriptors(); for (int i = 0; i < real_size; i++) { if ((descs->GetDetails(i).attributes() & filter) == 0 && !FilterKey(descs->GetKey(i), filter)) { - storage->set(index + offset, descs->GetKey(i)); - offset++; + storage->set(index++, descs->GetKey(i)); } } - return offset; } else { - return property_dictionary()->CopyKeysTo(storage, index, filter, - NameDictionary::UNSORTED); + property_dictionary()->CopyKeysTo(storage, + index, + filter, + NameDictionary::UNSORTED); } } @@ -14056,11 +14055,13 @@ template Handle HashTable:: Shrink(Handle, uint32_t); -template int - Dictionary >::CopyKeysTo( - FixedArray*, int, PropertyAttributes, - Dictionary >::SortMode); +template void Dictionary >:: + CopyKeysTo( + FixedArray*, + int, + PropertyAttributes, + Dictionary< + NameDictionary, NameDictionaryShape, Handle >::SortMode); template int Dictionary >:: @@ -15207,28 +15208,27 @@ void NameDictionary::CopyEnumKeysTo(FixedArray* storage) { } -template -int Dictionary::CopyKeysTo( - FixedArray* storage, int index, PropertyAttributes filter, +template +void Dictionary::CopyKeysTo( + FixedArray* storage, + int index, + PropertyAttributes filter, typename Dictionary::SortMode sort_mode) { DCHECK(storage->length() >= NumberOfElementsFilterAttributes(filter)); int capacity = DerivedHashTable::Capacity(); - int offset = 0; for (int i = 0; i < capacity; i++) { Object* k = DerivedHashTable::KeyAt(i); if (DerivedHashTable::IsKey(k) && !FilterKey(k, filter)) { PropertyDetails details = DetailsAt(i); if (details.IsDeleted()) continue; PropertyAttributes attr = details.attributes(); - if ((attr & filter) == 0) storage->set(index + offset, k); - offset++; + if ((attr & filter) == 0) storage->set(index++, k); } } if (sort_mode == Dictionary::SORTED) { - storage->SortPairs(storage, index + offset); + storage->SortPairs(storage, index); } - DCHECK(storage->length() >= index + offset); - return offset; + DCHECK(storage->length() >= index); } diff --git a/src/objects.h b/src/objects.h index fb282c9..5e46502 100644 --- a/src/objects.h +++ b/src/objects.h @@ -2328,9 +2328,9 @@ class JSObject: public JSReceiver { // with the specified attributes (ignoring interceptors). int NumberOfOwnProperties(PropertyAttributes filter = NONE); // Fill in details for properties into storage starting at the specified - // index. Returns the number of properties that were added. - int GetOwnPropertyNames(FixedArray* storage, int index, - PropertyAttributes filter = NONE); + // index. + void GetOwnPropertyNames( + FixedArray* storage, int index, PropertyAttributes filter = NONE); // Returns the number of properties on this object filtering out properties // with the specified attributes (ignoring interceptors). @@ -3863,8 +3863,10 @@ class Dictionary: public HashTable { PropertyAttributes filter, SortMode sort_mode); // Fill in details for properties into storage. - int CopyKeysTo(FixedArray* storage, int index, PropertyAttributes filter, - SortMode sort_mode); + void CopyKeysTo(FixedArray* storage, + int index, + PropertyAttributes filter, + SortMode sort_mode); // Accessors for next enumeration index. void SetNextEnumerationIndex(int index) { diff --git a/src/runtime.cc b/src/runtime.cc index 4c8723c..23360fe 100644 --- a/src/runtime.cc +++ b/src/runtime.cc @@ -5753,6 +5753,19 @@ RUNTIME_FUNCTION(Runtime_GetPropertyNamesFast) { } +// Find the length of the prototype chain that is to be handled as one. If a +// prototype object is hidden it is to be viewed as part of the the object it +// is prototype for. +static int OwnPrototypeChainLength(JSObject* obj) { + int count = 1; + for (PrototypeIterator iter(obj->GetIsolate(), obj); + !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) { + count++; + } + return count; +} + + // Return the names of the own named properties. // args[0]: object // args[1]: PropertyAttributes as int @@ -5766,12 +5779,30 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { CONVERT_SMI_ARG_CHECKED(filter_value, 1); PropertyAttributes filter = static_cast(filter_value); + // Skip the global proxy as it has no properties and always delegates to the + // real global object. + if (obj->IsJSGlobalProxy()) { + // Only collect names if access is permitted. + if (obj->IsAccessCheckNeeded() && + !isolate->MayNamedAccess( + obj, isolate->factory()->undefined_value(), v8::ACCESS_KEYS)) { + isolate->ReportFailedAccessCheck(obj, v8::ACCESS_KEYS); + RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); + return *isolate->factory()->NewJSArray(0); + } + PrototypeIterator iter(isolate, obj); + obj = Handle::cast(PrototypeIterator::GetCurrent(iter)); + } + + // Find the number of objects making up this. + int length = OwnPrototypeChainLength(*obj); + // Find the number of own properties for each of the objects. + ScopedVector own_property_count(length); int total_property_count = 0; { PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); - for (; !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); - iter.Advance()) { + for (int i = 0; i < length; i++) { DCHECK(!iter.IsAtEnd()); Handle jsproto = Handle::cast(PrototypeIterator::GetCurrent(iter)); @@ -5786,7 +5817,9 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { } int n; n = jsproto->NumberOfOwnProperties(filter); + own_property_count[i] = n; total_property_count += n; + iter.Advance(); } } @@ -5799,18 +5832,17 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { int hidden_strings = 0; { PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER); - for (; !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); - iter.Advance()) { + for (int i = 0; i < length; i++) { + DCHECK(!iter.IsAtEnd()); Handle jsproto = Handle::cast(PrototypeIterator::GetCurrent(iter)); - int own_property_count = - jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); - if (!jsproto.is_identical_to(obj)) { + jsproto->GetOwnPropertyNames(*names, next_copy_index, filter); + if (i > 0) { // Names from hidden prototypes may already have been added // for inherited function template instances. Count the duplicates // and stub them out; the final copy pass at the end ignores holes. - for (int j = next_copy_index; j < next_copy_index + own_property_count; - j++) { + for (int j = next_copy_index; + j < next_copy_index + own_property_count[i]; j++) { Object* name_from_hidden_proto = names->get(j); for (int k = 0; k < next_copy_index; k++) { if (names->get(k) != isolate->heap()->hidden_string()) { @@ -5824,12 +5856,13 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) { } } } - next_copy_index += own_property_count; + next_copy_index += own_property_count[i]; // Hidden properties only show up if the filter does not skip strings. if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) { hidden_strings++; } + iter.Advance(); } } -- 2.7.4