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 { ...@@ -37,6 +37,7 @@ namespace {
struct BlockEffectControlData { struct BlockEffectControlData {
Node* current_effect = nullptr; // New effect. Node* current_effect = nullptr; // New effect.
Node* current_control = nullptr; // New control. 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. // Effect phis that need to be updated after the first pass.
...@@ -222,10 +223,30 @@ void EffectControlLinearizer::Run() { ...@@ -222,10 +223,30 @@ void EffectControlLinearizer::Run() {
NodeProperties::ReplaceEffectInput(terminate, effect); 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. // Process the ordinary instructions.
for (; instr < block->NodeCount(); instr++) { for (; instr < block->NodeCount(); instr++) {
Node* node = block->NodeAt(instr); Node* node = block->NodeAt(instr);
ProcessNode(node, &effect, &control); ProcessNode(node, &frame_state, &effect, &control);
} }
switch (block->control()) { switch (block->control()) {
...@@ -240,13 +261,14 @@ void EffectControlLinearizer::Run() { ...@@ -240,13 +261,14 @@ void EffectControlLinearizer::Run() {
case BasicBlock::kReturn: case BasicBlock::kReturn:
case BasicBlock::kDeoptimize: case BasicBlock::kDeoptimize:
case BasicBlock::kThrow: case BasicBlock::kThrow:
ProcessNode(block->control_input(), &effect, &control); ProcessNode(block->control_input(), &frame_state, &effect, &control);
break; break;
} }
// Store the effect for later use. // Store the effect for later use.
block_effects[block->rpo_number()].current_effect = effect; block_effects[block->rpo_number()].current_effect = effect;
block_effects[block->rpo_number()].current_control = control; 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 // Update the incoming edges of the effect phis that could not be processed
...@@ -276,14 +298,19 @@ void TryScheduleCallIfSuccess(Node* node, Node** control) { ...@@ -276,14 +298,19 @@ void TryScheduleCallIfSuccess(Node* node, Node** control) {
} // namespace } // namespace
void EffectControlLinearizer::ProcessNode(Node* node, Node** effect, void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
Node** control) { Node** effect, Node** control) {
// If the node needs to be wired into the effect/control chain, do this // If the node needs to be wired into the effect/control chain, do this
// here. // here. Pass current frame state for lowering to eager deoptimization.
if (TryWireInStateEffect(node, effect, control)) { if (TryWireInStateEffect(node, *frame_state, effect, control)) {
return; 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 // Remove the end markers of 'atomic' allocation region because the
// region should be wired-in now. // region should be wired-in now.
if (node->opcode() == IrOpcode::kFinishRegion || if (node->opcode() == IrOpcode::kFinishRegion ||
...@@ -294,10 +321,10 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** effect, ...@@ -294,10 +321,10 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** effect,
} }
// Special treatment for checkpoint nodes. // Special treatment for checkpoint nodes.
// TODO(epertoso): Pickup the current frame state.
if (node->opcode() == IrOpcode::kCheckpoint) { if (node->opcode() == IrOpcode::kCheckpoint) {
// Unlink the check point; effect uses will be updated to the incoming // 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); node->TrimInputCount(0);
return; return;
} }
...@@ -347,7 +374,9 @@ void EffectControlLinearizer::ProcessNode(Node* node, Node** effect, ...@@ -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) { Node** control) {
ValueEffectControl state(nullptr, nullptr, nullptr); ValueEffectControl state(nullptr, nullptr, nullptr);
switch (node->opcode()) { switch (node->opcode()) {
...@@ -388,16 +417,16 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect, ...@@ -388,16 +417,16 @@ bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect,
state = LowerTruncateTaggedToFloat64(node, *effect, *control); state = LowerTruncateTaggedToFloat64(node, *effect, *control);
break; break;
case IrOpcode::kCheckedUint32ToInt32: case IrOpcode::kCheckedUint32ToInt32:
state = LowerCheckedUint32ToInt32(node, *effect, *control); state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control);
break; break;
case IrOpcode::kCheckedFloat64ToInt32: case IrOpcode::kCheckedFloat64ToInt32:
state = LowerCheckedFloat64ToInt32(node, *effect, *control); state = LowerCheckedFloat64ToInt32(node, frame_state, *effect, *control);
break; break;
case IrOpcode::kCheckedTaggedToInt32: case IrOpcode::kCheckedTaggedToInt32:
state = LowerCheckedTaggedToInt32(node, *effect, *control); state = LowerCheckedTaggedToInt32(node, frame_state, *effect, *control);
break; break;
case IrOpcode::kCheckedTaggedToFloat64: case IrOpcode::kCheckedTaggedToFloat64:
state = LowerCheckedTaggedToFloat64(node, *effect, *control); state = LowerCheckedTaggedToFloat64(node, frame_state, *effect, *control);
break; break;
case IrOpcode::kTruncateTaggedToWord32: case IrOpcode::kTruncateTaggedToWord32:
state = LowerTruncateTaggedToWord32(node, *effect, *control); state = LowerTruncateTaggedToWord32(node, *effect, *control);
...@@ -718,10 +747,11 @@ EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node, Node* effect, ...@@ -718,10 +747,11 @@ EffectControlLinearizer::LowerTruncateTaggedToFloat64(Node* node, Node* effect,
} }
EffectControlLinearizer::ValueEffectControl EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, Node* effect, EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
Node* frame_state,
Node* effect,
Node* control) { Node* control) {
Node* value = node->InputAt(0); Node* value = node->InputAt(0);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
Node* max_int = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::max()); Node* max_int = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::max());
Node* is_safe = Node* is_safe =
graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, max_int); graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, max_int);
...@@ -774,10 +804,11 @@ EffectControlLinearizer::BuildCheckedFloat64ToInt32(Node* value, ...@@ -774,10 +804,11 @@ EffectControlLinearizer::BuildCheckedFloat64ToInt32(Node* value,
} }
EffectControlLinearizer::ValueEffectControl EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, Node* effect, EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
Node* frame_state,
Node* effect,
Node* control) { Node* control) {
Node* value = node->InputAt(0); Node* value = node->InputAt(0);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
// Make sure the lowered node does not appear in any use lists. // Make sure the lowered node does not appear in any use lists.
node->TrimInputCount(0); node->TrimInputCount(0);
...@@ -786,10 +817,11 @@ EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, Node* effect, ...@@ -786,10 +817,11 @@ EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, Node* effect,
} }
EffectControlLinearizer::ValueEffectControl EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node, Node* effect, EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
Node* frame_state,
Node* effect,
Node* control) { Node* control) {
Node* value = node->InputAt(0); Node* value = node->InputAt(0);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
Node* check = ObjectIsSmi(value); Node* check = ObjectIsSmi(value);
Node* branch = Node* branch =
...@@ -863,10 +895,11 @@ EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64( ...@@ -863,10 +895,11 @@ EffectControlLinearizer::BuildCheckedHeapNumberOrOddballToFloat64(
} }
EffectControlLinearizer::ValueEffectControl EffectControlLinearizer::ValueEffectControl
EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node, Node* effect, EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
Node* frame_state,
Node* effect,
Node* control) { Node* control) {
Node* value = node->InputAt(0); Node* value = node->InputAt(0);
Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
Node* check = ObjectIsSmi(value); Node* check = ObjectIsSmi(value);
Node* branch = Node* branch =
......
...@@ -30,7 +30,8 @@ class EffectControlLinearizer { ...@@ -30,7 +30,8 @@ class EffectControlLinearizer {
void Run(); void Run();
private: private:
void ProcessNode(Node* node, Node** current_effect, Node** control); void ProcessNode(Node* node, Node** frame_state, Node** effect,
Node** control);
struct ValueEffectControl { struct ValueEffectControl {
Node* value; Node* value;
...@@ -40,7 +41,8 @@ class EffectControlLinearizer { ...@@ -40,7 +41,8 @@ class EffectControlLinearizer {
: value(value), effect(effect), control(control) {} : 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 LowerTypeGuard(Node* node, Node* effect, Node* control);
ValueEffectControl LowerChangeBitToTagged(Node* node, Node* effect, ValueEffectControl LowerChangeBitToTagged(Node* node, Node* effect,
Node* control); Node* control);
...@@ -60,14 +62,14 @@ class EffectControlLinearizer { ...@@ -60,14 +62,14 @@ class EffectControlLinearizer {
Node* control); Node* control);
ValueEffectControl LowerChangeTaggedToUint32(Node* node, Node* effect, ValueEffectControl LowerChangeTaggedToUint32(Node* node, Node* effect,
Node* control); Node* control);
ValueEffectControl LowerCheckedUint32ToInt32(Node* node, Node* effect, ValueEffectControl LowerCheckedUint32ToInt32(Node* node, Node* frame_state,
Node* control); Node* effect, Node* control);
ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* effect, ValueEffectControl LowerCheckedFloat64ToInt32(Node* node, Node* frame_state,
Node* control); Node* effect, Node* control);
ValueEffectControl LowerCheckedTaggedToInt32(Node* node, Node* effect, ValueEffectControl LowerCheckedTaggedToInt32(Node* node, Node* frame_state,
Node* control); Node* effect, Node* control);
ValueEffectControl LowerCheckedTaggedToFloat64(Node* node, Node* effect, ValueEffectControl LowerCheckedTaggedToFloat64(Node* node, Node* frame_state,
Node* control); Node* effect, Node* control);
ValueEffectControl LowerChangeTaggedToFloat64(Node* node, Node* effect, ValueEffectControl LowerChangeTaggedToFloat64(Node* node, Node* effect,
Node* control); Node* control);
ValueEffectControl LowerTruncateTaggedToFloat64(Node* node, Node* effect, ValueEffectControl LowerTruncateTaggedToFloat64(Node* node, Node* effect,
......
...@@ -105,13 +105,6 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) { ...@@ -105,13 +105,6 @@ int OperatorProperties::GetFrameStateInputCount(const Operator* op) {
case IrOpcode::kJSLessThanOrEqual: case IrOpcode::kJSLessThanOrEqual:
return 2; return 2;
// Checked conversions.
case IrOpcode::kCheckedUint32ToInt32:
case IrOpcode::kCheckedFloat64ToInt32:
case IrOpcode::kCheckedTaggedToInt32:
case IrOpcode::kCheckedTaggedToFloat64:
return 1;
default: default:
return 0; return 0;
} }
......
...@@ -447,13 +447,10 @@ Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op, ...@@ -447,13 +447,10 @@ Node* RepresentationChanger::InsertConversion(Node* node, const Operator* op,
Node* use_node) { Node* use_node) {
if (op->ControlInputCount() > 0) { if (op->ControlInputCount() > 0) {
// If the operator can deoptimize (which means it has control // If the operator can deoptimize (which means it has control
// input), we need to connect it to the effect and control chains // input), we need to connect it to the effect and control chains.
// and also provide it with a frame state.
Node* effect = NodeProperties::GetEffectInput(use_node); Node* effect = NodeProperties::GetEffectInput(use_node);
Node* control = NodeProperties::GetControlInput(use_node); Node* control = NodeProperties::GetControlInput(use_node);
Node* frame_state = NodeProperties::FindFrameStateBefore(use_node); Node* conversion = jsgraph()->graph()->NewNode(op, node, effect, control);
Node* conversion =
jsgraph()->graph()->NewNode(op, node, frame_state, effect, control);
NodeProperties::ReplaceControlInput(use_node, control); NodeProperties::ReplaceControlInput(use_node, control);
NodeProperties::ReplaceEffectInput(use_node, effect); NodeProperties::ReplaceEffectInput(use_node, effect);
return conversion; return conversion;
...@@ -559,8 +556,7 @@ Node* RepresentationChanger::GetCheckedWord32RepresentationFor( ...@@ -559,8 +556,7 @@ Node* RepresentationChanger::GetCheckedWord32RepresentationFor(
} }
if (op->ControlInputCount() > 0) { if (op->ControlInputCount() > 0) {
// If the operator can deoptimize (which means it has control // If the operator can deoptimize (which means it has control
// input), we need to connect it to the effect and control chains // input), we need to connect it to the effect and control chains.
// and also provide it with a frame state.
UNIMPLEMENTED(); UNIMPLEMENTED();
} }
return jsgraph()->graph()->NewNode(op, node); 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