Index: src/objects.cc |
diff --git a/src/objects.cc b/src/objects.cc |
index abaaa2f378bfe50211a0a5e5cf2f948aee15e727..295830e107d86bbcc7f65cd9a6c288d5a0c77c15 100644 |
--- a/src/objects.cc |
+++ b/src/objects.cc |
@@ -1546,7 +1546,7 @@ MaybeObject* JSObject::AddFastProperty(String* name, |
int index = map()->NextFreePropertyIndex(); |
// Allocate new instance descriptors with (name, index) added |
- FieldDescriptor new_field(name, index, attributes); |
+ FieldDescriptor new_field(name, index, attributes, 0); |
DescriptorArray* new_descriptors; |
{ MaybeObject* maybe_new_descriptors = |
old_descriptors->CopyInsert(&new_field); |
@@ -1555,18 +1555,11 @@ MaybeObject* JSObject::AddFastProperty(String* name, |
} |
} |
- // Only allow map transition if the object isn't the global object and there |
- // is not a transition for the name, or there's a transition for the name but |
- // it's unrelated to properties. |
- int descriptor_index = old_descriptors->SearchWithCache(name); |
- |
- // Element transitions are stored in the descriptor for property "", which is |
- // not a identifier and should have forced a switch to slow properties above. |
- bool can_insert_transition = descriptor_index == DescriptorArray::kNotFound; |
+ // Only allow map transition if the object isn't the global object. |
bool allow_map_transition = |
- can_insert_transition && |
(isolate->context()->global_context()->object_function()->map() != map()); |
+ ASSERT(old_descriptors->Search(name) == DescriptorArray::kNotFound); |
ASSERT(index < map()->inobject_properties() || |
(index - map()->inobject_properties()) < properties()->length() || |
map()->unused_property_fields() == 0); |
@@ -1622,7 +1615,7 @@ MaybeObject* JSObject::AddConstantFunctionProperty( |
JSFunction* function, |
PropertyAttributes attributes) { |
// Allocate new instance descriptors with (name, function) added |
- ConstantFunctionDescriptor d(name, function, attributes); |
+ ConstantFunctionDescriptor d(name, function, attributes, 0); |
DescriptorArray* new_descriptors; |
{ MaybeObject* maybe_new_descriptors = |
map()->instance_descriptors()->CopyInsert(&d); |
@@ -1865,7 +1858,7 @@ MaybeObject* JSObject::ConvertDescriptorToField(String* name, |
} |
int index = map()->NextFreePropertyIndex(); |
- FieldDescriptor new_field(name, index, attributes); |
+ FieldDescriptor new_field(name, index, attributes, 0); |
// Make a new DescriptorArray replacing an entry with FieldDescriptor. |
Object* descriptors_unchecked; |
{ MaybeObject* maybe_descriptors_unchecked = |
@@ -2938,7 +2931,7 @@ MaybeObject* JSObject::SetPropertyForResult(LookupResult* result, |
Map* transition_map = Map::cast(transition); |
DescriptorArray* descriptors = transition_map->instance_descriptors(); |
- int descriptor = descriptors->SearchWithCache(*name); |
+ int descriptor = descriptors->LastAdded(); |
PropertyDetails details = descriptors->GetDetails(descriptor); |
ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION); |
@@ -3062,7 +3055,7 @@ MaybeObject* JSObject::SetLocalPropertyIgnoreAttributes( |
Map* transition_map = Map::cast(transition); |
DescriptorArray* descriptors = transition_map->instance_descriptors(); |
- int descriptor = descriptors->Search(name); |
+ int descriptor = descriptors->LastAdded(); |
PropertyDetails details = descriptors->GetDetails(descriptor); |
ASSERT(details.type() == FIELD || details.type() == CONSTANT_FUNCTION); |
@@ -4610,7 +4603,7 @@ static MaybeObject* CreateFreshAccessor(JSObject* obj, |
// step 2: create a copy of the descriptors, incl. the new getter/setter pair |
Map* map1 = obj->map(); |
- CallbacksDescriptor callbacks_descr2(name, accessors2, attributes); |
+ CallbacksDescriptor callbacks_descr2(name, accessors2, attributes, 0); |
DescriptorArray* descriptors2; |
{ MaybeObject* maybe_descriptors2 = |
map1->instance_descriptors()->CopyInsert(&callbacks_descr2); |
@@ -4657,7 +4650,7 @@ static bool TransitionToSameAccessor(Object* map, |
Object* accessor, |
PropertyAttributes attributes ) { |
DescriptorArray* descs = Map::cast(map)->instance_descriptors(); |
- int number = descs->SearchWithCache(name); |
+ int number = descs->LastAdded(); |
ASSERT(number != DescriptorArray::kNotFound); |
Object* target_accessor = |
AccessorPair::cast(descs->GetCallbacksObject(number))->get(component); |
@@ -4681,7 +4674,7 @@ static MaybeObject* NewCallbackTransition(JSObject* obj, |
// step 2: create a copy of the descriptors, incl. the new getter/setter pair |
Map* map2 = obj->map(); |
- CallbacksDescriptor callbacks_descr3(name, accessors3, attributes); |
+ CallbacksDescriptor callbacks_descr3(name, accessors3, attributes, 0); |
DescriptorArray* descriptors3; |
{ MaybeObject* maybe_descriptors3 = |
map2->instance_descriptors()->CopyInsert(&callbacks_descr3); |
@@ -5817,8 +5810,7 @@ MaybeObject* DescriptorArray::Allocate(int number_of_descriptors, |
if (!maybe_array->To(&result)) return maybe_array; |
} |
- result->set(kEnumerationIndexIndex, |
- Smi::FromInt(PropertyDetails::kInitialIndex)); |
+ result->set(kLastAddedIndex, Smi::FromInt(-1)); |
result->set(kTransitionsIndex, Smi::FromInt(0)); |
return result; |
} |
@@ -5830,9 +5822,9 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
ASSERT(bridge_storage->length() >= kEnumCacheBridgeLength); |
ASSERT(new_index_cache->IsSmi() || new_index_cache->IsFixedArray()); |
if (HasEnumCache()) { |
- FixedArray::cast(get(kEnumerationIndexIndex))-> |
+ FixedArray::cast(get(kLastAddedIndex))-> |
set(kEnumCacheBridgeCacheIndex, new_cache); |
- FixedArray::cast(get(kEnumerationIndexIndex))-> |
+ FixedArray::cast(get(kLastAddedIndex))-> |
set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); |
} else { |
if (IsEmpty()) return; // Do nothing for empty descriptor array. |
@@ -5841,9 +5833,9 @@ void DescriptorArray::SetEnumCache(FixedArray* bridge_storage, |
FixedArray::cast(bridge_storage)-> |
set(kEnumCacheBridgeIndicesCacheIndex, new_index_cache); |
NoWriteBarrierSet(FixedArray::cast(bridge_storage), |
- kEnumCacheBridgeEnumIndex, |
- get(kEnumerationIndexIndex)); |
- set(kEnumerationIndexIndex, bridge_storage); |
+ kEnumCacheBridgeLastAdded, |
+ get(kLastAddedIndex)); |
+ set(kLastAddedIndex, bridge_storage); |
} |
} |
@@ -5910,14 +5902,11 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor) { |
// Set the enumeration index in the descriptors and set the enumeration index |
// in the result. |
- int enumeration_index = NextEnumerationIndex(); |
if (keep_enumeration_index) { |
descriptor->SetEnumerationIndex(GetDetails(index).index()); |
} else { |
- descriptor->SetEnumerationIndex(enumeration_index); |
- ++enumeration_index; |
+ descriptor->SetEnumerationIndex(NextEnumerationIndex()); |
} |
- new_descriptors->SetNextEnumerationIndex(enumeration_index); |
// Copy the descriptors, inserting or replacing a descriptor. |
int to_index = 0; |
@@ -5939,6 +5928,11 @@ MaybeObject* DescriptorArray::CopyInsert(Descriptor* descriptor) { |
ASSERT(insertion_index < new_descriptors->number_of_descriptors()); |
new_descriptors->Set(insertion_index, descriptor, witness); |
+ if (!replacing) { |
+ new_descriptors->SetLastAdded(insertion_index); |
+ } else { |
+ new_descriptors->SetLastAdded(LastAdded()); |
+ } |
ASSERT(to_index == new_descriptors->number_of_descriptors()); |
SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates()); |
@@ -5964,8 +5958,9 @@ MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) { |
new_descriptors->CopyFrom(i, this, i, witness); |
if (copy_result->IsFailure()) return copy_result; |
} |
+ new_descriptors->SetLastAdded(LastAdded()); |
} |
- new_descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); |
+ |
return new_descriptors; |
} |
@@ -5976,6 +5971,8 @@ MaybeObject* DescriptorArray::Copy(SharedMode shared_mode) { |
void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) { |
// In-place heap sort. |
int len = number_of_descriptors(); |
+ // Nothing to sort. |
+ if (len == 0) return; |
// Bottom-up max-heap construction. |
// Index of the last node with children |
@@ -6023,6 +6020,19 @@ void DescriptorArray::SortUnchecked(const WhitenessWitness& witness) { |
parent_index = child_index; |
} |
} |
+ |
+ int last_enum_index = -1; |
+ int last_added = -1; |
+ for (int i = 0; i < len; ++i) { |
+ int current_enum = GetDetails(i).index(); |
+ if (current_enum > last_enum_index) { |
+ last_added = i; |
+ last_enum_index = current_enum; |
+ } |
+ } |
+ SetLastAdded(last_added); |
+ |
+ ASSERT(LastAdded() != -1); |
} |
@@ -12720,7 +12730,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
JSFunction::cast(value), |
details.attributes(), |
details.index()); |
- descriptors->Set(next_descriptor++, &d, witness); |
+ descriptors->Set(next_descriptor, &d, witness); |
} else if (type == NORMAL) { |
if (current_offset < inobject_props) { |
obj->InObjectPropertyAtPut(current_offset, |
@@ -12734,7 +12744,7 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
current_offset++, |
details.attributes(), |
details.index()); |
- descriptors->Set(next_descriptor++, &d, witness); |
+ descriptors->Set(next_descriptor, &d, witness); |
} else if (type == CALLBACKS) { |
if (value->IsAccessorPair()) { |
MaybeObject* maybe_copy = |
@@ -12745,10 +12755,11 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
value, |
details.attributes(), |
details.index()); |
- descriptors->Set(next_descriptor++, &d, witness); |
+ descriptors->Set(next_descriptor, &d, witness); |
} else { |
UNREACHABLE(); |
} |
+ ++next_descriptor; |
} |
} |
ASSERT(current_offset == number_of_fields); |
@@ -12768,7 +12779,6 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor( |
obj->set_properties(FixedArray::cast(fields)); |
ASSERT(obj->IsJSObject()); |
- descriptors->SetNextEnumerationIndex(NextEnumerationIndex()); |
// Check that it really works. |
ASSERT(obj->HasFastProperties()); |