Index: src/builtins/builtins-collections-gen.cc |
diff --git a/src/builtins/builtins-collections-gen.cc b/src/builtins/builtins-collections-gen.cc |
index d72e43b16df3842d3b63f4a3fb087d22523cbec4..6547c671013994b9a139ebd281dd2aee26ed977e 100644 |
--- a/src/builtins/builtins-collections-gen.cc |
+++ b/src/builtins/builtins-collections-gen.cc |
@@ -28,6 +28,14 @@ class CollectionsBuiltinsAssembler : public CodeStubAssembler { |
Node* CallGetRaw(Node* const table, Node* const key); |
template <typename CollectionType, int entrysize> |
Node* CallHasRaw(Node* const table, Node* const key); |
+ |
+ // Tries to find OrderedHashMap entry for given Smi key, jumps |
+ // to {entry_found} if the key is found, or to {not_found} if the |
+ // key was not found. Returns the node with the entry index (relative to |
+ // OrderedHashMap::kHashTableStartIndex). The node can only be used in the |
+ // {entry_found} branch. |
+ Node* FindOrderedHashMapEntryForSmiKey(Node* table, Node* key_tagged, |
+ Label* entry_found, Label* not_found); |
}; |
template <typename CollectionType> |
@@ -372,26 +380,138 @@ Node* CollectionsBuiltinsAssembler::CallHasRaw(Node* const table, |
Word32NotEqual(Word32And(result, Int32Constant(0xFF)), Int32Constant(0))); |
} |
+Node* CollectionsBuiltinsAssembler::FindOrderedHashMapEntryForSmiKey( |
+ Node* table, Node* key_tagged, Label* entry_found, Label* not_found) { |
+ // Compute the hash. |
+ Node* const key = SmiUntag(key_tagged); |
+ Node* const hash = |
+ ChangeInt32ToIntPtr(ComputeIntegerHash(key, Int32Constant(0))); |
Camillo Bruni
2017/06/28 11:31:16
uh, I think we should add a cctest to ensure the C
|
+ |
+ // Get the index of the bucket. |
+ Node* const number_of_buckets = SmiUntag( |
+ LoadFixedArrayElement(table, OrderedHashMap::kNumberOfBucketsIndex)); |
+ Node* const bucket = |
+ WordAnd(hash, IntPtrSub(number_of_buckets, IntPtrConstant(1))); |
+ Node* const first_entry = SmiUntag(LoadFixedArrayElement( |
+ table, bucket, OrderedHashMap::kHashTableStartIndex * kPointerSize)); |
+ |
+ Node* entry_start_position; |
+ // Walk the bucket chain. |
+ { |
+ VARIABLE(var_entry, MachineType::PointerRepresentation(), first_entry); |
+ Label loop(this, &var_entry), continue_next_entry(this); |
+ Goto(&loop); |
+ BIND(&loop); |
+ |
+ // If the entry index is the not-found sentinel, we are done. |
+ GotoIf( |
+ WordEqual(var_entry.value(), IntPtrConstant(OrderedHashMap::kNotFound)), |
+ not_found); |
+ |
+ // Make sure the entry index is within range. |
+ CSA_ASSERT( |
+ this, |
+ UintPtrLessThan( |
+ var_entry.value(), |
+ SmiUntag(SmiAdd( |
+ LoadFixedArrayElement(table, |
+ OrderedHashMap::kNumberOfElementsIndex), |
+ LoadFixedArrayElement( |
+ table, OrderedHashMap::kNumberOfDeletedElementsIndex))))); |
+ |
+ // Compute the index of the entry relative to kHashTableStartIndex. |
+ entry_start_position = |
+ IntPtrAdd(IntPtrMul(var_entry.value(), |
+ IntPtrConstant(OrderedHashMap::kEntrySize)), |
+ number_of_buckets); |
+ |
+ // Load the key from the entry. |
+ Node* const candidate_key = LoadFixedArrayElement( |
+ table, entry_start_position, |
+ OrderedHashMap::kHashTableStartIndex * kPointerSize); |
+ |
+ // If the key is the same, we are done. |
+ GotoIf(WordEqual(candidate_key, key_tagged), entry_found); |
+ |
+ // If the candidate key is smi, then it must be different (because |
+ // we already checked for equality above). |
+ GotoIf(TaggedIsSmi(candidate_key), &continue_next_entry); |
+ |
+ // If the candidate key is not smi, we still have to check if it is a heap |
+ // number with the same value. |
+ GotoIfNot(IsHeapNumber(candidate_key), &continue_next_entry); |
+ |
+ Node* const candidate_key_number = LoadHeapNumberValue(candidate_key); |
+ Node* const key_number = SmiToFloat64(key_tagged); |
+ |
+ GotoIf(Float64Equal(candidate_key_number, key_number), entry_found); |
+ |
+ Goto(&continue_next_entry); |
+ |
+ BIND(&continue_next_entry); |
+ // Load the index of the next entry in the bucket chain. |
+ var_entry.Bind(SmiUntag(LoadFixedArrayElement( |
+ table, entry_start_position, |
+ (OrderedHashMap::kHashTableStartIndex + OrderedHashMap::kChainOffset) * |
+ kPointerSize))); |
+ |
+ Goto(&loop); |
+ } |
+ return entry_start_position; |
+} |
+ |
TF_BUILTIN(MapGet, CollectionsBuiltinsAssembler) { |
Node* const receiver = Parameter(Descriptor::kReceiver); |
- Node* const key = Parameter(Descriptor::kKey); |
+ Node* const key_tagged = Parameter(Descriptor::kKey); |
Node* const context = Parameter(Descriptor::kContext); |
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, "Map.prototype.get"); |
Node* const table = LoadObjectField(receiver, JSMap::kTableOffset); |
- Return(CallGetRaw(table, key)); |
+ |
+ Label if_key_smi(this); |
+ GotoIf(TaggedIsSmi(key_tagged), &if_key_smi); |
+ |
+ Return(CallGetRaw(table, key_tagged)); |
+ |
+ BIND(&if_key_smi); |
+ Label entry_found(this), not_found(this); |
+ Node* entry_start_position = FindOrderedHashMapEntryForSmiKey( |
+ table, key_tagged, &entry_found, ¬_found); |
+ |
+ BIND(&entry_found); |
+ Return(LoadFixedArrayElement( |
+ table, entry_start_position, |
+ (OrderedHashMap::kHashTableStartIndex + OrderedHashMap::kValueOffset) * |
+ kPointerSize)); |
+ |
+ BIND(¬_found); |
+ Return(UndefinedConstant()); |
} |
TF_BUILTIN(MapHas, CollectionsBuiltinsAssembler) { |
Node* const receiver = Parameter(Descriptor::kReceiver); |
- Node* const key = Parameter(Descriptor::kKey); |
+ Node* const key_tagged = Parameter(Descriptor::kKey); |
Node* const context = Parameter(Descriptor::kContext); |
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, "Map.prototype.has"); |
Node* const table = LoadObjectField(receiver, JSMap::kTableOffset); |
- Return(CallHasRaw<OrderedHashMap, 2>(table, key)); |
+ |
+ Label if_key_smi(this); |
+ GotoIf(TaggedIsSmi(key_tagged), &if_key_smi); |
+ |
+ Return(CallHasRaw<OrderedHashMap, 2>(table, key_tagged)); |
+ |
+ BIND(&if_key_smi); |
+ Label entry_found(this), not_found(this); |
+ FindOrderedHashMapEntryForSmiKey(table, key_tagged, &entry_found, ¬_found); |
+ |
+ BIND(&entry_found); |
+ Return(TrueConstant()); |
+ |
+ BIND(¬_found); |
+ Return(FalseConstant()); |
} |
Camillo Bruni
2017/06/28 11:31:16
Now that we have the Smi fast-path there is no way
|
TF_BUILTIN(SetHas, CollectionsBuiltinsAssembler) { |