Commit f2312019 authored by jarin's avatar jarin Committed by Commit bot

[turbofan] Introduce CheckIf node (deopt without explicit frame state).

Type feedback introduced DeoptimizeIf node in representation inference
(for Int32AddWithOverflow); we found the frame state for the deopt by
walking the effect chain. Unfortunately, the effect chain can hit
effect merges introduced by simplified lowering (e.g., in LoadBuffer)
and thus fail the assertion (we refuse to go through effect phis).

This CL postpones assignment of the frame state to the effect-control
lninearizer, so that we can correctly propagate the frame state to
the deopt point. The DeoptimizeIf node with unassigned frame state is
called CheckIf.

BUG=

Review-Url: https://codereview.chromium.org/2050813003
Cr-Commit-Position: refs/heads/master@{#36839}
parent 81c8ce72
......@@ -452,10 +452,13 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
case IrOpcode::kStringFromCharCode:
state = LowerStringFromCharCode(node, *effect, *control);
break;
case IrOpcode::kCheckIf:
state = LowerCheckIf(node, frame_state, *effect, *control);
break;
default:
return false;
}
NodeProperties::ReplaceUses(node, state.value);
NodeProperties::ReplaceUses(node, state.value, state.effect, state.control);
*effect = state.effect;
*control = state.control;
return true;
......@@ -1273,6 +1276,16 @@ EffectControlLinearizer::LowerStringFromCharCode(Node* node, Node* effect,
return ValueEffectControl(value, effect, control);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckIf(Node* node, Node* frame_state,
Node* effect, Node* control) {
NodeProperties::ReplaceEffectInput(node, effect);
NodeProperties::ReplaceControlInput(node, control);
node->InsertInput(graph()->zone(), 1, frame_state);
NodeProperties::ChangeOp(node, common()->DeoptimizeIf());
return ValueEffectControl(node, node, node);
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::AllocateHeapNumberWithValue(Node* value, Node* effect,
Node* control) {
......
......@@ -89,6 +89,8 @@ class EffectControlLinearizer {
Node* control);
ValueEffectControl LowerStringFromCharCode(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerCheckIf(Node* node, Node* frame_state, Node* effect,
Node* control);
ValueEffectControl AllocateHeapNumberWithValue(Node* node, Node* effect,
Node* control);
ValueEffectControl BuildCheckedFloat64ToInt32(Node* value, Node* frame_state,
......
......@@ -215,7 +215,8 @@ void NodeProperties::ReplaceUses(Node* node, Node* value, Node* effect,
DCHECK_NOT_NULL(exception);
edge.UpdateTo(exception);
} else {
UNREACHABLE();
DCHECK_NOT_NULL(success);
edge.UpdateTo(success);
}
} else if (IsEffectEdge(edge)) {
DCHECK_NOT_NULL(effect);
......
......@@ -216,6 +216,7 @@
V(CheckedFloat64ToInt32) \
V(CheckedTaggedToInt32) \
V(CheckedTaggedToFloat64) \
V(CheckIf) \
V(TruncateTaggedToWord32) \
V(TruncateTaggedToFloat64) \
V(Allocate) \
......
......@@ -1035,11 +1035,10 @@ class RepresentationSelector {
void ChangeToInt32OverflowOp(Node* node, const Operator* op) {
Node* effect = NodeProperties::GetEffectInput(node);
Node* control = NodeProperties::GetControlInput(node);
Node* frame_state = NodeProperties::FindFrameStateBefore(node);
Node* arith = graph()->NewNode(op, node->InputAt(0), node->InputAt(1));
Node* overflow = graph()->NewNode(common()->Projection(1), arith);
control = effect = graph()->NewNode(common()->DeoptimizeIf(), overflow,
frame_state, effect, control);
control = effect =
graph()->NewNode(simplified()->CheckIf(), overflow, effect, control);
Node* value = graph()->NewNode(common()->Projection(0), arith);
ReplaceEffectControlUses(node, effect, control);
......
......@@ -261,6 +261,13 @@ struct SimplifiedOperatorGlobalCache final {
CHECKED_OP_LIST(CHECKED)
#undef CHECKED
struct CheckIfOperator final : public Operator {
CheckIfOperator()
: Operator(IrOpcode::kCheckIf, Operator::kFoldable, "CheckIf", 1, 1, 1,
0, 1, 1) {}
};
CheckIfOperator kCheckIf;
template <PretenureFlag kPretenure>
struct AllocateOperator final : public Operator1<PretenureFlag> {
AllocateOperator()
......@@ -309,6 +316,10 @@ PURE_OP_LIST(GET_FROM_CACHE)
CHECKED_OP_LIST(GET_FROM_CACHE)
#undef GET_FROM_CACHE
const Operator* SimplifiedOperatorBuilder::CheckIf() {
return &cache_.kCheckIf;
}
const Operator* SimplifiedOperatorBuilder::ReferenceEqual(Type* type) {
return new (zone()) Operator(IrOpcode::kReferenceEqual,
Operator::kCommutative | Operator::kPure,
......
......@@ -190,6 +190,8 @@ class SimplifiedOperatorBuilder final : public ZoneObject {
const Operator* CheckedTaggedToInt32();
const Operator* CheckedTaggedToFloat64();
const Operator* CheckIf();
const Operator* ObjectIsCallable();
const Operator* ObjectIsNumber();
const Operator* ObjectIsReceiver();
......
......@@ -1945,6 +1945,11 @@ Type* Typer::Visitor::TypeCheckedTaggedToFloat64(Node* node) {
return Type::Number();
}
Type* Typer::Visitor::TypeCheckIf(Node* node) {
UNREACHABLE();
return nullptr;
}
Type* Typer::Visitor::TypeTruncateTaggedToWord32(Node* node) {
Type* arg = Operand(node, 0);
// TODO(jarin): DCHECK(arg->Is(Type::NumberOrUndefined()));
......
......@@ -278,6 +278,7 @@ void Verifier::Visitor::Check(Node* node) {
break;
case IrOpcode::kDeoptimizeIf:
case IrOpcode::kDeoptimizeUnless:
case IrOpcode::kCheckIf:
// Type is empty.
CheckNotTyped(node);
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment