| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 9f25145bf2c197048ee858906c251158c8e8570e..bbfa9902257f9e5346fed310a15208bdb9a29641 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -4280,25 +4280,27 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
|
| int number_of_elements = dictionary->NumberOfElements();
|
| if (number_of_elements > kMaxNumberOfDescriptors) return;
|
|
|
| + Handle<FixedArray> iteration_order;
|
| if (number_of_elements != dictionary->NextEnumerationIndex()) {
|
| - NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
|
| + iteration_order =
|
| + NameDictionary::DoGenerateNewEnumerationIndices(dictionary);
|
| + } else {
|
| + iteration_order = NameDictionary::BuildIterationIndicesArray(dictionary);
|
| }
|
|
|
| - int instance_descriptor_length = 0;
|
| + int instance_descriptor_length = iteration_order->length();
|
| int number_of_fields = 0;
|
|
|
| // Compute the length of the instance descriptor.
|
| - int capacity = dictionary->Capacity();
|
| - for (int i = 0; i < capacity; i++) {
|
| - Object* k = dictionary->KeyAt(i);
|
| - if (dictionary->IsKey(k)) {
|
| - Object* value = dictionary->ValueAt(i);
|
| - PropertyType type = dictionary->DetailsAt(i).type();
|
| - DCHECK(type != FIELD);
|
| - instance_descriptor_length++;
|
| - if (type == NORMAL && !value->IsJSFunction()) {
|
| - number_of_fields += 1;
|
| - }
|
| + for (int i = 0; i < instance_descriptor_length; i++) {
|
| + int index = Smi::cast(iteration_order->get(i))->value();
|
| + DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
|
| +
|
| + Object* value = dictionary->ValueAt(index);
|
| + PropertyType type = dictionary->DetailsAt(index).type();
|
| + DCHECK(type != FIELD);
|
| + if (type == NORMAL && !value->IsJSFunction()) {
|
| + number_of_fields += 1;
|
| }
|
| }
|
|
|
| @@ -4338,51 +4340,45 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
|
|
|
| // Fill in the instance descriptor and the fields.
|
| int current_offset = 0;
|
| - for (int i = 0; i < capacity; i++) {
|
| - Object* k = dictionary->KeyAt(i);
|
| - if (dictionary->IsKey(k)) {
|
| - Object* value = dictionary->ValueAt(i);
|
| - Handle<Name> key;
|
| - if (k->IsSymbol()) {
|
| - key = handle(Symbol::cast(k));
|
| - } else {
|
| - // Ensure the key is a unique name before writing into the
|
| - // instance descriptor.
|
| - key = factory->InternalizeString(handle(String::cast(k)));
|
| - }
|
| + for (int i = 0; i < instance_descriptor_length; i++) {
|
| + int index = Smi::cast(iteration_order->get(i))->value();
|
| + Object* k = dictionary->KeyAt(index);
|
| + DCHECK(dictionary->IsKey(k));
|
|
|
| - PropertyDetails details = dictionary->DetailsAt(i);
|
| - int enumeration_index = details.dictionary_index();
|
| - PropertyType type = details.type();
|
| -
|
| - if (value->IsJSFunction()) {
|
| - ConstantDescriptor d(key,
|
| - handle(value, isolate),
|
| - details.attributes());
|
| - descriptors->Set(enumeration_index - 1, &d);
|
| - } else if (type == NORMAL) {
|
| - if (current_offset < inobject_props) {
|
| - object->InObjectPropertyAtPut(current_offset,
|
| - value,
|
| - UPDATE_WRITE_BARRIER);
|
| - } else {
|
| - int offset = current_offset - inobject_props;
|
| - fields->set(offset, value);
|
| - }
|
| - FieldDescriptor d(key,
|
| - current_offset++,
|
| - details.attributes(),
|
| - // TODO(verwaest): value->OptimalRepresentation();
|
| - Representation::Tagged());
|
| - descriptors->Set(enumeration_index - 1, &d);
|
| - } else if (type == CALLBACKS) {
|
| - CallbacksDescriptor d(key,
|
| - handle(value, isolate),
|
| - details.attributes());
|
| - descriptors->Set(enumeration_index - 1, &d);
|
| + Object* value = dictionary->ValueAt(index);
|
| + Handle<Name> key;
|
| + if (k->IsSymbol()) {
|
| + key = handle(Symbol::cast(k));
|
| + } else {
|
| + // Ensure the key is a unique name before writing into the
|
| + // instance descriptor.
|
| + key = factory->InternalizeString(handle(String::cast(k)));
|
| + }
|
| +
|
| + PropertyDetails details = dictionary->DetailsAt(index);
|
| + int enumeration_index = details.dictionary_index();
|
| + PropertyType type = details.type();
|
| +
|
| + if (value->IsJSFunction()) {
|
| + ConstantDescriptor d(key, handle(value, isolate), details.attributes());
|
| + descriptors->Set(enumeration_index - 1, &d);
|
| + } else if (type == NORMAL) {
|
| + if (current_offset < inobject_props) {
|
| + object->InObjectPropertyAtPut(current_offset, value,
|
| + UPDATE_WRITE_BARRIER);
|
| } else {
|
| - UNREACHABLE();
|
| + int offset = current_offset - inobject_props;
|
| + fields->set(offset, value);
|
| }
|
| + FieldDescriptor d(key, current_offset++, details.attributes(),
|
| + // TODO(verwaest): value->OptimalRepresentation();
|
| + Representation::Tagged());
|
| + descriptors->Set(enumeration_index - 1, &d);
|
| + } else if (type == CALLBACKS) {
|
| + CallbacksDescriptor d(key, handle(value, isolate), details.attributes());
|
| + descriptors->Set(enumeration_index - 1, &d);
|
| + } else {
|
| + UNREACHABLE();
|
| }
|
| }
|
| DCHECK(current_offset == number_of_fields);
|
| @@ -14106,9 +14102,13 @@ template Handle<NameDictionary>
|
| Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
|
| Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
|
|
|
| -template void
|
| -Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::
|
| - GenerateNewEnumerationIndices(Handle<NameDictionary>);
|
| +template Handle<FixedArray> Dictionary<
|
| + NameDictionary, NameDictionaryShape,
|
| + Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
|
| +
|
| +template Handle<FixedArray> Dictionary<
|
| + NameDictionary, NameDictionaryShape,
|
| + Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
|
|
|
| template int
|
| Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
|
| @@ -14914,56 +14914,61 @@ Handle<Derived> Dictionary<Derived, Shape, Key>::New(
|
| }
|
|
|
|
|
| -template<typename Derived, typename Shape, typename Key>
|
| -void Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
|
| +template <typename Derived, typename Shape, typename Key>
|
| +Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
|
| Handle<Derived> dictionary) {
|
| Factory* factory = dictionary->GetIsolate()->factory();
|
| int length = dictionary->NumberOfElements();
|
|
|
| - // Allocate and initialize iteration order array.
|
| Handle<FixedArray> iteration_order = factory->NewFixedArray(length);
|
| - for (int i = 0; i < length; i++) {
|
| - iteration_order->set(i, Smi::FromInt(i));
|
| - }
|
| -
|
| - // Allocate array with enumeration order.
|
| Handle<FixedArray> enumeration_order = factory->NewFixedArray(length);
|
|
|
| - // Fill the enumeration order array with property details.
|
| + // Fill both the iteration order array and the enumeration order array
|
| + // with property details.
|
| int capacity = dictionary->Capacity();
|
| int pos = 0;
|
| for (int i = 0; i < capacity; i++) {
|
| if (dictionary->IsKey(dictionary->KeyAt(i))) {
|
| int index = dictionary->DetailsAt(i).dictionary_index();
|
| - enumeration_order->set(pos++, Smi::FromInt(index));
|
| + iteration_order->set(pos, Smi::FromInt(i));
|
| + enumeration_order->set(pos, Smi::FromInt(index));
|
| + pos++;
|
| }
|
| }
|
| + DCHECK(pos == length);
|
|
|
| // Sort the arrays wrt. enumeration order.
|
| iteration_order->SortPairs(*enumeration_order, enumeration_order->length());
|
| + return iteration_order;
|
| +}
|
| +
|
| +
|
| +template <typename Derived, typename Shape, typename Key>
|
| +Handle<FixedArray>
|
| +Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
|
| + Handle<Derived> dictionary) {
|
| + int length = dictionary->NumberOfElements();
|
|
|
| - // Overwrite the enumeration_order with the enumeration indices.
|
| + Handle<FixedArray> iteration_order = BuildIterationIndicesArray(dictionary);
|
| + DCHECK(iteration_order->length() == length);
|
| +
|
| + // Iterate over the dictionary using the enumeration order and update
|
| + // the dictionary with new enumeration indices.
|
| for (int i = 0; i < length; i++) {
|
| int index = Smi::cast(iteration_order->get(i))->value();
|
| + DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
|
| +
|
| int enum_index = PropertyDetails::kInitialIndex + i;
|
| - enumeration_order->set(index, Smi::FromInt(enum_index));
|
| - }
|
|
|
| - // Update the dictionary with new indices.
|
| - capacity = dictionary->Capacity();
|
| - pos = 0;
|
| - for (int i = 0; i < capacity; i++) {
|
| - if (dictionary->IsKey(dictionary->KeyAt(i))) {
|
| - int enum_index = Smi::cast(enumeration_order->get(pos++))->value();
|
| - PropertyDetails details = dictionary->DetailsAt(i);
|
| - PropertyDetails new_details = PropertyDetails(
|
| - details.attributes(), details.type(), enum_index);
|
| - dictionary->DetailsAtPut(i, new_details);
|
| - }
|
| + PropertyDetails details = dictionary->DetailsAt(index);
|
| + PropertyDetails new_details =
|
| + PropertyDetails(details.attributes(), details.type(), enum_index);
|
| + dictionary->DetailsAtPut(index, new_details);
|
| }
|
|
|
| // Set the next enumeration index.
|
| dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
|
| + return iteration_order;
|
| }
|
|
|
|
|
|
|