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

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: Fix 64-bit 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
« no previous file with comments | « src/compiler/bytecode-graph-builder.h ('k') | src/compiler/bytecode-loop-analysis.h » ('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/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 315 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 DCHECK_LE(static_cast<size_t>(offset + count), values()->size()); 392 DCHECK_LE(static_cast<size_t>(offset + count), values()->size());
391 Node** env_values = (count == 0) ? nullptr : &values()->at(offset); 393 Node** env_values = (count == 0) ? nullptr : &values()->at(offset);
392 for (int i = 0; i < count; i++) { 394 for (int i = 0; i < count; i++) {
393 if ((*state_values)->InputAt(i) != env_values[i]) { 395 if ((*state_values)->InputAt(i) != env_values[i]) {
394 return true; 396 return true;
395 } 397 }
396 } 398 }
397 return false; 399 return false;
398 } 400 }
399 401
402 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) {
403 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop);
404
405 Node* control = GetControlDependency();
406
407 // Create the loop exit node.
408 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop);
409 UpdateControlDependency(loop_exit);
410
411 // Rename the effect.
412 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(),
413 GetEffectDependency(), loop_exit);
414 UpdateEffectDependency(effect_rename);
415
416 // Rename the current context.
417 context_ = graph()->NewNode(common()->LoopExitValue(), context_, loop_exit);
418
419 // Rename the environmnent values.
420 for (size_t i = 0; i < values_.size(); i++) {
421 Node* rename =
422 graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit);
423 values_[i] = rename;
424 }
425 }
400 426
401 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values, 427 void BytecodeGraphBuilder::Environment::UpdateStateValues(Node** state_values,
402 int offset, 428 int offset,
403 int count) { 429 int count) {
404 if (StateValuesRequireUpdate(state_values, offset, count)) { 430 if (StateValuesRequireUpdate(state_values, offset, count)) {
405 const Operator* op = common()->StateValues(count); 431 const Operator* op = common()->StateValues(count);
406 (*state_values) = graph()->NewNode(op, count, &values()->at(offset)); 432 (*state_values) = graph()->NewNode(op, count, &values()->at(offset));
407 } 433 }
408 } 434 }
409 435
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
555 int const input_count = static_cast<int>(exit_controls_.size()); 581 int const input_count = static_cast<int>(exit_controls_.size());
556 Node** const inputs = &exit_controls_.front(); 582 Node** const inputs = &exit_controls_.front();
557 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); 583 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs);
558 graph()->SetEnd(end); 584 graph()->SetEnd(end);
559 585
560 return true; 586 return true;
561 } 587 }
562 588
563 void BytecodeGraphBuilder::VisitBytecodes() { 589 void BytecodeGraphBuilder::VisitBytecodes() {
564 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); 590 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone());
591 BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone());
565 analysis.Analyze(); 592 analysis.Analyze();
593 loop_analysis.Analyze();
566 set_branch_analysis(&analysis); 594 set_branch_analysis(&analysis);
595 set_loop_analysis(&loop_analysis);
567 interpreter::BytecodeArrayIterator iterator(bytecode_array()); 596 interpreter::BytecodeArrayIterator iterator(bytecode_array());
568 set_bytecode_iterator(&iterator); 597 set_bytecode_iterator(&iterator);
569 while (!iterator.done()) { 598 while (!iterator.done()) {
570 int current_offset = iterator.current_offset(); 599 int current_offset = iterator.current_offset();
571 EnterAndExitExceptionHandlers(current_offset); 600 EnterAndExitExceptionHandlers(current_offset);
572 SwitchToMergeEnvironment(current_offset); 601 SwitchToMergeEnvironment(current_offset);
573 if (environment() != nullptr) { 602 if (environment() != nullptr) {
574 BuildLoopHeaderEnvironment(current_offset); 603 BuildLoopHeaderEnvironment(current_offset);
575 604
576 switch (iterator.current_bytecode()) { 605 switch (iterator.current_bytecode()) {
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
1106 } 1135 }
1107 1136
1108 void BytecodeGraphBuilder::BuildThrow() { 1137 void BytecodeGraphBuilder::BuildThrow() {
1109 FrameStateBeforeAndAfter states(this); 1138 FrameStateBeforeAndAfter states(this);
1110 Node* value = environment()->LookupAccumulator(); 1139 Node* value = environment()->LookupAccumulator();
1111 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); 1140 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value);
1112 environment()->BindAccumulator(call, &states); 1141 environment()->BindAccumulator(call, &states);
1113 } 1142 }
1114 1143
1115 void BytecodeGraphBuilder::VisitThrow() { 1144 void BytecodeGraphBuilder::VisitThrow() {
1145 BuildLoopExitsForFunctionExit();
1116 BuildThrow(); 1146 BuildThrow();
1117 Node* call = environment()->LookupAccumulator(); 1147 Node* call = environment()->LookupAccumulator();
1118 Node* control = NewNode(common()->Throw(), call); 1148 Node* control = NewNode(common()->Throw(), call);
1119 MergeControlToLeaveFunction(control); 1149 MergeControlToLeaveFunction(control);
1120 } 1150 }
1121 1151
1122 void BytecodeGraphBuilder::VisitReThrow() { 1152 void BytecodeGraphBuilder::VisitReThrow() {
1153 BuildLoopExitsForFunctionExit();
1123 Node* value = environment()->LookupAccumulator(); 1154 Node* value = environment()->LookupAccumulator();
1124 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); 1155 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value);
1125 Node* control = NewNode(common()->Throw(), call); 1156 Node* control = NewNode(common()->Throw(), call);
1126 MergeControlToLeaveFunction(control); 1157 MergeControlToLeaveFunction(control);
1127 } 1158 }
1128 1159
1129 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { 1160 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) {
1130 FrameStateBeforeAndAfter states(this); 1161 FrameStateBeforeAndAfter states(this);
1131 Node* left = 1162 Node* left =
1132 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); 1163 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0));
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after
1425 void BytecodeGraphBuilder::VisitOsrPoll() { 1456 void BytecodeGraphBuilder::VisitOsrPoll() {
1426 // TODO(4764): This should be moved into the {VisitBytecodes} once we merge 1457 // TODO(4764): This should be moved into the {VisitBytecodes} once we merge
1427 // the polling with existing bytecode. This will also guarantee that we are 1458 // the polling with existing bytecode. This will also guarantee that we are
1428 // not missing the OSR entry point, which we wouldn't catch right now. 1459 // not missing the OSR entry point, which we wouldn't catch right now.
1429 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) { 1460 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) {
1430 environment()->PrepareForOsr(); 1461 environment()->PrepareForOsr();
1431 } 1462 }
1432 } 1463 }
1433 1464
1434 void BytecodeGraphBuilder::VisitReturn() { 1465 void BytecodeGraphBuilder::VisitReturn() {
1466 BuildLoopExitsForFunctionExit();
1435 Node* control = 1467 Node* control =
1436 NewNode(common()->Return(), environment()->LookupAccumulator()); 1468 NewNode(common()->Return(), environment()->LookupAccumulator());
1437 MergeControlToLeaveFunction(control); 1469 MergeControlToLeaveFunction(control);
1438 } 1470 }
1439 1471
1440 void BytecodeGraphBuilder::VisitDebugger() { 1472 void BytecodeGraphBuilder::VisitDebugger() {
1441 FrameStateBeforeAndAfter states(this); 1473 FrameStateBeforeAndAfter states(this);
1442 Node* call = 1474 Node* call =
1443 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); 1475 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement));
1444 environment()->BindAccumulator(call, &states); 1476 environment()->BindAccumulator(call, &states);
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after
1571 1603
1572 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { 1604 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) {
1573 if (branch_analysis()->backward_branches_target(current_offset)) { 1605 if (branch_analysis()->backward_branches_target(current_offset)) {
1574 // Add loop header and store a copy so we can connect merged back 1606 // Add loop header and store a copy so we can connect merged back
1575 // edge inputs to the loop header. 1607 // edge inputs to the loop header.
1576 merge_environments_[current_offset] = environment()->CopyForLoop(); 1608 merge_environments_[current_offset] = environment()->CopyForLoop();
1577 } 1609 }
1578 } 1610 }
1579 1611
1580 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { 1612 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) {
1613 BuildLoopExitsForBranch(target_offset);
1581 if (merge_environments_[target_offset] == nullptr) { 1614 if (merge_environments_[target_offset] == nullptr) {
1582 // Append merge nodes to the environment. We may merge here with another 1615 // Append merge nodes to the environment. We may merge here with another
1583 // environment. So add a place holder for merge nodes. We may add redundant 1616 // environment. So add a place holder for merge nodes. We may add redundant
1584 // but will be eliminated in a later pass. 1617 // but will be eliminated in a later pass.
1585 // TODO(mstarzinger): Be smarter about this! 1618 // TODO(mstarzinger): Be smarter about this!
1586 NewMerge(); 1619 NewMerge();
1587 merge_environments_[target_offset] = environment(); 1620 merge_environments_[target_offset] = environment();
1588 } else { 1621 } else {
1589 merge_environments_[target_offset]->Merge(environment()); 1622 merge_environments_[target_offset]->Merge(environment());
1590 } 1623 }
1591 set_environment(nullptr); 1624 set_environment(nullptr);
1592 } 1625 }
1593 1626
1594 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { 1627 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) {
1595 exit_controls_.push_back(exit); 1628 exit_controls_.push_back(exit);
1596 set_environment(nullptr); 1629 set_environment(nullptr);
1597 } 1630 }
1598 1631
1632 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) {
1633 int origin_offset = bytecode_iterator().current_offset();
1634 // Only build loop exits for forward edges.
1635 if (target_offset > origin_offset) {
1636 BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset));
1637 }
1638 }
1639
1640 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) {
1641 int origin_offset = bytecode_iterator().current_offset();
1642 int current_loop = loop_analysis()->GetLoopOffsetFor(origin_offset);
1643 while (loop_offset < current_loop) {
1644 Node* loop_node = merge_environments_[current_loop]->GetControlDependency();
1645 environment()->PrepareForLoopExit(loop_node);
1646 current_loop = loop_analysis()->GetParentLoopFor(current_loop);
1647 }
1648 }
1649
1650 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() {
1651 BuildLoopExitsUntilLoop(-1);
1652 }
1653
1599 void BytecodeGraphBuilder::BuildJump() { 1654 void BytecodeGraphBuilder::BuildJump() {
1600 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 1655 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
1601 } 1656 }
1602 1657
1603 1658
1604 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { 1659 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) {
1605 NewBranch(condition); 1660 NewBranch(condition);
1606 Environment* if_false_environment = environment()->CopyForConditional(); 1661 Environment* if_false_environment = environment()->CopyForConditional();
1607 NewIfTrue(); 1662 NewIfTrue();
1608 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); 1663 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset());
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
1823 // Phi does not exist yet, introduce one. 1878 // Phi does not exist yet, introduce one.
1824 value = NewPhi(inputs, value, control); 1879 value = NewPhi(inputs, value, control);
1825 value->ReplaceInput(inputs - 1, other); 1880 value->ReplaceInput(inputs - 1, other);
1826 } 1881 }
1827 return value; 1882 return value;
1828 } 1883 }
1829 1884
1830 } // namespace compiler 1885 } // namespace compiler
1831 } // namespace internal 1886 } // namespace internal
1832 } // namespace v8 1887 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/bytecode-graph-builder.h ('k') | src/compiler/bytecode-loop-analysis.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698