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 |