[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/707414
Reviewed-by: Sathya Gunasekaran <gsathya@chromium.org>
Commit-Queue: Benedikt Meurer <bmeurer@chromium.org>
Cr-Commit-Position: refs/heads/master@{#48404}
This commit is contained in:
Benedikt Meurer 2017-10-09 20:41:12 +02:00 committed by Commit Bot
parent f42017e1ba
commit 130cee39ef
13 changed files with 133 additions and 118 deletions

View File

@ -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));

View File

@ -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) \

View File

@ -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 = {

View File

@ -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();

View File

@ -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))));

View File

@ -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);

View File

@ -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());

View File

@ -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) \

View File

@ -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(),

View File

@ -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

View File

@ -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);

View File

@ -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(); }

View File

@ -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());