[turbofan] Introduce LookupSigned32HashStorageIndex specialization of Map#get.
This adds a new operator LookupSigned32HashStorageIndex, which is a specialization of the general LookupHashStorageIndex for Map#get that is used when TurboFan knows that the key is in Signed32 range. This improves the execution time of the ARES6 Basic test locally by around 5% and seems to make sense in general. Bug: v8:6410, v8:6354, v8:6278, v8:6344 Change-Id: I78dcbc9cc855a4109e1690d8cd14fbc88fd89861 Reviewed-on: https://chromium-review.googlesource.com/706787 Reviewed-by: Jaroslav Sevcik <jarin@chromium.org> Commit-Queue: Benedikt Meurer <bmeurer@chromium.org> Cr-Commit-Position: refs/heads/master@{#48361}
This commit is contained in:
parent
0e3b6bea6d
commit
1aa09302a0
@ -838,6 +838,9 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
|
||||
case IrOpcode::kLookupHashStorageIndex:
|
||||
result = LowerLookupHashStorageIndex(node);
|
||||
break;
|
||||
case IrOpcode::kLookupSigned32HashStorageIndex:
|
||||
result = LowerLookupSigned32HashStorageIndex(node);
|
||||
break;
|
||||
case IrOpcode::kLoadHashMapValue:
|
||||
result = LowerLoadHashMapValue(node);
|
||||
case IrOpcode::kTransitionAndStoreElement:
|
||||
@ -2701,15 +2704,31 @@ Node* EffectControlLinearizer::ChangeInt32ToSmi(Node* value) {
|
||||
return __ WordShl(value, SmiShiftBitsConstant());
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
|
||||
Node* EffectControlLinearizer::ChangeIntPtrToInt32(Node* value) {
|
||||
if (machine()->Is64()) {
|
||||
value = __ TruncateInt64ToInt32(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::ChangeUint32ToUintPtr(Node* value) {
|
||||
if (machine()->Is64()) {
|
||||
value = __ ChangeUint32ToUint64(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::ChangeUint32ToSmi(Node* value) {
|
||||
value = ChangeUint32ToUintPtr(value);
|
||||
return __ WordShl(value, SmiShiftBitsConstant());
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::ChangeSmiToIntPtr(Node* value) {
|
||||
return __ WordSar(value, SmiShiftBitsConstant());
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::ChangeSmiToInt32(Node* value) {
|
||||
value = __ WordSar(value, SmiShiftBitsConstant());
|
||||
value = ChangeSmiToIntPtr(value);
|
||||
if (machine()->Is64()) {
|
||||
value = __ TruncateInt64ToInt32(value);
|
||||
}
|
||||
@ -3570,6 +3589,97 @@ Node* EffectControlLinearizer::LowerLookupHashStorageIndex(Node* node) {
|
||||
}
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::ComputeIntegerHash(Node* value) {
|
||||
// See v8::internal::ComputeIntegerHash()
|
||||
value = __ Int32Add(__ Word32Xor(value, __ Int32Constant(0xffffffff)),
|
||||
__ Word32Shl(value, __ Int32Constant(15)));
|
||||
value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(12)));
|
||||
value = __ Int32Add(value, __ Word32Shl(value, __ Int32Constant(2)));
|
||||
value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(4)));
|
||||
value = __ Int32Mul(value, __ Int32Constant(2057));
|
||||
value = __ Word32Xor(value, __ Word32Shr(value, __ Int32Constant(16)));
|
||||
value = __ Word32And(value, __ Int32Constant(0x3fffffff));
|
||||
return value;
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::LowerLookupSigned32HashStorageIndex(Node* node) {
|
||||
Node* table = NodeProperties::GetValueInput(node, 0);
|
||||
Node* key = NodeProperties::GetValueInput(node, 1);
|
||||
|
||||
// Compute the integer hash code.
|
||||
Node* hash = ChangeUint32ToUintPtr(ComputeIntegerHash(key));
|
||||
|
||||
Node* number_of_buckets = ChangeSmiToIntPtr(__ LoadField(
|
||||
AccessBuilder::ForOrderedHashTableBaseNumberOfBuckets(), table));
|
||||
hash = __ WordAnd(hash, __ IntSub(number_of_buckets, __ IntPtrConstant(1)));
|
||||
Node* first_entry = ChangeSmiToIntPtr(__ Load(
|
||||
MachineType::TaggedSigned(), table,
|
||||
__ IntAdd(__ WordShl(hash, __ IntPtrConstant(kPointerSizeLog2)),
|
||||
__ IntPtrConstant(OrderedHashMap::kHashTableStartOffset -
|
||||
kHeapObjectTag))));
|
||||
|
||||
auto loop = __ MakeLoopLabel(MachineType::PointerRepresentation());
|
||||
auto done = __ MakeLabel(MachineRepresentation::kWord32);
|
||||
__ Goto(&loop, first_entry);
|
||||
__ Bind(&loop);
|
||||
{
|
||||
Node* entry = loop.PhiAt(0);
|
||||
Node* check =
|
||||
__ WordEqual(entry, __ IntPtrConstant(OrderedHashTableBase::kNotFound));
|
||||
__ GotoIf(check, &done, __ Int32Constant(-1));
|
||||
|
||||
Node* entry_start = __ IntAdd(
|
||||
__ IntMul(entry, __ IntPtrConstant(OrderedHashMap::kEntrySize)),
|
||||
number_of_buckets);
|
||||
|
||||
Node* candidate_key = __ Load(
|
||||
MachineType::AnyTagged(), table,
|
||||
__ IntAdd(__ WordShl(entry_start, __ IntPtrConstant(kPointerSizeLog2)),
|
||||
__ IntPtrConstant(OrderedHashMap::kHashTableStartOffset -
|
||||
kHeapObjectTag)));
|
||||
|
||||
auto if_match = __ MakeLabel();
|
||||
auto if_notmatch = __ MakeLabel();
|
||||
auto if_notsmi = __ MakeDeferredLabel();
|
||||
__ GotoIfNot(ObjectIsSmi(candidate_key), &if_notsmi);
|
||||
__ Branch(__ Word32Equal(ChangeSmiToInt32(candidate_key), key), &if_match,
|
||||
&if_notmatch);
|
||||
|
||||
__ Bind(&if_notsmi);
|
||||
__ GotoIfNot(
|
||||
__ WordEqual(__ LoadField(AccessBuilder::ForMap(), candidate_key),
|
||||
__ HeapNumberMapConstant()),
|
||||
&if_notmatch);
|
||||
__ Branch(__ Float64Equal(__ LoadField(AccessBuilder::ForHeapNumberValue(),
|
||||
candidate_key),
|
||||
__ ChangeInt32ToFloat64(key)),
|
||||
&if_match, &if_notmatch);
|
||||
|
||||
__ Bind(&if_match);
|
||||
{
|
||||
Node* index = ChangeIntPtrToInt32(__ IntAdd(
|
||||
entry_start, __ IntPtrConstant(OrderedHashMap::kHashTableStartIndex +
|
||||
OrderedHashMap::kValueOffset)));
|
||||
__ Goto(&done, index);
|
||||
}
|
||||
|
||||
__ Bind(&if_notmatch);
|
||||
{
|
||||
Node* next_entry = ChangeSmiToIntPtr(__ Load(
|
||||
MachineType::TaggedSigned(), table,
|
||||
__ IntAdd(
|
||||
__ WordShl(entry_start, __ IntPtrConstant(kPointerSizeLog2)),
|
||||
__ IntPtrConstant(OrderedHashMap::kHashTableStartOffset +
|
||||
OrderedHashMap::kChainOffset * kPointerSize -
|
||||
kHeapObjectTag))));
|
||||
__ Goto(&loop, next_entry);
|
||||
}
|
||||
}
|
||||
|
||||
__ Bind(&done);
|
||||
return done.PhiAt(0);
|
||||
}
|
||||
|
||||
Node* EffectControlLinearizer::LowerLoadHashMapValue(Node* node) {
|
||||
Node* table = NodeProperties::GetValueInput(node, 0);
|
||||
Node* index = NodeProperties::GetValueInput(node, 1);
|
||||
|
@ -126,6 +126,7 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
|
||||
Node* LowerLoadTypedElement(Node* node);
|
||||
void LowerStoreTypedElement(Node* node);
|
||||
Node* LowerLookupHashStorageIndex(Node* node);
|
||||
Node* LowerLookupSigned32HashStorageIndex(Node* node);
|
||||
Node* LowerLoadHashMapValue(Node* node);
|
||||
void LowerTransitionAndStoreElement(Node* node);
|
||||
void LowerRuntimeAbort(Node* node);
|
||||
@ -143,11 +144,15 @@ class V8_EXPORT_PRIVATE EffectControlLinearizer {
|
||||
Node* value,
|
||||
Node* frame_state);
|
||||
Node* BuildFloat64RoundDown(Node* value);
|
||||
Node* ComputeIntegerHash(Node* value);
|
||||
Node* LowerStringComparison(Callable const& callable, Node* node);
|
||||
Node* IsElementsKindGreaterThan(Node* kind, ElementsKind reference_kind);
|
||||
|
||||
Node* ChangeInt32ToSmi(Node* value);
|
||||
Node* ChangeIntPtrToInt32(Node* value);
|
||||
Node* ChangeUint32ToUintPtr(Node* value);
|
||||
Node* ChangeUint32ToSmi(Node* value);
|
||||
Node* ChangeSmiToIntPtr(Node* value);
|
||||
Node* ChangeSmiToInt32(Node* value);
|
||||
Node* ObjectIsSmi(Node* value);
|
||||
|
||||
|
@ -37,10 +37,12 @@ namespace compiler {
|
||||
V(WordAnd) \
|
||||
V(Word32Or) \
|
||||
V(Word32And) \
|
||||
V(Word32Xor) \
|
||||
V(Word32Shr) \
|
||||
V(Word32Shl) \
|
||||
V(IntAdd) \
|
||||
V(IntSub) \
|
||||
V(IntMul) \
|
||||
V(IntLessThan) \
|
||||
V(UintLessThan) \
|
||||
V(Int32Add) \
|
||||
|
@ -374,6 +374,7 @@
|
||||
V(MaybeGrowFastElements) \
|
||||
V(TransitionElementsKind) \
|
||||
V(LookupHashStorageIndex) \
|
||||
V(LookupSigned32HashStorageIndex) \
|
||||
V(LoadHashMapValue) \
|
||||
V(RuntimeAbort)
|
||||
|
||||
|
@ -2917,9 +2917,21 @@ class RepresentationSelector {
|
||||
// Assume the output is tagged.
|
||||
return SetOutput(node, MachineRepresentation::kTagged);
|
||||
|
||||
case IrOpcode::kLookupHashStorageIndex:
|
||||
VisitInputs(node);
|
||||
return SetOutput(node, MachineRepresentation::kTaggedSigned);
|
||||
case IrOpcode::kLookupHashStorageIndex: {
|
||||
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());
|
||||
}
|
||||
} else {
|
||||
VisitBinop(node, UseInfo::AnyTagged(),
|
||||
MachineRepresentation::kTaggedSigned);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
case IrOpcode::kLoadHashMapValue:
|
||||
ProcessInput(node, 0, UseInfo::AnyTagged()); // table
|
||||
|
@ -596,6 +596,14 @@ struct SimplifiedOperatorGlobalCache final {
|
||||
};
|
||||
LookupHashStorageIndexOperator kLookupHashStorageIndex;
|
||||
|
||||
struct LookupSigned32HashStorageIndexOperator final : public Operator {
|
||||
LookupSigned32HashStorageIndexOperator()
|
||||
: Operator(IrOpcode::kLookupSigned32HashStorageIndex,
|
||||
Operator::kEliminatable, "LookupSigned32HashStorageIndex", 2,
|
||||
1, 1, 1, 1, 0) {}
|
||||
};
|
||||
LookupSigned32HashStorageIndexOperator kLookupSigned32HashStorageIndex;
|
||||
|
||||
struct LoadHashMapValueOperator final : public Operator {
|
||||
LoadHashMapValueOperator()
|
||||
: Operator(IrOpcode::kLoadHashMapValue, Operator::kEliminatable,
|
||||
@ -780,6 +788,7 @@ 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(LoadHashMapValue)
|
||||
GET_FROM_CACHE(LoadFieldByIndex)
|
||||
#undef GET_FROM_CACHE
|
||||
|
@ -374,6 +374,7 @@ class V8_EXPORT_PRIVATE SimplifiedOperatorBuilder final
|
||||
const Operator* StringToUpperCaseIntl();
|
||||
|
||||
const Operator* LookupHashStorageIndex();
|
||||
const Operator* LookupSigned32HashStorageIndex();
|
||||
const Operator* LoadHashMapValue();
|
||||
|
||||
const Operator* SpeculativeToNumber(NumberOperationHint hint);
|
||||
|
@ -2054,6 +2054,10 @@ Type* Typer::Visitor::TypeLookupHashStorageIndex(Node* node) {
|
||||
return Type::SignedSmall();
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeLookupSigned32HashStorageIndex(Node* node) {
|
||||
return Type::SignedSmall();
|
||||
}
|
||||
|
||||
Type* Typer::Visitor::TypeLoadHashMapValue(Node* node) {
|
||||
return Type::NonInternal();
|
||||
}
|
||||
|
@ -1022,6 +1022,12 @@ void Verifier::Visitor::Check(Node* node) {
|
||||
CheckTypeIs(node, Type::Boolean());
|
||||
break;
|
||||
case IrOpcode::kLookupHashStorageIndex:
|
||||
CheckValueInputIs(node, 0, Type::Any());
|
||||
CheckTypeIs(node, Type::SignedSmall());
|
||||
break;
|
||||
case IrOpcode::kLookupSigned32HashStorageIndex:
|
||||
CheckValueInputIs(node, 0, Type::Any());
|
||||
CheckValueInputIs(node, 1, Type::Signed32());
|
||||
CheckTypeIs(node, Type::SignedSmall());
|
||||
break;
|
||||
case IrOpcode::kLoadHashMapValue:
|
||||
|
Loading…
Reference in New Issue
Block a user