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 383 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 int output_poke_end = output_poke_start + output_poke_count; | 460 int output_poke_end = output_poke_start + output_poke_count; |
459 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), | 461 return StateValuesAreUpToDate(¶meters_state_values_, 0, parameter_count(), |
460 output_poke_start, output_poke_end) && | 462 output_poke_start, output_poke_end) && |
461 StateValuesAreUpToDate(®isters_state_values_, register_base(), | 463 StateValuesAreUpToDate(®isters_state_values_, register_base(), |
462 register_count(), output_poke_start, | 464 register_count(), output_poke_start, |
463 output_poke_end) && | 465 output_poke_end) && |
464 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), | 466 StateValuesAreUpToDate(&accumulator_state_values_, accumulator_base(), |
465 1, output_poke_start, output_poke_end); | 467 1, output_poke_start, output_poke_end); |
466 } | 468 } |
467 | 469 |
470 void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) { | |
Michael Starzinger
2016/07/29 08:54:46
nit: Can we move this up a few functions close to
Jarin
2016/07/29 11:36:46
Done.
| |
471 DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); | |
472 | |
473 Node* control = GetControlDependency(); | |
474 | |
475 // Create the loop exit node. | |
476 Node* loop_exit = graph()->NewNode(common()->LoopExit(), control, loop); | |
477 UpdateControlDependency(loop_exit); | |
478 | |
479 // Rename the environmnent values. | |
Michael Starzinger
2016/07/29 08:58:21
Is it OK not to handle "context_" here?
Jarin
2016/07/29 11:36:46
Not ok, great catch! (Well, not ok if we want to a
| |
480 for (size_t i = 0; i < values()->size(); i++) { | |
481 Node* rename = | |
482 graph()->NewNode(common()->LoopExitValue(), (*values())[i], loop_exit); | |
Michael Starzinger
2016/07/29 08:54:46
nit: Just "values_[i]".
Jarin
2016/07/29 11:36:46
Done.
| |
483 (*values())[i] = rename; | |
Michael Starzinger
2016/07/29 08:54:45
nit: Just "values_[i]".
Jarin
2016/07/29 11:36:46
Done.
| |
484 } | |
485 | |
486 // Rename the effect. | |
Michael Starzinger
2016/07/29 08:54:46
nit: Can we handle the effect before the values, j
Jarin
2016/07/29 11:36:46
Done.
| |
487 Node* effect_rename = graph()->NewNode(common()->LoopExitEffect(), | |
488 GetEffectDependency(), loop_exit); | |
489 UpdateEffectDependency(effect_rename); | |
490 } | |
491 | |
468 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, | 492 BytecodeGraphBuilder::BytecodeGraphBuilder(Zone* local_zone, |
469 CompilationInfo* info, | 493 CompilationInfo* info, |
470 JSGraph* jsgraph) | 494 JSGraph* jsgraph) |
471 : local_zone_(local_zone), | 495 : local_zone_(local_zone), |
472 jsgraph_(jsgraph), | 496 jsgraph_(jsgraph), |
473 bytecode_array_(handle(info->shared_info()->bytecode_array())), | 497 bytecode_array_(handle(info->shared_info()->bytecode_array())), |
474 exception_handler_table_( | 498 exception_handler_table_( |
475 handle(HandlerTable::cast(bytecode_array()->handler_table()))), | 499 handle(HandlerTable::cast(bytecode_array()->handler_table()))), |
476 feedback_vector_(handle(info->closure()->feedback_vector())), | 500 feedback_vector_(handle(info->closure()->feedback_vector())), |
477 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( | 501 frame_state_function_info_(common()->CreateFrameStateFunctionInfo( |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
564 int const input_count = static_cast<int>(exit_controls_.size()); | 588 int const input_count = static_cast<int>(exit_controls_.size()); |
565 Node** const inputs = &exit_controls_.front(); | 589 Node** const inputs = &exit_controls_.front(); |
566 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); | 590 Node* end = graph()->NewNode(common()->End(input_count), input_count, inputs); |
567 graph()->SetEnd(end); | 591 graph()->SetEnd(end); |
568 | 592 |
569 return true; | 593 return true; |
570 } | 594 } |
571 | 595 |
572 void BytecodeGraphBuilder::VisitBytecodes() { | 596 void BytecodeGraphBuilder::VisitBytecodes() { |
573 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); | 597 BytecodeBranchAnalysis analysis(bytecode_array(), local_zone()); |
598 BytecodeLoopAnalysis loop_analysis(bytecode_array(), &analysis, local_zone()); | |
574 analysis.Analyze(); | 599 analysis.Analyze(); |
600 loop_analysis.Analyze(); | |
575 set_branch_analysis(&analysis); | 601 set_branch_analysis(&analysis); |
602 set_loop_analysis(&loop_analysis); | |
576 interpreter::BytecodeArrayIterator iterator(bytecode_array()); | 603 interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
577 set_bytecode_iterator(&iterator); | 604 set_bytecode_iterator(&iterator); |
578 while (!iterator.done()) { | 605 while (!iterator.done()) { |
579 int current_offset = iterator.current_offset(); | 606 int current_offset = iterator.current_offset(); |
580 EnterAndExitExceptionHandlers(current_offset); | 607 EnterAndExitExceptionHandlers(current_offset); |
581 SwitchToMergeEnvironment(current_offset); | 608 SwitchToMergeEnvironment(current_offset); |
582 if (environment() != nullptr) { | 609 if (environment() != nullptr) { |
583 BuildLoopHeaderEnvironment(current_offset); | 610 BuildLoopHeaderEnvironment(current_offset); |
584 | 611 |
585 switch (iterator.current_bytecode()) { | 612 switch (iterator.current_bytecode()) { |
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1108 } | 1135 } |
1109 | 1136 |
1110 void BytecodeGraphBuilder::BuildThrow() { | 1137 void BytecodeGraphBuilder::BuildThrow() { |
1111 FrameStateBeforeAndAfter states(this); | 1138 FrameStateBeforeAndAfter states(this); |
1112 Node* value = environment()->LookupAccumulator(); | 1139 Node* value = environment()->LookupAccumulator(); |
1113 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); | 1140 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); |
1114 environment()->BindAccumulator(call, &states); | 1141 environment()->BindAccumulator(call, &states); |
1115 } | 1142 } |
1116 | 1143 |
1117 void BytecodeGraphBuilder::VisitThrow() { | 1144 void BytecodeGraphBuilder::VisitThrow() { |
1145 BuildLoopExitsForFunctionExit(); | |
1118 BuildThrow(); | 1146 BuildThrow(); |
1119 Node* call = environment()->LookupAccumulator(); | 1147 Node* call = environment()->LookupAccumulator(); |
1120 Node* control = NewNode(common()->Throw(), call); | 1148 Node* control = NewNode(common()->Throw(), call); |
1121 MergeControlToLeaveFunction(control); | 1149 MergeControlToLeaveFunction(control); |
1122 } | 1150 } |
1123 | 1151 |
1124 void BytecodeGraphBuilder::VisitReThrow() { | 1152 void BytecodeGraphBuilder::VisitReThrow() { |
1153 BuildLoopExitsForFunctionExit(); | |
1125 Node* value = environment()->LookupAccumulator(); | 1154 Node* value = environment()->LookupAccumulator(); |
1126 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); | 1155 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); |
1127 Node* control = NewNode(common()->Throw(), call); | 1156 Node* control = NewNode(common()->Throw(), call); |
1128 MergeControlToLeaveFunction(control); | 1157 MergeControlToLeaveFunction(control); |
1129 } | 1158 } |
1130 | 1159 |
1131 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { | 1160 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { |
1132 FrameStateBeforeAndAfter states(this); | 1161 FrameStateBeforeAndAfter states(this); |
1133 Node* left = | 1162 Node* left = |
1134 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); | 1163 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); |
(...skipping 296 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1431 void BytecodeGraphBuilder::VisitOsrPoll() { | 1460 void BytecodeGraphBuilder::VisitOsrPoll() { |
1432 // TODO(4764): This should be moved into the {VisitBytecodes} once we merge | 1461 // 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 | 1462 // 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. | 1463 // not missing the OSR entry point, which we wouldn't catch right now. |
1435 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) { | 1464 if (osr_ast_id_.ToInt() == bytecode_iterator().current_offset()) { |
1436 environment()->PrepareForOsr(); | 1465 environment()->PrepareForOsr(); |
1437 } | 1466 } |
1438 } | 1467 } |
1439 | 1468 |
1440 void BytecodeGraphBuilder::VisitReturn() { | 1469 void BytecodeGraphBuilder::VisitReturn() { |
1470 BuildLoopExitsForFunctionExit(); | |
1441 Node* control = | 1471 Node* control = |
1442 NewNode(common()->Return(), environment()->LookupAccumulator()); | 1472 NewNode(common()->Return(), environment()->LookupAccumulator()); |
1443 MergeControlToLeaveFunction(control); | 1473 MergeControlToLeaveFunction(control); |
1444 } | 1474 } |
1445 | 1475 |
1446 void BytecodeGraphBuilder::VisitDebugger() { | 1476 void BytecodeGraphBuilder::VisitDebugger() { |
1447 FrameStateBeforeAndAfter states(this); | 1477 FrameStateBeforeAndAfter states(this); |
1448 Node* call = | 1478 Node* call = |
1449 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); | 1479 NewNode(javascript()->CallRuntime(Runtime::kHandleDebuggerStatement)); |
1450 environment()->BindAccumulator(call, &states); | 1480 environment()->BindAccumulator(call, &states); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1576 | 1606 |
1577 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { | 1607 void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { |
1578 if (branch_analysis()->backward_branches_target(current_offset)) { | 1608 if (branch_analysis()->backward_branches_target(current_offset)) { |
1579 // Add loop header and store a copy so we can connect merged back | 1609 // Add loop header and store a copy so we can connect merged back |
1580 // edge inputs to the loop header. | 1610 // edge inputs to the loop header. |
1581 merge_environments_[current_offset] = environment()->CopyForLoop(); | 1611 merge_environments_[current_offset] = environment()->CopyForLoop(); |
1582 } | 1612 } |
1583 } | 1613 } |
1584 | 1614 |
1585 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { | 1615 void BytecodeGraphBuilder::MergeIntoSuccessorEnvironment(int target_offset) { |
1616 BuildLoopExitsForBranch(target_offset); | |
1586 if (merge_environments_[target_offset] == nullptr) { | 1617 if (merge_environments_[target_offset] == nullptr) { |
1587 // Append merge nodes to the environment. We may merge here with another | 1618 // 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 | 1619 // environment. So add a place holder for merge nodes. We may add redundant |
1589 // but will be eliminated in a later pass. | 1620 // but will be eliminated in a later pass. |
1590 // TODO(mstarzinger): Be smarter about this! | 1621 // TODO(mstarzinger): Be smarter about this! |
1591 NewMerge(); | 1622 NewMerge(); |
1592 merge_environments_[target_offset] = environment(); | 1623 merge_environments_[target_offset] = environment(); |
1593 } else { | 1624 } else { |
1594 merge_environments_[target_offset]->Merge(environment()); | 1625 merge_environments_[target_offset]->Merge(environment()); |
1595 } | 1626 } |
1596 set_environment(nullptr); | 1627 set_environment(nullptr); |
1597 } | 1628 } |
1598 | 1629 |
1599 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { | 1630 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
1600 exit_controls_.push_back(exit); | 1631 exit_controls_.push_back(exit); |
1601 set_environment(nullptr); | 1632 set_environment(nullptr); |
1602 } | 1633 } |
1603 | 1634 |
1635 void BytecodeGraphBuilder::BuildLoopExitsForBranch(int target_offset) { | |
1636 int origin_offset = bytecode_iterator().current_offset(); | |
1637 // Only build loop exits for forward edges. | |
1638 if (target_offset > origin_offset) { | |
1639 BuildLoopExitsUntilLoop(loop_analysis()->GetLoopOffsetFor(target_offset)); | |
1640 } | |
1641 } | |
1642 | |
1643 void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { | |
1644 int origin_offset = bytecode_iterator().current_offset(); | |
1645 int current_loop = loop_analysis()->GetLoopOffsetFor(origin_offset); | |
1646 while (loop_offset < current_loop) { | |
1647 Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); | |
1648 environment()->PrepareForLoopExit(loop_node); | |
1649 current_loop = loop_analysis()->GetParentLoopFor(current_loop); | |
1650 } | |
1651 } | |
1652 | |
1653 void BytecodeGraphBuilder::BuildLoopExitsForFunctionExit() { | |
1654 BuildLoopExitsUntilLoop(-1); | |
1655 } | |
1656 | |
1604 void BytecodeGraphBuilder::BuildJump() { | 1657 void BytecodeGraphBuilder::BuildJump() { |
1605 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); | 1658 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
1606 } | 1659 } |
1607 | 1660 |
1608 | 1661 |
1609 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { | 1662 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { |
1610 NewBranch(condition); | 1663 NewBranch(condition); |
1611 Environment* if_false_environment = environment()->CopyForConditional(); | 1664 Environment* if_false_environment = environment()->CopyForConditional(); |
1612 NewIfTrue(); | 1665 NewIfTrue(); |
1613 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); | 1666 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. | 1885 // Phi does not exist yet, introduce one. |
1833 value = NewPhi(inputs, value, control); | 1886 value = NewPhi(inputs, value, control); |
1834 value->ReplaceInput(inputs - 1, other); | 1887 value->ReplaceInput(inputs - 1, other); |
1835 } | 1888 } |
1836 return value; | 1889 return value; |
1837 } | 1890 } |
1838 | 1891 |
1839 } // namespace compiler | 1892 } // namespace compiler |
1840 } // namespace internal | 1893 } // namespace internal |
1841 } // namespace v8 | 1894 } // namespace v8 |
OLD | NEW |