Don't use OwnPrototypeChainLength in GetOwnPropertyNames
BUG= R=ishell@chromium.org Review URL: https://codereview.chromium.org/574753002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@23997 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ac1b9b11dc
commit
d0ad526359
@ -13346,23 +13346,24 @@ 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.
|
||||
void JSObject::GetOwnPropertyNames(
|
||||
FixedArray* storage, int index, PropertyAttributes filter) {
|
||||
int 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++, descs->GetKey(i));
|
||||
storage->set(index + offset, descs->GetKey(i));
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
} else {
|
||||
property_dictionary()->CopyKeysTo(storage,
|
||||
index,
|
||||
filter,
|
||||
NameDictionary::UNSORTED);
|
||||
return property_dictionary()->CopyKeysTo(storage, index, filter,
|
||||
NameDictionary::UNSORTED);
|
||||
}
|
||||
}
|
||||
|
||||
@ -14055,13 +14056,11 @@ template Handle<SeededNumberDictionary>
|
||||
HashTable<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
|
||||
Shrink(Handle<SeededNumberDictionary>, uint32_t);
|
||||
|
||||
template void Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
|
||||
CopyKeysTo(
|
||||
FixedArray*,
|
||||
int,
|
||||
PropertyAttributes,
|
||||
Dictionary<
|
||||
NameDictionary, NameDictionaryShape, Handle<Name> >::SortMode);
|
||||
template int
|
||||
Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::CopyKeysTo(
|
||||
FixedArray*, int, PropertyAttributes,
|
||||
Dictionary<NameDictionary, NameDictionaryShape,
|
||||
Handle<Name> >::SortMode);
|
||||
|
||||
template int
|
||||
Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
|
||||
@ -15208,27 +15207,28 @@ void NameDictionary::CopyEnumKeysTo(FixedArray* storage) {
|
||||
}
|
||||
|
||||
|
||||
template<typename Derived, typename Shape, typename Key>
|
||||
void Dictionary<Derived, Shape, Key>::CopyKeysTo(
|
||||
FixedArray* storage,
|
||||
int index,
|
||||
PropertyAttributes filter,
|
||||
template <typename Derived, typename Shape, typename Key>
|
||||
int Dictionary<Derived, Shape, Key>::CopyKeysTo(
|
||||
FixedArray* storage, int index, PropertyAttributes filter,
|
||||
typename Dictionary<Derived, Shape, Key>::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++, k);
|
||||
if ((attr & filter) == 0) storage->set(index + offset, k);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
if (sort_mode == Dictionary::SORTED) {
|
||||
storage->SortPairs(storage, index);
|
||||
storage->SortPairs(storage, index + offset);
|
||||
}
|
||||
DCHECK(storage->length() >= index);
|
||||
DCHECK(storage->length() >= index + offset);
|
||||
return offset;
|
||||
}
|
||||
|
||||
|
||||
|
@ -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.
|
||||
void GetOwnPropertyNames(
|
||||
FixedArray* storage, int index, PropertyAttributes filter = NONE);
|
||||
// index. Returns the number of properties that were added.
|
||||
int 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,10 +3863,8 @@ class Dictionary: public HashTable<Derived, Shape, Key> {
|
||||
PropertyAttributes filter,
|
||||
SortMode sort_mode);
|
||||
// Fill in details for properties into storage.
|
||||
void CopyKeysTo(FixedArray* storage,
|
||||
int index,
|
||||
PropertyAttributes filter,
|
||||
SortMode sort_mode);
|
||||
int CopyKeysTo(FixedArray* storage, int index, PropertyAttributes filter,
|
||||
SortMode sort_mode);
|
||||
|
||||
// Accessors for next enumeration index.
|
||||
void SetNextEnumerationIndex(int index) {
|
||||
|
@ -5744,19 +5744,6 @@ 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
|
||||
@ -5770,30 +5757,12 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
||||
CONVERT_SMI_ARG_CHECKED(filter_value, 1);
|
||||
PropertyAttributes filter = static_cast<PropertyAttributes>(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<JSObject>::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<int> own_property_count(length);
|
||||
int total_property_count = 0;
|
||||
{
|
||||
PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
|
||||
for (int i = 0; i < length; i++) {
|
||||
for (; !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN);
|
||||
iter.Advance()) {
|
||||
DCHECK(!iter.IsAtEnd());
|
||||
Handle<JSObject> jsproto =
|
||||
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
||||
@ -5808,9 +5777,7 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
||||
}
|
||||
int n;
|
||||
n = jsproto->NumberOfOwnProperties(filter);
|
||||
own_property_count[i] = n;
|
||||
total_property_count += n;
|
||||
iter.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
@ -5823,17 +5790,18 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
||||
int hidden_strings = 0;
|
||||
{
|
||||
PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
|
||||
for (int i = 0; i < length; i++) {
|
||||
DCHECK(!iter.IsAtEnd());
|
||||
for (; !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN);
|
||||
iter.Advance()) {
|
||||
Handle<JSObject> jsproto =
|
||||
Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
||||
jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
|
||||
if (i > 0) {
|
||||
int own_property_count =
|
||||
jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
|
||||
if (!jsproto.is_identical_to(obj)) {
|
||||
// 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[i]; j++) {
|
||||
for (int j = next_copy_index; j < next_copy_index + own_property_count;
|
||||
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()) {
|
||||
@ -5847,13 +5815,12 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
||||
}
|
||||
}
|
||||
}
|
||||
next_copy_index += own_property_count[i];
|
||||
next_copy_index += own_property_count;
|
||||
|
||||
// Hidden properties only show up if the filter does not skip strings.
|
||||
if ((filter & STRING) == 0 && JSObject::HasHiddenProperties(jsproto)) {
|
||||
hidden_strings++;
|
||||
}
|
||||
iter.Advance();
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user