Chromium Code Reviews| Index: src/code-stub-assembler.cc |
| diff --git a/src/code-stub-assembler.cc b/src/code-stub-assembler.cc |
| index b03007755e5ee12c68c7a7747f02f13d67c197b1..e3b3e17c9c84579dcc3ad55e26e71ea647d148b3 100644 |
| --- a/src/code-stub-assembler.cc |
| +++ b/src/code-stub-assembler.cc |
| @@ -1335,13 +1335,15 @@ Node* CodeStubAssembler::StoreObjectFieldRoot(Node* object, int offset, |
| Node* CodeStubAssembler::StoreFixedArrayElement(Node* object, Node* index_node, |
| Node* value, |
| + int additional_offset, |
|
rmcilroy
2016/11/21 17:25:18
Would it be worth reordering these so that you don
Igor Sheludko
2016/11/22 12:05:07
+1. And if you put additional parameter after Writ
Jakob Kummerow
2016/11/22 13:47:57
Done.
|
| WriteBarrierMode barrier_mode, |
| ParameterMode parameter_mode) { |
| DCHECK(barrier_mode == SKIP_WRITE_BARRIER || |
| barrier_mode == UPDATE_WRITE_BARRIER); |
| - Node* offset = |
| - ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS, parameter_mode, |
| - FixedArray::kHeaderSize - kHeapObjectTag); |
| + int header_size = |
| + FixedArray::kHeaderSize + additional_offset - kHeapObjectTag; |
| + Node* offset = ElementOffsetFromIndex(index_node, FAST_HOLEY_ELEMENTS, |
| + parameter_mode, header_size); |
| MachineRepresentation rep = MachineRepresentation::kTagged; |
| if (barrier_mode == SKIP_WRITE_BARRIER) { |
| return StoreNoWriteBarrier(rep, object, offset, value); |
| @@ -4036,19 +4038,57 @@ Node* CodeStubAssembler::IntPtrMax(Node* left, Node* right) { |
| MachineType::PointerRepresentation()); |
| } |
| +template <class Dictionary> |
| +Node* CodeStubAssembler::GetNumberOfElements(Node* dictionary) { |
| + return LoadFixedArrayElement( |
| + dictionary, IntPtrConstant(Dictionary::kNumberOfElementsIndex), 0, |
| + INTPTR_PARAMETERS); |
| +} |
| + |
| +template <class Dictionary> |
| +void CodeStubAssembler::SetNumberOfElements(Node* dictionary, |
| + Node* num_elements_smi) { |
| + StoreFixedArrayElement( |
| + dictionary, IntPtrConstant(Dictionary::kNumberOfElementsIndex), |
| + num_elements_smi, 0, SKIP_WRITE_BARRIER, INTPTR_PARAMETERS); |
| +} |
| + |
| +template <class Dictionary> |
| +Node* CodeStubAssembler::GetCapacity(Node* dictionary) { |
| + return LoadFixedArrayElement(dictionary, |
| + IntPtrConstant(Dictionary::kCapacityIndex), 0, |
| + INTPTR_PARAMETERS); |
| +} |
| + |
| +template <class Dictionary> |
| +Node* CodeStubAssembler::GetNextEnumerationIndex(Node* dictionary) { |
| + return LoadFixedArrayElement( |
| + dictionary, IntPtrConstant(Dictionary::kNextEnumerationIndexIndex), 0, |
| + INTPTR_PARAMETERS); |
| +} |
| + |
| +template <class Dictionary> |
| +void CodeStubAssembler::SetNextEnumerationIndex(Node* dictionary, |
| + Node* next_enum_index_smi) { |
| + StoreFixedArrayElement( |
| + dictionary, IntPtrConstant(Dictionary::kNextEnumerationIndexIndex), |
| + next_enum_index_smi, 0, SKIP_WRITE_BARRIER, INTPTR_PARAMETERS); |
| +} |
| + |
| template <typename Dictionary> |
| void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, |
| Node* unique_name, Label* if_found, |
| Variable* var_name_index, |
| Label* if_not_found, |
| - int inlined_probes) { |
| + int inlined_probes, |
| + LookupMode mode) { |
| CSA_ASSERT(this, IsDictionary(dictionary)); |
| DCHECK_EQ(MachineType::PointerRepresentation(), var_name_index->rep()); |
| + DCHECK_IMPLIES(mode == kFindInsertionIndex, |
| + inlined_probes == 0 && if_found == nullptr); |
| Comment("NameDictionaryLookup"); |
| - Node* capacity = SmiUntag(LoadFixedArrayElement( |
| - dictionary, IntPtrConstant(Dictionary::kCapacityIndex), 0, |
| - INTPTR_PARAMETERS)); |
| + Node* capacity = SmiUntag(GetCapacity<Dictionary>(dictionary)); |
| Node* mask = IntPtrSub(capacity, IntPtrConstant(1)); |
| Node* hash = ChangeUint32ToWord(LoadNameHash(unique_name)); |
| @@ -4068,8 +4108,13 @@ void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, |
| count = IntPtrConstant(i + 1); |
| entry = WordAnd(IntPtrAdd(entry, count), mask); |
| } |
| + if (mode == kFindInsertionIndex) { |
| + // Appease the variable merging algorithm for "Goto(&loop)" below. |
| + var_name_index->Bind(IntPtrConstant(0)); |
| + } |
| Node* undefined = UndefinedConstant(); |
| + Node* the_hole = mode == kFindExisting ? nullptr : TheHoleConstant(); |
| Variable var_count(this, MachineType::PointerRepresentation()); |
| Variable var_entry(this, MachineType::PointerRepresentation()); |
| @@ -4089,7 +4134,12 @@ void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, |
| Node* current = |
| LoadFixedArrayElement(dictionary, index, 0, INTPTR_PARAMETERS); |
| GotoIf(WordEqual(current, undefined), if_not_found); |
| - GotoIf(WordEqual(current, unique_name), if_found); |
| + if (mode == kFindExisting) { |
| + GotoIf(WordEqual(current, unique_name), if_found); |
| + } else { |
| + DCHECK(mode == kFindInsertionIndex); |
|
Igor Sheludko
2016/11/22 12:05:08
DCHECK_EQ
Jakob Kummerow
2016/11/22 13:47:57
Done. (FWIW, I disagree with the preference -- I t
|
| + GotoIf(WordEqual(current, the_hole), if_not_found); |
| + } |
| // See Dictionary::NextProbe(). |
| count = IntPtrAdd(count, IntPtrConstant(1)); |
| @@ -4103,9 +4153,9 @@ void CodeStubAssembler::NameDictionaryLookup(Node* dictionary, |
| // Instantiate template methods to workaround GCC compilation issue. |
| template void CodeStubAssembler::NameDictionaryLookup<NameDictionary>( |
| - Node*, Node*, Label*, Variable*, Label*, int); |
| + Node*, Node*, Label*, Variable*, Label*, int, LookupMode); |
| template void CodeStubAssembler::NameDictionaryLookup<GlobalDictionary>( |
| - Node*, Node*, Label*, Variable*, Label*, int); |
| + Node*, Node*, Label*, Variable*, Label*, int, LookupMode); |
| Node* CodeStubAssembler::ComputeIntegerHash(Node* key, Node* seed) { |
| // See v8::internal::ComputeIntegerHash() |
| @@ -4131,9 +4181,7 @@ void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, |
| DCHECK_EQ(MachineType::PointerRepresentation(), var_entry->rep()); |
| Comment("NumberDictionaryLookup"); |
| - Node* capacity = SmiUntag(LoadFixedArrayElement( |
| - dictionary, IntPtrConstant(Dictionary::kCapacityIndex), 0, |
| - INTPTR_PARAMETERS)); |
| + Node* capacity = SmiUntag(GetCapacity<Dictionary>(dictionary)); |
| Node* mask = IntPtrSub(capacity, IntPtrConstant(1)); |
| Node* int32_seed; |
| @@ -4197,6 +4245,80 @@ void CodeStubAssembler::NumberDictionaryLookup(Node* dictionary, |
| } |
| } |
| +template <class Dictionary> |
| +void CodeStubAssembler::FindInsertionEntry(Node* dictionary, Node* key, |
| + Variable* var_key_index) { |
| + UNREACHABLE(); |
| +} |
| + |
| +template <> |
| +void CodeStubAssembler::FindInsertionEntry<NameDictionary>( |
| + Node* dictionary, Node* key, Variable* var_key_index) { |
| + Label done(this); |
| + NameDictionaryLookup<NameDictionary>(dictionary, key, nullptr, var_key_index, |
| + &done, 0, kFindInsertionIndex); |
| + Bind(&done); |
| +} |
| + |
| +template <class Dictionary> |
| +void CodeStubAssembler::Add(Node* dictionary, Node* key, Node* value, |
|
Igor Sheludko
2016/11/22 12:05:07
This implementation is not fully applicable for Gl
Jakob Kummerow
2016/11/22 13:47:57
Done. (Pulled out the second half as "InsertEntry<
|
| + Label* bailout) { |
| + Node* capacity = GetCapacity<Dictionary>(dictionary); |
| + Node* nof = GetNumberOfElements<Dictionary>(dictionary); |
| + Node* new_nof = SmiAdd(nof, SmiConstant(1)); |
| + // Require 33% to still be free after adding additional_elements. |
| + // This is a simplification of the C++ implementation's behavior, which |
| + // also rehashes the dictionary when there are too many deleted elements. |
| + // Computing "x + (x >> 1)" on a Smi x does not return a valid Smi! |
| + // But that's OK here because it's only used for a comparison. |
| + Node* required_capacity_pseudo_smi = SmiAdd(new_nof, WordShr(new_nof, 1)); |
| + GotoIf(UintPtrLessThan(capacity, required_capacity_pseudo_smi), bailout); |
| + Node* enum_index = nullptr; |
| + if (Dictionary::kIsEnumerable) { |
| + enum_index = GetNextEnumerationIndex<Dictionary>(dictionary); |
| + Node* new_enum_index = SmiAdd(enum_index, SmiConstant(1)); |
| + Node* max_enum_index = SmiConstant( |
| + Smi::FromInt(PropertyDetails::DictionaryStorageField::kMax)); |
|
Igor Sheludko
2016/11/22 12:05:07
Can you drop Smi::FromInt?
Jakob Kummerow
2016/11/22 13:47:57
Done.
|
| + GotoIf(UintPtrGreaterThan(new_enum_index, max_enum_index), bailout); |
| + |
| + // No more bailouts after this point. |
| + // Operations from here on can have side effects. |
| + |
| + SetNextEnumerationIndex<Dictionary>(dictionary, new_enum_index); |
| + } else { |
| + USE(enum_index); |
| + } |
| + SetNumberOfElements<Dictionary>(dictionary, new_nof); |
| + |
| + Variable var_key_index(this, MachineType::PointerRepresentation()); |
| + FindInsertionEntry<Dictionary>(dictionary, key, &var_key_index); |
| + Node* index = var_key_index.value(); |
| + StoreFixedArrayElement(dictionary, index, key, 0, UPDATE_WRITE_BARRIER, |
| + INTPTR_PARAMETERS); |
| + const int kNameToValueOffset = |
| + (Dictionary::kEntryValueIndex - Dictionary::kEntryKeyIndex) * |
| + kPointerSize; |
| + StoreFixedArrayElement(dictionary, index, value, kNameToValueOffset, |
| + UPDATE_WRITE_BARRIER, INTPTR_PARAMETERS); |
| + if (Dictionary::kIsEnumerable) { |
|
Igor Sheludko
2016/11/22 12:05:07
Shoudn't we also set details if the dictionary is
Jakob Kummerow
2016/11/22 13:47:57
Oops, good point. Done.
|
| + const int kInitialIndex = 0; |
| + PropertyDetails d(NONE, DATA, kInitialIndex, PropertyCellType::kNoCell); |
| + Node* details = SmiConstant(d.AsSmi()); |
| + enum_index = |
| + WordShl(enum_index, PropertyDetails::DictionaryStorageField::kShift); |
| + STATIC_ASSERT(kInitialIndex == 0); |
| + details = WordOr(details, enum_index); |
| + const int kNameToDetailsOffset = |
| + (Dictionary::kEntryDetailsIndex - Dictionary::kEntryKeyIndex) * |
| + kPointerSize; |
| + StoreFixedArrayElement(dictionary, index, details, kNameToDetailsOffset, |
| + SKIP_WRITE_BARRIER, INTPTR_PARAMETERS); |
| + } |
| +} |
| + |
| +template void CodeStubAssembler::Add<NameDictionary>(Node*, Node*, Node*, |
| + Label*); |
| + |
| void CodeStubAssembler::DescriptorLookupLinear(Node* unique_name, |
| Node* descriptors, Node* nof, |
| Label* if_found, |
| @@ -4982,7 +5104,7 @@ void CodeStubAssembler::UpdateFeedback(compiler::Node* feedback, |
| Node* previous_feedback = |
| LoadFixedArrayElement(type_feedback_vector, slot_id); |
| Node* combined_feedback = SmiOr(previous_feedback, SmiFromWord32(feedback)); |
| - StoreFixedArrayElement(type_feedback_vector, slot_id, combined_feedback, |
| + StoreFixedArrayElement(type_feedback_vector, slot_id, combined_feedback, 0, |
| SKIP_WRITE_BARRIER); |
| } |
| @@ -5193,7 +5315,7 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key, |
| CSA_ASSERT(this, WordNotEqual(result, TheHoleConstant())); |
| var_result.Bind(result); |
| } else { |
| - StoreFixedArrayElement(the_context, mapped_index, value, |
| + StoreFixedArrayElement(the_context, mapped_index, value, 0, |
| UPDATE_WRITE_BARRIER, INTPTR_PARAMETERS); |
| } |
| Goto(&end); |
| @@ -5217,7 +5339,7 @@ Node* CodeStubAssembler::EmitKeyedSloppyArguments(Node* receiver, Node* key, |
| GotoIf(WordEqual(result, TheHoleConstant()), bailout); |
| var_result.Bind(result); |
| } else { |
| - StoreFixedArrayElement(backing_store, key, value, UPDATE_WRITE_BARRIER, |
| + StoreFixedArrayElement(backing_store, key, value, 0, UPDATE_WRITE_BARRIER, |
| INTPTR_PARAMETERS); |
| } |
| Goto(&end); |
| @@ -5300,7 +5422,7 @@ void CodeStubAssembler::StoreElement(Node* elements, ElementsKind kind, |
| value = Float64SilenceNaN(value); |
| StoreFixedDoubleArrayElement(elements, index, value, mode); |
| } else { |
| - StoreFixedArrayElement(elements, index, value, barrier_mode, mode); |
| + StoreFixedArrayElement(elements, index, value, 0, barrier_mode, mode); |
| } |
| } |
| @@ -5692,7 +5814,7 @@ Node* CodeStubAssembler::CreateAllocationSiteInFeedbackVector( |
| StoreObjectField(site, AllocationSite::kWeakNextOffset, next_site); |
| StoreNoWriteBarrier(MachineRepresentation::kTagged, site_list, site); |
| - StoreFixedArrayElement(feedback_vector, slot, site, UPDATE_WRITE_BARRIER, |
| + StoreFixedArrayElement(feedback_vector, slot, site, 0, UPDATE_WRITE_BARRIER, |
| CodeStubAssembler::SMI_PARAMETERS); |
| return site; |
| } |
| @@ -5710,7 +5832,7 @@ Node* CodeStubAssembler::CreateWeakCellInFeedbackVector(Node* feedback_vector, |
| Heap::kTheHoleValueRootIndex); |
| // Store the WeakCell in the feedback vector. |
| - StoreFixedArrayElement(feedback_vector, slot, cell, UPDATE_WRITE_BARRIER, |
| + StoreFixedArrayElement(feedback_vector, slot, cell, 0, UPDATE_WRITE_BARRIER, |
| CodeStubAssembler::SMI_PARAMETERS); |
| return cell; |
| } |