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

Side by Side Diff: src/compiler/bytecode-graph-builder.cc

Issue 2188533002: [turbofan] Generate loop exits in the bytecode graph builder. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Address review comments Created 4 years, 4 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
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/bytecode-graph-builder.h" 5 #include "src/compiler/bytecode-graph-builder.h"
6 6
7 #include "src/compiler/bytecode-branch-analysis.h" 7 #include "src/compiler/bytecode-branch-analysis.h"
8 #include "src/compiler/linkage.h" 8 #include "src/compiler/linkage.h"
9 #include "src/compiler/operator-properties.h" 9 #include "src/compiler/operator-properties.h"
10 #include "src/interpreter/bytecodes.h" 10 #include "src/interpreter/bytecodes.h"
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 } 55 }
56 56
57 Node* Context() const { return context_; } 57 Node* Context() const { return context_; }
58 void SetContext(Node* new_context) { context_ = new_context; } 58 void SetContext(Node* new_context) { context_ = new_context; }
59 59
60 Environment* CopyForConditional() const; 60 Environment* CopyForConditional() const;
61 Environment* CopyForLoop(); 61 Environment* CopyForLoop();
62 void Merge(Environment* other); 62 void Merge(Environment* other);
63 void PrepareForOsr(); 63 void PrepareForOsr();
64 64
65 void PrepareForLoopExit(Node* loop);
66
65 private: 67 private:
66 explicit Environment(const Environment* copy); 68 explicit Environment(const Environment* copy);
67 void PrepareForLoop(); 69 void PrepareForLoop();
68 bool StateValuesAreUpToDate(Node** state_values, int offset, int count, 70 bool StateValuesAreUpToDate(Node** state_values, int offset, int count,
69 int output_poke_start, int output_poke_end); 71 int output_poke_start, int output_poke_end);
70 bool StateValuesRequireUpdate(Node** state_values, int offset, int count); 72 bool StateValuesRequireUpdate(Node** state_values, int offset, int count);
71 void UpdateStateValues(Node** state_values, int offset, int count); 73 void UpdateStateValues(Node** state_values, int offset, int count);
72 74
73 int RegisterToValuesIndex(interpreter::Register the_register) const; 75 int RegisterToValuesIndex(interpreter::Register the_register) const;
74 76
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); 401 DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
400 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); 402 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
401 for (int i = 0; i < count; i++) { 403 for (int i = 0; i < count; i++) {
402 if ((*state_values)->InputAt(i) != env_values[i]) { 404 if ((*state_values)->InputAt(i) != env_values[i]) {
403 return true; 405 return true;
404 } 406 }
405 } 407 }
406 return false; 408 return false;
407 } 409 }
408 410
411 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) {
412 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
413
414 Node* control = GetControlDependency();
415
416 // Create the loop exit node.
417 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
418 UpdateControlDependency(loop_exit);
419
420 // Rename the effect.
421 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
422 GetEffectDependency(), loop_exit);
423 UpdateEffectDependency(effect_rename);
424
425 // Rename the current context.
426 context_ = graph()->NewNode(common()->LoopExitValue(), context_, loop_exit);
427
428 // Rename the environmnent values.
429 for (size_t i = 0; i < values_.size(); i++) {
430 Node* rename =
431 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit);
432 values_[i] = rename;
433 }
434 }
409 435
410 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, 436 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
411 int offset, 437 int offset,
412 int count) { 438 int count) {
413 if (StateValuesRequireUpdate(state_values, offset, count)) { 439 if (StateValuesRequireUpdate(state_values, offset, count)) {
414 const Operator* op = common()->StateValues(count); 440 const Operator* op = common()->StateValues(count);
415 (*state_values) = graph()->NewNode(op, count, &values()->at(offset)); 441 (*state_values) = graph()->NewNode(op, count, &values()->at(offset));
416 } 442 }
417 } 443 }
418 444
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
564 int const input_count = static_cast<int>(exit_controls_.size()); 590 int const input_count = static_cast<int>(exit_controls_.size());
565 Node** const inputs = &exit_controls_.front(); 591 Node** const inputs = &exit_controls_.front();
566 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); 592 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
567 graph()->SetEnd(end); 593 graph()->SetEnd(end);
568 594
569 return true; 595 return true;
570 } 596 }
571 597
572 void BytecodeGraphBuilder::VisitBytecodes() { 598 void BytecodeGraphBuilder::VisitBytecodes() {
573 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); 599 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone());
600 BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone());
574 analysis.Analyze(); 601 analysis.Analyze();
602 loop_analysis.Analyze();
575 set_branch_analysis(&analysis); 603 set_branch_analysis(&analysis);
604 set_loop_analysis(&loop_analysis);
576 interpreter::BytecodeArrayIterator iterator(bytecode_array()); 605 interpreter::BytecodeArrayIterator iterator(bytecode_array());
577 set_bytecode_iterator(&iterator); 606 set_bytecode_iterator(&iterator);
578 while (!iterator.done()) { 607 while (!iterator.done()) {
579 int current_offset = iterator.current_offset(); 608 int current_offset = iterator.current_offset();
580 EnterAndExitExceptionHandlers(current_offset); 609 EnterAndExitExceptionHandlers(current_offset);
581 SwitchToMergeEnvironment(current_offset); 610 SwitchToMergeEnvironment(current_offset);
582 if (environment() != nullptr) { 611 if (environment() != nullptr) {
583 BuildLoopHeaderEnvironment(current_offset); 612 BuildLoopHeaderEnvironment(current_offset);
584 613
585 switch (iterator.current_bytecode()) { 614 switch (iterator.current_bytecode()) {
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 } 1137 }
1109 1138
1110 void BytecodeGraphBuilder::BuildThrow() { 1139 void BytecodeGraphBuilder::BuildThrow() {
1111 FrameStateBeforeAndAfter states(this); 1140 FrameStateBeforeAndAfter states(this);
1112 Node* value = environment()->LookupAccumulator(); 1141 Node* value = environment()->LookupAccumulator();
1113 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); 1142 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value);
1114 environment()->BindAccumulator(call, &states); 1143 environment()->BindAccumulator(call, &states);
1115 } 1144 }
1116 1145
1117 void BytecodeGraphBuilder::VisitThrow() { 1146 void BytecodeGraphBuilder::VisitThrow() {
1147 BuildLoopExitsForFunctionExit();
1118 BuildThrow(); 1148 BuildThrow();
1119 Node* call = environment()->LookupAccumulator(); 1149 Node* call = environment()->LookupAccumulator();
1120 Node* control = NewNode(common()->Throw(), call); 1150 Node* control = NewNode(common()->Throw(), call);
1121 MergeControlToLeaveFunction(control); 1151 MergeControlToLeaveFunction(control);
1122 } 1152 }
1123 1153
1124 void BytecodeGraphBuilder::VisitReThrow() { 1154 void BytecodeGraphBuilder::VisitReThrow() {
1155 BuildLoopExitsForFunctionExit();
1125 Node* value = environment()->LookupAccumulator(); 1156 Node* value = environment()->LookupAccumulator();
1126 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); 1157 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value);
1127 Node* control = NewNode(common()->Throw(), call); 1158 Node* control = NewNode(common()->Throw(), call);
1128 MergeControlToLeaveFunction(control); 1159 MergeControlToLeaveFunction(control);
1129 } 1160 }
1130 1161
1131 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { 1162 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) {
1132 FrameStateBeforeAndAfter states(this); 1163 FrameStateBeforeAndAfter states(this);
1133 Node* left = 1164 Node* left =
1134 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1165 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1431 void BytecodeGraphBuilder::VisitOsrPoll() { 1462 void BytecodeGraphBuilder::VisitOsrPoll() {
1432 // TODO(4764): This should be moved into the {VisitBytecodes} once we merge 1463 // TODO(4764): This should be moved into the {VisitBytecodes} once we merge
1433 // the polling with existing bytecode. This will also guarantee that we are 1464 // the polling with existing bytecode. This will also guarantee that we are
1434 // not missing the OSR entry point, which we wouldn't catch right now. 1465 // not missing the OSR entry point, which we wouldn't catch right now.
1435 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) { 1466 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) {
1436 environment()->PrepareForOsr(); 1467 environment()->PrepareForOsr();
1437 } 1468 }
1438 } 1469 }
1439 1470
1440 void BytecodeGraphBuilder::VisitReturn() { 1471 void BytecodeGraphBuilder::VisitReturn() {
1472 BuildLoopExitsForFunctionExit();
1441 Node* control = 1473 Node* control =
1442 NewNode(common()->Return(), environment()->LookupAccumulator()); 1474 NewNode(common()->Return(), environment()->LookupAccumulator());
1443 MergeControlToLeaveFunction(control); 1475 MergeControlToLeaveFunction(control);
1444 } 1476 }
1445 1477
1446 void BytecodeGraphBuilder::VisitDebugger() { 1478 void BytecodeGraphBuilder::VisitDebugger() {
1447 FrameStateBeforeAndAfter states(this); 1479 FrameStateBeforeAndAfter states(this);
1448 Node* call = 1480 Node* call =
1449 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); 1481 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
1450 environment()->BindAccumulator(call, &states); 1482 environment()->BindAccumulator(call, &states);
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
1576 1608
1577 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { 1609 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
1578 if (branch_analysis()->backward_branches_target(current_offset)) { 1610 if (branch_analysis()->backward_branches_target(current_offset)) {
1579 // Add loop header and store a copy so we can connect merged back 1611 // Add loop header and store a copy so we can connect merged back
1580 // edge inputs to the loop header. 1612 // edge inputs to the loop header.
1581 merge_environments_[current_offset] = environment()->CopyForLoop(); 1613 merge_environments_[current_offset] = environment()->CopyForLoop();
1582 } 1614 }
1583 } 1615 }
1584 1616
1585 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { 1617 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
1618 BuildLoopExitsForBranch(target_offset);
1586 if (merge_environments_[target_offset] == nullptr) { 1619 if (merge_environments_[target_offset] == nullptr) {
1587 // Append merge nodes to the environment. We may merge here with another 1620 // Append merge nodes to the environment. We may merge here with another
1588 // environment. So add a place holder for merge nodes. We may add redundant 1621 // environment. So add a place holder for merge nodes. We may add redundant
1589 // but will be eliminated in a later pass. 1622 // but will be eliminated in a later pass.
1590 // TODO(mstarzinger): Be smarter about this! 1623 // TODO(mstarzinger): Be smarter about this!
1591 NewMerge(); 1624 NewMerge();
1592 merge_environments_[target_offset] = environment(); 1625 merge_environments_[target_offset] = environment();
1593 } else { 1626 } else {
1594 merge_environments_[target_offset]->Merge(environment()); 1627 merge_environments_[target_offset]->Merge(environment());
1595 } 1628 }
1596 set_environment(nullptr); 1629 set_environment(nullptr);
1597 } 1630 }
1598 1631
1599 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { 1632 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
1600 exit_controls_.push_back(exit); 1633 exit_controls_.push_back(exit);
1601 set_environment(nullptr); 1634 set_environment(nullptr);
1602 } 1635 }
1603 1636
1637 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) {
1638 int origin_offset = bytecode_iterator().current_offset();
1639 // Only build loop exits for forward edges.
1640 if (target_offset > origin_offset) {
1641 BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset));
1642 }
1643 }
1644
1645 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) {
1646 int origin_offset = bytecode_iterator().current_offset();
1647 int current_loop = loop_analysis()->GetLoopOffsetFor(origin_offset);
1648 while (loop_offset < current_loop) {
1649 Node* loop_node = merge_environments_[current_loop]->GetControlDependency();
1650 environment()->PrepareForLoopExit(loop_node);
1651 current_loop = loop_analysis()->GetParentLoopFor(current_loop);
1652 }
1653 }
1654
1655 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() {
1656 BuildLoopExitsUntilLoop(-1);
1657 }
1658
1604 void BytecodeGraphBuilder::BuildJump() { 1659 void BytecodeGraphBuilder::BuildJump() {
1605 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 1660 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
1606 } 1661 }
1607 1662
1608 1663
1609 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { 1664 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) {
1610 NewBranch(condition); 1665 NewBranch(condition);
1611 Environment* if_false_environment = environment()->CopyForConditional(); 1666 Environment* if_false_environment = environment()->CopyForConditional();
1612 NewIfTrue(); 1667 NewIfTrue();
1613 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 1668 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
1832 // Phi does not exist yet, introduce one. 1887 // Phi does not exist yet, introduce one.
1833 value = NewPhi(inputs, value, control); 1888 value = NewPhi(inputs, value, control);
1834 value->ReplaceInput(inputs - 1, other); 1889 value->ReplaceInput(inputs - 1, other);
1835 } 1890 }
1836 return value; 1891 return value;
1837 } 1892 }
1838 1893
1839 } // namespace compiler 1894 } // namespace compiler
1840 } // namespace internal 1895 } // namespace internal
1841 } // namespace v8 1896 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698