| 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());
|
|
|
|
|