Speed up non-interceptor case of Object.getOwnPropertyNames

When there are interceptors on an object, it's possible to
end up with duplicate property names. But when all the names
are provided by v8, a collision is not possible, so we can
fast-path that case by not de-duping.

Also added better test coverage for interceptor API.

Review URL: https://codereview.chromium.org/12314081

git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13725 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
adamk@chromium.org 2013-02-25 18:58:47 +00:00
parent cb5c8554c0
commit 30a4a798e5
2 changed files with 46 additions and 20 deletions

View File

@ -1018,9 +1018,13 @@ function ObjectGetOwnPropertyNames(obj) {
// Get the local element names. // Get the local element names.
var propertyNames = %GetLocalElementNames(obj); var propertyNames = %GetLocalElementNames(obj);
for (var i = 0; i < propertyNames.length; ++i) {
propertyNames[i] = %_NumberToString(propertyNames[i]);
}
// Get names for indexed interceptor properties. // Get names for indexed interceptor properties.
if (%GetInterceptorInfo(obj) & 1) { var interceptorInfo = %GetInterceptorInfo(obj);
if ((interceptorInfo & 1) != 0) {
var indexedInterceptorNames = var indexedInterceptorNames =
%GetIndexedInterceptorElementNames(obj); %GetIndexedInterceptorElementNames(obj);
if (indexedInterceptorNames) { if (indexedInterceptorNames) {
@ -1034,8 +1038,7 @@ function ObjectGetOwnPropertyNames(obj) {
propertyNames = propertyNames.concat(%GetLocalPropertyNames(obj)); propertyNames = propertyNames.concat(%GetLocalPropertyNames(obj));
// Get names for named interceptor properties if any. // Get names for named interceptor properties if any.
if ((interceptorInfo & 2) != 0) {
if (%GetInterceptorInfo(obj) & 2) {
var namedInterceptorNames = var namedInterceptorNames =
%GetNamedInterceptorPropertyNames(obj); %GetNamedInterceptorPropertyNames(obj);
if (namedInterceptorNames) { if (namedInterceptorNames) {
@ -1043,21 +1046,24 @@ function ObjectGetOwnPropertyNames(obj) {
} }
} }
// Property names are expected to be unique strings. // Property names are expected to be unique strings,
var propertySet = { __proto__: null }; // but interceptors can interfere with that assumption.
var j = 0; if (interceptorInfo != 0) {
for (var i = 0; i < propertyNames.length; ++i) { var propertySet = { __proto__: null };
var name = ToString(propertyNames[i]); var j = 0;
// We need to check for the exact property value since for intrinsic for (var i = 0; i < propertyNames.length; ++i) {
// properties like toString if(propertySet["toString"]) will always var name = ToString(propertyNames[i]);
// succeed. // We need to check for the exact property value since for intrinsic
if (propertySet[name] === true) { // properties like toString if(propertySet["toString"]) will always
continue; // succeed.
if (propertySet[name] === true) {
continue;
}
propertySet[name] = true;
propertyNames[j++] = name;
} }
propertySet[name] = true; propertyNames.length = j;
propertyNames[j++] = name;
} }
propertyNames.length = j;
return propertyNames; return propertyNames;
} }

View File

@ -7554,9 +7554,18 @@ THREADED_TEST(AccessControlGetOwnPropertyNames) {
} }
static v8::Handle<v8::Array> IndexedPropertyEnumerator(const AccessorInfo&) {
v8::Handle<v8::Array> result = v8::Array::New(2);
result->Set(0, v8::Integer::New(7));
result->Set(1, v8::Object::New());
return result;
}
static v8::Handle<v8::Array> NamedPropertyEnumerator(const AccessorInfo& info) { static v8::Handle<v8::Array> NamedPropertyEnumerator(const AccessorInfo& info) {
v8::Handle<v8::Array> result = v8::Array::New(1); v8::Handle<v8::Array> result = v8::Array::New(2);
result->Set(0, v8_str("x")); result->Set(0, v8_str("x"));
result->Set(1, v8::Object::New());
return result; return result;
} }
@ -7565,7 +7574,10 @@ THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
v8::HandleScope handle_scope; v8::HandleScope handle_scope;
v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New(); v8::Handle<v8::ObjectTemplate> obj_template = v8::ObjectTemplate::New();
obj_template->Set(v8_str("7"), v8::Integer::New(7));
obj_template->Set(v8_str("x"), v8::Integer::New(42)); obj_template->Set(v8_str("x"), v8::Integer::New(42));
obj_template->SetIndexedPropertyHandler(NULL, NULL, NULL, NULL,
IndexedPropertyEnumerator);
obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL, obj_template->SetNamedPropertyHandler(NULL, NULL, NULL, NULL,
NamedPropertyEnumerator); NamedPropertyEnumerator);
@ -7573,9 +7585,17 @@ THREADED_TEST(GetOwnPropertyNamesWithInterceptor) {
v8::Handle<v8::Object> global = context->Global(); v8::Handle<v8::Object> global = context->Global();
global->Set(v8_str("object"), obj_template->NewInstance()); global->Set(v8_str("object"), obj_template->NewInstance());
v8::Handle<Value> value = v8::Handle<v8::Value> result =
CompileRun("Object.getOwnPropertyNames(object).join(',')"); CompileRun("Object.getOwnPropertyNames(object)");
CHECK_EQ(v8_str("x"), value); CHECK(result->IsArray());
v8::Handle<v8::Array> result_array = v8::Handle<v8::Array>::Cast(result);
CHECK_EQ(3, result_array->Length());
CHECK(result_array->Get(0)->IsString());
CHECK(result_array->Get(1)->IsString());
CHECK(result_array->Get(2)->IsString());
CHECK_EQ(v8_str("7"), result_array->Get(0));
CHECK_EQ(v8_str("[object Object]"), result_array->Get(1));
CHECK_EQ(v8_str("x"), result_array->Get(2));
} }