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 |