[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}
This commit is contained in:
jarin 2016-06-08 22:40:02 -07:00 committed by Commit bot
parent 81c8ce723a
commit f2312019af
9 changed files with 40 additions and 5 deletions

View File

@ -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) {

View File

@ -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,

View File

@ -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);

View File

@ -216,6 +216,7 @@
V(CheckedFloat64ToInt32) \
V(CheckedTaggedToInt32) \
V(CheckedTaggedToFloat64) \
V(CheckIf) \
V(TruncateTaggedToWord32) \
V(TruncateTaggedToFloat64) \
V(Allocate) \

View File

@ -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);

View File

@ -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,

View File

@ -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();

View File

@ -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()));

View File

@ -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;