Commit f58558d9 authored by ishell@chromium.org's avatar ishell@chromium.org

Preserve order of fields when doing slow-to-fast object migration.

R=jkummerow@chromium.org

Review URL: https://codereview.chromium.org/614883003

git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@24594 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
parent da0c3805
...@@ -6903,9 +6903,9 @@ Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate, ...@@ -6903,9 +6903,9 @@ Handle<Object> NameDictionaryShape::AsHandle(Isolate* isolate,
} }
void NameDictionary::DoGenerateNewEnumerationIndices( Handle<FixedArray> NameDictionary::DoGenerateNewEnumerationIndices(
Handle<NameDictionary> dictionary) { Handle<NameDictionary> dictionary) {
DerivedDictionary::GenerateNewEnumerationIndices(dictionary); return DerivedDictionary::GenerateNewEnumerationIndices(dictionary);
} }
......
...@@ -4280,25 +4280,27 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object, ...@@ -4280,25 +4280,27 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
int number_of_elements = dictionary->NumberOfElements(); int number_of_elements = dictionary->NumberOfElements();
if (number_of_elements > kMaxNumberOfDescriptors) return; if (number_of_elements > kMaxNumberOfDescriptors) return;
Handle<FixedArray> iteration_order;
if (number_of_elements != dictionary->NextEnumerationIndex()) { 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; int number_of_fields = 0;
// Compute the length of the instance descriptor. // Compute the length of the instance descriptor.
int capacity = dictionary->Capacity(); for (int i = 0; i < instance_descriptor_length; i++) {
for (int i = 0; i < capacity; i++) { int index = Smi::cast(iteration_order->get(i))->value();
Object* k = dictionary->KeyAt(i); DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
if (dictionary->IsKey(k)) {
Object* value = dictionary->ValueAt(i); Object* value = dictionary->ValueAt(index);
PropertyType type = dictionary->DetailsAt(i).type(); PropertyType type = dictionary->DetailsAt(index).type();
DCHECK(type != FIELD); DCHECK(type != FIELD);
instance_descriptor_length++; if (type == NORMAL && !value->IsJSFunction()) {
if (type == NORMAL && !value->IsJSFunction()) { number_of_fields += 1;
number_of_fields += 1;
}
} }
} }
...@@ -4338,51 +4340,45 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object, ...@@ -4338,51 +4340,45 @@ void JSObject::MigrateSlowToFast(Handle<JSObject> object,
// Fill in the instance descriptor and the fields. // Fill in the instance descriptor and the fields.
int current_offset = 0; int current_offset = 0;
for (int i = 0; i < capacity; i++) { for (int i = 0; i < instance_descriptor_length; i++) {
Object* k = dictionary->KeyAt(i); int index = Smi::cast(iteration_order->get(i))->value();
if (dictionary->IsKey(k)) { Object* k = dictionary->KeyAt(index);
Object* value = dictionary->ValueAt(i); DCHECK(dictionary->IsKey(k));
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); Object* value = dictionary->ValueAt(index);
int enumeration_index = details.dictionary_index(); Handle<Name> key;
PropertyType type = details.type(); if (k->IsSymbol()) {
key = handle(Symbol::cast(k));
if (value->IsJSFunction()) { } else {
ConstantDescriptor d(key, // Ensure the key is a unique name before writing into the
handle(value, isolate), // instance descriptor.
details.attributes()); key = factory->InternalizeString(handle(String::cast(k)));
descriptors->Set(enumeration_index - 1, &d); }
} else if (type == NORMAL) {
if (current_offset < inobject_props) { PropertyDetails details = dictionary->DetailsAt(index);
object->InObjectPropertyAtPut(current_offset, int enumeration_index = details.dictionary_index();
value, PropertyType type = details.type();
UPDATE_WRITE_BARRIER);
} else { if (value->IsJSFunction()) {
int offset = current_offset - inobject_props; ConstantDescriptor d(key, handle(value, isolate), details.attributes());
fields->set(offset, value); descriptors->Set(enumeration_index - 1, &d);
} } else if (type == NORMAL) {
FieldDescriptor d(key, if (current_offset < inobject_props) {
current_offset++, object->InObjectPropertyAtPut(current_offset, value,
details.attributes(), UPDATE_WRITE_BARRIER);
// 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 { } 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); DCHECK(current_offset == number_of_fields);
...@@ -14112,9 +14108,13 @@ template Handle<NameDictionary> ...@@ -14112,9 +14108,13 @@ template Handle<NameDictionary>
Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add( Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >::Add(
Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails); Handle<NameDictionary>, Handle<Name>, Handle<Object>, PropertyDetails);
template void template Handle<FixedArray> Dictionary<
Dictionary<NameDictionary, NameDictionaryShape, Handle<Name> >:: NameDictionary, NameDictionaryShape,
GenerateNewEnumerationIndices(Handle<NameDictionary>); Handle<Name> >::BuildIterationIndicesArray(Handle<NameDictionary>);
template Handle<FixedArray> Dictionary<
NameDictionary, NameDictionaryShape,
Handle<Name> >::GenerateNewEnumerationIndices(Handle<NameDictionary>);
template int template int
Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>:: Dictionary<SeededNumberDictionary, SeededNumberDictionaryShape, uint32_t>::
...@@ -14920,56 +14920,61 @@ Handle<Derived> Dictionary<Derived, Shape, Key>::New( ...@@ -14920,56 +14920,61 @@ Handle<Derived> Dictionary<Derived, Shape, Key>::New(
} }
template<typename Derived, typename Shape, typename Key> template <typename Derived, typename Shape, typename Key>
void Dictionary<Derived, Shape, Key>::GenerateNewEnumerationIndices( Handle<FixedArray> Dictionary<Derived, Shape, Key>::BuildIterationIndicesArray(
Handle<Derived> dictionary) { Handle<Derived> dictionary) {
Factory* factory = dictionary->GetIsolate()->factory(); Factory* factory = dictionary->GetIsolate()->factory();
int length = dictionary->NumberOfElements(); int length = dictionary->NumberOfElements();
// Allocate and initialize iteration order array.
Handle<FixedArray> iteration_order = factory->NewFixedArray(length); 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); 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 capacity = dictionary->Capacity();
int pos = 0; int pos = 0;
for (int i = 0; i < capacity; i++) { for (int i = 0; i < capacity; i++) {
if (dictionary->IsKey(dictionary->KeyAt(i))) { if (dictionary->IsKey(dictionary->KeyAt(i))) {
int index = dictionary->DetailsAt(i).dictionary_index(); 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. // Sort the arrays wrt. enumeration order.
iteration_order->SortPairs(*enumeration_order, enumeration_order->length()); 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++) { for (int i = 0; i < length; i++) {
int index = Smi::cast(iteration_order->get(i))->value(); int index = Smi::cast(iteration_order->get(i))->value();
DCHECK(dictionary->IsKey(dictionary->KeyAt(index)));
int enum_index = PropertyDetails::kInitialIndex + i; int enum_index = PropertyDetails::kInitialIndex + i;
enumeration_order->set(index, Smi::FromInt(enum_index));
}
// Update the dictionary with new indices. PropertyDetails details = dictionary->DetailsAt(index);
capacity = dictionary->Capacity(); PropertyDetails new_details =
pos = 0; PropertyDetails(details.attributes(), details.type(), enum_index);
for (int i = 0; i < capacity; i++) { dictionary->DetailsAtPut(index, new_details);
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);
}
} }
// Set the next enumeration index. // Set the next enumeration index.
dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length); dictionary->SetNextEnumerationIndex(PropertyDetails::kInitialIndex+length);
return iteration_order;
} }
......
...@@ -3586,6 +3586,11 @@ class Dictionary: public HashTable<Derived, Shape, Key> { ...@@ -3586,6 +3586,11 @@ class Dictionary: public HashTable<Derived, Shape, Key> {
Handle<Object> value, Handle<Object> value,
PropertyDetails details); 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: protected:
// Generic at put operation. // Generic at put operation.
MUST_USE_RESULT static Handle<Derived> AtPut( MUST_USE_RESULT static Handle<Derived> AtPut(
...@@ -3602,7 +3607,9 @@ class Dictionary: public HashTable<Derived, Shape, Key> { ...@@ -3602,7 +3607,9 @@ class Dictionary: public HashTable<Derived, Shape, Key> {
uint32_t hash); uint32_t hash);
// Generate new enumeration indices to avoid enumeration index overflow. // 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 kMaxNumberKeyIndex = DerivedHashTable::kPrefixStartIndex;
static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1; static const int kNextEnumerationIndexIndex = kMaxNumberKeyIndex + 1;
}; };
...@@ -3631,7 +3638,7 @@ class NameDictionary: public Dictionary<NameDictionary, ...@@ -3631,7 +3638,7 @@ class NameDictionary: public Dictionary<NameDictionary,
// Copies enumerable keys to preallocated fixed array. // Copies enumerable keys to preallocated fixed array.
void CopyEnumKeysTo(FixedArray* storage); void CopyEnumKeysTo(FixedArray* storage);
inline static void DoGenerateNewEnumerationIndices( inline static Handle<FixedArray> DoGenerateNewEnumerationIndices(
Handle<NameDictionary> dictionary); Handle<NameDictionary> dictionary);
// Find entry for key, otherwise return kNotFound. Optimized version of // Find entry for key, otherwise return kNotFound. Optimized version of
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment