summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/simplified-lowering.cc
diff options
context:
space:
mode:
authorMichaël Zasso <targos@protonmail.com>2018-12-04 08:20:37 +0100
committerMichaël Zasso <targos@protonmail.com>2018-12-06 15:23:33 +0100
commit9b4bf7de6c9a7c25f116c7a502384c20b5cfaea3 (patch)
tree2b0c843168dafb939d8df8a15b2aa72b76dee51d /deps/v8/src/compiler/simplified-lowering.cc
parentb8fbe69db1292307adb2c2b2e0d5ef48c4ab2faf (diff)
downloadandroid-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.cc665
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();