| Index: src/compiler/effect-control-linearizer.cc
|
| diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc
|
| index cf38229777cf4cfa07988297f7c7debfcb59e512..f5c5d2d1e80ba08968caef18ba2a59ec870164eb 100644
|
| --- a/src/compiler/effect-control-linearizer.cc
|
| +++ b/src/compiler/effect-control-linearizer.cc
|
| @@ -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 =
|
|
|