Index: src/heap.cc |
=================================================================== |
--- src/heap.cc (revision 5455) |
+++ src/heap.cc (working copy) |
@@ -2650,6 +2650,20 @@ |
} |
+static bool HasDuplicates(DescriptorArray* descriptors) { |
+ int count = descriptors->number_of_descriptors(); |
+ if (count > 1) { |
+ String* prev_key = descriptors->GetKey(0); |
+ for (int i = 1; i != count; i++) { |
+ String* current_key = descriptors->GetKey(i); |
+ if (prev_key == current_key) return true; |
+ prev_key = current_key; |
+ } |
+ } |
+ return false; |
+} |
+ |
+ |
Object* Heap::AllocateInitialMap(JSFunction* fun) { |
ASSERT(!fun->has_initial_map()); |
@@ -2683,23 +2697,34 @@ |
if (fun->shared()->CanGenerateInlineConstructor(prototype)) { |
int count = fun->shared()->this_property_assignments_count(); |
if (count > in_object_properties) { |
- count = in_object_properties; |
+ // Inline constructor can only handle inobject properties. |
+ fun->shared()->ForbidInlineConstructor(); |
+ } else { |
+ Object* descriptors_obj = DescriptorArray::Allocate(count); |
+ if (descriptors_obj->IsFailure()) return descriptors_obj; |
+ DescriptorArray* descriptors = DescriptorArray::cast(descriptors_obj); |
+ for (int i = 0; i < count; i++) { |
+ String* name = fun->shared()->GetThisPropertyAssignmentName(i); |
+ ASSERT(name->IsSymbol()); |
+ FieldDescriptor field(name, i, NONE); |
+ field.SetEnumerationIndex(i); |
+ descriptors->Set(i, &field); |
+ } |
+ descriptors->SetNextEnumerationIndex(count); |
+ descriptors->SortUnchecked(); |
+ |
+ // The descriptors may contain duplicates because the compiler does not |
+ // guarantee the uniqueness of property names (it would have required |
Søren Thygesen Gjesse
2010/09/16 06:43:41
We could do the sorting and checking for duplicate
Vladislav Kaznacheev
2010/09/16 10:50:21
I have considered this and decided against it. If
|
+ // quadratic time). Once the descriptors are sorted we can check for |
+ // duplicates in linear time. |
+ if (HasDuplicates(descriptors)) { |
+ fun->shared()->ForbidInlineConstructor(); |
+ } else { |
+ map->set_instance_descriptors(descriptors); |
+ map->set_pre_allocated_property_fields(count); |
+ map->set_unused_property_fields(in_object_properties - count); |
+ } |
} |
- Object* descriptors_obj = DescriptorArray::Allocate(count); |
- if (descriptors_obj->IsFailure()) return descriptors_obj; |
- DescriptorArray* descriptors = DescriptorArray::cast(descriptors_obj); |
- for (int i = 0; i < count; i++) { |
- String* name = fun->shared()->GetThisPropertyAssignmentName(i); |
- ASSERT(name->IsSymbol()); |
- FieldDescriptor field(name, i, NONE); |
- field.SetEnumerationIndex(i); |
- descriptors->Set(i, &field); |
- } |
- descriptors->SetNextEnumerationIndex(count); |
- descriptors->Sort(); |
- map->set_instance_descriptors(descriptors); |
- map->set_pre_allocated_property_fields(count); |
- map->set_unused_property_fields(in_object_properties - count); |
} |
return map; |
} |