OLD | NEW |
1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 | 6 |
7 #include "src/bailout-reason.h" | 7 #include "src/bailout-reason.h" |
8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
9 #include "src/field-index.h" | 9 #include "src/field-index.h" |
10 #include "src/hydrogen.h" | 10 #include "src/hydrogen.h" |
(...skipping 1587 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1598 | 1598 |
1599 return value; | 1599 return value; |
1600 } | 1600 } |
1601 | 1601 |
1602 | 1602 |
1603 Handle<Code> StoreGlobalStub::GenerateCode() { | 1603 Handle<Code> StoreGlobalStub::GenerateCode() { |
1604 return DoGenerateCode(this); | 1604 return DoGenerateCode(this); |
1605 } | 1605 } |
1606 | 1606 |
1607 | 1607 |
1608 template<> | 1608 template <> |
| 1609 HValue* CodeStubGraphBuilder<LoadGlobalViaContextStub>::BuildCodeStub() { |
| 1610 LoadGlobalViaContextStub* stub = casted_stub(); |
| 1611 int depth_value = stub->depth(); |
| 1612 HValue* depth = GetParameter(0); |
| 1613 HValue* slot_index = GetParameter(1); |
| 1614 HValue* name = GetParameter(2); |
| 1615 |
| 1616 // Choose between dynamic or static context script fetching versions. |
| 1617 depth = depth_value < LoadGlobalViaContextStub::kDynamicDepth |
| 1618 ? nullptr |
| 1619 : AddUncasted<HForceRepresentation>(depth, Representation::Smi()); |
| 1620 slot_index = |
| 1621 AddUncasted<HForceRepresentation>(slot_index, Representation::Smi()); |
| 1622 |
| 1623 HValue* script_context = BuildGetParentContext(depth, depth_value); |
| 1624 HValue* cell = |
| 1625 Add<HLoadKeyed>(script_context, slot_index, nullptr, FAST_ELEMENTS); |
| 1626 |
| 1627 HValue* value = Add<HLoadNamedField>(cell, nullptr, |
| 1628 HObjectAccess::ForPropertyCellValue()); |
| 1629 |
| 1630 IfBuilder builder(this); |
| 1631 HValue* hole_value = graph()->GetConstantHole(); |
| 1632 builder.IfNot<HCompareObjectEqAndBranch, HValue*>(value, hole_value); |
| 1633 builder.Then(); |
| 1634 { Push(value); } |
| 1635 builder.Else(); |
| 1636 { |
| 1637 Add<HPushArguments>(script_context, slot_index, name); |
| 1638 Push(Add<HCallRuntime>( |
| 1639 isolate()->factory()->empty_string(), |
| 1640 Runtime::FunctionForId(Runtime::kLoadGlobalViaContext), 3)); |
| 1641 } |
| 1642 builder.End(); |
| 1643 return Pop(); |
| 1644 } |
| 1645 |
| 1646 |
| 1647 Handle<Code> LoadGlobalViaContextStub::GenerateCode() { |
| 1648 return DoGenerateCode(this); |
| 1649 } |
| 1650 |
| 1651 |
| 1652 template <> |
| 1653 HValue* CodeStubGraphBuilder<StoreGlobalViaContextStub>::BuildCodeStub() { |
| 1654 StoreGlobalViaContextStub* stub = casted_stub(); |
| 1655 int depth_value = stub->depth(); |
| 1656 HValue* depth = GetParameter(0); |
| 1657 HValue* slot_index = GetParameter(1); |
| 1658 HValue* name = GetParameter(2); |
| 1659 HValue* value = GetParameter(3); |
| 1660 |
| 1661 // Choose between dynamic or static context script fetching versions. |
| 1662 depth = depth_value < StoreGlobalViaContextStub::kDynamicDepth |
| 1663 ? nullptr |
| 1664 : AddUncasted<HForceRepresentation>(depth, Representation::Smi()); |
| 1665 slot_index = |
| 1666 AddUncasted<HForceRepresentation>(slot_index, Representation::Smi()); |
| 1667 |
| 1668 HValue* script_context = BuildGetParentContext(depth, depth_value); |
| 1669 HValue* cell = |
| 1670 Add<HLoadKeyed>(script_context, slot_index, nullptr, FAST_ELEMENTS); |
| 1671 |
| 1672 // Fast case that requires storing to cell. |
| 1673 HIfContinuation if_fast_store_continuation(graph()->CreateBasicBlock(), |
| 1674 graph()->CreateBasicBlock()); |
| 1675 |
| 1676 // Fast case that does not require storing to cell. |
| 1677 HIfContinuation if_fast_no_store_continuation(graph()->CreateBasicBlock(), |
| 1678 graph()->CreateBasicBlock()); |
| 1679 |
| 1680 // This stub does the same as StoreGlobalStub but in a dynamic manner. |
| 1681 |
| 1682 HValue* cell_contents = Add<HLoadNamedField>( |
| 1683 cell, nullptr, HObjectAccess::ForPropertyCellValue()); |
| 1684 |
| 1685 IfBuilder if_hole(this); |
| 1686 HValue* hole_value = graph()->GetConstantHole(); |
| 1687 if_hole.IfNot<HCompareObjectEqAndBranch, HValue*>(cell_contents, hole_value); |
| 1688 if_hole.Then(); |
| 1689 { |
| 1690 HValue* details = Add<HLoadNamedField>( |
| 1691 cell, nullptr, HObjectAccess::ForPropertyCellDetails()); |
| 1692 HValue* cell_type = |
| 1693 BuildDecodeField<PropertyDetails::PropertyCellTypeField>(details); |
| 1694 |
| 1695 // The code below relies on this. |
| 1696 STATIC_ASSERT(PropertyCellType::kUndefined < PropertyCellType::kConstant); |
| 1697 STATIC_ASSERT(PropertyCellType::kConstant < |
| 1698 PropertyCellType::kConstantType); |
| 1699 STATIC_ASSERT(PropertyCellType::kConstant < PropertyCellType::kMutable); |
| 1700 |
| 1701 // Handle all cell type cases. |
| 1702 IfBuilder if_not_const(this); |
| 1703 |
| 1704 int cell_type_constant = static_cast<int>(PropertyCellType::kConstant); |
| 1705 if_not_const.If<HCompareNumericAndBranch, HValue*>( |
| 1706 cell_type, Add<HConstant>(cell_type_constant), Token::GT); |
| 1707 if_not_const.Then(); |
| 1708 { |
| 1709 // kConstantType or kMutable. |
| 1710 IfBuilder if_const_type(this); |
| 1711 int cell_type_constant_type = |
| 1712 static_cast<int>(PropertyCellType::kConstantType); |
| 1713 if_const_type.If<HCompareNumericAndBranch, HValue*>( |
| 1714 cell_type, Add<HConstant>(cell_type_constant_type), Token::EQ); |
| 1715 if_const_type.Then(); |
| 1716 { |
| 1717 // Check that either both value and cell_contents are smi or |
| 1718 // both have the same map. |
| 1719 IfBuilder if_cell_is_smi(this); |
| 1720 if_cell_is_smi.If<HIsSmiAndBranch>(cell_contents); |
| 1721 if_cell_is_smi.Then(); |
| 1722 { |
| 1723 IfBuilder if_value_is_smi(this); |
| 1724 if_value_is_smi.If<HIsSmiAndBranch>(value); |
| 1725 if_value_is_smi.Then(); |
| 1726 { |
| 1727 // Both cell_contents and value are smis, do store. |
| 1728 } |
| 1729 if_value_is_smi.Else(); // Slow case. |
| 1730 if_value_is_smi.JoinContinuation(&if_fast_store_continuation); |
| 1731 } |
| 1732 if_cell_is_smi.Else(); |
| 1733 { |
| 1734 IfBuilder if_value_is_heap_object(this); |
| 1735 if_value_is_heap_object.IfNot<HIsSmiAndBranch>(value); |
| 1736 if_value_is_heap_object.Then(); |
| 1737 { |
| 1738 // Both cell_contents and value are heap objects, do store. |
| 1739 HValue* expected_map = Add<HLoadNamedField>( |
| 1740 cell_contents, nullptr, HObjectAccess::ForMap()); |
| 1741 HValue* map = |
| 1742 Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap()); |
| 1743 IfBuilder map_check(this); |
| 1744 map_check.If<HCompareObjectEqAndBranch>(expected_map, map); |
| 1745 map_check.Then(); |
| 1746 map_check.Else(); // Slow case. |
| 1747 map_check.JoinContinuation(&if_fast_store_continuation); |
| 1748 |
| 1749 // The accessor case is handled by the map check above, since |
| 1750 // the value must not have a AccessorPair map. |
| 1751 } |
| 1752 if_value_is_heap_object.Else(); // Slow case. |
| 1753 if_value_is_heap_object.JoinContinuation(&if_fast_store_continuation); |
| 1754 } |
| 1755 if_cell_is_smi.EndUnreachable(); |
| 1756 } |
| 1757 if_const_type.Else(); |
| 1758 { |
| 1759 // Check that the property kind is kData. |
| 1760 HValue* kind = BuildDecodeField<PropertyDetails::KindField>(details); |
| 1761 HValue* data_kind_value = Add<HConstant>(kData); |
| 1762 |
| 1763 IfBuilder builder(this); |
| 1764 builder.If<HCompareNumericAndBranch, HValue*>(kind, data_kind_value, |
| 1765 Token::EQ); |
| 1766 builder.Then(); |
| 1767 builder.Else(); // Slow case. |
| 1768 builder.JoinContinuation(&if_fast_store_continuation); |
| 1769 } |
| 1770 if_const_type.EndUnreachable(); |
| 1771 } |
| 1772 if_not_const.Else(); |
| 1773 { |
| 1774 // kUndefined or kConstant, just check that the value matches. |
| 1775 IfBuilder builder(this); |
| 1776 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); |
| 1777 builder.Then(); |
| 1778 builder.Else(); // Slow case. |
| 1779 builder.JoinContinuation(&if_fast_no_store_continuation); |
| 1780 } |
| 1781 if_not_const.EndUnreachable(); |
| 1782 } |
| 1783 if_hole.Else(); // Slow case. |
| 1784 if_hole.JoinContinuation(&if_fast_store_continuation); |
| 1785 |
| 1786 // Do store for fast case. |
| 1787 IfBuilder if_fast_store(this, &if_fast_store_continuation); |
| 1788 if_fast_store.Then(); |
| 1789 { |
| 1790 // All checks are done, store the value to the cell. |
| 1791 Add<HStoreNamedField>(cell, HObjectAccess::ForPropertyCellValue(), value); |
| 1792 } |
| 1793 if_fast_store.Else(); |
| 1794 if_fast_store.JoinContinuation(&if_fast_no_store_continuation); |
| 1795 |
| 1796 // Bailout to runtime call for slow case. |
| 1797 IfBuilder if_no_fast_store(this, &if_fast_no_store_continuation); |
| 1798 if_no_fast_store.Then(); |
| 1799 { |
| 1800 // Nothing else to do. |
| 1801 } |
| 1802 if_no_fast_store.Else(); |
| 1803 { |
| 1804 // Slow case, call runtime. |
| 1805 HInstruction* lang_mode = Add<HConstant>(casted_stub()->language_mode()); |
| 1806 Add<HPushArguments>(script_context, slot_index, name, value); |
| 1807 Add<HPushArguments>(lang_mode); |
| 1808 Add<HCallRuntime>(isolate()->factory()->empty_string(), |
| 1809 Runtime::FunctionForId(Runtime::kStoreGlobalViaContext), |
| 1810 5); |
| 1811 } |
| 1812 if_no_fast_store.End(); |
| 1813 return value; |
| 1814 } |
| 1815 |
| 1816 |
| 1817 Handle<Code> StoreGlobalViaContextStub::GenerateCode() { |
| 1818 return DoGenerateCode(this); |
| 1819 } |
| 1820 |
| 1821 |
| 1822 template <> |
1609 HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() { | 1823 HValue* CodeStubGraphBuilder<ElementsTransitionAndStoreStub>::BuildCodeStub() { |
1610 HValue* value = GetParameter(ElementsTransitionAndStoreStub::kValueIndex); | 1824 HValue* value = GetParameter(ElementsTransitionAndStoreStub::kValueIndex); |
1611 HValue* map = GetParameter(ElementsTransitionAndStoreStub::kMapIndex); | 1825 HValue* map = GetParameter(ElementsTransitionAndStoreStub::kMapIndex); |
1612 HValue* key = GetParameter(ElementsTransitionAndStoreStub::kKeyIndex); | 1826 HValue* key = GetParameter(ElementsTransitionAndStoreStub::kKeyIndex); |
1613 HValue* object = GetParameter(ElementsTransitionAndStoreStub::kObjectIndex); | 1827 HValue* object = GetParameter(ElementsTransitionAndStoreStub::kObjectIndex); |
1614 | 1828 |
1615 if (FLAG_trace_elements_transitions) { | 1829 if (FLAG_trace_elements_transitions) { |
1616 // Tracing elements transitions is the job of the runtime. | 1830 // Tracing elements transitions is the job of the runtime. |
1617 Add<HDeoptimize>(Deoptimizer::kTracingElementsTransitions, | 1831 Add<HDeoptimize>(Deoptimizer::kTracingElementsTransitions, |
1618 Deoptimizer::EAGER); | 1832 Deoptimizer::EAGER); |
(...skipping 646 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2265 return Pop(); | 2479 return Pop(); |
2266 } | 2480 } |
2267 | 2481 |
2268 | 2482 |
2269 Handle<Code> KeyedLoadGenericStub::GenerateCode() { | 2483 Handle<Code> KeyedLoadGenericStub::GenerateCode() { |
2270 return DoGenerateCode(this); | 2484 return DoGenerateCode(this); |
2271 } | 2485 } |
2272 | 2486 |
2273 } // namespace internal | 2487 } // namespace internal |
2274 } // namespace v8 | 2488 } // namespace v8 |
OLD | NEW |