Revision: 24594
Author: [email protected]
Date: Tue Oct 14 11:03:35 2014 UTC
Log: Preserve order of fields when doing slow-to-fast object migration.
[email protected]
Review URL: https://codereview.chromium.org/614883003
https://code.google.com/p/v8/source/detail?r=24594
Modified:
/branches/bleeding_edge/src/objects-inl.h
/branches/bleeding_edge/src/objects.cc
/branches/bleeding_edge/src/objects.h
=======================================
--- /branches/bleeding_edge/src/objects-inl.h Mon Oct 13 07:50:21 2014 UTC
+++ /branches/bleeding_edge/src/objects-inl.h Tue Oct 14 11:03:35 2014 UTC
@@ -6903,9 +6903,9 @@
}
-void NameDictionary::DoGenerateNewEnumerationIndices(
+Handle<FixedArray> NameDictionary::DoGenerateNewEnumerationIndices(
Handle<NameDictionary> dictionary) {
- DerivedDictionary::GenerateNewEnumerationIndices(dictionary);
+ return DerivedDictionary::GenerateNewEnumerationIndices(dictionary);
}
=======================================
--- /branches/bleeding_edge/src/objects.cc Fri Oct 10 10:51:34 2014 UTC
+++ /branches/bleeding_edge/src/objects.cc Tue Oct 14 11:03:35 2014 UTC
@@ -4280,25 +4280,27 @@
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 @@
// 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));
+
+ 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(i);
- int enumeration_index = details.dictionary_index();
- PropertyType type = details.type();
+ 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 {
- 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);
+ 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);
@@ -14112,9 +14108,13 @@
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>::
@@ -14920,56 +14920,61 @@
}
-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;
+}
- // Overwrite the enumeration_order with the enumeration indices.
+
+template <typename Derived, typename Shape, typename Key>
+Handle<FixedArray>
+Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices(
+ Handle<Derived> dictionary) {
+ int length = dictionary->NumberOfElements();
+
+ 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;
}
=======================================
--- /branches/bleeding_edge/src/objects.h Mon Oct 13 07:50:21 2014 UTC
+++ /branches/bleeding_edge/src/objects.h Tue Oct 14 11:03:35 2014 UTC
@@ -3586,6 +3586,11 @@
Handle<Object> value,
PropertyDetails details);
+ // Returns iteration indices array for the |dictionary|.
+ // Values are direct indices in the |HashTable| array.
+ static Handle<FixedArray> BuildIterationIndicesArray(
+ Handle<Derived> dictionary);
+
protected:
// Generic at put operation.
MUST_USE_RESULT static Handle<Derived> AtPut(
@@ -3602,7 +3607,9 @@
uint32_t hash);
// Generate new enumeration indices to avoid enumeration index overflow.
- static void GenerateNewEnumerationIndices(Handle<Derived> dictionary);
+ // Returns iteration indices array for the |dictionary|.
+ static Handle<FixedArray> GenerateNewEnumerationIndices(
+ Handle<Derived> dictionary);
static const int kMaxNumberKeyIndex =
DerivedHashTable::kPrefixStartIndex;
static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
};
@@ -3631,7 +3638,7 @@
// Copies enumerable keys to preallocated fixed array.
void CopyEnumKeysTo(FixedArray* storage);
- inline static void DoGenerateNewEnumerationIndices(
+ inline static Handle<FixedArray> DoGenerateNewEnumerationIndices(
Handle<NameDictionary> dictionary);
// Find entry for key, otherwise return kNotFound. Optimized version of
--
--
v8-dev mailing list
[email protected]
http://groups.google.com/group/v8-dev
---
You received this message because you are subscribed to the Google Groups "v8-dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.