Commit 10284b29 authored by mstarzinger's avatar mstarzinger Committed by Commit bot

[turbofan] Add frame state propagation to linearizer.

This implements propagation of frame states from checkpoints to all
deoptimization points inserted by the EffectControlLinearizer. It also
allows us to remove the eager frame state input from all the checked
conversion operations.

R=jarin@chromium.org
BUG=v8:5021

Review-Url: https://codereview.chromium.org/2033143002
Cr-Commit-Position: refs/heads/master@{#36710}
parent 9fbf9e28
......@@ -37,6 +37,7 @@ namespace {
struct BlockEffectControlData {
Node* current_effect = nullptr; // New effect.
Node* current_control = nullptr; // New control.
Node* current_frame_state = nullptr; // New frame state.
};
// Effect phis that need to be updated after the first pass.
......@@ -222,10 +223,30 @@ void EffectControlLinearizer::Run() {
NodeProperties::ReplaceEffectInput(terminate, effect);
}
// The frame state at block entry is determined by the frame states leaving
// all predecessors. In case there is no frame state dominating this block,
// we can rely on a checkpoint being present before the next deoptimization.
// TODO(mstarzinger): Eventually we will need to go hunt for a frame state
// once deoptimizing nodes roam freely through the schedule.
Node* frame_state = nullptr;
if (block != schedule()->start()) {
// If all the predecessors have the same effect, we can use it
// as our current effect.
int rpo_number = block->PredecessorAt(0)->rpo_number();
frame_state = block_effects[rpo_number].current_frame_state;
for (size_t i = 1; i < block->PredecessorCount(); i++) {
int rpo_number = block->PredecessorAt(i)->rpo_number();
if (block_effects[rpo_number].current_frame_state != frame_state) {
frame_state = nullptr;
break;
}
}
}
// Process the ordinary instructions.
for (; instr < block->NodeCount(); instr++) {
Node* node = block->NodeAt(instr);
ProcessNode(node, &effect, &control);
ProcessNode(node, &frame_state, &effect, &control);
}
switch (block->control()) {
......@@ -240,13 +261,14 @@ void EffectControlLinearizer::Run() {
case BasicBlock::kReturn:
case BasicBlock::kDeoptimize:
case BasicBlock::kThrow:
ProcessNode(block->control_input(), &effect, &control);
ProcessNode(block->control_input(), &frame_state, &effect, &control);
break;
}
// Store the effect for later use.
block_effects[block->rpo_number()].current_effect = effect;
block_effects[block->rpo_number()].current_control = control;
block_effects[block->rpo_number()].current_frame_state = frame_state;
}
// Update the incoming edges of the effect phis that could not be processed
......@@ -276,14 +298,19 @@ void TryScheduleCallIfSuccess(Node* node, Node** control) {
} // namespace
void EffectControlLinearizer::ProcessNode(Node* node, Node** effect,
Node** control) {
void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
Node** effect, Node** control) {
// If the node needs to be wired into the effect/control chain, do this
// here.
if (TryWireInStateEffect(node, effect, control)) {
// here. Pass current frame state for lowering to eager deoptimization.
if (TryWireInStateEffect(node, *frame_state, effect, control)) {
return;
}
// If the node has a visible effect, then there must be a checkpoint in the
// effect chain before we are allowed to place another eager deoptimization
// point. We zap the frame state to ensure this invariant is maintained.
if (!node->op()->HasProperty(Operator::kNoWrite)) *frame_state = nullptr;
// Remove the end markers of 'atomic' allocation region because the
// region should be wired-in now.
if (node->opcode() == IrOpcode::kFinishRegion ||
......@@ -294,10 +321,10 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** effect,
}
// Special treatment for checkpoint nodes.
// TODO(epertoso): Pickup the current frame state.
if (node->opcode() == IrOpcode::kCheckpoint) {
// Unlink the check point; effect uses will be updated to the incoming
// effect that is passed.
// effect that is passed. The frame state is preserved for lowering.
*frame_state = NodeProperties::GetFrameStateInput(node, 0);
node->TrimInputCount(0);
return;
}
......@@ -347,7 +374,9 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** effect,
}
}
bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect,
bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
Node* frame_state,
Node** effect,
Node** control) {
ValueEffectControl state(nullptr, nullptr, nullptr);
switch (node->opcode()) {
......@@ -388,16 +417,16 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect,
state = LowerTruncateTaggedToFloat64(node, *effect, *control);
break;
case IrOpcode::kCheckedUint32ToInt32:
state = LowerCheckedUint32ToInt32(node, *effect, *control);
state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedFloat64ToInt32:
state = LowerCheckedFloat64ToInt32(node, *effect, *control);
state = LowerCheckedFloat64ToInt32(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedTaggedToInt32:
state = LowerCheckedTaggedToInt32(node, *effect, *control);
state = LowerCheckedTaggedToInt32(node, frame_state, *effect, *control);
break;
case IrOpcode::kCheckedTaggedToFloat64:
state = LowerCheckedTaggedToFloat64(node, *effect, *control);
state = LowerCheckedTaggedToFloat64(node, frame_state, *effect, *control);
break;
case IrOpcode::kTruncateTaggedToWord32:
state = LowerTruncateTaggedToWord32(node, *effect, *control);
......@@ -718,10 +747,11 @@ EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node, Node* effect,
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, Node* effect,
EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
Node* frame_state,
Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
Node* max_int = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::max());
Node* is_safe =
graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, max_int);
......@@ -774,10 +804,11 @@ EffectControlLinearizer::BuildCheckedFloat64ToInt32(Node* value,
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, Node* effect,
EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
Node* frame_state,
Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
// Make sure the lowered node does not appear in any use lists.
node->TrimInputCount(0);
......@@ -786,10 +817,11 @@ EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, Node* effect,
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node, Node* effect,
EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
Node* frame_state,
Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
Node* check = ObjectIsSmi(value);
Node* branch =
......@@ -863,10 +895,11 @@ EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
}
EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node, Node* effect,
EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
Node* frame_state,
Node* effect,
Node* control) {
Node* value = node->InputAt(0);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
Node* check = ObjectIsSmi(value);
Node* branch =
......
......@@ -30,7 +30,8 @@ class EffectControlLinearizer {
void Run();
private:
void ProcessNode(Node* node, Node** current_effect, Node** control);
void ProcessNode(Node* node, Node** frame_state, Node** effect,
Node** control);
struct ValueEffectControl {
Node* value;
......@@ -40,7 +41,8 @@ class EffectControlLinearizer {
: value(value), effect(effect), control(control) {}
};
bool TryWireInStateEffect(Node* node, Node** effect, Node** control);
bool TryWireInStateEffect(Node* node, Node* frame_state, Node** effect,
Node** control);
ValueEffectControl LowerTypeGuard(Node* node, Node* effect, Node* control);
ValueEffectControl LowerChangeBitToTagged(Node* node, Node* effect,
Node* control);
......@@ -60,14 +62,14 @@ class EffectControlLinearizer {
Node* control);
ValueEffectControl LowerChangeTaggedToUint32(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerCheckedUint32ToInt32(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerCheckedTaggedToInt32(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerCheckedTaggedToFloat64(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerCheckedUint32ToInt32(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedTaggedToInt32(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerCheckedTaggedToFloat64(Node* node, Node* frame_state,
Node* effect, Node* control);
ValueEffectControl LowerChangeTaggedToFloat64(Node* node, Node* effect,
Node* control);
ValueEffectControl LowerTruncateTaggedToFloat64(Node* node, Node* effect,
......
......@@ -105,13 +105,6 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
case IrOpcode::kJSLessThanOrEqual:
return 2;
// Checked conversions.
case IrOpcode::kCheckedUint32ToInt32:
case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedTaggedToInt32:
case IrOpcode::kCheckedTaggedToFloat64:
return 1;
default:
return 0;
}
......
......@@ -447,13 +447,10 @@ Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
Node* use_node) {
if (op->ControlInputCount() > 0) {
// If the operator can deoptimize (which means it has control
// input), we need to connect it to the effect and control chains
// and also provide it with a frame state.
// input), we need to connect it to the effect and control chains.
Node* effect = NodeProperties::GetEffectInput(use_node);
Node* control = NodeProperties::GetControlInput(use_node);
Node* frame_state = NodeProperties::FindFrameStateBefore(use_node);
Node* conversion =
jsgraph()->graph()->NewNode(op, node, frame_state, effect, control);
Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
NodeProperties::ReplaceControlInput(use_node, control);
NodeProperties::ReplaceEffectInput(use_node, effect);
return conversion;
......@@ -559,8 +556,7 @@ Node* RepresentationChanger::GetCheckedWord32RepresentationFor(
}
if (op->ControlInputCount() > 0) {
// If the operator can deoptimize (which means it has control
// input), we need to connect it to the effect and control chains
// and also provide it with a frame state.
// input), we need to connect it to the effect and control chains.
UNIMPLEMENTED();
}
return jsgraph()->graph()->NewNode(op, node);
......
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