summaryrefslogtreecommitdiff
path: root/deps/v8/src/compiler/simplified-lowering.cc
diff options
context:
space:
mode:
Diffstat (limited to 'deps/v8/src/compiler/simplified-lowering.cc')
-rw-r--r--deps/v8/src/compiler/simplified-lowering.cc269
1 files changed, 208 insertions, 61 deletions
diff --git a/deps/v8/src/compiler/simplified-lowering.cc b/deps/v8/src/compiler/simplified-lowering.cc
index 4acc77f22f..d0f952a9ec 100644
--- a/deps/v8/src/compiler/simplified-lowering.cc
+++ b/deps/v8/src/compiler/simplified-lowering.cc
@@ -88,13 +88,13 @@ MachineRepresentation MachineRepresentationFromArrayType(
}
UseInfo CheckedUseInfoAsWord32FromHint(
- NumberOperationHint hint, CheckForMinusZeroMode minus_zero_mode =
- CheckForMinusZeroMode::kCheckForMinusZero) {
+ NumberOperationHint hint,
+ IdentifyZeros identify_zeros = kDistinguishZeros) {
switch (hint) {
case NumberOperationHint::kSignedSmall:
- return UseInfo::CheckedSignedSmallAsWord32(minus_zero_mode);
+ return UseInfo::CheckedSignedSmallAsWord32(identify_zeros);
case NumberOperationHint::kSigned32:
- return UseInfo::CheckedSigned32AsWord32(minus_zero_mode);
+ return UseInfo::CheckedSigned32AsWord32(identify_zeros);
case NumberOperationHint::kNumber:
return UseInfo::CheckedNumberAsWord32();
case NumberOperationHint::kNumberOrOddball:
@@ -454,10 +454,32 @@ class RepresentationSelector {
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; \
+ }
+ SIMPLIFIED_SPECULATIVE_NUMBER_UNOP_LIST(DECLARE_CASE)
+#undef DECLARE_CASE
+
case IrOpcode::kPlainPrimitiveToNumber:
new_type = op_typer_.ToNumber(FeedbackTypeOf(node->InputAt(0)));
break;
+ case IrOpcode::kCheckFloat64Hole:
+ new_type = Type::Intersect(
+ op_typer_.CheckFloat64Hole(FeedbackTypeOf(node->InputAt(0))),
+ 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());
+ break;
+
case IrOpcode::kPhi: {
new_type = TypePhi(node);
if (type != nullptr) {
@@ -809,6 +831,15 @@ class RepresentationSelector {
if (lower()) Kill(node);
}
+ // Helper for no-op node.
+ void VisitNoop(Node* node, Truncation truncation) {
+ if (truncation.IsUnused()) return VisitUnused(node);
+ MachineRepresentation representation =
+ GetOutputInfoForPhi(node, TypeOf(node), truncation);
+ VisitUnop(node, UseInfo(representation, truncation), representation);
+ if (lower()) DeferReplacement(node, node->InputAt(0));
+ }
+
// Helper for binops of the R x L -> O variety.
void VisitBinop(Node* node, UseInfo left_use, UseInfo right_use,
MachineRepresentation output,
@@ -840,11 +871,12 @@ class RepresentationSelector {
}
// Helper for unops of the I -> O variety.
- void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output) {
+ void VisitUnop(Node* node, UseInfo input_use, MachineRepresentation output,
+ Type* restriction_type = Type::Any()) {
DCHECK_EQ(1, node->op()->ValueInputCount());
ProcessInput(node, 0, input_use);
ProcessRemainingInputs(node, 1);
- SetOutput(node, output);
+ SetOutput(node, output, restriction_type);
}
// Helper for leaf nodes.
@@ -1167,7 +1199,7 @@ class RepresentationSelector {
// If one of the inputs is positive and/or truncation is being applied,
// there is no need to return -0.
CheckForMinusZeroMode mz_mode =
- truncation.IsUsedAsWord32() ||
+ truncation.IdentifiesZeroAndMinusZero() ||
(input0_type->Is(Type::OrderedNumber()) &&
input0_type->Min() > 0) ||
(input1_type->Is(Type::OrderedNumber()) &&
@@ -1226,13 +1258,23 @@ class RepresentationSelector {
VisitBinop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32, Type::Signed32());
} else {
- UseInfo left_use = CheckedUseInfoAsWord32FromHint(hint);
+ // If the output's truncation is identify-zeros, we can pass it
+ // along. Moreover, if the operation is addition and we know the
+ // right-hand side is not minus zero, we do not have to distinguish
+ // between 0 and -0.
+ IdentifyZeros left_identify_zeros = truncation.identify_zeros();
+ if (node->opcode() == IrOpcode::kSpeculativeNumberAdd &&
+ !right_feedback_type->Maybe(Type::MinusZero())) {
+ left_identify_zeros = kIdentifyZeros;
+ }
+ UseInfo left_use =
+ CheckedUseInfoAsWord32FromHint(hint, left_identify_zeros);
// For CheckedInt32Add and CheckedInt32Sub, we don't need to do
// a minus zero check for the right hand side, since we already
// know that the left hand side is a proper Signed32 value,
// potentially guarded by a check.
- UseInfo right_use = CheckedUseInfoAsWord32FromHint(
- hint, CheckForMinusZeroMode::kDontCheckForMinusZero);
+ UseInfo right_use =
+ CheckedUseInfoAsWord32FromHint(hint, kIdentifyZeros);
VisitBinop(node, left_use, right_use, MachineRepresentation::kWord32,
Type::Signed32());
}
@@ -2061,20 +2103,27 @@ class RepresentationSelector {
return;
}
case IrOpcode::kNumberMax: {
- // TODO(turbofan): We should consider feedback types here as well.
- if (BothInputsAreUnsigned32(node)) {
+ // 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.
+ 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())) {
VisitWord32TruncatingBinop(node);
if (lower()) {
lowering->DoMax(node, lowering->machine()->Uint32LessThan(),
MachineRepresentation::kWord32);
}
- } else if (BothInputsAreSigned32(node)) {
+ } else if (lhs_type->Is(Type::Signed32()) &&
+ rhs_type->Is(Type::Signed32())) {
VisitWord32TruncatingBinop(node);
if (lower()) {
lowering->DoMax(node, lowering->machine()->Int32LessThan(),
MachineRepresentation::kWord32);
}
- } else if (BothInputsAre(node, Type::PlainNumber())) {
+ } else if (lhs_type->Is(Type::PlainNumber()) &&
+ rhs_type->Is(Type::PlainNumber())) {
VisitFloat64Binop(node);
if (lower()) {
lowering->DoMax(node, lowering->machine()->Float64LessThan(),
@@ -2087,20 +2136,27 @@ class RepresentationSelector {
return;
}
case IrOpcode::kNumberMin: {
- // TODO(turbofan): We should consider feedback types here as well.
- if (BothInputsAreUnsigned32(node)) {
+ // 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.
+ 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())) {
VisitWord32TruncatingBinop(node);
if (lower()) {
lowering->DoMin(node, lowering->machine()->Uint32LessThan(),
MachineRepresentation::kWord32);
}
- } else if (BothInputsAreSigned32(node)) {
+ } else if (lhs_type->Is(Type::Signed32()) &&
+ rhs_type->Is(Type::Signed32())) {
VisitWord32TruncatingBinop(node);
if (lower()) {
lowering->DoMin(node, lowering->machine()->Int32LessThan(),
MachineRepresentation::kWord32);
}
- } else if (BothInputsAre(node, Type::PlainNumber())) {
+ } else if (lhs_type->Is(Type::PlainNumber()) &&
+ rhs_type->Is(Type::PlainNumber())) {
VisitFloat64Binop(node);
if (lower()) {
lowering->DoMin(node, lowering->machine()->Float64LessThan(),
@@ -2271,16 +2327,22 @@ class RepresentationSelector {
case IrOpcode::kCheckBounds: {
Type* index_type = TypeOf(node->InputAt(0));
Type* length_type = TypeOf(node->InputAt(1));
- if (index_type->Is(Type::Unsigned32())) {
+ if (index_type->Is(Type::Integral32OrMinusZero())) {
+ // Map -0 to 0, and the values in the [-2^31,-1] range to the
+ // [2^31,2^32-1] range, which will be considered out-of-bounds
+ // as well, because the {length_type} is limited to Unsigned31.
VisitBinop(node, UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32);
- if (lower() && index_type->Max() < length_type->Min()) {
- // The bounds check is redundant if we already know that
- // the index is within the bounds of [0.0, length[.
- DeferReplacement(node, node->InputAt(0));
+ if (lower()) {
+ if (index_type->Min() >= 0.0 &&
+ index_type->Max() < length_type->Min()) {
+ // The bounds check is redundant if we already know that
+ // the index is within the bounds of [0.0, length[.
+ DeferReplacement(node, node->InputAt(0));
+ }
}
} else {
- VisitBinop(node, UseInfo::CheckedSigned32AsWord32(),
+ VisitBinop(node, UseInfo::CheckedSigned32AsWord32(kIdentifyZeros),
UseInfo::TruncatingWord32(),
MachineRepresentation::kWord32);
}
@@ -2315,19 +2377,9 @@ class RepresentationSelector {
return;
}
case IrOpcode::kCheckNumber: {
- if (InputIs(node, Type::Number())) {
- if (truncation.IsUsedAsWord32()) {
- VisitUnop(node, UseInfo::TruncatingWord32(),
- MachineRepresentation::kWord32);
- } else {
- // TODO(jarin,bmeurer): We need to go to Tagged here, because
- // otherwise we cannot distinguish the hole NaN (which might need to
- // be treated as undefined). We should have a dedicated Type for
- // that at some point, and maybe even a dedicated truncation.
- VisitUnop(node, UseInfo::AnyTagged(),
- MachineRepresentation::kTagged);
- }
- if (lower()) DeferReplacement(node, node->InputAt(0));
+ Type* const input_type = TypeOf(node->InputAt(0));
+ if (input_type->Is(Type::Number())) {
+ VisitNoop(node, truncation);
} else {
VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kTagged);
}
@@ -2346,7 +2398,8 @@ class RepresentationSelector {
}
case IrOpcode::kCheckSmi: {
if (SmiValuesAre32Bits() && truncation.IsUsedAsWord32()) {
- VisitUnop(node, UseInfo::CheckedSignedSmallAsWord32(),
+ VisitUnop(node,
+ UseInfo::CheckedSignedSmallAsWord32(kDistinguishZeros),
MachineRepresentation::kWord32);
} else {
VisitUnop(node, UseInfo::CheckedSignedSmallAsTaggedSigned(),
@@ -2541,10 +2594,56 @@ class RepresentationSelector {
}
return;
}
+ case IrOpcode::kSpeculativeToNumber: {
+ NumberOperationHint const hint = NumberOperationHintOf(node->op());
+ switch (hint) {
+ case NumberOperationHint::kSigned32:
+ case NumberOperationHint::kSignedSmall:
+ VisitUnop(node, CheckedUseInfoAsWord32FromHint(hint),
+ MachineRepresentation::kWord32, Type::Signed32());
+ break;
+ case NumberOperationHint::kNumber:
+ case NumberOperationHint::kNumberOrOddball:
+ VisitUnop(node, CheckedUseInfoAsFloat64FromHint(hint),
+ MachineRepresentation::kFloat64);
+ break;
+ }
+ if (lower()) DeferReplacement(node, node->InputAt(0));
+ return;
+ }
case IrOpcode::kObjectIsDetectableCallable: {
VisitObjectIs(node, Type::DetectableCallable(), lowering);
return;
}
+ case IrOpcode::kObjectIsNaN: {
+ Type* const input_type = GetUpperBound(node->InputAt(0));
+ if (input_type->Is(Type::NaN())) {
+ VisitUnop(node, UseInfo::None(), MachineRepresentation::kBit);
+ if (lower()) {
+ DeferReplacement(node, lowering->jsgraph()->Int32Constant(1));
+ }
+ } else if (!input_type->Maybe(Type::NaN())) {
+ VisitUnop(node, UseInfo::Any(), MachineRepresentation::kBit);
+ if (lower()) {
+ DeferReplacement(node, lowering->jsgraph()->Int32Constant(0));
+ }
+ } else if (input_type->Is(Type::Number())) {
+ VisitUnop(node, UseInfo::TruncatingFloat64(),
+ MachineRepresentation::kBit);
+ if (lower()) {
+ // ObjectIsNaN(x:kRepFloat64) => Word32Equal(Float64Equal(x,x),#0)
+ Node* const input = node->InputAt(0);
+ node->ReplaceInput(
+ 0, jsgraph_->graph()->NewNode(
+ lowering->machine()->Float64Equal(), input, input));
+ node->AppendInput(jsgraph_->zone(), jsgraph_->Int32Constant(0));
+ NodeProperties::ChangeOp(node, lowering->machine()->Word32Equal());
+ }
+ } else {
+ VisitUnop(node, UseInfo::AnyTagged(), MachineRepresentation::kBit);
+ }
+ return;
+ }
case IrOpcode::kObjectIsNonCallable: {
VisitObjectIs(node, Type::NonCallable(), lowering);
return;
@@ -2566,14 +2665,26 @@ class RepresentationSelector {
VisitObjectIs(node, Type::String(), lowering);
return;
}
+ case IrOpcode::kObjectIsSymbol: {
+ VisitObjectIs(node, Type::Symbol(), lowering);
+ return;
+ }
case IrOpcode::kObjectIsUndetectable: {
VisitObjectIs(node, Type::Undetectable(), lowering);
return;
}
- case IrOpcode::kNewRestParameterElements:
+ case IrOpcode::kArgumentsFrame: {
+ SetOutput(node, MachineType::PointerRepresentation());
+ return;
+ }
+ case IrOpcode::kArgumentsLength: {
+ VisitUnop(node, UseInfo::PointerInt(),
+ MachineRepresentation::kTaggedSigned);
+ return;
+ }
case IrOpcode::kNewUnmappedArgumentsElements: {
- ProcessRemainingInputs(node, 0);
- SetOutput(node, MachineRepresentation::kTaggedPointer);
+ VisitBinop(node, UseInfo::PointerInt(), UseInfo::TaggedSigned(),
+ MachineRepresentation::kTaggedPointer);
return;
}
case IrOpcode::kArrayBufferWasNeutered: {
@@ -2581,13 +2692,36 @@ class RepresentationSelector {
return;
}
case IrOpcode::kCheckFloat64Hole: {
- CheckFloat64HoleMode mode = CheckFloat64HoleModeOf(node->op());
- ProcessInput(node, 0, UseInfo::TruncatingFloat64());
- ProcessRemainingInputs(node, 1);
- SetOutput(node, MachineRepresentation::kFloat64);
- if (truncation.IsUsedAsFloat64() &&
- mode == CheckFloat64HoleMode::kAllowReturnHole) {
- if (lower()) DeferReplacement(node, node->InputAt(0));
+ Type* const input_type = TypeOf(node->InputAt(0));
+ if (input_type->Is(Type::Number())) {
+ VisitNoop(node, truncation);
+ } else {
+ CheckFloat64HoleMode mode = CheckFloat64HoleModeOf(node->op());
+ switch (mode) {
+ case CheckFloat64HoleMode::kAllowReturnHole:
+ if (truncation.IsUnused()) return VisitUnused(node);
+ if (truncation.IsUsedAsWord32()) {
+ VisitUnop(node, UseInfo::TruncatingWord32(),
+ MachineRepresentation::kWord32);
+ if (lower()) DeferReplacement(node, node->InputAt(0));
+ } else if (truncation.IsUsedAsFloat64()) {
+ VisitUnop(node, UseInfo::TruncatingFloat64(),
+ MachineRepresentation::kFloat64);
+ if (lower()) DeferReplacement(node, node->InputAt(0));
+ } else {
+ VisitUnop(
+ node,
+ UseInfo(MachineRepresentation::kFloat64, Truncation::Any()),
+ MachineRepresentation::kFloat64, Type::Number());
+ }
+ break;
+ case CheckFloat64HoleMode::kNeverReturnHole:
+ VisitUnop(
+ node,
+ UseInfo(MachineRepresentation::kFloat64, Truncation::Any()),
+ MachineRepresentation::kFloat64, Type::Number());
+ break;
+ }
}
return;
}
@@ -2687,7 +2821,8 @@ class RepresentationSelector {
case IrOpcode::kBeginRegion:
case IrOpcode::kProjection:
case IrOpcode::kOsrValue:
- case IrOpcode::kArgumentsObjectState:
+ case IrOpcode::kArgumentsElementsState:
+ case IrOpcode::kArgumentsLengthState:
// All JavaScript operators except JSToNumber have uniform handling.
#define OPCODE_CASE(name) case IrOpcode::k##name:
JS_SIMPLE_BINOP_LIST(OPCODE_CASE)
@@ -2842,7 +2977,6 @@ void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
Node* frame_state = node->InputAt(2);
Node* effect = node->InputAt(3);
Node* control = node->InputAt(4);
- Node* throwing;
Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
Node* branch0 =
@@ -2860,10 +2994,18 @@ void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
Node* efalse0 = effect;
Node* vfalse0;
{
- throwing = vfalse0 = efalse0 =
+ vfalse0 = efalse0 = if_false0 =
graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
frame_state, efalse0, if_false0);
- if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
+
+ // Update potential {IfException} uses of {node} to point to the above
+ // {ToNumber} stub call node instead.
+ Node* on_exception = nullptr;
+ if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
+ NodeProperties::ReplaceControlInput(on_exception, vfalse0);
+ NodeProperties::ReplaceEffectInput(on_exception, efalse0);
+ if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
+ }
Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
@@ -2905,10 +3047,9 @@ void SimplifiedLowering::DoJSToNumberTruncatesToFloat64(
if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
edge.from()->ReplaceUses(control);
edge.from()->Kill();
- } else if (edge.from()->opcode() == IrOpcode::kIfException) {
- edge.UpdateTo(throwing);
} else {
- UNREACHABLE();
+ DCHECK(edge.from()->opcode() != IrOpcode::kIfException);
+ edge.UpdateTo(control);
}
} else if (NodeProperties::IsEffectEdge(edge)) {
edge.UpdateTo(effect);
@@ -2926,7 +3067,6 @@ void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
Node* frame_state = node->InputAt(2);
Node* effect = node->InputAt(3);
Node* control = node->InputAt(4);
- Node* throwing;
Node* check0 = graph()->NewNode(simplified()->ObjectIsSmi(), value);
Node* branch0 =
@@ -2941,10 +3081,18 @@ void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
Node* efalse0 = effect;
Node* vfalse0;
{
- throwing = vfalse0 = efalse0 =
+ vfalse0 = efalse0 = if_false0 =
graph()->NewNode(ToNumberOperator(), ToNumberCode(), value, context,
frame_state, efalse0, if_false0);
- if_false0 = graph()->NewNode(common()->IfSuccess(), throwing);
+
+ // Update potential {IfException} uses of {node} to point to the above
+ // {ToNumber} stub call node instead.
+ Node* on_exception = nullptr;
+ if (NodeProperties::IsExceptionalCall(node, &on_exception)) {
+ NodeProperties::ReplaceControlInput(on_exception, vfalse0);
+ NodeProperties::ReplaceEffectInput(on_exception, efalse0);
+ if_false0 = graph()->NewNode(common()->IfSuccess(), vfalse0);
+ }
Node* check1 = graph()->NewNode(simplified()->ObjectIsSmi(), vfalse0);
Node* branch1 = graph()->NewNode(common()->Branch(), check1, if_false0);
@@ -2982,10 +3130,9 @@ void SimplifiedLowering::DoJSToNumberTruncatesToWord32(
if (edge.from()->opcode() == IrOpcode::kIfSuccess) {
edge.from()->ReplaceUses(control);
edge.from()->Kill();
- } else if (edge.from()->opcode() == IrOpcode::kIfException) {
- edge.UpdateTo(throwing);
} else {
- UNREACHABLE();
+ DCHECK(edge.from()->opcode() != IrOpcode::kIfException);
+ edge.UpdateTo(control);
}
} else if (NodeProperties::IsEffectEdge(edge)) {
edge.UpdateTo(effect);