diff options
author | Michaël Zasso <targos@protonmail.com> | 2018-12-04 08:20:37 +0100 |
---|---|---|
committer | Michaël Zasso <targos@protonmail.com> | 2018-12-06 15:23:33 +0100 |
commit | 9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3 (patch) | |
tree | 2b0c843168dafb939d8df8a15b2aa72b76dee51d /deps/v8/src/compiler/simplified-lowering.cc | |
parent | b8fbe69db1292307adb2c2b2e0d5ef48c4ab2faf (diff) | |
download | android-node-v8-9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3.tar.gz android-node-v8-9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3.tar.bz2 android-node-v8-9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3.zip |
deps: update V8 to 7.1.302.28
PR-URL: https://github.com/nodejs/node/pull/23423
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Gus Caplan <me@gus.host>
Reviewed-By: Myles Borins <myles.borins@gmail.com>
Diffstat (limited to 'deps/v8/src/compiler/simplified-lowering.cc')
-rw-r--r-- | deps/v8/src/compiler/simplified-lowering.cc | 665 |
1 files changed, 404 insertions, 261 deletions
diff --git a/deps/v8/src/compiler/simplified-lowering.cc b/deps/v8/src/compiler/simplified-lowering.cc index 2d82fc99bc..739f81f90d 100644 --- a/deps/v8/src/compiler/simplified-lowering.cc +++ b/deps/v8/src/compiler/simplified-lowering.cc @@ -107,8 +107,9 @@ UseInfo CheckedUseInfoAsWord32FromHint( UNREACHABLE(); } -UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint, - const VectorSlotPair& feedback) { +UseInfo CheckedUseInfoAsFloat64FromHint( + NumberOperationHint hint, const VectorSlotPair& feedback, + IdentifyZeros identify_zeros = kDistinguishZeros) { switch (hint) { case NumberOperationHint::kSignedSmall: case NumberOperationHint::kSignedSmallInputs: @@ -117,9 +118,9 @@ UseInfo CheckedUseInfoAsFloat64FromHint(NumberOperationHint hint, UNREACHABLE(); break; case NumberOperationHint::kNumber: - return UseInfo::CheckedNumberAsFloat64(feedback); + return UseInfo::CheckedNumberAsFloat64(identify_zeros, feedback); case NumberOperationHint::kNumberOrOddball: - return UseInfo::CheckedNumberOrOddballAsFloat64(feedback); + return UseInfo::CheckedNumberOrOddballAsFloat64(identify_zeros, feedback); } UNREACHABLE(); } @@ -140,7 +141,7 @@ UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { case MachineRepresentation::kWord32: return UseInfo::TruncatingWord32(); case MachineRepresentation::kWord64: - return UseInfo::TruncatingWord64(); + return UseInfo::Word64(); case MachineRepresentation::kBit: return UseInfo::Bool(); case MachineRepresentation::kSimd128: @@ -151,11 +152,11 @@ UseInfo TruncatingUseInfoFromRepresentation(MachineRepresentation rep) { } UseInfo UseInfoForBasePointer(const FieldAccess& access) { - return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); + return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::Word(); } UseInfo UseInfoForBasePointer(const ElementAccess& access) { - return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::PointerInt(); + return access.tag() != 0 ? UseInfo::AnyTagged() : UseInfo::Word(); } void ReplaceEffectControlUses(Node* node, Node* effect, Node* control) { @@ -186,32 +187,6 @@ void ChangeToPureOp(Node* node, const Operator* new_op) { NodeProperties::ChangeOp(node, new_op); } -#ifdef DEBUG -// Helpers for monotonicity checking. -class InputUseInfos { - public: - explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {} - - void SetAndCheckInput(Node* node, int index, UseInfo use_info) { - if (input_use_infos_.empty()) { - input_use_infos_.resize(node->InputCount(), UseInfo::None()); - } - // Check that the new use informatin is a super-type of the old - // one. - DCHECK(IsUseLessGeneral(input_use_infos_[index], use_info)); - input_use_infos_[index] = use_info; - } - - private: - ZoneVector<UseInfo> input_use_infos_; - - static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) { - return use1.truncation().IsLessGeneralThan(use2.truncation()); - } -}; - -#endif // DEBUG - bool CanOverflowSigned32(const Operator* op, Type left, Type right, Zone* type_zone) { // We assume the inputs are checked Signed32 (or known statically @@ -241,6 +216,32 @@ bool IsSomePositiveOrderedNumber(Type type) { } // namespace +#ifdef DEBUG +// Helpers for monotonicity checking. +class InputUseInfos { + public: + explicit InputUseInfos(Zone* zone) : input_use_infos_(zone) {} + + void SetAndCheckInput(Node* node, int index, UseInfo use_info) { + if (input_use_infos_.empty()) { + input_use_infos_.resize(node->InputCount(), UseInfo::None()); + } + // Check that the new use informatin is a super-type of the old + // one. + DCHECK(IsUseLessGeneral(input_use_infos_[index], use_info)); + input_use_infos_[index] = use_info; + } + + private: + ZoneVector<UseInfo> input_use_infos_; + + static bool IsUseLessGeneral(UseInfo use1, UseInfo use2) { + return use1.truncation().IsLessGeneralThan(use2.truncation()); + } +}; + +#endif // DEBUG + class RepresentationSelector { public: // Information for each node tracked during the fixpoint. @@ -306,7 +307,7 @@ class RepresentationSelector { source_positions_(source_positions), node_origins_(node_origins), type_cache_(TypeCache::Get()), - op_typer_(jsgraph->isolate(), js_heap_broker, graph_zone()) { + op_typer_(js_heap_broker, graph_zone()) { } // Forward propagation of types from type feedback. @@ -430,64 +431,71 @@ class RepresentationSelector { } } + // We preload these values here to avoid increasing the binary size too + // much, which happens if we inline the calls into the macros below. + Type input0_type; + if (node->InputCount() > 0) input0_type = FeedbackTypeOf(node->InputAt(0)); + Type input1_type; + if (node->InputCount() > 1) input1_type = FeedbackTypeOf(node->InputAt(1)); + switch (node->opcode()) { -#define DECLARE_CASE(Name) \ - case IrOpcode::k##Name: { \ - new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ - FeedbackTypeOf(node->InputAt(1))); \ - break; \ +#define DECLARE_CASE(Name) \ + case IrOpcode::k##Name: { \ + new_type = op_typer_.Name(input0_type, input1_type); \ + break; \ } SIMPLIFIED_NUMBER_BINOP_LIST(DECLARE_CASE) DECLARE_CASE(SameValue) #undef DECLARE_CASE -#define DECLARE_CASE(Name) \ - case IrOpcode::k##Name: { \ - new_type = \ - Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0)), \ - FeedbackTypeOf(node->InputAt(1))), \ - info->restriction_type(), graph_zone()); \ - break; \ +#define DECLARE_CASE(Name) \ + case IrOpcode::k##Name: { \ + new_type = Type::Intersect(op_typer_.Name(input0_type, input1_type), \ + info->restriction_type(), graph_zone()); \ + break; \ } SIMPLIFIED_SPECULATIVE_NUMBER_BINOP_LIST(DECLARE_CASE) #undef DECLARE_CASE -#define DECLARE_CASE(Name) \ - case IrOpcode::k##Name: { \ - new_type = op_typer_.Name(FeedbackTypeOf(node->InputAt(0))); \ - break; \ +#define DECLARE_CASE(Name) \ + case IrOpcode::k##Name: { \ + new_type = op_typer_.Name(input0_type); \ + break; \ } SIMPLIFIED_NUMBER_UNOP_LIST(DECLARE_CASE) #undef DECLARE_CASE -#define DECLARE_CASE(Name) \ - case IrOpcode::k##Name: { \ - new_type = \ - Type::Intersect(op_typer_.Name(FeedbackTypeOf(node->InputAt(0))), \ - info->restriction_type(), graph_zone()); \ - break; \ +#define DECLARE_CASE(Name) \ + case IrOpcode::k##Name: { \ + new_type = Type::Intersect(op_typer_.Name(input0_type), \ + info->restriction_type(), graph_zone()); \ + break; \ } SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE) #undef DECLARE_CASE case IrOpcode::kConvertReceiver: - new_type = op_typer_.ConvertReceiver(FeedbackTypeOf(node->InputAt(0))); + new_type = op_typer_.ConvertReceiver(input0_type); break; case IrOpcode::kPlainPrimitiveToNumber: - new_type = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0))); + new_type = op_typer_.ToNumber(input0_type); + break; + + case IrOpcode::kCheckBounds: + new_type = + Type::Intersect(op_typer_.CheckBounds(input0_type, input1_type), + info->restriction_type(), graph_zone()); break; case IrOpcode::kCheckFloat64Hole: - new_type = Type::Intersect( - op_typer_.CheckFloat64Hole(FeedbackTypeOf(node->InputAt(0))), - info->restriction_type(), graph_zone()); + new_type = Type::Intersect(op_typer_.CheckFloat64Hole(input0_type), + info->restriction_type(), graph_zone()); break; case IrOpcode::kCheckNumber: - new_type = Type::Intersect( - op_typer_.CheckNumber(FeedbackTypeOf(node->InputAt(0))), - info->restriction_type(), graph_zone()); + new_type = Type::Intersect(op_typer_.CheckNumber(input0_type), + info->restriction_type(), graph_zone()); break; case IrOpcode::kPhi: { @@ -913,6 +921,9 @@ class RepresentationSelector { VisitBinop(node, UseInfo::TruncatingFloat64(), MachineRepresentation::kFloat64); } + void VisitInt64Binop(Node* node) { + VisitBinop(node, UseInfo::Word64(), MachineRepresentation::kWord64); + } void VisitWord32TruncatingBinop(Node* node) { VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); @@ -1067,16 +1078,15 @@ class RepresentationSelector { if (type.IsNone()) { return MachineType::None(); } - // TODO(turbofan): Special treatment for ExternalPointer here, - // to avoid incompatible truncations. We really need a story - // for the JSFunction::entry field. - if (type.Is(Type::ExternalPointer())) { - return MachineType::Pointer(); - } // Do not distinguish between various Tagged variations. if (IsAnyTagged(rep)) { return MachineType::AnyTagged(); } + // Word64 representation is only valid for safe integer values. + if (rep == MachineRepresentation::kWord64) { + DCHECK(type.Is(TypeCache::Get().kSafeInteger)); + return MachineType(rep, MachineSemantic::kInt64); + } MachineType machine_type(rep, DeoptValueSemanticOf(type)); DCHECK(machine_type.representation() != MachineRepresentation::kWord32 || machine_type.semantic() == MachineSemantic::kInt32 || @@ -1174,6 +1184,10 @@ class RepresentationSelector { return changer_->Int32OverflowOperatorFor(node->opcode()); } + const Operator* Int64Op(Node* node) { + return changer_->Int64OperatorFor(node->opcode()); + } + const Operator* Uint32Op(Node* node) { return changer_->Uint32OperatorFor(node->opcode()); } @@ -1205,7 +1219,7 @@ class RepresentationSelector { return kNoWriteBarrier; } if (value_type.IsHeapConstant()) { - Heap::RootListIndex root_index; + RootIndex root_index; Heap* heap = jsgraph_->isolate()->heap(); if (heap->IsRootHandle(value_type.AsHeapConstant()->Value(), &root_index)) { @@ -1366,7 +1380,9 @@ class RepresentationSelector { } // default case => Float64Add/Sub - VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()), + VisitBinop(node, + UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros, + VectorSlotPair()), MachineRepresentation::kFloat64, Type::Number()); if (lower()) { ChangeToPureOp(node, Float64Op(node)); @@ -1424,17 +1440,24 @@ class RepresentationSelector { if (hint == NumberOperationHint::kSignedSmall || hint == NumberOperationHint::kSigned32) { // If the result is truncated, we only need to check the inputs. + // For the left hand side we just propagate the identify zeros + // mode of the {truncation}; and for modulus the sign of the + // right hand side doesn't matter anyways, so in particular there's + // no observable difference between a 0 and a -0 then. + UseInfo const lhs_use = CheckedUseInfoAsWord32FromHint( + hint, VectorSlotPair(), truncation.identify_zeros()); + UseInfo const rhs_use = CheckedUseInfoAsWord32FromHint( + hint, VectorSlotPair(), kIdentifyZeros); if (truncation.IsUsedAsWord32()) { - VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), - MachineRepresentation::kWord32); + VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kWord32); if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); } else if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN())) { - VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), - MachineRepresentation::kWord32, Type::Unsigned32()); + VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kWord32, + Type::Unsigned32()); if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); } else { - VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), - MachineRepresentation::kWord32, Type::Signed32()); + VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kWord32, + Type::Signed32()); if (lower()) ChangeToInt32OverflowOp(node); } return; @@ -1444,10 +1467,7 @@ class RepresentationSelector { TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) && (truncation.IsUsedAsWord32() || NodeProperties::GetType(node).Is(Type::Unsigned32()))) { - // We can only promise Float64 truncation here, as the decision is - // based on the feedback types of the inputs. - VisitBinop(node, - UseInfo(MachineRepresentation::kWord32, Truncation::Float64()), + VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kWord32, Type::Number()); if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); return; @@ -1456,21 +1476,51 @@ class RepresentationSelector { TypeOf(node->InputAt(1)).Is(Type::Signed32()) && (truncation.IsUsedAsWord32() || NodeProperties::GetType(node).Is(Type::Signed32()))) { - // We can only promise Float64 truncation here, as the decision is - // based on the feedback types of the inputs. - VisitBinop(node, - UseInfo(MachineRepresentation::kWord32, Truncation::Float64()), + VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kWord32, Type::Number()); if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); return; } + // default case => Float64Mod - VisitBinop(node, UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()), - MachineRepresentation::kFloat64, Type::Number()); + // For the left hand side we just propagate the identify zeros + // mode of the {truncation}; and for modulus the sign of the + // right hand side doesn't matter anyways, so in particular there's + // no observable difference between a 0 and a -0 then. + UseInfo const lhs_use = UseInfo::CheckedNumberOrOddballAsFloat64( + truncation.identify_zeros(), VectorSlotPair()); + UseInfo const rhs_use = UseInfo::CheckedNumberOrOddballAsFloat64( + kIdentifyZeros, VectorSlotPair()); + VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kFloat64, + Type::Number()); if (lower()) ChangeToPureOp(node, Float64Op(node)); return; } + void InsertUnreachableIfNecessary(Node* node) { + DCHECK(lower()); + // If the node is effectful and it produces an impossible value, then we + // insert Unreachable node after it. + if (node->op()->ValueOutputCount() > 0 && + node->op()->EffectOutputCount() > 0 && + node->opcode() != IrOpcode::kUnreachable && TypeOf(node).IsNone()) { + Node* control = node->op()->ControlOutputCount() > 0 + ? node + : NodeProperties::GetControlInput(node, 0); + + Node* unreachable = + graph()->NewNode(common()->Unreachable(), node, control); + + // Insert unreachable node and replace all the effect uses of the {node} + // with the new unreachable node. + for (Edge edge : node->use_edges()) { + if (NodeProperties::IsEffectEdge(edge) && edge.from() != unreachable) { + edge.UpdateTo(unreachable); + } + } + } + } + // Dispatching routine for visiting the node {node} with the usage {use}. // Depending on the operator, propagate new usage info to the inputs. void VisitNode(Node* node, Truncation truncation, @@ -1485,9 +1535,12 @@ class RepresentationSelector { // a sane state still) and we would afterwards replace that use with // Dead as well. if (node->op()->ValueInputCount() > 0 && - node->op()->HasProperty(Operator::kPure)) { - if (truncation.IsUnused()) return VisitUnused(node); + node->op()->HasProperty(Operator::kPure) && truncation.IsUnused()) { + return VisitUnused(node); } + + if (lower()) InsertUnreachableIfNecessary(node); + switch (node->opcode()) { //------------------------------------------------------------------ // Common operators. @@ -1521,6 +1574,7 @@ class RepresentationSelector { return; } case IrOpcode::kHeapConstant: + case IrOpcode::kDelayedStringConstant: return VisitLeaf(node, MachineRepresentation::kTaggedPointer); case IrOpcode::kPointerConstant: { VisitLeaf(node, MachineType::PointerRepresentation()); @@ -1609,9 +1663,13 @@ class RepresentationSelector { case IrOpcode::kNumberEqual: { Type const lhs_type = TypeOf(node->InputAt(0)); Type const rhs_type = TypeOf(node->InputAt(1)); - // Number comparisons reduce to integer comparisons for integer inputs. - if ((lhs_type.Is(Type::Unsigned32()) && - rhs_type.Is(Type::Unsigned32())) || + // Regular number comparisons in JavaScript generally identify zeros, + // so we always pass kIdentifyZeros for the inputs, and in addition + // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs. + // For equality we also handle the case that one side is non-zero, in + // which case we allow to truncate NaN to 0 on the other side. + if ((lhs_type.Is(Type::Unsigned32OrMinusZero()) && + rhs_type.Is(Type::Unsigned32OrMinusZero())) || (lhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) && rhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) && OneInputCannotBe(node, type_cache_.kZeroish))) { @@ -1621,7 +1679,8 @@ class RepresentationSelector { if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); return; } - if ((lhs_type.Is(Type::Signed32()) && rhs_type.Is(Type::Signed32())) || + if ((lhs_type.Is(Type::Signed32OrMinusZero()) && + rhs_type.Is(Type::Signed32OrMinusZero())) || (lhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) && rhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) && OneInputCannotBe(node, type_cache_.kZeroish))) { @@ -1632,29 +1691,33 @@ class RepresentationSelector { return; } // => Float64Cmp - VisitBinop(node, UseInfo::TruncatingFloat64(), + VisitBinop(node, UseInfo::TruncatingFloat64(kIdentifyZeros), MachineRepresentation::kBit); if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); return; } case IrOpcode::kNumberLessThan: case IrOpcode::kNumberLessThanOrEqual: { - // Number comparisons reduce to integer comparisons for integer inputs. - if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && - TypeOf(node->InputAt(1)).Is(Type::Unsigned32())) { + Type const lhs_type = TypeOf(node->InputAt(0)); + Type const rhs_type = TypeOf(node->InputAt(1)); + // Regular number comparisons in JavaScript generally identify zeros, + // so we always pass kIdentifyZeros for the inputs, and in addition + // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs. + if (lhs_type.Is(Type::Unsigned32OrMinusZero()) && + rhs_type.Is(Type::Unsigned32OrMinusZero())) { // => unsigned Int32Cmp VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); if (lower()) NodeProperties::ChangeOp(node, Uint32Op(node)); - } else if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && - TypeOf(node->InputAt(1)).Is(Type::Signed32())) { + } else if (lhs_type.Is(Type::Signed32OrMinusZero()) && + rhs_type.Is(Type::Signed32OrMinusZero())) { // => signed Int32Cmp VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); if (lower()) NodeProperties::ChangeOp(node, Int32Op(node)); } else { // => Float64Cmp - VisitBinop(node, UseInfo::TruncatingFloat64(), + VisitBinop(node, UseInfo::TruncatingFloat64(kIdentifyZeros), MachineRepresentation::kBit); if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); } @@ -1672,16 +1735,20 @@ class RepresentationSelector { case IrOpcode::kSpeculativeNumberLessThan: case IrOpcode::kSpeculativeNumberLessThanOrEqual: case IrOpcode::kSpeculativeNumberEqual: { - // Number comparisons reduce to integer comparisons for integer inputs. - if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && - TypeOf(node->InputAt(1)).Is(Type::Unsigned32())) { + Type const lhs_type = TypeOf(node->InputAt(0)); + Type const rhs_type = TypeOf(node->InputAt(1)); + // Regular number comparisons in JavaScript generally identify zeros, + // so we always pass kIdentifyZeros for the inputs, and in addition + // we can truncate -0 to 0 for otherwise Unsigned32 or Signed32 inputs. + if (lhs_type.Is(Type::Unsigned32OrMinusZero()) && + rhs_type.Is(Type::Unsigned32OrMinusZero())) { // => unsigned Int32Cmp VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); if (lower()) ChangeToPureOp(node, Uint32Op(node)); return; - } else if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && - TypeOf(node->InputAt(1)).Is(Type::Signed32())) { + } else if (lhs_type.Is(Type::Signed32OrMinusZero()) && + rhs_type.Is(Type::Signed32OrMinusZero())) { // => signed Int32Cmp VisitBinop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); @@ -1694,7 +1761,9 @@ class RepresentationSelector { case NumberOperationHint::kSigned32: case NumberOperationHint::kSignedSmall: if (propagate()) { - VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), + VisitBinop(node, + CheckedUseInfoAsWord32FromHint(hint, VectorSlotPair(), + kIdentifyZeros), MachineRepresentation::kBit); } else if (retype()) { SetOutput(node, MachineRepresentation::kBit, Type::Any()); @@ -1704,15 +1773,17 @@ class RepresentationSelector { Node* rhs = node->InputAt(1); if (IsNodeRepresentationTagged(lhs) && IsNodeRepresentationTagged(rhs)) { - VisitBinop( - node, - UseInfo::CheckedSignedSmallAsTaggedSigned(VectorSlotPair()), - MachineRepresentation::kBit); + VisitBinop(node, + UseInfo::CheckedSignedSmallAsTaggedSigned( + VectorSlotPair(), kIdentifyZeros), + MachineRepresentation::kBit); ChangeToPureOp( node, changer_->TaggedSignedOperatorFor(node->opcode())); } else { - VisitBinop(node, CheckedUseInfoAsWord32FromHint(hint), + VisitBinop(node, + CheckedUseInfoAsWord32FromHint( + hint, VectorSlotPair(), kIdentifyZeros), MachineRepresentation::kBit); ChangeToPureOp(node, Int32Op(node)); } @@ -1729,7 +1800,8 @@ class RepresentationSelector { V8_FALLTHROUGH; case NumberOperationHint::kNumber: VisitBinop(node, - CheckedUseInfoAsFloat64FromHint(hint, VectorSlotPair()), + CheckedUseInfoAsFloat64FromHint(hint, VectorSlotPair(), + kIdentifyZeros), MachineRepresentation::kBit); if (lower()) ChangeToPureOp(node, Float64Op(node)); return; @@ -1740,13 +1812,22 @@ class RepresentationSelector { case IrOpcode::kNumberAdd: case IrOpcode::kNumberSubtract: { - if (BothInputsAre(node, type_cache_.kAdditiveSafeIntegerOrMinusZero) && - (GetUpperBound(node).Is(Type::Signed32()) || - GetUpperBound(node).Is(Type::Unsigned32()) || + if (TypeOf(node->InputAt(0)) + .Is(type_cache_.kAdditiveSafeIntegerOrMinusZero) && + TypeOf(node->InputAt(1)) + .Is(type_cache_.kAdditiveSafeIntegerOrMinusZero) && + (TypeOf(node).Is(Type::Signed32()) || + TypeOf(node).Is(Type::Unsigned32()) || truncation.IsUsedAsWord32())) { // => Int32Add/Sub VisitWord32TruncatingBinop(node); if (lower()) ChangeToPureOp(node, Int32Op(node)); + } else if (jsgraph_->machine()->Is64() && + BothInputsAre(node, type_cache_.kSafeInteger) && + GetUpperBound(node).Is(type_cache_.kSafeInteger)) { + // => Int64Add/Sub + VisitInt64Binop(node); + if (lower()) ChangeToPureOp(node, Int64Op(node)); } else { // => Float64Add/Sub VisitFloat64Binop(node); @@ -1803,18 +1884,19 @@ class RepresentationSelector { // Checked float64 x float64 => float64 VisitBinop(node, - UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()), + UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros, + VectorSlotPair()), MachineRepresentation::kFloat64, Type::Number()); if (lower()) ChangeToPureOp(node, Float64Op(node)); return; } case IrOpcode::kNumberMultiply: { - if (BothInputsAre(node, Type::Integral32()) && - (NodeProperties::GetType(node).Is(Type::Signed32()) || - NodeProperties::GetType(node).Is(Type::Unsigned32()) || + if (TypeOf(node->InputAt(0)).Is(Type::Integral32()) && + TypeOf(node->InputAt(1)).Is(Type::Integral32()) && + (TypeOf(node).Is(Type::Signed32()) || + TypeOf(node).Is(Type::Unsigned32()) || (truncation.IsUsedAsWord32() && - NodeProperties::GetType(node).Is( - type_cache_.kSafeIntegerOrMinusZero)))) { + TypeOf(node).Is(type_cache_.kSafeIntegerOrMinusZero)))) { // Multiply reduces to Int32Mul if the inputs are integers, and // (a) the output is either known to be Signed32, or // (b) the output is known to be Unsigned32, or @@ -1898,31 +1980,30 @@ class RepresentationSelector { // default case => Float64Div VisitBinop(node, - UseInfo::CheckedNumberOrOddballAsFloat64(VectorSlotPair()), + UseInfo::CheckedNumberOrOddballAsFloat64(kDistinguishZeros, + VectorSlotPair()), MachineRepresentation::kFloat64, Type::Number()); if (lower()) ChangeToPureOp(node, Float64Op(node)); return; } case IrOpcode::kNumberDivide: { - if (BothInputsAreUnsigned32(node) && truncation.IsUsedAsWord32()) { + if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && + TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) && + (truncation.IsUsedAsWord32() || + TypeOf(node).Is(Type::Unsigned32()))) { // => unsigned Uint32Div VisitWord32TruncatingBinop(node); if (lower()) DeferReplacement(node, lowering->Uint32Div(node)); return; } - if (BothInputsAreSigned32(node)) { - if (NodeProperties::GetType(node).Is(Type::Signed32())) { - // => signed Int32Div - VisitWord32TruncatingBinop(node); - if (lower()) DeferReplacement(node, lowering->Int32Div(node)); - return; - } - if (truncation.IsUsedAsWord32()) { - // => signed Int32Div - VisitWord32TruncatingBinop(node); - if (lower()) DeferReplacement(node, lowering->Int32Div(node)); - return; - } + if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && + TypeOf(node->InputAt(1)).Is(Type::Signed32()) && + (truncation.IsUsedAsWord32() || + TypeOf(node).Is(Type::Signed32()))) { + // => signed Int32Div + VisitWord32TruncatingBinop(node); + if (lower()) DeferReplacement(node, lowering->Int32Div(node)); + return; } // Number x Number => Float64Div VisitFloat64Binop(node); @@ -1932,48 +2013,36 @@ class RepresentationSelector { case IrOpcode::kSpeculativeNumberModulus: return VisitSpeculativeNumberModulus(node, truncation, lowering); case IrOpcode::kNumberModulus: { - if (BothInputsAre(node, Type::Unsigned32OrMinusZeroOrNaN()) && + Type const lhs_type = TypeOf(node->InputAt(0)); + Type const rhs_type = TypeOf(node->InputAt(1)); + if ((lhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN()) && + rhs_type.Is(Type::Unsigned32OrMinusZeroOrNaN())) && (truncation.IsUsedAsWord32() || - NodeProperties::GetType(node).Is(Type::Unsigned32()))) { + TypeOf(node).Is(Type::Unsigned32()))) { // => unsigned Uint32Mod VisitWord32TruncatingBinop(node); if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); return; } - if (BothInputsAre(node, Type::Signed32OrMinusZeroOrNaN()) && - (truncation.IsUsedAsWord32() || - NodeProperties::GetType(node).Is(Type::Signed32()))) { + if ((lhs_type.Is(Type::Signed32OrMinusZeroOrNaN()) && + rhs_type.Is(Type::Signed32OrMinusZeroOrNaN())) && + (truncation.IsUsedAsWord32() || TypeOf(node).Is(Type::Signed32()) || + (truncation.IdentifiesZeroAndMinusZero() && + TypeOf(node).Is(Type::Signed32OrMinusZero())))) { // => signed Int32Mod VisitWord32TruncatingBinop(node); if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); return; } - if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32()) && - TypeOf(node->InputAt(1)).Is(Type::Unsigned32()) && - (truncation.IsUsedAsWord32() || - NodeProperties::GetType(node).Is(Type::Unsigned32()))) { - // We can only promise Float64 truncation here, as the decision is - // based on the feedback types of the inputs. - VisitBinop(node, UseInfo(MachineRepresentation::kWord32, - Truncation::Float64()), - MachineRepresentation::kWord32); - if (lower()) DeferReplacement(node, lowering->Uint32Mod(node)); - return; - } - if (TypeOf(node->InputAt(0)).Is(Type::Signed32()) && - TypeOf(node->InputAt(1)).Is(Type::Signed32()) && - (truncation.IsUsedAsWord32() || - NodeProperties::GetType(node).Is(Type::Signed32()))) { - // We can only promise Float64 truncation here, as the decision is - // based on the feedback types of the inputs. - VisitBinop(node, UseInfo(MachineRepresentation::kWord32, - Truncation::Float64()), - MachineRepresentation::kWord32); - if (lower()) DeferReplacement(node, lowering->Int32Mod(node)); - return; - } - // default case => Float64Mod - VisitFloat64Binop(node); + // => Float64Mod + // For the left hand side we just propagate the identify zeros + // mode of the {truncation}; and for modulus the sign of the + // right hand side doesn't matter anyways, so in particular there's + // no observable difference between a 0 and a -0 then. + UseInfo const lhs_use = + UseInfo::TruncatingFloat64(truncation.identify_zeros()); + UseInfo const rhs_use = UseInfo::TruncatingFloat64(kIdentifyZeros); + VisitBinop(node, lhs_use, rhs_use, MachineRepresentation::kFloat64); if (lower()) ChangeToPureOp(node, Float64Op(node)); return; } @@ -2096,21 +2165,24 @@ class RepresentationSelector { return; } case IrOpcode::kNumberAbs: { - if (TypeOf(node->InputAt(0)).Is(Type::Unsigned32())) { + // NumberAbs maps both 0 and -0 to 0, so we can generally + // pass the kIdentifyZeros truncation to its input, and + // choose to ignore minus zero in all cases. + Type const input_type = TypeOf(node->InputAt(0)); + if (input_type.Is(Type::Unsigned32OrMinusZero())) { VisitUnop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); if (lower()) DeferReplacement(node, node->InputAt(0)); - } else if (TypeOf(node->InputAt(0)).Is(Type::Signed32())) { + } else if (input_type.Is(Type::Signed32OrMinusZero())) { VisitUnop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kWord32); if (lower()) DeferReplacement(node, lowering->Int32Abs(node)); - } else if (TypeOf(node->InputAt(0)) - .Is(type_cache_.kPositiveIntegerOrMinusZeroOrNaN)) { - VisitUnop(node, UseInfo::TruncatingFloat64(), + } else if (input_type.Is(type_cache_.kPositiveIntegerOrNaN)) { + VisitUnop(node, UseInfo::TruncatingFloat64(kIdentifyZeros), MachineRepresentation::kFloat64); if (lower()) DeferReplacement(node, node->InputAt(0)); } else { - VisitUnop(node, UseInfo::TruncatingFloat64(), + VisitUnop(node, UseInfo::TruncatingFloat64(kIdentifyZeros), MachineRepresentation::kFloat64); if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); } @@ -2138,32 +2210,45 @@ class RepresentationSelector { // It is safe to use the feedback types for left and right hand side // here, since we can only narrow those types and thus we can only // promise a more specific truncation. + // For NumberMax we generally propagate whether the truncation + // identifies zeros to the inputs, and we choose to ignore minus + // zero in those cases. Type const lhs_type = TypeOf(node->InputAt(0)); Type const rhs_type = TypeOf(node->InputAt(1)); - if (lhs_type.Is(Type::Unsigned32()) && - rhs_type.Is(Type::Unsigned32())) { + if ((lhs_type.Is(Type::Unsigned32()) && + rhs_type.Is(Type::Unsigned32())) || + (lhs_type.Is(Type::Unsigned32OrMinusZero()) && + rhs_type.Is(Type::Unsigned32OrMinusZero()) && + truncation.IdentifiesZeroAndMinusZero())) { VisitWord32TruncatingBinop(node); if (lower()) { lowering->DoMax(node, lowering->machine()->Uint32LessThan(), MachineRepresentation::kWord32); } - } else if (lhs_type.Is(Type::Signed32()) && - rhs_type.Is(Type::Signed32())) { + } else if ((lhs_type.Is(Type::Signed32()) && + rhs_type.Is(Type::Signed32())) || + (lhs_type.Is(Type::Signed32OrMinusZero()) && + rhs_type.Is(Type::Signed32OrMinusZero()) && + truncation.IdentifiesZeroAndMinusZero())) { VisitWord32TruncatingBinop(node); if (lower()) { lowering->DoMax(node, lowering->machine()->Int32LessThan(), MachineRepresentation::kWord32); } - } else if (lhs_type.Is(Type::PlainNumber()) && - rhs_type.Is(Type::PlainNumber())) { - VisitFloat64Binop(node); + } else { + VisitBinop(node, + UseInfo::TruncatingFloat64(truncation.identify_zeros()), + MachineRepresentation::kFloat64); if (lower()) { - lowering->DoMax(node, lowering->machine()->Float64LessThan(), - MachineRepresentation::kFloat64); + if (truncation.IdentifiesZeroAndMinusZero() || + (lhs_type.Is(Type::PlainNumber()) && + rhs_type.Is(Type::PlainNumber()))) { + lowering->DoMax(node, lowering->machine()->Float64LessThan(), + MachineRepresentation::kFloat64); + } else { + NodeProperties::ChangeOp(node, Float64Op(node)); + } } - } else { - VisitFloat64Binop(node); - if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); } return; } @@ -2171,32 +2256,45 @@ class RepresentationSelector { // It is safe to use the feedback types for left and right hand side // here, since we can only narrow those types and thus we can only // promise a more specific truncation. + // For NumberMin we generally propagate whether the truncation + // identifies zeros to the inputs, and we choose to ignore minus + // zero in those cases. Type const lhs_type = TypeOf(node->InputAt(0)); Type const rhs_type = TypeOf(node->InputAt(1)); - if (lhs_type.Is(Type::Unsigned32()) && - rhs_type.Is(Type::Unsigned32())) { + if ((lhs_type.Is(Type::Unsigned32()) && + rhs_type.Is(Type::Unsigned32())) || + (lhs_type.Is(Type::Unsigned32OrMinusZero()) && + rhs_type.Is(Type::Unsigned32OrMinusZero()) && + truncation.IdentifiesZeroAndMinusZero())) { VisitWord32TruncatingBinop(node); if (lower()) { lowering->DoMin(node, lowering->machine()->Uint32LessThan(), MachineRepresentation::kWord32); } - } else if (lhs_type.Is(Type::Signed32()) && - rhs_type.Is(Type::Signed32())) { + } else if ((lhs_type.Is(Type::Signed32()) && + rhs_type.Is(Type::Signed32())) || + (lhs_type.Is(Type::Signed32OrMinusZero()) && + rhs_type.Is(Type::Signed32OrMinusZero()) && + truncation.IdentifiesZeroAndMinusZero())) { VisitWord32TruncatingBinop(node); if (lower()) { lowering->DoMin(node, lowering->machine()->Int32LessThan(), MachineRepresentation::kWord32); } - } else if (lhs_type.Is(Type::PlainNumber()) && - rhs_type.Is(Type::PlainNumber())) { - VisitFloat64Binop(node); + } else { + VisitBinop(node, + UseInfo::TruncatingFloat64(truncation.identify_zeros()), + MachineRepresentation::kFloat64); if (lower()) { - lowering->DoMin(node, lowering->machine()->Float64LessThan(), - MachineRepresentation::kFloat64); + if (truncation.IdentifiesZeroAndMinusZero() || + (lhs_type.Is(Type::PlainNumber()) && + rhs_type.Is(Type::PlainNumber()))) { + lowering->DoMin(node, lowering->machine()->Float64LessThan(), + MachineRepresentation::kFloat64); + } else { + NodeProperties::ChangeOp(node, Float64Op(node)); + } } - } else { - VisitFloat64Binop(node); - if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); } return; } @@ -2207,18 +2305,38 @@ class RepresentationSelector { if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); return; } + case IrOpcode::kNumberCeil: + case IrOpcode::kNumberFloor: + case IrOpcode::kNumberRound: + case IrOpcode::kNumberTrunc: { + // For NumberCeil, NumberFloor, NumberRound and NumberTrunc we propagate + // the zero identification part of the truncation, and we turn them into + // no-ops if we figure out (late) that their input is already an + // integer, NaN or -0. + Type const input_type = TypeOf(node->InputAt(0)); + VisitUnop(node, UseInfo::TruncatingFloat64(truncation.identify_zeros()), + MachineRepresentation::kFloat64); + if (lower()) { + if (input_type.Is(type_cache_.kIntegerOrMinusZeroOrNaN)) { + DeferReplacement(node, node->InputAt(0)); + } else if (node->opcode() == IrOpcode::kNumberRound) { + DeferReplacement(node, lowering->Float64Round(node)); + } else { + NodeProperties::ChangeOp(node, Float64Op(node)); + } + } + return; + } case IrOpcode::kNumberAcos: case IrOpcode::kNumberAcosh: case IrOpcode::kNumberAsin: case IrOpcode::kNumberAsinh: case IrOpcode::kNumberAtan: case IrOpcode::kNumberAtanh: - case IrOpcode::kNumberCeil: case IrOpcode::kNumberCos: case IrOpcode::kNumberCosh: case IrOpcode::kNumberExp: case IrOpcode::kNumberExpm1: - case IrOpcode::kNumberFloor: case IrOpcode::kNumberLog: case IrOpcode::kNumberLog1p: case IrOpcode::kNumberLog2: @@ -2227,19 +2345,12 @@ class RepresentationSelector { case IrOpcode::kNumberSin: case IrOpcode::kNumberSinh: case IrOpcode::kNumberTan: - case IrOpcode::kNumberTanh: - case IrOpcode::kNumberTrunc: { + case IrOpcode::kNumberTanh: { VisitUnop(node, UseInfo::TruncatingFloat64(), MachineRepresentation::kFloat64); if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); return; } - case IrOpcode::kNumberRound: { - VisitUnop(node, UseInfo::TruncatingFloat64(), - MachineRepresentation::kFloat64); - if (lower()) DeferReplacement(node, lowering->Float64Round(node)); - return; - } case IrOpcode::kNumberSign: { if (InputIs(node, Type::Signed32())) { VisitUnop(node, UseInfo::TruncatingWord32(), @@ -2252,6 +2363,20 @@ class RepresentationSelector { } return; } + case IrOpcode::kNumberSilenceNaN: { + Type const input_type = TypeOf(node->InputAt(0)); + if (input_type.Is(Type::OrderedNumber())) { + // No need to silence anything if the input cannot be NaN. + VisitUnop(node, UseInfo::TruncatingFloat64(), + MachineRepresentation::kFloat64); + if (lower()) DeferReplacement(node, node->InputAt(0)); + } else { + VisitUnop(node, UseInfo::TruncatingFloat64(), + MachineRepresentation::kFloat64); + if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); + } + return; + } case IrOpcode::kNumberSqrt: { VisitUnop(node, UseInfo::TruncatingFloat64(), MachineRepresentation::kFloat64); @@ -2259,17 +2384,22 @@ class RepresentationSelector { return; } case IrOpcode::kNumberToBoolean: { + // For NumberToBoolean we don't care whether the input is 0 or + // -0, since both of them are mapped to false anyways, so we + // can generally pass kIdentifyZeros truncation. Type const input_type = TypeOf(node->InputAt(0)); - if (input_type.Is(Type::Integral32())) { + if (input_type.Is(Type::Integral32OrMinusZeroOrNaN())) { + // 0, -0 and NaN all map to false, so we can safely truncate + // all of them to zero here. VisitUnop(node, UseInfo::TruncatingWord32(), MachineRepresentation::kBit); if (lower()) lowering->DoIntegral32ToBit(node); } else if (input_type.Is(Type::OrderedNumber())) { - VisitUnop(node, UseInfo::TruncatingFloat64(), + VisitUnop(node, UseInfo::TruncatingFloat64(kIdentifyZeros), MachineRepresentation::kBit); if (lower()) lowering->DoOrderedNumberToBit(node); } else { - VisitUnop(node, UseInfo::TruncatingFloat64(), + VisitUnop(node, UseInfo::TruncatingFloat64(kIdentifyZeros), MachineRepresentation::kBit); if (lower()) lowering->DoNumberToBit(node); } @@ -2337,6 +2467,18 @@ class RepresentationSelector { MachineRepresentation::kTaggedPointer); } case IrOpcode::kNewConsString: { + ProcessInput(node, 0, UseInfo::TruncatingWord32()); // length + ProcessInput(node, 1, UseInfo::AnyTagged()); // first + ProcessInput(node, 2, UseInfo::AnyTagged()); // second + SetOutput(node, MachineRepresentation::kTaggedPointer); + return; + } + case IrOpcode::kStringConcat: { + // TODO(turbofan): We currently depend on having this first length input + // to make sure that the overflow check is properly scheduled before the + // actual string concatenation. We should also use the length to pass it + // to the builtin or decide in optimized code how to construct the + // resulting string (i.e. cons string or sequential string). ProcessInput(node, 0, UseInfo::TaggedSigned()); // length ProcessInput(node, 1, UseInfo::AnyTagged()); // first ProcessInput(node, 2, UseInfo::AnyTagged()); // second @@ -2350,13 +2492,11 @@ class RepresentationSelector { MachineRepresentation::kTaggedPointer); } case IrOpcode::kStringCharCodeAt: { - return VisitBinop(node, UseInfo::AnyTagged(), - UseInfo::TruncatingWord32(), + return VisitBinop(node, UseInfo::AnyTagged(), UseInfo::Word(), MachineRepresentation::kWord32); } case IrOpcode::kStringCodePointAt: { - return VisitBinop(node, UseInfo::AnyTagged(), - UseInfo::TruncatingWord32(), + return VisitBinop(node, UseInfo::AnyTagged(), UseInfo::Word(), MachineRepresentation::kTaggedSigned); } case IrOpcode::kStringFromSingleCharCode: { @@ -2380,8 +2520,7 @@ class RepresentationSelector { // TODO(bmeurer): The input representation should be TaggedPointer. // Fix this once we have a dedicated StringConcat/JSStringAdd // operator, which marks it's output as TaggedPointer properly. - VisitUnop(node, UseInfo::AnyTagged(), - MachineRepresentation::kTaggedSigned); + VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kWord32); return; } case IrOpcode::kStringSubstring: { @@ -2491,7 +2630,7 @@ class RepresentationSelector { } case IrOpcode::kAllocate: { - ProcessInput(node, 0, UseInfo::TruncatingWord32()); + ProcessInput(node, 0, UseInfo::Word()); ProcessRemainingInputs(node, 1); SetOutput(node, MachineRepresentation::kTaggedPointer); return; @@ -2543,8 +2682,7 @@ class RepresentationSelector { case IrOpcode::kLoadElement: { if (truncation.IsUnused()) return VisitUnused(node); ElementAccess access = ElementAccessOf(node->op()); - VisitBinop(node, UseInfoForBasePointer(access), - UseInfo::TruncatingWord32(), + VisitBinop(node, UseInfoForBasePointer(access), UseInfo::Word(), access.machine_type.representation()); return; } @@ -2564,7 +2702,7 @@ class RepresentationSelector { access.base_is_tagged, element_representation, access.type, input_info->representation(), value_node); ProcessInput(node, 0, UseInfoForBasePointer(access)); // base - ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index + ProcessInput(node, 1, UseInfo::Word()); // index ProcessInput(node, 2, TruncatingUseInfoFromRepresentation( element_representation)); // value @@ -2587,8 +2725,8 @@ class RepresentationSelector { case IrOpcode::kTransitionAndStoreElement: { Type value_type = TypeOf(node->InputAt(2)); - ProcessInput(node, 0, UseInfo::AnyTagged()); // array - ProcessInput(node, 1, UseInfo::TruncatingWord32()); // index + ProcessInput(node, 0, UseInfo::AnyTagged()); // array + ProcessInput(node, 1, UseInfo::Word()); // index if (value_type.Is(Type::SignedSmall())) { ProcessInput(node, 2, UseInfo::TruncatingWord32()); // value @@ -2623,10 +2761,10 @@ class RepresentationSelector { case IrOpcode::kLoadTypedElement: { MachineRepresentation const rep = MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); - ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer - ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer - ProcessInput(node, 2, UseInfo::PointerInt()); // external pointer - ProcessInput(node, 3, UseInfo::TruncatingWord32()); // index + ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer + ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer + ProcessInput(node, 2, UseInfo::Word()); // external pointer + ProcessInput(node, 3, UseInfo::Word()); // index ProcessRemainingInputs(node, 4); SetOutput(node, rep); return; @@ -2634,10 +2772,10 @@ class RepresentationSelector { case IrOpcode::kLoadDataViewElement: { MachineRepresentation const rep = MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); - ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer - ProcessInput(node, 1, UseInfo::PointerInt()); // external pointer - ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index - ProcessInput(node, 3, UseInfo::Bool()); // little-endian + ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer + ProcessInput(node, 1, UseInfo::Word()); // external pointer + ProcessInput(node, 2, UseInfo::Word()); // index + ProcessInput(node, 3, UseInfo::Bool()); // little-endian ProcessRemainingInputs(node, 4); SetOutput(node, rep); return; @@ -2645,10 +2783,10 @@ class RepresentationSelector { case IrOpcode::kStoreTypedElement: { MachineRepresentation const rep = MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); - ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer - ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer - ProcessInput(node, 2, UseInfo::PointerInt()); // external pointer - ProcessInput(node, 3, UseInfo::TruncatingWord32()); // index + ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer + ProcessInput(node, 1, UseInfo::AnyTagged()); // base pointer + ProcessInput(node, 2, UseInfo::Word()); // external pointer + ProcessInput(node, 3, UseInfo::Word()); // index ProcessInput(node, 4, TruncatingUseInfoFromRepresentation(rep)); // value ProcessRemainingInputs(node, 5); @@ -2659,8 +2797,8 @@ class RepresentationSelector { MachineRepresentation const rep = MachineRepresentationFromArrayType(ExternalArrayTypeOf(node->op())); ProcessInput(node, 0, UseInfo::AnyTagged()); // buffer - ProcessInput(node, 1, UseInfo::PointerInt()); // external pointer - ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index + ProcessInput(node, 1, UseInfo::Word()); // external pointer + ProcessInput(node, 2, UseInfo::Word()); // index ProcessInput(node, 3, TruncatingUseInfoFromRepresentation(rep)); // value ProcessInput(node, 4, UseInfo::Bool()); // little-endian @@ -2949,8 +3087,7 @@ class RepresentationSelector { return; } case IrOpcode::kArgumentsLength: { - VisitUnop(node, UseInfo::PointerInt(), - MachineRepresentation::kTaggedSigned); + VisitUnop(node, UseInfo::Word(), MachineRepresentation::kTaggedSigned); return; } case IrOpcode::kNewDoubleElements: @@ -2960,14 +3097,10 @@ class RepresentationSelector { return; } case IrOpcode::kNewArgumentsElements: { - VisitBinop(node, UseInfo::PointerInt(), UseInfo::TaggedSigned(), + VisitBinop(node, UseInfo::Word(), UseInfo::TaggedSigned(), MachineRepresentation::kTaggedPointer); return; } - case IrOpcode::kArrayBufferWasNeutered: { - VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit); - return; - } case IrOpcode::kCheckFloat64Hole: { Type const input_type = TypeOf(node->InputAt(0)); if (input_type.Is(Type::Number())) { @@ -3045,20 +3178,28 @@ class RepresentationSelector { return VisitBinop(node, UseInfo::AnyTagged(), MachineRepresentation::kTaggedPointer); case IrOpcode::kMaybeGrowFastElements: { + Type const index_type = TypeOf(node->InputAt(2)); + Type const length_type = TypeOf(node->InputAt(3)); ProcessInput(node, 0, UseInfo::AnyTagged()); // object ProcessInput(node, 1, UseInfo::AnyTagged()); // elements ProcessInput(node, 2, UseInfo::TruncatingWord32()); // index ProcessInput(node, 3, UseInfo::TruncatingWord32()); // length ProcessRemainingInputs(node, 4); SetOutput(node, MachineRepresentation::kTaggedPointer); + if (lower()) { + // If the index is known to be less than the length (or if + // we're in dead code), we know that we don't need to grow + // the elements, so we can just remove this operation all + // together and replace it with the elements that we have + // on the inputs. + if (index_type.IsNone() || length_type.IsNone() || + index_type.Max() < length_type.Min()) { + DeferReplacement(node, node->InputAt(1)); + } + } return; } - case IrOpcode::kNumberSilenceNaN: - VisitUnop(node, UseInfo::TruncatingFloat64(), - MachineRepresentation::kFloat64); - if (lower()) NodeProperties::ChangeOp(node, Float64Op(node)); - return; case IrOpcode::kDateNow: VisitInputs(node); return SetOutput(node, MachineRepresentation::kTaggedPointer); @@ -3104,7 +3245,7 @@ class RepresentationSelector { Type const key_type = TypeOf(node->InputAt(1)); if (key_type.Is(Type::Signed32OrMinusZero())) { VisitBinop(node, UseInfo::AnyTagged(), UseInfo::TruncatingWord32(), - MachineRepresentation::kWord32); + MachineType::PointerRepresentation()); if (lower()) { NodeProperties::ChangeOp( node, @@ -3151,7 +3292,6 @@ class RepresentationSelector { case IrOpcode::kJSDecrement: case IrOpcode::kJSIncrement: case IrOpcode::kJSNegate: - case IrOpcode::kJSToInteger: case IrOpcode::kJSToLength: case IrOpcode::kJSToName: case IrOpcode::kJSToObject: @@ -3950,7 +4090,7 @@ Node* SimplifiedLowering::ToNumberConvertBigIntCode() { Node* SimplifiedLowering::ToNumericCode() { if (!to_numeric_code_.is_set()) { Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumeric); - to_number_code_.set(jsgraph()->HeapConstant(callable.code())); + to_numeric_code_.set(jsgraph()->HeapConstant(callable.code())); } return to_numeric_code_.get(); } @@ -3959,9 +4099,10 @@ Operator const* SimplifiedLowering::ToNumberOperator() { if (!to_number_operator_.is_set()) { Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumber); CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; - auto call_descriptor = - Linkage::GetStubCallDescriptor(graph()->zone(), callable.descriptor(), - 0, flags, Operator::kNoProperties); + auto call_descriptor = Linkage::GetStubCallDescriptor( + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, + Operator::kNoProperties); to_number_operator_.set(common()->Call(call_descriptor)); } return to_number_operator_.get(); @@ -3972,9 +4113,10 @@ Operator const* SimplifiedLowering::ToNumberConvertBigIntOperator() { Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumberConvertBigInt); CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; - auto call_descriptor = - Linkage::GetStubCallDescriptor(graph()->zone(), callable.descriptor(), - 0, flags, Operator::kNoProperties); + auto call_descriptor = Linkage::GetStubCallDescriptor( + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, + Operator::kNoProperties); to_number_convert_big_int_operator_.set(common()->Call(call_descriptor)); } return to_number_convert_big_int_operator_.get(); @@ -3984,9 +4126,10 @@ Operator const* SimplifiedLowering::ToNumericOperator() { if (!to_numeric_operator_.is_set()) { Callable callable = Builtins::CallableFor(isolate(), Builtins::kToNumeric); CallDescriptor::Flags flags = CallDescriptor::kNeedsFrameState; - auto call_descriptor = - Linkage::GetStubCallDescriptor(graph()->zone(), callable.descriptor(), - 0, flags, Operator::kNoProperties); + auto call_descriptor = Linkage::GetStubCallDescriptor( + graph()->zone(), callable.descriptor(), + callable.descriptor().GetStackParameterCount(), flags, + Operator::kNoProperties); to_numeric_operator_.set(common()->Call(call_descriptor)); } return to_numeric_operator_.get(); |