| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |