Commit 130cee39 authored by Benedikt Meurer's avatar Benedikt Meurer Committed by Commit Bot

[collections] Refactor map entry lookup and make naming more consistent.

Rename the MapLookupHashIndex builtin to FindOrderedHashMapEntry and
also rename the TurboFan operators LookupHashStorageIndex and
LookupSigned32HashStorageIndex to FindOrderedHashMapEntry and
FindOrderedHashMapEntryForInt32Key respectively. This way the naming is
more consistent and it's immediately obvious from the operator name that
this operator deals with OrderedHashMaps, which wasn't clear before.

Also fix the result of the operation to be either -1 or the index of
the entry relative to the hash table start (that is, no longer eagerly
add hash table start plus value offset to the entry index). This removes
this non-foldable integer additon from TurboFan code for both Map#get
and Map#has.

Drive-by-fix: Also provide more concrete types for the
FindOrderedHashMapEntry operators.

Bug: v8:5049
Change-Id: I418d107b806f3031a52a525cffc20456dc2342db
Reviewed-on: https://chromium-review.googlesource.com/707414Reviewed-by: 's avatarSathya Gunasekaran <gsathya@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48404}
parent f42017e1
......@@ -884,14 +884,18 @@ TF_BUILTIN(MapPrototypeGet, CollectionsBuiltinsAssembler) {
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, "Map.prototype.get");
Node* const table = LoadObjectField(receiver, JSMap::kTableOffset);
Node* index = CallBuiltin(Builtins::kMapLookupHashIndex, context, table, key);
Node* index =
CallBuiltin(Builtins::kFindOrderedHashMapEntry, context, table, key);
Label if_found(this), if_not_found(this);
Branch(SmiGreaterThanOrEqual(index, SmiConstant(0)), &if_found,
&if_not_found);
BIND(&if_found);
Return(LoadFixedArrayElement(table, SmiUntag(index)));
Return(LoadFixedArrayElement(
table, SmiUntag(index),
(OrderedHashMap::kHashTableStartIndex + OrderedHashMap::kValueOffset) *
kPointerSize));
BIND(&if_not_found);
Return(UndefinedConstant());
......@@ -905,7 +909,8 @@ TF_BUILTIN(MapPrototypeHas, CollectionsBuiltinsAssembler) {
ThrowIfNotInstanceType(context, receiver, JS_MAP_TYPE, "Map.prototype.has");
Node* const table = LoadObjectField(receiver, JSMap::kTableOffset);
Node* index = CallBuiltin(Builtins::kMapLookupHashIndex, context, table, key);
Node* index =
CallBuiltin(Builtins::kFindOrderedHashMapEntry, context, table, key);
Label if_found(this), if_not_found(this);
Branch(SmiGreaterThanOrEqual(index, SmiConstant(0)), &if_found,
......@@ -1688,7 +1693,7 @@ void CollectionsBuiltinsAssembler::TryLookupOrderedHashTableIndex(
}
}
TF_BUILTIN(MapLookupHashIndex, CollectionsBuiltinsAssembler) {
TF_BUILTIN(FindOrderedHashMapEntry, CollectionsBuiltinsAssembler) {
Node* const table = Parameter(Descriptor::kTable);
Node* const key = Parameter(Descriptor::kKey);
Node* const context = Parameter(Descriptor::kContext);
......@@ -1701,10 +1706,7 @@ TF_BUILTIN(MapLookupHashIndex, CollectionsBuiltinsAssembler) {
table, key, context, &entry_start_position, &entry_found, &not_found);
BIND(&entry_found);
Node* index = IntPtrAdd(entry_start_position.value(),
IntPtrConstant(OrderedHashMap::kHashTableStartIndex +
OrderedHashMap::kValueOffset));
Return(SmiTag(index));
Return(SmiTag(entry_start_position.value()));
BIND(&not_found);
Return(SmiConstant(-1));
......
......@@ -553,7 +553,7 @@ namespace internal {
TFH(LoadGlobalICInsideTypeofTrampoline, LoadGlobal) \
\
/* Map */ \
TFS(MapLookupHashIndex, kTable, kKey) \
TFS(FindOrderedHashMapEntry, kTable, kKey) \
TFJ(MapConstructor, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
TFJ(MapPrototypeSet, 2, kKey, kValue) \
TFJ(MapPrototypeDelete, 1, kKey) \
......
......@@ -1078,6 +1078,16 @@ FieldAccess AccessBuilder::ForOrderedHashTableBaseNumberOfElements() {
return access;
}
// static
ElementAccess AccessBuilder::ForOrderedHashMapEntryValue() {
ElementAccess const access = {kTaggedBase,
OrderedHashMap::kHashTableStartOffset +
OrderedHashMap::kValueOffset * kPointerSize,
Type::Any(), MachineType::AnyTagged(),
kFullWriteBarrier};
return access;
}
// static
FieldAccess AccessBuilder::ForDictionaryMaxNumberKey() {
FieldAccess access = {
......
......@@ -300,6 +300,9 @@ class V8_EXPORT_PRIVATE AccessBuilder final
static FieldAccess ForOrderedHashTableBaseNumberOfElements();
static FieldAccess ForOrderedHashTableBaseNumberOfDeletedElements();
// Provides access to OrderedHashMap elements.
static ElementAccess ForOrderedHashMapEntryValue();
// Provides access to Dictionary fields.
static FieldAccess ForDictionaryMaxNumberKey();
static FieldAccess ForDictionaryNextEnumerationIndex();
......
......@@ -894,11 +894,11 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kStoreSignedSmallElement:
LowerStoreSignedSmallElement(node);
break;
case IrOpcode::kLookupHashStorageIndex:
result = LowerLookupHashStorageIndex(node);
case IrOpcode::kFindOrderedHashMapEntry:
result = LowerFindOrderedHashMapEntry(node);
break;
case IrOpcode::kLookupSigned32HashStorageIndex:
result = LowerLookupSigned32HashStorageIndex(node);
case IrOpcode::kFindOrderedHashMapEntryForInt32Key:
result = LowerFindOrderedHashMapEntryForInt32Key(node);
break;
case IrOpcode::kTransitionAndStoreElement:
LowerTransitionAndStoreElement(node);
......@@ -3697,13 +3697,13 @@ Maybe<Node*> EffectControlLinearizer::LowerFloat64RoundTruncate(Node* node) {
return Just(done.PhiAt(0));
}
Node* EffectControlLinearizer::LowerLookupHashStorageIndex(Node* node) {
Node* EffectControlLinearizer::LowerFindOrderedHashMapEntry(Node* node) {
Node* table = NodeProperties::GetValueInput(node, 0);
Node* key = NodeProperties::GetValueInput(node, 1);
{
Callable const callable =
Builtins::CallableFor(isolate(), Builtins::kMapLookupHashIndex);
Builtins::CallableFor(isolate(), Builtins::kFindOrderedHashMapEntry);
Operator::Properties const properties = node->op()->properties();
CallDescriptor::Flags const flags = CallDescriptor::kNoFlags;
CallDescriptor* desc = Linkage::GetStubCallDescriptor(
......@@ -3727,7 +3727,8 @@ Node* EffectControlLinearizer::ComputeIntegerHash(Node* value) {
return value;
}
Node* EffectControlLinearizer::LowerLookupSigned32HashStorageIndex(Node* node) {
Node* EffectControlLinearizer::LowerFindOrderedHashMapEntryForInt32Key(
Node* node) {
Node* table = NodeProperties::GetValueInput(node, 0);
Node* key = NodeProperties::GetValueInput(node, 1);
......@@ -3750,16 +3751,15 @@ Node* EffectControlLinearizer::LowerLookupSigned32HashStorageIndex(Node* node) {
{
Node* entry = loop.PhiAt(0);
Node* check =
__ WordEqual(entry, __ IntPtrConstant(OrderedHashTableBase::kNotFound));
__ WordEqual(entry, __ IntPtrConstant(OrderedHashMap::kNotFound));
__ GotoIf(check, &done, __ Int32Constant(-1));
Node* entry_start = __ IntAdd(
entry = __ IntAdd(
__ IntMul(entry, __ IntPtrConstant(OrderedHashMap::kEntrySize)),
number_of_buckets);
Node* candidate_key = __ Load(
MachineType::AnyTagged(), table,
__ IntAdd(__ WordShl(entry_start, __ IntPtrConstant(kPointerSizeLog2)),
__ IntAdd(__ WordShl(entry, __ IntPtrConstant(kPointerSizeLog2)),
__ IntPtrConstant(OrderedHashMap::kHashTableStartOffset -
kHeapObjectTag)));
......@@ -3782,9 +3782,7 @@ Node* EffectControlLinearizer::LowerLookupSigned32HashStorageIndex(Node* node) {
__ Bind(&if_match);
{
Node* index = ChangeIntPtrToInt32(__ IntAdd(
entry_start, __ IntPtrConstant(OrderedHashMap::kHashTableStartIndex +
OrderedHashMap::kValueOffset)));
Node* index = ChangeIntPtrToInt32(entry);
__ Goto(&done, index);
}
......@@ -3793,7 +3791,7 @@ Node* EffectControlLinearizer::LowerLookupSigned32HashStorageIndex(Node* node) {
Node* next_entry = ChangeSmiToIntPtr(__ Load(
MachineType::TaggedSigned(), table,
__ IntAdd(
__ WordShl(entry_start, __ IntPtrConstant(kPointerSizeLog2)),
__ WordShl(entry, __ IntPtrConstant(kPointerSizeLog2)),
__ IntPtrConstant(OrderedHashMap::kHashTableStartOffset +
OrderedHashMap::kChainOffset * kPointerSize -
kHeapObjectTag))));
......
......@@ -126,8 +126,8 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
Node* LowerLoadTypedElement(Node* node);
void LowerStoreTypedElement(Node* node);
void LowerStoreSignedSmallElement(Node* node);
Node* LowerLookupHashStorageIndex(Node* node);
Node* LowerLookupSigned32HashStorageIndex(Node* node);
Node* LowerFindOrderedHashMapEntry(Node* node);
Node* LowerFindOrderedHashMapEntryForInt32Key(Node* node);
void LowerTransitionAndStoreElement(Node* node);
void LowerRuntimeAbort(Node* node);
......
......@@ -1827,14 +1827,14 @@ Reduction JSBuiltinReducer::ReduceMapGet(Node* node) {
if (!HasInstanceTypeWitness(receiver, effect, JS_MAP_TYPE)) return NoChange();
Node* storage = effect = graph()->NewNode(
Node* table = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
effect, control);
Node* index = effect = graph()->NewNode(
simplified()->LookupHashStorageIndex(), storage, key, effect, control);
Node* entry = effect = graph()->NewNode(
simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
Node* check = graph()->NewNode(simplified()->NumberEqual(), index,
Node* check = graph()->NewNode(simplified()->NumberEqual(), entry,
jsgraph()->MinusOneConstant());
Node* branch = graph()->NewNode(common()->Branch(), check, control);
......@@ -1848,8 +1848,8 @@ Reduction JSBuiltinReducer::ReduceMapGet(Node* node) {
Node* if_false = graph()->NewNode(common()->IfFalse(), branch);
Node* efalse = effect;
Node* vfalse = efalse = graph()->NewNode(
simplified()->LoadElement(AccessBuilder::ForFixedArrayElement()), storage,
index, efalse, if_false);
simplified()->LoadElement(AccessBuilder::ForOrderedHashMapEntryValue()),
table, entry, efalse, if_false);
control = graph()->NewNode(common()->Merge(2), if_true, if_false);
Node* value = graph()->NewNode(
......@@ -1870,12 +1870,12 @@ Reduction JSBuiltinReducer::ReduceMapHas(Node* node) {
if (!HasInstanceTypeWitness(receiver, effect, JS_MAP_TYPE)) return NoChange();
Node* storage = effect = graph()->NewNode(
Node* table = effect = graph()->NewNode(
simplified()->LoadField(AccessBuilder::ForJSCollectionTable()), receiver,
effect, control);
Node* index = effect = graph()->NewNode(
simplified()->LookupHashStorageIndex(), storage, key, effect, control);
simplified()->FindOrderedHashMapEntry(), table, key, effect, control);
Node* check = graph()->NewNode(simplified()->NumberEqual(), index,
jsgraph()->MinusOneConstant());
......
......@@ -317,67 +317,67 @@
#define SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(V) V(SpeculativeToNumber)
#define SIMPLIFIED_OTHER_OP_LIST(V) \
V(PlainPrimitiveToNumber) \
V(PlainPrimitiveToWord32) \
V(PlainPrimitiveToFloat64) \
V(BooleanNot) \
V(StringCharAt) \
V(StringCharCodeAt) \
V(SeqStringCharCodeAt) \
V(StringFromCharCode) \
V(StringFromCodePoint) \
V(StringIndexOf) \
V(StringToLowerCaseIntl) \
V(StringToUpperCaseIntl) \
V(CheckBounds) \
V(CheckIf) \
V(CheckMaps) \
V(CheckNumber) \
V(CheckInternalizedString) \
V(CheckReceiver) \
V(CheckString) \
V(CheckSeqString) \
V(CheckSymbol) \
V(CheckSmi) \
V(CheckHeapObject) \
V(CheckFloat64Hole) \
V(CheckNotTaggedHole) \
V(CompareMaps) \
V(ConvertTaggedHoleToUndefined) \
V(Allocate) \
V(LoadFieldByIndex) \
V(LoadField) \
V(LoadElement) \
V(LoadTypedElement) \
V(StoreField) \
V(StoreElement) \
V(StoreTypedElement) \
V(StoreSignedSmallElement) \
V(TransitionAndStoreElement) \
V(ObjectIsArrayBufferView) \
V(ObjectIsCallable) \
V(ObjectIsDetectableCallable) \
V(ObjectIsMinusZero) \
V(ObjectIsNaN) \
V(ObjectIsNonCallable) \
V(ObjectIsNumber) \
V(ObjectIsReceiver) \
V(ObjectIsSmi) \
V(ObjectIsString) \
V(ObjectIsSymbol) \
V(ObjectIsUndetectable) \
V(ArgumentsFrame) \
V(ArgumentsLength) \
V(NewDoubleElements) \
V(NewSmiOrObjectElements) \
V(NewArgumentsElements) \
V(ArrayBufferWasNeutered) \
V(EnsureWritableFastElements) \
V(MaybeGrowFastElements) \
V(TransitionElementsKind) \
V(LookupHashStorageIndex) \
V(LookupSigned32HashStorageIndex) \
#define SIMPLIFIED_OTHER_OP_LIST(V) \
V(PlainPrimitiveToNumber) \
V(PlainPrimitiveToWord32) \
V(PlainPrimitiveToFloat64) \
V(BooleanNot) \
V(StringCharAt) \
V(StringCharCodeAt) \
V(SeqStringCharCodeAt) \
V(StringFromCharCode) \
V(StringFromCodePoint) \
V(StringIndexOf) \
V(StringToLowerCaseIntl) \
V(StringToUpperCaseIntl) \
V(CheckBounds) \
V(CheckIf) \
V(CheckMaps) \
V(CheckNumber) \
V(CheckInternalizedString) \
V(CheckReceiver) \
V(CheckString) \
V(CheckSeqString) \
V(CheckSymbol) \
V(CheckSmi) \
V(CheckHeapObject) \
V(CheckFloat64Hole) \
V(CheckNotTaggedHole) \
V(CompareMaps) \
V(ConvertTaggedHoleToUndefined) \
V(Allocate) \
V(LoadFieldByIndex) \
V(LoadField) \
V(LoadElement) \
V(LoadTypedElement) \
V(StoreField) \
V(StoreElement) \
V(StoreTypedElement) \
V(StoreSignedSmallElement) \
V(TransitionAndStoreElement) \
V(ObjectIsArrayBufferView) \
V(ObjectIsCallable) \
V(ObjectIsDetectableCallable) \
V(ObjectIsMinusZero) \
V(ObjectIsNaN) \
V(ObjectIsNonCallable) \
V(ObjectIsNumber) \
V(ObjectIsReceiver) \
V(ObjectIsSmi) \
V(ObjectIsString) \
V(ObjectIsSymbol) \
V(ObjectIsUndetectable) \
V(ArgumentsFrame) \
V(ArgumentsLength) \
V(NewDoubleElements) \
V(NewSmiOrObjectElements) \
V(NewArgumentsElements) \
V(ArrayBufferWasNeutered) \
V(EnsureWritableFastElements) \
V(MaybeGrowFastElements) \
V(TransitionElementsKind) \
V(FindOrderedHashMapEntry) \
V(FindOrderedHashMapEntryForInt32Key) \
V(RuntimeAbort)
#define SIMPLIFIED_OP_LIST(V) \
......
......@@ -2927,14 +2927,15 @@ class RepresentationSelector {
// Assume the output is tagged.
return SetOutput(node, MachineRepresentation::kTagged);
case IrOpcode::kLookupHashStorageIndex: {
case IrOpcode::kFindOrderedHashMapEntry: {
Type* const key_type = TypeOf(node->InputAt(1));
if (key_type->Is(Type::Signed32())) {
VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32);
if (lower()) {
NodeProperties::ChangeOp(
node, lowering->simplified()->LookupSigned32HashStorageIndex());
node,
lowering->simplified()->FindOrderedHashMapEntryForInt32Key());
}
} else {
VisitBinop(node, UseInfo::AnyTagged(),
......
......@@ -589,20 +589,21 @@ struct SimplifiedOperatorGlobalCache final {
};
ArrayBufferWasNeuteredOperator kArrayBufferWasNeutered;
struct LookupHashStorageIndexOperator final : public Operator {
LookupHashStorageIndexOperator()
: Operator(IrOpcode::kLookupHashStorageIndex, Operator::kEliminatable,
"LookupHashStorageIndex", 2, 1, 1, 1, 1, 0) {}
struct FindOrderedHashMapEntryOperator final : public Operator {
FindOrderedHashMapEntryOperator()
: Operator(IrOpcode::kFindOrderedHashMapEntry, Operator::kEliminatable,
"FindOrderedHashMapEntry", 2, 1, 1, 1, 1, 0) {}
};
LookupHashStorageIndexOperator kLookupHashStorageIndex;
FindOrderedHashMapEntryOperator kFindOrderedHashMapEntry;
struct LookupSigned32HashStorageIndexOperator final : public Operator {
LookupSigned32HashStorageIndexOperator()
: Operator(IrOpcode::kLookupSigned32HashStorageIndex,
Operator::kEliminatable, "LookupSigned32HashStorageIndex", 2,
1, 1, 1, 1, 0) {}
struct FindOrderedHashMapEntryForInt32KeyOperator final : public Operator {
FindOrderedHashMapEntryForInt32KeyOperator()
: Operator(IrOpcode::kFindOrderedHashMapEntryForInt32Key,
Operator::kEliminatable,
"FindOrderedHashMapEntryForInt32Key", 2, 1, 1, 1, 1, 0) {}
};
LookupSigned32HashStorageIndexOperator kLookupSigned32HashStorageIndex;
FindOrderedHashMapEntryForInt32KeyOperator
kFindOrderedHashMapEntryForInt32Key;
struct ArgumentsFrameOperator final : public Operator {
ArgumentsFrameOperator()
......@@ -780,8 +781,8 @@ PURE_OP_LIST(GET_FROM_CACHE)
CHECKED_OP_LIST(GET_FROM_CACHE)
GET_FROM_CACHE(ArrayBufferWasNeutered)
GET_FROM_CACHE(ArgumentsFrame)
GET_FROM_CACHE(LookupHashStorageIndex)
GET_FROM_CACHE(LookupSigned32HashStorageIndex)
GET_FROM_CACHE(FindOrderedHashMapEntry)
GET_FROM_CACHE(FindOrderedHashMapEntryForInt32Key)
GET_FROM_CACHE(LoadFieldByIndex)
#undef GET_FROM_CACHE
......
......@@ -373,8 +373,8 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
const Operator* StringToLowerCaseIntl();
const Operator* StringToUpperCaseIntl();
const Operator* LookupHashStorageIndex();
const Operator* LookupSigned32HashStorageIndex();
const Operator* FindOrderedHashMapEntry();
const Operator* FindOrderedHashMapEntryForInt32Key();
const Operator* SpeculativeToNumber(NumberOperationHint hint);
......
......@@ -2056,12 +2056,12 @@ Type* Typer::Visitor::TypeArrayBufferWasNeutered(Node* node) {
return Type::Boolean();
}
Type* Typer::Visitor::TypeLookupHashStorageIndex(Node* node) {
return Type::SignedSmall();
Type* Typer::Visitor::TypeFindOrderedHashMapEntry(Node* node) {
return Type::Range(-1.0, FixedArray::kMaxLength, zone());
}
Type* Typer::Visitor::TypeLookupSigned32HashStorageIndex(Node* node) {
return Type::SignedSmall();
Type* Typer::Visitor::TypeFindOrderedHashMapEntryForInt32Key(Node* node) {
return Type::Range(-1.0, FixedArray::kMaxLength, zone());
}
Type* Typer::Visitor::TypeRuntimeAbort(Node* node) { UNREACHABLE(); }
......
......@@ -1026,11 +1026,11 @@ void Verifier::Visitor::Check(Node* node) {
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::Boolean());
break;
case IrOpcode::kLookupHashStorageIndex:
case IrOpcode::kFindOrderedHashMapEntry:
CheckValueInputIs(node, 0, Type::Any());
CheckTypeIs(node, Type::SignedSmall());
break;
case IrOpcode::kLookupSigned32HashStorageIndex:
case IrOpcode::kFindOrderedHashMapEntryForInt32Key:
CheckValueInputIs(node, 0, Type::Any());
CheckValueInputIs(node, 1, Type::Signed32());
CheckTypeIs(node, Type::SignedSmall());
......
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