| 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 19 matching lines...) Expand all Loading... |
| 30 void ExchangeRegisters(interpreter::Register reg0, | 30 void ExchangeRegisters(interpreter::Register reg0, |
| 31 interpreter::Register reg1); | 31 interpreter::Register reg1); |
| 32 | 32 |
| 33 void BindAccumulator(Node* node, FrameStateBeforeAndAfter* states = nullptr); | 33 void BindAccumulator(Node* node, FrameStateBeforeAndAfter* states = nullptr); |
| 34 void BindRegister(interpreter::Register the_register, Node* node, | 34 void BindRegister(interpreter::Register the_register, Node* node, |
| 35 FrameStateBeforeAndAfter* states = nullptr); | 35 FrameStateBeforeAndAfter* states = nullptr); |
| 36 void BindRegistersToProjections(interpreter::Register first_reg, Node* node, | 36 void BindRegistersToProjections(interpreter::Register first_reg, Node* node, |
| 37 FrameStateBeforeAndAfter* states = nullptr); | 37 FrameStateBeforeAndAfter* states = nullptr); |
| 38 void RecordAfterState(Node* node, FrameStateBeforeAndAfter* states); | 38 void RecordAfterState(Node* node, FrameStateBeforeAndAfter* states); |
| 39 | 39 |
| 40 bool IsMarkedAsUnreachable() const; | |
| 41 void MarkAsUnreachable(); | |
| 42 | |
| 43 // Effect dependency tracked by this environment. | 40 // Effect dependency tracked by this environment. |
| 44 Node* GetEffectDependency() { return effect_dependency_; } | 41 Node* GetEffectDependency() { return effect_dependency_; } |
| 45 void UpdateEffectDependency(Node* dependency) { | 42 void UpdateEffectDependency(Node* dependency) { |
| 46 effect_dependency_ = dependency; | 43 effect_dependency_ = dependency; |
| 47 } | 44 } |
| 48 | 45 |
| 49 // Preserve a checkpoint of the environment for the IR graph. Any | 46 // Preserve a checkpoint of the environment for the IR graph. Any |
| 50 // further mutation of the environment will not affect checkpoints. | 47 // further mutation of the environment will not affect checkpoints. |
| 51 Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine); | 48 Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine); |
| 52 | 49 |
| (...skipping 247 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 300 } | 297 } |
| 301 } | 298 } |
| 302 | 299 |
| 303 | 300 |
| 304 void BytecodeGraphBuilder::Environment::RecordAfterState( | 301 void BytecodeGraphBuilder::Environment::RecordAfterState( |
| 305 Node* node, FrameStateBeforeAndAfter* states) { | 302 Node* node, FrameStateBeforeAndAfter* states) { |
| 306 states->AddToNode(node, OutputFrameStateCombine::Ignore()); | 303 states->AddToNode(node, OutputFrameStateCombine::Ignore()); |
| 307 } | 304 } |
| 308 | 305 |
| 309 | 306 |
| 310 bool BytecodeGraphBuilder::Environment::IsMarkedAsUnreachable() const { | |
| 311 return GetControlDependency()->opcode() == IrOpcode::kDead; | |
| 312 } | |
| 313 | |
| 314 | |
| 315 void BytecodeGraphBuilder::Environment::MarkAsUnreachable() { | |
| 316 UpdateControlDependency(builder()->jsgraph()->Dead()); | |
| 317 } | |
| 318 | |
| 319 | |
| 320 BytecodeGraphBuilder::Environment* | 307 BytecodeGraphBuilder::Environment* |
| 321 BytecodeGraphBuilder::Environment::CopyForLoop() { | 308 BytecodeGraphBuilder::Environment::CopyForLoop() { |
| 322 PrepareForLoop(); | 309 PrepareForLoop(); |
| 323 return new (zone()) Environment(this); | 310 return new (zone()) Environment(this); |
| 324 } | 311 } |
| 325 | 312 |
| 326 | 313 |
| 327 BytecodeGraphBuilder::Environment* | 314 BytecodeGraphBuilder::Environment* |
| 328 BytecodeGraphBuilder::Environment::CopyForConditional() const { | 315 BytecodeGraphBuilder::Environment::CopyForConditional() const { |
| 329 return new (zone()) Environment(this); | 316 return new (zone()) Environment(this); |
| 330 } | 317 } |
| 331 | 318 |
| 332 | 319 |
| 333 void BytecodeGraphBuilder::Environment::Merge( | 320 void BytecodeGraphBuilder::Environment::Merge( |
| 334 BytecodeGraphBuilder::Environment* other) { | 321 BytecodeGraphBuilder::Environment* other) { |
| 335 // Nothing to do if the other environment is dead. | |
| 336 if (other->IsMarkedAsUnreachable()) { | |
| 337 return; | |
| 338 } | |
| 339 | |
| 340 // Create a merge of the control dependencies of both environments and update | 322 // Create a merge of the control dependencies of both environments and update |
| 341 // the current environment's control dependency accordingly. | 323 // the current environment's control dependency accordingly. |
| 342 Node* control = builder()->MergeControl(GetControlDependency(), | 324 Node* control = builder()->MergeControl(GetControlDependency(), |
| 343 other->GetControlDependency()); | 325 other->GetControlDependency()); |
| 344 UpdateControlDependency(control); | 326 UpdateControlDependency(control); |
| 345 | 327 |
| 346 // Create a merge of the effect dependencies of both environments and update | 328 // Create a merge of the effect dependencies of both environments and update |
| 347 // the current environment's effect dependency accordingly. | 329 // the current environment's effect dependency accordingly. |
| 348 Node* effect = builder()->MergeEffect(GetEffectDependency(), | 330 Node* effect = builder()->MergeEffect(GetEffectDependency(), |
| 349 other->GetEffectDependency(), control); | 331 other->GetEffectDependency(), control); |
| (...skipping 899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1249 const Operator* call = javascript()->CallConstruct( | 1231 const Operator* call = javascript()->CallConstruct( |
| 1250 static_cast<int>(arg_count) + 2, VectorSlotPair()); | 1232 static_cast<int>(arg_count) + 2, VectorSlotPair()); |
| 1251 Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2); | 1233 Node* value = ProcessCallNewArguments(call, callee, first_arg, arg_count + 2); |
| 1252 environment()->BindAccumulator(value, &states); | 1234 environment()->BindAccumulator(value, &states); |
| 1253 } | 1235 } |
| 1254 | 1236 |
| 1255 void BytecodeGraphBuilder::VisitNew() { BuildCallConstruct(); } | 1237 void BytecodeGraphBuilder::VisitNew() { BuildCallConstruct(); } |
| 1256 | 1238 |
| 1257 void BytecodeGraphBuilder::VisitNewWide() { BuildCallConstruct(); } | 1239 void BytecodeGraphBuilder::VisitNewWide() { BuildCallConstruct(); } |
| 1258 | 1240 |
| 1259 void BytecodeGraphBuilder::VisitThrow() { | 1241 void BytecodeGraphBuilder::BuildThrowOp(const Operator* call_op) { |
| 1260 FrameStateBeforeAndAfter states(this); | 1242 FrameStateBeforeAndAfter states(this); |
| 1261 Node* value = environment()->LookupAccumulator(); | 1243 Node* value = environment()->LookupAccumulator(); |
| 1262 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); | 1244 Node* call = NewNode(call_op, value); |
| 1263 environment()->RecordAfterState(call, &states); | 1245 environment()->RecordAfterState(call, &states); |
| 1264 Node* control = NewNode(common()->Throw(), value); | 1246 } |
| 1265 UpdateControlDependencyToLeaveFunction(control); | 1247 |
| 1248 void BytecodeGraphBuilder::VisitThrow() { |
| 1249 BuildThrowOp(javascript()->CallRuntime(Runtime::kThrow)); |
| 1250 Node* control = |
| 1251 NewNode(common()->Throw(), environment()->LookupAccumulator()); |
| 1252 MergeControlToLeaveFunction(control); |
| 1266 } | 1253 } |
| 1267 | 1254 |
| 1268 void BytecodeGraphBuilder::VisitReThrow() { | 1255 void BytecodeGraphBuilder::VisitReThrow() { |
| 1269 FrameStateBeforeAndAfter states(this); | 1256 BuildThrowOp(javascript()->CallRuntime(Runtime::kReThrow)); |
| 1270 Node* value = environment()->LookupAccumulator(); | 1257 Node* control = |
| 1271 Node* call = NewNode(javascript()->CallRuntime(Runtime::kReThrow), value); | 1258 NewNode(common()->Throw(), environment()->LookupAccumulator()); |
| 1272 environment()->RecordAfterState(call, &states); | 1259 MergeControlToLeaveFunction(control); |
| 1273 Node* control = NewNode(common()->Throw(), value); | |
| 1274 UpdateControlDependencyToLeaveFunction(control); | |
| 1275 } | 1260 } |
| 1276 | 1261 |
| 1277 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { | 1262 void BytecodeGraphBuilder::BuildBinaryOp(const Operator* js_op) { |
| 1278 FrameStateBeforeAndAfter states(this); | 1263 FrameStateBeforeAndAfter states(this); |
| 1279 Node* left = | 1264 Node* left = |
| 1280 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); | 1265 environment()->LookupRegister(bytecode_iterator().GetRegisterOperand(0)); |
| 1281 Node* right = environment()->LookupAccumulator(); | 1266 Node* right = environment()->LookupAccumulator(); |
| 1282 Node* node = NewNode(js_op, left, right); | 1267 Node* node = NewNode(js_op, left, right); |
| 1283 environment()->BindAccumulator(node, &states); | 1268 environment()->BindAccumulator(node, &states); |
| 1284 } | 1269 } |
| (...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1539 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); | 1524 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); |
| 1540 } | 1525 } |
| 1541 | 1526 |
| 1542 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstantWide() { | 1527 void BytecodeGraphBuilder::VisitJumpIfUndefinedConstantWide() { |
| 1543 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); | 1528 BuildJumpIfEqual(jsgraph()->UndefinedConstant()); |
| 1544 } | 1529 } |
| 1545 | 1530 |
| 1546 void BytecodeGraphBuilder::VisitReturn() { | 1531 void BytecodeGraphBuilder::VisitReturn() { |
| 1547 Node* control = | 1532 Node* control = |
| 1548 NewNode(common()->Return(), environment()->LookupAccumulator()); | 1533 NewNode(common()->Return(), environment()->LookupAccumulator()); |
| 1549 UpdateControlDependencyToLeaveFunction(control); | 1534 MergeControlToLeaveFunction(control); |
| 1550 set_environment(nullptr); | |
| 1551 } | 1535 } |
| 1552 | 1536 |
| 1553 void BytecodeGraphBuilder::BuildForInPrepare() { | 1537 void BytecodeGraphBuilder::BuildForInPrepare() { |
| 1554 FrameStateBeforeAndAfter states(this); | 1538 FrameStateBeforeAndAfter states(this); |
| 1555 Node* receiver = environment()->LookupAccumulator(); | 1539 Node* receiver = environment()->LookupAccumulator(); |
| 1556 Node* prepare = NewNode(javascript()->ForInPrepare(), receiver); | 1540 Node* prepare = NewNode(javascript()->ForInPrepare(), receiver); |
| 1557 environment()->BindRegistersToProjections( | 1541 environment()->BindRegistersToProjections( |
| 1558 bytecode_iterator().GetRegisterOperand(0), prepare, &states); | 1542 bytecode_iterator().GetRegisterOperand(0), prepare, &states); |
| 1559 } | 1543 } |
| 1560 | 1544 |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1625 // but will be eliminated in a later pass. | 1609 // but will be eliminated in a later pass. |
| 1626 // TODO(mstarzinger): Be smarter about this! | 1610 // TODO(mstarzinger): Be smarter about this! |
| 1627 NewMerge(); | 1611 NewMerge(); |
| 1628 merge_environments_[target_offset] = environment(); | 1612 merge_environments_[target_offset] = environment(); |
| 1629 } else { | 1613 } else { |
| 1630 merge_environments_[target_offset]->Merge(environment()); | 1614 merge_environments_[target_offset]->Merge(environment()); |
| 1631 } | 1615 } |
| 1632 set_environment(nullptr); | 1616 set_environment(nullptr); |
| 1633 } | 1617 } |
| 1634 | 1618 |
| 1619 void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
| 1620 exit_controls_.push_back(exit); |
| 1621 set_environment(nullptr); |
| 1622 } |
| 1635 | 1623 |
| 1636 void BytecodeGraphBuilder::BuildJump() { | 1624 void BytecodeGraphBuilder::BuildJump() { |
| 1637 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); | 1625 MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
| 1638 } | 1626 } |
| 1639 | 1627 |
| 1640 | 1628 |
| 1641 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { | 1629 void BytecodeGraphBuilder::BuildConditionalJump(Node* condition) { |
| 1642 NewBranch(condition); | 1630 NewBranch(condition); |
| 1643 Environment* if_false_environment = environment()->CopyForConditional(); | 1631 Environment* if_false_environment = environment()->CopyForConditional(); |
| 1644 NewIfTrue(); | 1632 NewIfTrue(); |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1740 // with the real frame state. | 1728 // with the real frame state. |
| 1741 *current_input++ = jsgraph()->Dead(); | 1729 *current_input++ = jsgraph()->Dead(); |
| 1742 } | 1730 } |
| 1743 if (has_effect) { | 1731 if (has_effect) { |
| 1744 *current_input++ = environment()->GetEffectDependency(); | 1732 *current_input++ = environment()->GetEffectDependency(); |
| 1745 } | 1733 } |
| 1746 if (has_control) { | 1734 if (has_control) { |
| 1747 *current_input++ = environment()->GetControlDependency(); | 1735 *current_input++ = environment()->GetControlDependency(); |
| 1748 } | 1736 } |
| 1749 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); | 1737 result = graph()->NewNode(op, input_count_with_deps, buffer, incomplete); |
| 1750 if (!environment()->IsMarkedAsUnreachable()) { | 1738 // Update the current control dependency for control-producing nodes. |
| 1751 // Update the current control dependency for control-producing nodes. | 1739 if (NodeProperties::IsControl(result)) { |
| 1752 if (NodeProperties::IsControl(result)) { | 1740 environment()->UpdateControlDependency(result); |
| 1753 environment()->UpdateControlDependency(result); | 1741 } |
| 1754 } | 1742 // Update the current effect dependency for effect-producing nodes. |
| 1755 // Update the current effect dependency for effect-producing nodes. | 1743 if (result->op()->EffectOutputCount() > 0) { |
| 1756 if (result->op()->EffectOutputCount() > 0) { | 1744 environment()->UpdateEffectDependency(result); |
| 1757 environment()->UpdateEffectDependency(result); | 1745 } |
| 1758 } | 1746 // Add implicit exception continuation for throwing nodes. |
| 1759 // Add implicit exception continuation for throwing nodes. | 1747 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { |
| 1760 if (!result->op()->HasProperty(Operator::kNoThrow) && inside_handler) { | 1748 int handler_offset = exception_handlers_.top().handler_offset_; |
| 1761 int handler_offset = exception_handlers_.top().handler_offset_; | 1749 // TODO(mstarzinger): Thread through correct prediction! |
| 1762 // TODO(mstarzinger): Thread through correct prediction! | 1750 IfExceptionHint hint = IfExceptionHint::kLocallyCaught; |
| 1763 IfExceptionHint hint = IfExceptionHint::kLocallyCaught; | 1751 Environment* success_env = environment()->CopyForConditional(); |
| 1764 Environment* success_env = environment()->CopyForConditional(); | 1752 const Operator* op = common()->IfException(hint); |
| 1765 const Operator* op = common()->IfException(hint); | 1753 Node* effect = environment()->GetEffectDependency(); |
| 1766 Node* effect = environment()->GetEffectDependency(); | 1754 Node* on_exception = graph()->NewNode(op, effect, result); |
| 1767 Node* on_exception = graph()->NewNode(op, effect, result); | 1755 environment()->UpdateControlDependency(on_exception); |
| 1768 environment()->UpdateControlDependency(on_exception); | 1756 environment()->UpdateEffectDependency(on_exception); |
| 1769 environment()->UpdateEffectDependency(on_exception); | 1757 environment()->BindAccumulator(on_exception); |
| 1770 environment()->BindAccumulator(on_exception); | 1758 MergeIntoSuccessorEnvironment(handler_offset); |
| 1771 MergeIntoSuccessorEnvironment(handler_offset); | 1759 set_environment(success_env); |
| 1772 set_environment(success_env); | 1760 } |
| 1773 } | 1761 // Add implicit success continuation for throwing nodes. |
| 1774 // Add implicit success continuation for throwing nodes. | 1762 if (!result->op()->HasProperty(Operator::kNoThrow)) { |
| 1775 if (!result->op()->HasProperty(Operator::kNoThrow)) { | 1763 const Operator* if_success = common()->IfSuccess(); |
| 1776 const Operator* if_success = common()->IfSuccess(); | 1764 Node* on_success = graph()->NewNode(if_success, result); |
| 1777 Node* on_success = graph()->NewNode(if_success, result); | 1765 environment()->UpdateControlDependency(on_success); |
| 1778 environment()->UpdateControlDependency(on_success); | |
| 1779 } | |
| 1780 } | 1766 } |
| 1781 } | 1767 } |
| 1782 | 1768 |
| 1783 return result; | 1769 return result; |
| 1784 } | 1770 } |
| 1785 | 1771 |
| 1786 | 1772 |
| 1787 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { | 1773 Node* BytecodeGraphBuilder::NewPhi(int count, Node* input, Node* control) { |
| 1788 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); | 1774 const Operator* phi_op = common()->Phi(MachineRepresentation::kTagged, count); |
| 1789 Node** buffer = EnsureInputBufferSize(count + 1); | 1775 Node** buffer = EnsureInputBufferSize(count + 1); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1852 NodeProperties::ChangeOp( | 1838 NodeProperties::ChangeOp( |
| 1853 value, common()->Phi(MachineRepresentation::kTagged, inputs)); | 1839 value, common()->Phi(MachineRepresentation::kTagged, inputs)); |
| 1854 } else if (value != other) { | 1840 } else if (value != other) { |
| 1855 // Phi does not exist yet, introduce one. | 1841 // Phi does not exist yet, introduce one. |
| 1856 value = NewPhi(inputs, value, control); | 1842 value = NewPhi(inputs, value, control); |
| 1857 value->ReplaceInput(inputs - 1, other); | 1843 value->ReplaceInput(inputs - 1, other); |
| 1858 } | 1844 } |
| 1859 return value; | 1845 return value; |
| 1860 } | 1846 } |
| 1861 | 1847 |
| 1862 | |
| 1863 void BytecodeGraphBuilder::UpdateControlDependencyToLeaveFunction(Node* exit) { | |
| 1864 if (environment()->IsMarkedAsUnreachable()) return; | |
| 1865 environment()->MarkAsUnreachable(); | |
| 1866 exit_controls_.push_back(exit); | |
| 1867 } | |
| 1868 | |
| 1869 } // namespace compiler | 1848 } // namespace compiler |
| 1870 } // namespace internal | 1849 } // namespace internal |
| 1871 } // namespace v8 | 1850 } // namespace v8 |
| OLD | NEW |