| Index: src/objects.cc
|
| diff --git a/src/objects.cc b/src/objects.cc
|
| index 64f5a452d7c74ae961b6af3ec44a48d981f30fd1..f6c2c7f4d26a035c7e7a7d79e14d036e0df72c84 100644
|
| --- a/src/objects.cc
|
| +++ b/src/objects.cc
|
| @@ -483,9 +483,11 @@ MaybeObject* JSObject::SetNormalizedProperty(String* name,
|
| return value;
|
| }
|
| // Preserve enumeration index.
|
| - details = PropertyDetails(details.attributes(),
|
| - details.type(),
|
| - property_dictionary()->DetailsAt(entry).index());
|
| + details = PropertyDetails(
|
| + details.attributes(),
|
| + details.type(),
|
| + property_dictionary()->DetailsAt(entry).dictionary_index());
|
| +
|
| if (IsGlobalObject()) {
|
| JSGlobalPropertyCell* cell =
|
| JSGlobalPropertyCell::cast(property_dictionary()->ValueAt(entry));
|
| @@ -1732,7 +1734,7 @@ MaybeObject* JSObject::ReplaceSlowProperty(String* name,
|
| int new_enumeration_index = 0; // 0 means "Use the next available index."
|
| if (old_index != -1) {
|
| // All calls to ReplaceSlowProperty have had all transitions removed.
|
| - new_enumeration_index = dictionary->DetailsAt(old_index).index();
|
| + new_enumeration_index = dictionary->DetailsAt(old_index).dictionary_index();
|
| }
|
|
|
| PropertyDetails new_details(attributes, NORMAL, new_enumeration_index);
|
| @@ -2080,33 +2082,6 @@ MaybeObject* JSObject::SetPropertyViaPrototypes(
|
| }
|
|
|
|
|
| -void Map::LookupDescriptor(JSObject* holder,
|
| - String* name,
|
| - LookupResult* result) {
|
| - DescriptorArray* descriptors = this->instance_descriptors();
|
| - int number = descriptors->SearchWithCache(name);
|
| - if (number != DescriptorArray::kNotFound) {
|
| - result->DescriptorResult(holder, descriptors->GetDetails(number), number);
|
| - } else {
|
| - result->NotFound();
|
| - }
|
| -}
|
| -
|
| -
|
| -void Map::LookupTransition(JSObject* holder,
|
| - String* name,
|
| - LookupResult* result) {
|
| - if (HasTransitionArray()) {
|
| - TransitionArray* transition_array = transitions();
|
| - int number = transition_array->Search(name);
|
| - if (number != TransitionArray::kNotFound) {
|
| - return result->TransitionResult(holder, number);
|
| - }
|
| - }
|
| - result->NotFound();
|
| -}
|
| -
|
| -
|
| enum RightTrimMode { FROM_GC, FROM_MUTATOR };
|
|
|
|
|
| @@ -2202,14 +2177,14 @@ void Map::CopyAppendCallbackDescriptors(Handle<Map> map,
|
| AccessorInfo* entry = AccessorInfo::cast(callbacks.get(i));
|
| String* key = String::cast(entry->name());
|
| // Check if a descriptor with this name already exists before writing.
|
| - if (LinearSearch(*result, key, map->NumberOfSetDescriptors()) ==
|
| + if (LinearSearch(*result, key, map->NumberOfOwnDescriptors()) ==
|
| DescriptorArray::kNotFound) {
|
| CallbacksDescriptor desc(key, entry, entry->property_attributes());
|
| map->AppendDescriptor(&desc, witness);
|
| }
|
| }
|
|
|
| - int new_number_of_descriptors = map->NumberOfSetDescriptors();
|
| + int new_number_of_descriptors = map->NumberOfOwnDescriptors();
|
| // Reinstall the original descriptor array if no new elements were added.
|
| if (new_number_of_descriptors == descriptor_count) {
|
| Map::SetDescriptors(map, array);
|
| @@ -3300,8 +3275,9 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
|
| PropertyDetails details = descs->GetDetails(i);
|
| switch (details.type()) {
|
| case CONSTANT_FUNCTION: {
|
| - PropertyDetails d =
|
| - PropertyDetails(details.attributes(), NORMAL, details.index());
|
| + PropertyDetails d = PropertyDetails(details.attributes(),
|
| + NORMAL,
|
| + details.descriptor_index());
|
| Object* value = descs->GetConstantFunction(i);
|
| MaybeObject* maybe_dictionary =
|
| dictionary->Add(descs->GetKey(i), value, d);
|
| @@ -3309,8 +3285,9 @@ MaybeObject* JSObject::NormalizeProperties(PropertyNormalizationMode mode,
|
| break;
|
| }
|
| case FIELD: {
|
| - PropertyDetails d =
|
| - PropertyDetails(details.attributes(), NORMAL, details.index());
|
| + PropertyDetails d = PropertyDetails(details.attributes(),
|
| + NORMAL,
|
| + details.descriptor_index());
|
| Object* value = FastPropertyAt(descs->GetFieldIndex(i));
|
| MaybeObject* maybe_dictionary =
|
| dictionary->Add(descs->GetKey(i), value, d);
|
| @@ -3683,10 +3660,15 @@ MaybeObject* JSObject::GetHiddenPropertiesHashTable(
|
| // hidden symbols hash code is zero (and no other string has hash
|
| // code zero) it will always occupy the first entry if present.
|
| DescriptorArray* descriptors = this->map()->instance_descriptors();
|
| - if ((descriptors->number_of_descriptors() > 0) &&
|
| - (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
|
| - ASSERT(descriptors->GetType(0) == FIELD);
|
| - inline_value = this->FastPropertyAt(descriptors->GetFieldIndex(0));
|
| + if (descriptors->number_of_descriptors() > 0) {
|
| + int sorted_index = descriptors->GetSortedKeyIndex(0);
|
| + if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) {
|
| + ASSERT(descriptors->GetType(sorted_index) == FIELD);
|
| + inline_value = this->FastPropertyAt(
|
| + descriptors->GetFieldIndex(sorted_index));
|
| + } else {
|
| + inline_value = GetHeap()->undefined_value();
|
| + }
|
| } else {
|
| inline_value = GetHeap()->undefined_value();
|
| }
|
| @@ -3746,11 +3728,14 @@ MaybeObject* JSObject::SetHiddenPropertiesHashTable(Object* value) {
|
| // hidden symbols hash code is zero (and no other string has hash
|
| // code zero) it will always occupy the first entry if present.
|
| DescriptorArray* descriptors = this->map()->instance_descriptors();
|
| - if ((descriptors->number_of_descriptors() > 0) &&
|
| - (descriptors->GetKey(0) == GetHeap()->hidden_symbol())) {
|
| - ASSERT(descriptors->GetType(0) == FIELD);
|
| - this->FastPropertyAtPut(descriptors->GetFieldIndex(0), value);
|
| - return this;
|
| + if (descriptors->number_of_descriptors() > 0) {
|
| + int sorted_index = descriptors->GetSortedKeyIndex(0);
|
| + if (descriptors->GetKey(sorted_index) == GetHeap()->hidden_symbol()) {
|
| + ASSERT(descriptors->GetType(sorted_index) == FIELD);
|
| + this->FastPropertyAtPut(descriptors->GetFieldIndex(sorted_index),
|
| + value);
|
| + return this;
|
| + }
|
| }
|
| }
|
| MaybeObject* store_result =
|
| @@ -4863,7 +4848,7 @@ MaybeObject* Map::RawCopy(int instance_size) {
|
| result->set_bit_field(bit_field());
|
| result->set_bit_field2(bit_field2());
|
| result->set_bit_field3(bit_field3());
|
| - result->SetLastAdded(kNoneAdded);
|
| + result->SetNumberOfOwnDescriptors(0);
|
| return result;
|
| }
|
|
|
| @@ -4915,20 +4900,15 @@ MaybeObject* Map::CopyDropDescriptors() {
|
|
|
| MaybeObject* Map::CopyReplaceDescriptors(DescriptorArray* descriptors,
|
| String* name,
|
| - int last_added,
|
| TransitionFlag flag) {
|
| Map* result;
|
| MaybeObject* maybe_result = CopyDropDescriptors();
|
| if (!maybe_result->To(&result)) return maybe_result;
|
|
|
| - if (last_added == kNoneAdded) {
|
| - ASSERT(descriptors->number_of_descriptors() == 0);
|
| - } else {
|
| - ASSERT(descriptors->GetDetails(last_added).index() ==
|
| - descriptors->number_of_descriptors());
|
| + if (descriptors->number_of_descriptors() != 0) {
|
| MaybeObject* maybe_failure = result->SetDescriptors(descriptors);
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
| - result->SetLastAdded(last_added);
|
| + result->SetNumberOfOwnDescriptors(descriptors->number_of_descriptors());
|
| }
|
|
|
| if (flag == INSERT_TRANSITION && CanHaveMoreTransitions()) {
|
| @@ -4982,22 +4962,13 @@ MaybeObject* Map::CopyWithPreallocatedFieldDescriptors() {
|
| Map* map = ctor->initial_map();
|
| DescriptorArray* descriptors = map->instance_descriptors();
|
|
|
| - int last_added = map->LastAdded();
|
| -
|
| - return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION);
|
| + return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION);
|
| }
|
|
|
|
|
| MaybeObject* Map::Copy() {
|
| DescriptorArray* descriptors = instance_descriptors();
|
| - int last_added = LastAdded();
|
| -
|
| - return CopyReplaceDescriptors(descriptors, NULL, last_added, OMIT_TRANSITION);
|
| -}
|
| -
|
| -
|
| -static bool InsertionPointFound(String* key1, String* key2) {
|
| - return key1->Hash() > key2->Hash() || key1 == key2;
|
| + return CopyReplaceDescriptors(descriptors, NULL, OMIT_TRANSITION);
|
| }
|
|
|
|
|
| @@ -5022,26 +4993,15 @@ MaybeObject* Map::CopyAddDescriptor(Descriptor* descriptor,
|
| FixedArray::WhitenessWitness witness(new_descriptors);
|
|
|
| // Copy the descriptors, inserting a descriptor.
|
| - int insertion_index = -1;
|
| - int to = 0;
|
| - for (int from = 0; from < old_size; ++from) {
|
| - if (insertion_index < 0 &&
|
| - InsertionPointFound(descriptors->GetKey(from), key)) {
|
| - insertion_index = to++;
|
| - }
|
| - new_descriptors->CopyFrom(to++, descriptors, from, witness);
|
| + for (int i = 0; i < old_size; ++i) {
|
| + new_descriptors->CopyFrom(i, descriptors, i, witness);
|
| }
|
| - if (insertion_index < 0) insertion_index = to++;
|
|
|
| - ASSERT(to == new_size);
|
| - ASSERT(new_size == descriptors->NextEnumerationIndex());
|
| -
|
| - descriptor->SetEnumerationIndex(new_size);
|
| - new_descriptors->Set(insertion_index, descriptor, witness);
|
| + new_descriptors->Append(descriptor, witness, old_size);
|
|
|
| SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
|
|
|
| - return CopyReplaceDescriptors(new_descriptors, key, insertion_index, flag);
|
| + return CopyReplaceDescriptors(new_descriptors, key, flag);
|
| }
|
|
|
|
|
| @@ -5088,13 +5048,15 @@ MaybeObject* Map::CopyReplaceDescriptor(Descriptor* descriptor,
|
| new_descriptors->CopyFrom(index, descriptors, index, witness);
|
| }
|
|
|
| - descriptor->SetEnumerationIndex(
|
| - descriptors->GetDetails(insertion_index).index());
|
| + PropertyDetails original_details = descriptors->GetDetails(insertion_index);
|
| + descriptor->SetEnumerationIndex(original_details.descriptor_index());
|
| + descriptor->SetSortedKey(original_details.pointer());
|
| +
|
| new_descriptors->Set(insertion_index, descriptor, witness);
|
|
|
| SLOW_ASSERT(new_descriptors->IsSortedNoDuplicates());
|
|
|
| - return CopyReplaceDescriptors(new_descriptors, key, LastAdded(), flag);
|
| + return CopyReplaceDescriptors(new_descriptors, key, flag);
|
| }
|
|
|
|
|
| @@ -5920,27 +5882,29 @@ void DescriptorArray::CopyFrom(int dst_index,
|
| // descriptor array. If the descriptor array were to be black, the shuffling
|
| // would move a slot that was already recorded as pointing into an evacuation
|
| // candidate. This would result in missing updates upon evacuation.
|
| -void DescriptorArray::Sort(const WhitenessWitness& witness) {
|
| +void DescriptorArray::Sort() {
|
| // In-place heap sort.
|
| int len = number_of_descriptors();
|
| + // Reset sorting since the descriptor array might contain invalid pointers.
|
| + for (int i = 0; i < len; ++i) SetSortedKey(i, i);
|
| // Bottom-up max-heap construction.
|
| // Index of the last node with children
|
| const int max_parent_index = (len / 2) - 1;
|
| for (int i = max_parent_index; i >= 0; --i) {
|
| int parent_index = i;
|
| - const uint32_t parent_hash = GetKey(i)->Hash();
|
| + const uint32_t parent_hash = GetSortedKey(i)->Hash();
|
| while (parent_index <= max_parent_index) {
|
| int child_index = 2 * parent_index + 1;
|
| - uint32_t child_hash = GetKey(child_index)->Hash();
|
| + uint32_t child_hash = GetSortedKey(child_index)->Hash();
|
| if (child_index + 1 < len) {
|
| - uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
|
| + uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
|
| if (right_child_hash > child_hash) {
|
| child_index++;
|
| child_hash = right_child_hash;
|
| }
|
| }
|
| if (child_hash <= parent_hash) break;
|
| - NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
|
| + SwapSortedKeys(parent_index, child_index);
|
| // Now element at child_index could be < its children.
|
| parent_index = child_index; // parent_hash remains correct.
|
| }
|
| @@ -5949,23 +5913,23 @@ void DescriptorArray::Sort(const WhitenessWitness& witness) {
|
| // Extract elements and create sorted array.
|
| for (int i = len - 1; i > 0; --i) {
|
| // Put max element at the back of the array.
|
| - NoIncrementalWriteBarrierSwapDescriptors(0, i);
|
| + SwapSortedKeys(0, i);
|
| // Shift down the new top element.
|
| int parent_index = 0;
|
| - const uint32_t parent_hash = GetKey(parent_index)->Hash();
|
| + const uint32_t parent_hash = GetSortedKey(parent_index)->Hash();
|
| const int max_parent_index = (i / 2) - 1;
|
| while (parent_index <= max_parent_index) {
|
| int child_index = parent_index * 2 + 1;
|
| - uint32_t child_hash = GetKey(child_index)->Hash();
|
| + uint32_t child_hash = GetSortedKey(child_index)->Hash();
|
| if (child_index + 1 < i) {
|
| - uint32_t right_child_hash = GetKey(child_index + 1)->Hash();
|
| + uint32_t right_child_hash = GetSortedKey(child_index + 1)->Hash();
|
| if (right_child_hash > child_hash) {
|
| child_index++;
|
| child_hash = right_child_hash;
|
| }
|
| }
|
| if (child_hash <= parent_hash) break;
|
| - NoIncrementalWriteBarrierSwapDescriptors(parent_index, child_index);
|
| + SwapSortedKeys(parent_index, child_index);
|
| parent_index = child_index;
|
| }
|
| }
|
| @@ -7310,11 +7274,7 @@ bool Map::EquivalentToForNormalization(Map* other,
|
| instance_type() == other->instance_type() &&
|
| bit_field() == other->bit_field() &&
|
| bit_field2() == other->bit_field2() &&
|
| - static_cast<uint32_t>(bit_field3()) ==
|
| - LastAddedBits::update(
|
| - IsShared::update(DictionaryMap::update(other->bit_field3(), true),
|
| - true),
|
| - kNoneAdded);
|
| + function_with_prototype() == other->function_with_prototype();
|
| }
|
|
|
|
|
| @@ -9411,7 +9371,8 @@ MaybeObject* JSObject::SetDictionaryElement(uint32_t index,
|
| // is read-only (a declared const that has not been initialized). If a
|
| // value is being defined we skip attribute checks completely.
|
| if (set_mode == DEFINE_PROPERTY) {
|
| - details = PropertyDetails(attributes, NORMAL, details.index());
|
| + details = PropertyDetails(
|
| + attributes, NORMAL, details.dictionary_index());
|
| dictionary->DetailsAtPut(entry, details);
|
| } else if (details.IsReadOnly() && !element->IsTheHole()) {
|
| if (strict_mode == kNonStrictMode) {
|
| @@ -12179,7 +12140,8 @@ MaybeObject* Dictionary<Shape, Key>::GenerateNewEnumerationIndices() {
|
| int pos = 0;
|
| for (int i = 0; i < capacity; i++) {
|
| if (Dictionary<Shape, Key>::IsKey(Dictionary<Shape, Key>::KeyAt(i))) {
|
| - enumeration_order->set(pos++, Smi::FromInt(DetailsAt(i).index()));
|
| + enumeration_order->set(
|
| + pos++, Smi::FromInt(DetailsAt(i).dictionary_index()));
|
| }
|
| }
|
|
|
| @@ -12305,7 +12267,8 @@ MaybeObject* Dictionary<Shape, Key>::AddEntry(Key key,
|
|
|
| uint32_t entry = Dictionary<Shape, Key>::FindInsertionEntry(hash);
|
| // Insert element at empty or deleted entry
|
| - if (!details.IsDeleted() && details.index() == 0 && Shape::kIsEnumerable) {
|
| + if (!details.IsDeleted() &&
|
| + details.dictionary_index() == 0 && Shape::kIsEnumerable) {
|
| // Assign an enumeration index to the property and update
|
| // SetNextEnumerationIndex.
|
| int index = NextEnumerationIndex();
|
| @@ -12396,7 +12359,7 @@ MaybeObject* SeededNumberDictionary::Set(uint32_t key,
|
| // Preserve enumeration index.
|
| details = PropertyDetails(details.attributes(),
|
| details.type(),
|
| - DetailsAt(entry).index());
|
| + DetailsAt(entry).dictionary_index());
|
| MaybeObject* maybe_object_key = SeededNumberDictionaryShape::AsObject(key);
|
| Object* object_key;
|
| if (!maybe_object_key->ToObject(&object_key)) return maybe_object_key;
|
| @@ -12478,7 +12441,7 @@ void StringDictionary::CopyEnumKeysTo(FixedArray* storage,
|
| PropertyDetails details = DetailsAt(i);
|
| if (details.IsDeleted() || details.IsDontEnum()) continue;
|
| storage->set(index, k);
|
| - sort_array->set(index, Smi::FromInt(details.index()));
|
| + sort_array->set(index, Smi::FromInt(details.dictionary_index()));
|
| index++;
|
| }
|
| }
|
| @@ -12603,7 +12566,6 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
|
| if (!maybe_fields->To(&fields)) return maybe_fields;
|
|
|
| // Fill in the instance descriptor and the fields.
|
| - int next_descriptor = 0;
|
| int current_offset = 0;
|
| for (int i = 0; i < capacity; i++) {
|
| Object* k = KeyAt(i);
|
| @@ -12615,14 +12577,15 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
|
| if (!maybe_key->To(&key)) return maybe_key;
|
|
|
| PropertyDetails details = DetailsAt(i);
|
| + int enumeration_index = details.dictionary_index();
|
| PropertyType type = details.type();
|
|
|
| if (value->IsJSFunction() && !heap->InNewSpace(value)) {
|
| ConstantFunctionDescriptor d(key,
|
| JSFunction::cast(value),
|
| details.attributes(),
|
| - details.index());
|
| - descriptors->Set(next_descriptor, &d, witness);
|
| + enumeration_index);
|
| + descriptors->Set(enumeration_index - 1, &d, witness);
|
| } else if (type == NORMAL) {
|
| if (current_offset < inobject_props) {
|
| obj->InObjectPropertyAtPut(current_offset,
|
| @@ -12635,23 +12598,22 @@ MaybeObject* StringDictionary::TransformPropertiesToFastFor(
|
| FieldDescriptor d(key,
|
| current_offset++,
|
| details.attributes(),
|
| - details.index());
|
| - descriptors->Set(next_descriptor, &d, witness);
|
| + enumeration_index);
|
| + descriptors->Set(enumeration_index - 1, &d, witness);
|
| } else if (type == CALLBACKS) {
|
| CallbacksDescriptor d(key,
|
| value,
|
| details.attributes(),
|
| - details.index());
|
| - descriptors->Set(next_descriptor, &d, witness);
|
| + enumeration_index);
|
| + descriptors->Set(enumeration_index - 1, &d, witness);
|
| } else {
|
| UNREACHABLE();
|
| }
|
| - ++next_descriptor;
|
| }
|
| }
|
| ASSERT(current_offset == number_of_fields);
|
|
|
| - descriptors->Sort(witness);
|
| + descriptors->Sort();
|
|
|
| MaybeObject* maybe_failure = new_map->InitializeDescriptors(descriptors);
|
| if (maybe_failure->IsFailure()) return maybe_failure;
|
|
|