Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(231)

Side by Side Diff: src/compiler/effect-control-linearizer.cc

Issue 2033143002: [turbofan] Add frame state propagation to linearizer. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@local_turbofan-checkpoint-6
Patch Set: Addressed comment. Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/effect-control-linearizer.h ('k') | src/compiler/operator-properties.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/effect-control-linearizer.h" 5 #include "src/compiler/effect-control-linearizer.h"
6 6
7 #include "src/code-factory.h" 7 #include "src/code-factory.h"
8 #include "src/compiler/access-builder.h" 8 #include "src/compiler/access-builder.h"
9 #include "src/compiler/js-graph.h" 9 #include "src/compiler/js-graph.h"
10 #include "src/compiler/linkage.h" 10 #include "src/compiler/linkage.h"
(...skipping 19 matching lines...) Expand all
30 } 30 }
31 MachineOperatorBuilder* EffectControlLinearizer::machine() const { 31 MachineOperatorBuilder* EffectControlLinearizer::machine() const {
32 return js_graph_->machine(); 32 return js_graph_->machine();
33 } 33 }
34 34
35 namespace { 35 namespace {
36 36
37 struct BlockEffectControlData { 37 struct BlockEffectControlData {
38 Node* current_effect = nullptr; // New effect. 38 Node* current_effect = nullptr; // New effect.
39 Node* current_control = nullptr; // New control. 39 Node* current_control = nullptr; // New control.
40 Node* current_frame_state = nullptr; // New frame state.
40 }; 41 };
41 42
42 // Effect phis that need to be updated after the first pass. 43 // Effect phis that need to be updated after the first pass.
43 struct PendingEffectPhi { 44 struct PendingEffectPhi {
44 Node* effect_phi; 45 Node* effect_phi;
45 BasicBlock* block; 46 BasicBlock* block;
46 47
47 PendingEffectPhi(Node* effect_phi, BasicBlock* block) 48 PendingEffectPhi(Node* effect_phi, BasicBlock* block)
48 : effect_phi(effect_phi), block(block) {} 49 : effect_phi(effect_phi), block(block) {}
49 }; 50 };
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after
215 effect = control; 216 effect = control;
216 } 217 }
217 } 218 }
218 } 219 }
219 220
220 // Fixup the Terminate node. 221 // Fixup the Terminate node.
221 if (terminate != nullptr) { 222 if (terminate != nullptr) {
222 NodeProperties::ReplaceEffectInput(terminate, effect); 223 NodeProperties::ReplaceEffectInput(terminate, effect);
223 } 224 }
224 225
226 // The frame state at block entry is determined by the frame states leaving
227 // all predecessors. In case there is no frame state dominating this block,
228 // we can rely on a checkpoint being present before the next deoptimization.
229 // TODO(mstarzinger): Eventually we will need to go hunt for a frame state
230 // once deoptimizing nodes roam freely through the schedule.
231 Node* frame_state = nullptr;
232 if (block != schedule()->start()) {
233 // If all the predecessors have the same effect, we can use it
234 // as our current effect.
235 int rpo_number = block->PredecessorAt(0)->rpo_number();
236 frame_state = block_effects[rpo_number].current_frame_state;
237 for (size_t i = 1; i < block->PredecessorCount(); i++) {
238 int rpo_number = block->PredecessorAt(i)->rpo_number();
239 if (block_effects[rpo_number].current_frame_state != frame_state) {
240 frame_state = nullptr;
241 break;
242 }
243 }
244 }
245
225 // Process the ordinary instructions. 246 // Process the ordinary instructions.
226 for (; instr < block->NodeCount(); instr++) { 247 for (; instr < block->NodeCount(); instr++) {
227 Node* node = block->NodeAt(instr); 248 Node* node = block->NodeAt(instr);
228 ProcessNode(node, &effect, &control); 249 ProcessNode(node, &frame_state, &effect, &control);
229 } 250 }
230 251
231 switch (block->control()) { 252 switch (block->control()) {
232 case BasicBlock::kGoto: 253 case BasicBlock::kGoto:
233 case BasicBlock::kNone: 254 case BasicBlock::kNone:
234 break; 255 break;
235 256
236 case BasicBlock::kCall: 257 case BasicBlock::kCall:
237 case BasicBlock::kTailCall: 258 case BasicBlock::kTailCall:
238 case BasicBlock::kBranch: 259 case BasicBlock::kBranch:
239 case BasicBlock::kSwitch: 260 case BasicBlock::kSwitch:
240 case BasicBlock::kReturn: 261 case BasicBlock::kReturn:
241 case BasicBlock::kDeoptimize: 262 case BasicBlock::kDeoptimize:
242 case BasicBlock::kThrow: 263 case BasicBlock::kThrow:
243 ProcessNode(block->control_input(), &effect, &control); 264 ProcessNode(block->control_input(), &frame_state, &effect, &control);
244 break; 265 break;
245 } 266 }
246 267
247 // Store the effect for later use. 268 // Store the effect for later use.
248 block_effects[block->rpo_number()].current_effect = effect; 269 block_effects[block->rpo_number()].current_effect = effect;
249 block_effects[block->rpo_number()].current_control = control; 270 block_effects[block->rpo_number()].current_control = control;
271 block_effects[block->rpo_number()].current_frame_state = frame_state;
250 } 272 }
251 273
252 // Update the incoming edges of the effect phis that could not be processed 274 // Update the incoming edges of the effect phis that could not be processed
253 // during the first pass (because they could have incoming back edges). 275 // during the first pass (because they could have incoming back edges).
254 for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) { 276 for (const PendingEffectPhi& pending_effect_phi : pending_effect_phis) {
255 UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block, 277 UpdateEffectPhi(pending_effect_phi.effect_phi, pending_effect_phi.block,
256 &block_effects); 278 &block_effects);
257 } 279 }
258 for (BasicBlock* pending_block_control : pending_block_controls) { 280 for (BasicBlock* pending_block_control : pending_block_controls) {
259 UpdateBlockControl(pending_block_control, &block_effects); 281 UpdateBlockControl(pending_block_control, &block_effects);
260 } 282 }
261 } 283 }
262 284
263 namespace { 285 namespace {
264 286
265 void TryScheduleCallIfSuccess(Node* node, Node** control) { 287 void TryScheduleCallIfSuccess(Node* node, Node** control) {
266 // Schedule the call's IfSuccess node if there is no exception use. 288 // Schedule the call's IfSuccess node if there is no exception use.
267 if (!NodeProperties::IsExceptionalCall(node)) { 289 if (!NodeProperties::IsExceptionalCall(node)) {
268 for (Edge edge : node->use_edges()) { 290 for (Edge edge : node->use_edges()) {
269 if (NodeProperties::IsControlEdge(edge) && 291 if (NodeProperties::IsControlEdge(edge) &&
270 edge.from()->opcode() == IrOpcode::kIfSuccess) { 292 edge.from()->opcode() == IrOpcode::kIfSuccess) {
271 *control = edge.from(); 293 *control = edge.from();
272 } 294 }
273 } 295 }
274 } 296 }
275 } 297 }
276 298
277 } // namespace 299 } // namespace
278 300
279 void EffectControlLinearizer::ProcessNode(Node* node, Node** effect, 301 void EffectControlLinearizer::ProcessNode(Node* node, Node** frame_state,
280 Node** control) { 302 Node** effect, Node** control) {
281 // If the node needs to be wired into the effect/control chain, do this 303 // If the node needs to be wired into the effect/control chain, do this
282 // here. 304 // here. Pass current frame state for lowering to eager deoptimization.
283 if (TryWireInStateEffect(node, effect, control)) { 305 if (TryWireInStateEffect(node, *frame_state, effect, control)) {
284 return; 306 return;
285 } 307 }
286 308
309 // If the node has a visible effect, then there must be a checkpoint in the
310 // effect chain before we are allowed to place another eager deoptimization
311 // point. We zap the frame state to ensure this invariant is maintained.
312 if (!node->op()->HasProperty(Operator::kNoWrite)) *frame_state = nullptr;
313
287 // Remove the end markers of 'atomic' allocation region because the 314 // Remove the end markers of 'atomic' allocation region because the
288 // region should be wired-in now. 315 // region should be wired-in now.
289 if (node->opcode() == IrOpcode::kFinishRegion || 316 if (node->opcode() == IrOpcode::kFinishRegion ||
290 node->opcode() == IrOpcode::kBeginRegion) { 317 node->opcode() == IrOpcode::kBeginRegion) {
291 // Update the value uses to the value input of the finish node and 318 // Update the value uses to the value input of the finish node and
292 // the effect uses to the effect input. 319 // the effect uses to the effect input.
293 return RemoveRegionNode(node); 320 return RemoveRegionNode(node);
294 } 321 }
295 322
296 // Special treatment for checkpoint nodes. 323 // Special treatment for checkpoint nodes.
297 // TODO(epertoso): Pickup the current frame state.
298 if (node->opcode() == IrOpcode::kCheckpoint) { 324 if (node->opcode() == IrOpcode::kCheckpoint) {
299 // Unlink the check point; effect uses will be updated to the incoming 325 // Unlink the check point; effect uses will be updated to the incoming
300 // effect that is passed. 326 // effect that is passed. The frame state is preserved for lowering.
327 *frame_state = NodeProperties::GetFrameStateInput(node, 0);
301 node->TrimInputCount(0); 328 node->TrimInputCount(0);
302 return; 329 return;
303 } 330 }
304 331
305 if (node->opcode() == IrOpcode::kIfSuccess) { 332 if (node->opcode() == IrOpcode::kIfSuccess) {
306 // We always schedule IfSuccess with its call, so skip it here. 333 // We always schedule IfSuccess with its call, so skip it here.
307 DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode()); 334 DCHECK_EQ(IrOpcode::kCall, node->InputAt(0)->opcode());
308 // The IfSuccess node should not belong to an exceptional call node 335 // The IfSuccess node should not belong to an exceptional call node
309 // because such IfSuccess nodes should only start a basic block (and 336 // because such IfSuccess nodes should only start a basic block (and
310 // basic block start nodes are not handled in the ProcessNode method). 337 // basic block start nodes are not handled in the ProcessNode method).
(...skipping 29 matching lines...) Expand all
340 // Update the current control and wire IfSuccess right after calls. 367 // Update the current control and wire IfSuccess right after calls.
341 if (node->op()->ControlOutputCount() > 0) { 368 if (node->op()->ControlOutputCount() > 0) {
342 *control = node; 369 *control = node;
343 if (node->opcode() == IrOpcode::kCall) { 370 if (node->opcode() == IrOpcode::kCall) {
344 // Schedule the call's IfSuccess node (if there is no exception use). 371 // Schedule the call's IfSuccess node (if there is no exception use).
345 TryScheduleCallIfSuccess(node, control); 372 TryScheduleCallIfSuccess(node, control);
346 } 373 }
347 } 374 }
348 } 375 }
349 376
350 bool EffectControlLinearizer::TryWireInStateEffect(Node* node, Node** effect, 377 bool EffectControlLinearizer::TryWireInStateEffect(Node* node,
378 Node* frame_state,
379 Node** effect,
351 Node** control) { 380 Node** control) {
352 ValueEffectControl state(nullptr, nullptr, nullptr); 381 ValueEffectControl state(nullptr, nullptr, nullptr);
353 switch (node->opcode()) { 382 switch (node->opcode()) {
354 case IrOpcode::kTypeGuard: 383 case IrOpcode::kTypeGuard:
355 state = LowerTypeGuard(node, *effect, *control); 384 state = LowerTypeGuard(node, *effect, *control);
356 break; 385 break;
357 case IrOpcode::kChangeBitToTagged: 386 case IrOpcode::kChangeBitToTagged:
358 state = LowerChangeBitToTagged(node, *effect, *control); 387 state = LowerChangeBitToTagged(node, *effect, *control);
359 break; 388 break;
360 case IrOpcode::kChangeInt31ToTaggedSigned: 389 case IrOpcode::kChangeInt31ToTaggedSigned:
(...skipping 20 matching lines...) Expand all
381 case IrOpcode::kChangeTaggedToUint32: 410 case IrOpcode::kChangeTaggedToUint32:
382 state = LowerChangeTaggedToUint32(node, *effect, *control); 411 state = LowerChangeTaggedToUint32(node, *effect, *control);
383 break; 412 break;
384 case IrOpcode::kChangeTaggedToFloat64: 413 case IrOpcode::kChangeTaggedToFloat64:
385 state = LowerChangeTaggedToFloat64(node, *effect, *control); 414 state = LowerChangeTaggedToFloat64(node, *effect, *control);
386 break; 415 break;
387 case IrOpcode::kTruncateTaggedToFloat64: 416 case IrOpcode::kTruncateTaggedToFloat64:
388 state = LowerTruncateTaggedToFloat64(node, *effect, *control); 417 state = LowerTruncateTaggedToFloat64(node, *effect, *control);
389 break; 418 break;
390 case IrOpcode::kCheckedUint32ToInt32: 419 case IrOpcode::kCheckedUint32ToInt32:
391 state = LowerCheckedUint32ToInt32(node, *effect, *control); 420 state = LowerCheckedUint32ToInt32(node, frame_state, *effect, *control);
392 break; 421 break;
393 case IrOpcode::kCheckedFloat64ToInt32: 422 case IrOpcode::kCheckedFloat64ToInt32:
394 state = LowerCheckedFloat64ToInt32(node, *effect, *control); 423 state = LowerCheckedFloat64ToInt32(node, frame_state, *effect, *control);
395 break; 424 break;
396 case IrOpcode::kCheckedTaggedToInt32: 425 case IrOpcode::kCheckedTaggedToInt32:
397 state = LowerCheckedTaggedToInt32(node, *effect, *control); 426 state = LowerCheckedTaggedToInt32(node, frame_state, *effect, *control);
398 break; 427 break;
399 case IrOpcode::kCheckedTaggedToFloat64: 428 case IrOpcode::kCheckedTaggedToFloat64:
400 state = LowerCheckedTaggedToFloat64(node, *effect, *control); 429 state = LowerCheckedTaggedToFloat64(node, frame_state, *effect, *control);
401 break; 430 break;
402 case IrOpcode::kTruncateTaggedToWord32: 431 case IrOpcode::kTruncateTaggedToWord32:
403 state = LowerTruncateTaggedToWord32(node, *effect, *control); 432 state = LowerTruncateTaggedToWord32(node, *effect, *control);
404 break; 433 break;
405 case IrOpcode::kObjectIsCallable: 434 case IrOpcode::kObjectIsCallable:
406 state = LowerObjectIsCallable(node, *effect, *control); 435 state = LowerObjectIsCallable(node, *effect, *control);
407 break; 436 break;
408 case IrOpcode::kObjectIsNumber: 437 case IrOpcode::kObjectIsNumber:
409 state = LowerObjectIsNumber(node, *effect, *control); 438 state = LowerObjectIsNumber(node, *effect, *control);
410 break; 439 break;
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
711 740
712 control = graph()->NewNode(common()->Merge(2), if_true, if_false); 741 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
713 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); 742 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
714 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2), 743 value = graph()->NewNode(common()->Phi(MachineRepresentation::kFloat64, 2),
715 vtrue, vfalse, control); 744 vtrue, vfalse, control);
716 745
717 return ValueEffectControl(value, effect, control); 746 return ValueEffectControl(value, effect, control);
718 } 747 }
719 748
720 EffectControlLinearizer::ValueEffectControl 749 EffectControlLinearizer::ValueEffectControl
721 EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node, Node* effect, 750 EffectControlLinearizer::LowerCheckedUint32ToInt32(Node* node,
751 Node* frame_state,
752 Node* effect,
722 Node* control) { 753 Node* control) {
723 Node* value = node->InputAt(0); 754 Node* value = node->InputAt(0);
724 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
725 Node* max_int = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::max()); 755 Node* max_int = jsgraph()->Int32Constant(std::numeric_limits<int32_t>::max());
726 Node* is_safe = 756 Node* is_safe =
727 graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, max_int); 757 graph()->NewNode(machine()->Uint32LessThanOrEqual(), value, max_int);
728 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), is_safe, 758 control = effect = graph()->NewNode(common()->DeoptimizeUnless(), is_safe,
729 frame_state, effect, control); 759 frame_state, effect, control);
730 760
731 // Make sure the lowered node does not appear in any use lists. 761 // Make sure the lowered node does not appear in any use lists.
732 node->TrimInputCount(0); 762 node->TrimInputCount(0);
733 763
734 return ValueEffectControl(value, effect, control); 764 return ValueEffectControl(value, effect, control);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
767 Node* merge = 797 Node* merge =
768 graph()->NewNode(common()->Merge(2), deopt_minus_zero, if_notzero); 798 graph()->NewNode(common()->Merge(2), deopt_minus_zero, if_notzero);
769 799
770 effect = 800 effect =
771 graph()->NewNode(common()->EffectPhi(2), deopt_minus_zero, effect, merge); 801 graph()->NewNode(common()->EffectPhi(2), deopt_minus_zero, effect, merge);
772 802
773 return ValueEffectControl(value32, effect, merge); 803 return ValueEffectControl(value32, effect, merge);
774 } 804 }
775 805
776 EffectControlLinearizer::ValueEffectControl 806 EffectControlLinearizer::ValueEffectControl
777 EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node, Node* effect, 807 EffectControlLinearizer::LowerCheckedFloat64ToInt32(Node* node,
808 Node* frame_state,
809 Node* effect,
778 Node* control) { 810 Node* control) {
779 Node* value = node->InputAt(0); 811 Node* value = node->InputAt(0);
780 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
781 812
782 // Make sure the lowered node does not appear in any use lists. 813 // Make sure the lowered node does not appear in any use lists.
783 node->TrimInputCount(0); 814 node->TrimInputCount(0);
784 815
785 return BuildCheckedFloat64ToInt32(value, frame_state, effect, control); 816 return BuildCheckedFloat64ToInt32(value, frame_state, effect, control);
786 } 817 }
787 818
788 EffectControlLinearizer::ValueEffectControl 819 EffectControlLinearizer::ValueEffectControl
789 EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node, Node* effect, 820 EffectControlLinearizer::LowerCheckedTaggedToInt32(Node* node,
821 Node* frame_state,
822 Node* effect,
790 Node* control) { 823 Node* control) {
791 Node* value = node->InputAt(0); 824 Node* value = node->InputAt(0);
792 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
793 825
794 Node* check = ObjectIsSmi(value); 826 Node* check = ObjectIsSmi(value);
795 Node* branch = 827 Node* branch =
796 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); 828 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
797 829
798 // In the Smi case, just convert to int32. 830 // In the Smi case, just convert to int32.
799 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 831 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
800 Node* etrue = effect; 832 Node* etrue = effect;
801 Node* vtrue = ChangeSmiToInt32(value); 833 Node* vtrue = ChangeSmiToInt32(value);
802 834
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 control = graph()->NewNode(common()->Merge(2), if_true, if_false); 888 control = graph()->NewNode(common()->Merge(2), if_true, if_false);
857 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control); 889 effect = graph()->NewNode(common()->EffectPhi(2), etrue, efalse, control);
858 890
859 Node* result = effect = graph()->NewNode( 891 Node* result = effect = graph()->NewNode(
860 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value, 892 simplified()->LoadField(AccessBuilder::ForHeapNumberValue()), value,
861 effect, control); 893 effect, control);
862 return ValueEffectControl(result, effect, control); 894 return ValueEffectControl(result, effect, control);
863 } 895 }
864 896
865 EffectControlLinearizer::ValueEffectControl 897 EffectControlLinearizer::ValueEffectControl
866 EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node, Node* effect, 898 EffectControlLinearizer::LowerCheckedTaggedToFloat64(Node* node,
899 Node* frame_state,
900 Node* effect,
867 Node* control) { 901 Node* control) {
868 Node* value = node->InputAt(0); 902 Node* value = node->InputAt(0);
869 Node* frame_state = NodeProperties::GetFrameStateInput(node, 0);
870 903
871 Node* check = ObjectIsSmi(value); 904 Node* check = ObjectIsSmi(value);
872 Node* branch = 905 Node* branch =
873 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control); 906 graph()->NewNode(common()->Branch(BranchHint::kTrue), check, control);
874 907
875 // In the Smi case, just convert to int32 and then float64. 908 // In the Smi case, just convert to int32 and then float64.
876 Node* if_true = graph()->NewNode(common()->IfTrue(), branch); 909 Node* if_true = graph()->NewNode(common()->IfTrue(), branch);
877 Node* etrue = effect; 910 Node* etrue = effect;
878 Node* vtrue = ChangeSmiToInt32(value); 911 Node* vtrue = ChangeSmiToInt32(value);
879 vtrue = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue); 912 vtrue = graph()->NewNode(machine()->ChangeInt32ToFloat64(), vtrue);
(...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after
1305 return isolate()->factory(); 1338 return isolate()->factory();
1306 } 1339 }
1307 1340
1308 Isolate* EffectControlLinearizer::isolate() const { 1341 Isolate* EffectControlLinearizer::isolate() const {
1309 return jsgraph()->isolate(); 1342 return jsgraph()->isolate();
1310 } 1343 }
1311 1344
1312 } // namespace compiler 1345 } // namespace compiler
1313 } // namespace internal 1346 } // namespace internal
1314 } // namespace v8 1347 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/effect-control-linearizer.h ('k') | src/compiler/operator-properties.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698