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