| Index: src/runtime/runtime-object.cc
|
| diff --git a/src/runtime/runtime-object.cc b/src/runtime/runtime-object.cc
|
| index d0d215d43bb18b53fd6213974c81370517118da2..5bf1d078780b9ee8b9cbf4459ac7ce65eacd3b07 100644
|
| --- a/src/runtime/runtime-object.cc
|
| +++ b/src/runtime/runtime-object.cc
|
| @@ -810,19 +810,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
|
| @@ -832,47 +819,18 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
| if (!args[0]->IsJSObject()) {
|
| return isolate->heap()->undefined_value();
|
| }
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, obj, 0);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, object, 0);
|
| 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->MayAccess(obj)) {
|
| - isolate->ReportFailedAccessCheck(obj);
|
| - 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++) {
|
| - DCHECK(!iter.IsAtEnd());
|
| - Handle<JSObject> jsproto =
|
| - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
| - // Only collect names if access is permitted.
|
| - if (jsproto->IsAccessCheckNeeded() && !isolate->MayAccess(jsproto)) {
|
| - isolate->ReportFailedAccessCheck(jsproto);
|
| - RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate);
|
| - return *isolate->factory()->NewJSArray(0);
|
| - }
|
| - int n;
|
| - n = jsproto->NumberOfOwnProperties(filter);
|
| - own_property_count[i] = n;
|
| - total_property_count += n;
|
| - iter.Advance();
|
| - }
|
| + for (PrototypeIterator iter(isolate, object,
|
| + PrototypeIterator::START_AT_RECEIVER);
|
| + !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
|
| + Handle<JSObject> jsproto =
|
| + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
| + total_property_count += jsproto->NumberOfOwnProperties(filter);
|
| }
|
|
|
| // Allocate an array with storage for all the property names.
|
| @@ -882,53 +840,69 @@ RUNTIME_FUNCTION(Runtime_GetOwnPropertyNames) {
|
| // Get the property names.
|
| int next_copy_index = 0;
|
| int hidden_strings = 0;
|
| - {
|
| - PrototypeIterator iter(isolate, obj, PrototypeIterator::START_AT_RECEIVER);
|
| - for (int i = 0; i < length; i++) {
|
| - DCHECK(!iter.IsAtEnd());
|
| - Handle<JSObject> jsproto =
|
| - Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
| - jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
|
| - // 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++) {
|
| - Object* name_from_hidden_proto = names->get(j);
|
| - if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) {
|
| - hidden_strings++;
|
| - } else {
|
| - for (int k = 0; k < next_copy_index; k++) {
|
| - Object* name = names->get(k);
|
| - if (name_from_hidden_proto == name) {
|
| - names->set(j, isolate->heap()->hidden_string());
|
| - hidden_strings++;
|
| - break;
|
| - }
|
| + Handle<Object> hidden_string = isolate->factory()->hidden_string();
|
| + for (PrototypeIterator iter(isolate, object,
|
| + PrototypeIterator::START_AT_RECEIVER);
|
| + !iter.IsAtEnd(PrototypeIterator::END_AT_NON_HIDDEN); iter.Advance()) {
|
| + Handle<JSObject> jsproto =
|
| + Handle<JSObject>::cast(PrototypeIterator::GetCurrent(iter));
|
| + int own = jsproto->GetOwnPropertyNames(*names, next_copy_index, filter);
|
| + // 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; j++) {
|
| + Object* name_from_hidden_proto = names->get(j);
|
| + if (isolate->IsInternallyUsedPropertyName(name_from_hidden_proto)) {
|
| + hidden_strings++;
|
| + } else {
|
| + for (int k = 0; k < next_copy_index; k++) {
|
| + Object* name = names->get(k);
|
| + if (name_from_hidden_proto == name) {
|
| + names->set(j, *hidden_string);
|
| + hidden_strings++;
|
| + break;
|
| }
|
| }
|
| }
|
| - next_copy_index += own_property_count[i];
|
| + }
|
| + next_copy_index += own;
|
| + }
|
| +
|
| + CHECK_EQ(total_property_count, next_copy_index);
|
|
|
| - iter.Advance();
|
| + if (object->IsAccessCheckNeeded() && !isolate->MayAccess(object)) {
|
| + for (int i = 0; i < total_property_count; i++) {
|
| + Handle<Name> name(Name::cast(names->get(i)));
|
| + if (name.is_identical_to(hidden_string)) continue;
|
| + LookupIterator it(object, name, LookupIterator::HIDDEN_SKIP_INTERCEPTOR);
|
| + if (!JSObject::AllCanRead(&it)) {
|
| + names->set(i, *hidden_string);
|
| + hidden_strings++;
|
| + }
|
| }
|
| }
|
|
|
| // Filter out name of hidden properties object and
|
| // hidden prototype duplicates.
|
| if (hidden_strings > 0) {
|
| - Handle<FixedArray> old_names = names;
|
| - names = isolate->factory()->NewFixedArray(names->length() - hidden_strings);
|
| - int dest_pos = 0;
|
| - for (int i = 0; i < total_property_count; i++) {
|
| - Object* name = old_names->get(i);
|
| - if (isolate->IsInternallyUsedPropertyName(name)) {
|
| - hidden_strings--;
|
| - continue;
|
| + if (hidden_strings == total_property_count) {
|
| + names = isolate->factory()->empty_fixed_array();
|
| + } else {
|
| + int i;
|
| + for (i = 0; i < total_property_count; i++) {
|
| + Object* name = names->get(i);
|
| + if (name == *hidden_string) break;
|
| + }
|
| + int dest_pos = i;
|
| + for (; i < total_property_count; i++) {
|
| + Object* name = names->get(i);
|
| + if (name == *hidden_string) continue;
|
| + names->set(dest_pos++, name);
|
| }
|
| - names->set(dest_pos++, name);
|
| +
|
| + isolate->heap()->RightTrimFixedArray<Heap::CONCURRENT_TO_SWEEPER>(
|
| + *names, hidden_strings);
|
| }
|
| - DCHECK_EQ(0, hidden_strings);
|
| }
|
|
|
| return *isolate->factory()->NewJSArrayWithElements(names);
|
|
|