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_const(this); | |
1703 | |
1704 int cell_type_constant = static_cast<int>(PropertyCellType::kConstant); | |
1705 if_const.If<HCompareNumericAndBranch, HValue*>( | |
1706 cell_type, Add<HConstant>(cell_type_constant), Token::LTE); | |
1707 if_const.Then(); | |
1708 { | |
1709 // kUndefined or kConstant, just check that the value matches. | |
1710 IfBuilder builder(this); | |
1711 builder.If<HCompareObjectEqAndBranch>(cell_contents, value); | |
1712 builder.Then(); | |
1713 builder.Else(); // Slow case. | |
1714 builder.JoinContinuation(&if_fast_no_store_continuation); | |
1715 } | |
1716 if_const.Else(); | |
1717 { | |
1718 // kConstantType or kMutable. | |
1719 IfBuilder if_const_type(this); | |
1720 int cell_type_constant_type = | |
1721 static_cast<int>(PropertyCellType::kConstantType); | |
Toon Verwaest
2015/07/10 16:46:11
I'd reorder these cases to first handle ConstantTy
Igor Sheludko
2015/07/13 08:34:50
Done, but this stub would probably require further
| |
1722 if_const_type.If<HCompareNumericAndBranch, HValue*>( | |
1723 cell_type, Add<HConstant>(cell_type_constant_type), Token::EQ); | |
1724 if_const_type.Then(); | |
1725 { | |
1726 // Check that either both value and cell_contents are smi or | |
1727 // both have the same map. | |
1728 IfBuilder if_cell_is_smi(this); | |
1729 if_cell_is_smi.If<HIsSmiAndBranch>(cell_contents); | |
1730 if_cell_is_smi.Then(); | |
1731 { | |
1732 IfBuilder if_value_is_smi(this); | |
1733 if_value_is_smi.If<HIsSmiAndBranch>(value); | |
1734 if_value_is_smi.Then(); | |
1735 { | |
1736 // Both cell_contents and value are smis, do store. | |
1737 } | |
1738 if_value_is_smi.Else(); // Slow case. | |
1739 if_value_is_smi.JoinContinuation(&if_fast_store_continuation); | |
1740 } | |
1741 if_cell_is_smi.Else(); | |
1742 { | |
1743 IfBuilder if_value_is_heap_object(this); | |
1744 if_value_is_heap_object.IfNot<HIsSmiAndBranch>(value); | |
1745 if_value_is_heap_object.Then(); | |
1746 { | |
1747 // Both cell_contents and value are heap objects, do store. | |
1748 HValue* expected_map = Add<HLoadNamedField>( | |
1749 cell_contents, nullptr, HObjectAccess::ForMap()); | |
1750 HValue* map = | |
1751 Add<HLoadNamedField>(value, nullptr, HObjectAccess::ForMap()); | |
1752 IfBuilder map_check(this); | |
1753 map_check.If<HCompareObjectEqAndBranch>(expected_map, map); | |
1754 map_check.Then(); | |
1755 map_check.Else(); // Slow case. | |
1756 map_check.JoinContinuation(&if_fast_store_continuation); | |
1757 | |
1758 // The accessor case is handled by the map check above, since | |
1759 // the value must not have a AccessorPair map. | |
1760 } | |
1761 if_value_is_heap_object.Else(); // Slow case. | |
1762 if_value_is_heap_object.JoinContinuation(&if_fast_store_continuation); | |
1763 } | |
1764 if_cell_is_smi.EndUnreachable(); | |
1765 } | |
1766 if_const_type.Else(); | |
1767 { | |
1768 // Check that the property kind is kData. | |
1769 HValue* kind = BuildDecodeField<PropertyDetails::KindField>(details); | |
1770 HValue* data_kind_value = Add<HConstant>(kData); | |
1771 | |
1772 IfBuilder builder(this); | |
1773 builder.If<HCompareNumericAndBranch, HValue*>(kind, data_kind_value, | |
1774 Token::EQ); | |
1775 builder.Then(); | |
1776 builder.Else(); // Slow case. | |
1777 builder.JoinContinuation(&if_fast_store_continuation); | |
1778 } | |
1779 if_const_type.EndUnreachable(); | |
1780 } | |
1781 if_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 |