Index: src/runtime.cc |
diff --git a/src/runtime.cc b/src/runtime.cc |
index a175836adb2a8a83eaac8b3e0342ee2b19b4c8eb..713d4501ae5dfe521f6d28d743335366019db7a4 100644 |
--- a/src/runtime.cc |
+++ b/src/runtime.cc |
@@ -5801,32 +5801,55 @@ RUNTIME_FUNCTION(MaybeObject*, Runtime_GetLocalPropertyNames) { |
// Get the property names. |
jsproto = obj; |
- int proto_with_hidden_properties = 0; |
int next_copy_index = 0; |
+ int hidden_strings = 0; |
for (int i = 0; i < length; i++) { |
jsproto->GetLocalPropertyNames(*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 + local_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()) { |
+ Object* name = names->get(k); |
+ if (name_from_hidden_proto == name) { |
+ names->set(j, isolate->heap()->hidden_string()); |
+ hidden_strings++; |
+ break; |
+ } |
+ } |
+ } |
+ } |
+ } |
next_copy_index += local_property_count[i]; |
if (jsproto->HasHiddenProperties()) { |
- proto_with_hidden_properties++; |
+ hidden_strings++; |
} |
if (i < length - 1) { |
jsproto = Handle<JSObject>(JSObject::cast(jsproto->GetPrototype())); |
} |
} |
- // Filter out name of hidden properties object. |
- if (proto_with_hidden_properties > 0) { |
+ // 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() - proto_with_hidden_properties); |
+ names->length() - hidden_strings); |
int dest_pos = 0; |
for (int i = 0; i < total_property_count; i++) { |
Object* name = old_names->get(i); |
if (name == isolate->heap()->hidden_string()) { |
+ hidden_strings--; |
continue; |
} |
names->set(dest_pos++, name); |
} |
+ ASSERT_EQ(0, hidden_strings); |
} |
return *isolate->factory()->NewJSArrayWithElements(names); |