| 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 |