| OLD | NEW |
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 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/v8.h" | 5 #include "src/v8.h" |
| 6 #include "test/cctest/cctest.h" | 6 #include "test/cctest/cctest.h" |
| 7 | 7 |
| 8 #include "src/compiler/common-operator.h" | 8 #include "src/compiler/common-operator.h" |
| 9 #include "src/compiler/generic-node-inl.h" | 9 #include "src/compiler/generic-node-inl.h" |
| 10 #include "src/compiler/generic-node.h" | 10 #include "src/compiler/generic-node.h" |
| (...skipping 1619 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1630 | 1630 |
| 1631 Schedule* schedule = ComputeAndVerifySchedule(19, &graph); | 1631 Schedule* schedule = ComputeAndVerifySchedule(19, &graph); |
| 1632 // Make sure the integer-only add gets hoisted to a different block that the | 1632 // Make sure the integer-only add gets hoisted to a different block that the |
| 1633 // JSAdd. | 1633 // JSAdd. |
| 1634 CHECK(schedule->block(n19) != schedule->block(n20)); | 1634 CHECK(schedule->block(n19) != schedule->block(n20)); |
| 1635 } | 1635 } |
| 1636 | 1636 |
| 1637 | 1637 |
| 1638 #if V8_TURBOFAN_TARGET | 1638 #if V8_TURBOFAN_TARGET |
| 1639 | 1639 |
| 1640 // So we can get a real JS function. | |
| 1641 static Handle<JSFunction> Compile(const char* source) { | |
| 1642 Isolate* isolate = CcTest::i_isolate(); | |
| 1643 Handle<String> source_code = isolate->factory() | |
| 1644 ->NewStringFromUtf8(CStrVector(source)) | |
| 1645 .ToHandleChecked(); | |
| 1646 Handle<SharedFunctionInfo> shared_function = Compiler::CompileScript( | |
| 1647 source_code, Handle<String>(), 0, 0, false, | |
| 1648 Handle<Context>(isolate->native_context()), NULL, NULL, | |
| 1649 v8::ScriptCompiler::kNoCompileOptions, NOT_NATIVES_CODE); | |
| 1650 return isolate->factory()->NewFunctionFromSharedFunctionInfo( | |
| 1651 shared_function, isolate->native_context()); | |
| 1652 } | |
| 1653 | |
| 1654 | |
| 1655 TEST(BuildScheduleTrivialLazyDeoptCall) { | |
| 1656 FLAG_turbo_deoptimization = true; | |
| 1657 | |
| 1658 HandleAndZoneScope scope; | |
| 1659 Isolate* isolate = scope.main_isolate(); | |
| 1660 Graph graph(scope.main_zone()); | |
| 1661 CommonOperatorBuilder common(scope.main_zone()); | |
| 1662 JSOperatorBuilder js_builder(scope.main_zone()); | |
| 1663 | |
| 1664 InitializedHandleScope handles; | |
| 1665 Handle<JSFunction> function = Compile("m()"); | |
| 1666 CompilationInfoWithZone info(function); | |
| 1667 Linkage linkage(&info); | |
| 1668 | |
| 1669 // Manually transcribed code for: | |
| 1670 // function turbo_fan_test() { | |
| 1671 // m(); | |
| 1672 // } | |
| 1673 // where m can lazy deopt (so it has a deopt block associated with it). | |
| 1674 | |
| 1675 | |
| 1676 // Start // | |
| 1677 // ^ // | |
| 1678 // | (EC) // | |
| 1679 // | // | |
| 1680 // /------> Call <--------------\ // | |
| 1681 // / ^ ^ \ // | |
| 1682 // / | | \ undef // | |
| 1683 // / / \ \ ^ // | |
| 1684 // (E) | (C) / \ (C) \ (E) | // | |
| 1685 // | Continuation LazyDeoptimization | | // | |
| 1686 // \___ ^ ^ / | // | |
| 1687 // \ | | ______/ Framestate // | |
| 1688 // undef \ | (VC) | (C) / ^ // | |
| 1689 // \ \ | | / / // | |
| 1690 // Return Deoptimization ----------/ // | |
| 1691 // ^ ^ // | |
| 1692 // \ / // | |
| 1693 // (C) \ / (C) // | |
| 1694 // \ / // | |
| 1695 // Merge // | |
| 1696 // ^ // | |
| 1697 // | // | |
| 1698 // End // | |
| 1699 | |
| 1700 Handle<Object> undef_object = | |
| 1701 Handle<Object>(isolate->heap()->undefined_value(), isolate); | |
| 1702 PrintableUnique<Object> undef_constant = | |
| 1703 PrintableUnique<Object>::CreateUninitialized(scope.main_zone(), | |
| 1704 undef_object); | |
| 1705 | |
| 1706 Node* undef_node = graph.NewNode(common.HeapConstant(undef_constant)); | |
| 1707 | |
| 1708 Node* start_node = graph.NewNode(common.Start(0)); | |
| 1709 | |
| 1710 CallDescriptor* descriptor = linkage.GetJSCallDescriptor(0); | |
| 1711 Node* call_node = graph.NewNode(common.Call(descriptor), | |
| 1712 undef_node, // function | |
| 1713 undef_node, // context | |
| 1714 start_node, // effect | |
| 1715 start_node); // control | |
| 1716 | |
| 1717 Node* cont_node = graph.NewNode(common.Continuation(), call_node); | |
| 1718 Node* lazy_deopt_node = graph.NewNode(common.LazyDeoptimization(), call_node); | |
| 1719 | |
| 1720 Node* parameters = graph.NewNode(common.StateValues(1), undef_node); | |
| 1721 Node* locals = graph.NewNode(common.StateValues(0)); | |
| 1722 Node* stack = graph.NewNode(common.StateValues(0)); | |
| 1723 | |
| 1724 Node* state_node = graph.NewNode(common.FrameState(BailoutId(1234)), | |
| 1725 parameters, locals, stack); | |
| 1726 | |
| 1727 Node* return_node = graph.NewNode(common.Return(), | |
| 1728 undef_node, // return value | |
| 1729 call_node, // effect | |
| 1730 cont_node); // control | |
| 1731 Node* deoptimization_node = graph.NewNode(common.Deoptimize(), | |
| 1732 state_node, // deopt environment | |
| 1733 call_node, // effect | |
| 1734 lazy_deopt_node); // control | |
| 1735 | |
| 1736 Node* merge_node = | |
| 1737 graph.NewNode(common.Merge(2), return_node, deoptimization_node); | |
| 1738 | |
| 1739 Node* end_node = graph.NewNode(common.End(), merge_node); | |
| 1740 | |
| 1741 graph.SetStart(start_node); | |
| 1742 graph.SetEnd(end_node); | |
| 1743 | |
| 1744 Schedule* schedule = ComputeAndVerifySchedule(12, &graph); | |
| 1745 | |
| 1746 // Tests: | |
| 1747 // Continuation and deopt have basic blocks. | |
| 1748 BasicBlock* cont_block = schedule->block(cont_node); | |
| 1749 BasicBlock* deopt_block = schedule->block(lazy_deopt_node); | |
| 1750 BasicBlock* call_block = schedule->block(call_node); | |
| 1751 CHECK_NE(NULL, cont_block); | |
| 1752 CHECK_NE(NULL, deopt_block); | |
| 1753 CHECK_NE(NULL, call_block); | |
| 1754 // The basic blocks are different. | |
| 1755 CHECK_NE(cont_block, deopt_block); | |
| 1756 CHECK_NE(cont_block, call_block); | |
| 1757 CHECK_NE(deopt_block, call_block); | |
| 1758 // The call node finishes its own basic block. | |
| 1759 CHECK_EQ(BasicBlock::kCall, call_block->control_); | |
| 1760 CHECK_EQ(call_node, call_block->control_input_); | |
| 1761 // The lazy deopt block is deferred. | |
| 1762 CHECK(deopt_block->deferred_); | |
| 1763 CHECK(!call_block->deferred_); | |
| 1764 CHECK(!cont_block->deferred_); | |
| 1765 // The lazy deopt block contains framestate + bailout (and nothing else). | |
| 1766 CHECK_EQ(deoptimization_node, deopt_block->control_input_); | |
| 1767 CHECK_EQ(5, static_cast<int>(deopt_block->nodes_.size())); | |
| 1768 CHECK_EQ(lazy_deopt_node, deopt_block->nodes_[0]); | |
| 1769 CHECK_EQ(IrOpcode::kStateValues, deopt_block->nodes_[1]->op()->opcode()); | |
| 1770 CHECK_EQ(IrOpcode::kStateValues, deopt_block->nodes_[2]->op()->opcode()); | |
| 1771 CHECK_EQ(IrOpcode::kStateValues, deopt_block->nodes_[3]->op()->opcode()); | |
| 1772 CHECK_EQ(state_node, deopt_block->nodes_[4]); | |
| 1773 } | |
| 1774 | |
| 1775 | |
| 1776 static Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common, | 1640 static Node* CreateDiamond(Graph* graph, CommonOperatorBuilder* common, |
| 1777 Node* cond) { | 1641 Node* cond) { |
| 1778 Node* tv = graph->NewNode(common->Int32Constant(6)); | 1642 Node* tv = graph->NewNode(common->Int32Constant(6)); |
| 1779 Node* fv = graph->NewNode(common->Int32Constant(7)); | 1643 Node* fv = graph->NewNode(common->Int32Constant(7)); |
| 1780 Node* br = graph->NewNode(common->Branch(), cond, graph->start()); | 1644 Node* br = graph->NewNode(common->Branch(), cond, graph->start()); |
| 1781 Node* t = graph->NewNode(common->IfTrue(), br); | 1645 Node* t = graph->NewNode(common->IfTrue(), br); |
| 1782 Node* f = graph->NewNode(common->IfFalse(), br); | 1646 Node* f = graph->NewNode(common->IfFalse(), br); |
| 1783 Node* m = graph->NewNode(common->Merge(2), t, f); | 1647 Node* m = graph->NewNode(common->Merge(2), t, f); |
| 1784 Node* phi = graph->NewNode(common->Phi(2), tv, fv, m); | 1648 Node* phi = graph->NewNode(common->Phi(2), tv, fv, m); |
| 1785 return phi; | 1649 return phi; |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1845 Node* d3 = CreateDiamond(&graph, &common, add); | 1709 Node* d3 = CreateDiamond(&graph, &common, add); |
| 1846 Node* ret = graph.NewNode(common.Return(), d3, start, start); | 1710 Node* ret = graph.NewNode(common.Return(), d3, start, start); |
| 1847 Node* end = graph.NewNode(common.End(), ret, start); | 1711 Node* end = graph.NewNode(common.End(), ret, start); |
| 1848 | 1712 |
| 1849 graph.SetEnd(end); | 1713 graph.SetEnd(end); |
| 1850 | 1714 |
| 1851 ComputeAndVerifySchedule(33, &graph); | 1715 ComputeAndVerifySchedule(33, &graph); |
| 1852 } | 1716 } |
| 1853 | 1717 |
| 1854 #endif | 1718 #endif |
| OLD | NEW |