| 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/ic/ic.h" | 5 #include "src/ic/ic.h" |
| 6 | 6 |
| 7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
| 8 #include "src/api.h" | 8 #include "src/api.h" |
| 9 #include "src/arguments.h" | 9 #include "src/arguments.h" |
| 10 #include "src/base/bits.h" | 10 #include "src/base/bits.h" |
| (...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 110 // then print "apply from" and advance one frame | 110 // then print "apply from" and advance one frame |
| 111 | 111 |
| 112 Object* maybe_function = | 112 Object* maybe_function = |
| 113 Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset); | 113 Memory::Object_at(fp_ + JavaScriptFrameConstants::kFunctionOffset); |
| 114 if (maybe_function->IsJSFunction()) { | 114 if (maybe_function->IsJSFunction()) { |
| 115 JSFunction* function = JSFunction::cast(maybe_function); | 115 JSFunction* function = JSFunction::cast(maybe_function); |
| 116 JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(), | 116 JavaScriptFrame::PrintFunctionAndOffset(function, function->code(), pc(), |
| 117 stdout, true); | 117 stdout, true); |
| 118 } | 118 } |
| 119 | 119 |
| 120 ExtraICState extra_state = new_target->extra_ic_state(); | |
| 121 const char* modifier = ""; | 120 const char* modifier = ""; |
| 122 if (new_target->kind() == Code::KEYED_STORE_IC) { | 121 if (new_target->kind() == Code::KEYED_STORE_IC) { |
| 123 KeyedAccessStoreMode mode = | 122 KeyedAccessStoreMode mode = |
| 124 FLAG_vector_stores | 123 casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode(); |
| 125 ? casted_nexus<KeyedStoreICNexus>()->GetKeyedAccessStoreMode() | |
| 126 : KeyedStoreIC::GetKeyedAccessStoreMode(extra_state); | |
| 127 modifier = GetTransitionMarkModifier(mode); | 124 modifier = GetTransitionMarkModifier(mode); |
| 128 } | 125 } |
| 129 PrintF(" (%c->%c%s) ", TransitionMarkFromState(old_state), | 126 PrintF(" (%c->%c%s) ", TransitionMarkFromState(old_state), |
| 130 TransitionMarkFromState(new_state), modifier); | 127 TransitionMarkFromState(new_state), modifier); |
| 131 #ifdef OBJECT_PRINT | 128 #ifdef OBJECT_PRINT |
| 132 OFStream os(stdout); | 129 OFStream os(stdout); |
| 133 name->Print(os); | 130 name->Print(os); |
| 134 #else | 131 #else |
| 135 name->ShortPrint(stdout); | 132 name->ShortPrint(stdout); |
| 136 #endif | 133 #endif |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 463 | 460 |
| 464 void IC::Clear(Isolate* isolate, Address address, Address constant_pool) { | 461 void IC::Clear(Isolate* isolate, Address address, Address constant_pool) { |
| 465 Code* target = GetTargetAtAddress(address, constant_pool); | 462 Code* target = GetTargetAtAddress(address, constant_pool); |
| 466 | 463 |
| 467 // Don't clear debug break inline cache as it will remove the break point. | 464 // Don't clear debug break inline cache as it will remove the break point. |
| 468 if (target->is_debug_stub()) return; | 465 if (target->is_debug_stub()) return; |
| 469 | 466 |
| 470 switch (target->kind()) { | 467 switch (target->kind()) { |
| 471 case Code::LOAD_IC: | 468 case Code::LOAD_IC: |
| 472 case Code::KEYED_LOAD_IC: | 469 case Code::KEYED_LOAD_IC: |
| 470 case Code::STORE_IC: |
| 471 case Code::KEYED_STORE_IC: |
| 473 return; | 472 return; |
| 474 case Code::STORE_IC: | |
| 475 if (FLAG_vector_stores) return; | |
| 476 return StoreIC::Clear(isolate, address, target, constant_pool); | |
| 477 case Code::KEYED_STORE_IC: | |
| 478 if (FLAG_vector_stores) return; | |
| 479 return KeyedStoreIC::Clear(isolate, address, target, constant_pool); | |
| 480 case Code::COMPARE_IC: | 473 case Code::COMPARE_IC: |
| 481 return CompareIC::Clear(isolate, address, target, constant_pool); | 474 return CompareIC::Clear(isolate, address, target, constant_pool); |
| 482 case Code::COMPARE_NIL_IC: | 475 case Code::COMPARE_NIL_IC: |
| 483 return CompareNilIC::Clear(address, target, constant_pool); | 476 return CompareNilIC::Clear(address, target, constant_pool); |
| 484 case Code::CALL_IC: // CallICs are vector-based and cleared differently. | 477 case Code::CALL_IC: // CallICs are vector-based and cleared differently. |
| 485 case Code::BINARY_OP_IC: | 478 case Code::BINARY_OP_IC: |
| 486 case Code::TO_BOOLEAN_IC: | 479 case Code::TO_BOOLEAN_IC: |
| 487 // Clearing these is tricky and does not | 480 // Clearing these is tricky and does not |
| 488 // make any performance difference. | 481 // make any performance difference. |
| 489 return; | 482 return; |
| (...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 803 if (UseVector()) { | 796 if (UseVector()) { |
| 804 if (!nexus()->FindHandlers(&handlers, maps.length())) return false; | 797 if (!nexus()->FindHandlers(&handlers, maps.length())) return false; |
| 805 } else { | 798 } else { |
| 806 if (!target()->FindHandlers(&handlers, maps.length())) return false; | 799 if (!target()->FindHandlers(&handlers, maps.length())) return false; |
| 807 } | 800 } |
| 808 | 801 |
| 809 number_of_valid_maps++; | 802 number_of_valid_maps++; |
| 810 if (number_of_valid_maps > 1 && target()->is_keyed_stub()) return false; | 803 if (number_of_valid_maps > 1 && target()->is_keyed_stub()) return false; |
| 811 Handle<Code> ic; | 804 Handle<Code> ic; |
| 812 if (number_of_valid_maps == 1) { | 805 if (number_of_valid_maps == 1) { |
| 813 if (UseVector()) { | 806 ConfigureVectorState(name, receiver_map(), code); |
| 814 ConfigureVectorState(name, receiver_map(), code); | |
| 815 } else { | |
| 816 ic = PropertyICCompiler::ComputeMonomorphic(kind(), name, map, code, | |
| 817 extra_ic_state()); | |
| 818 } | |
| 819 } else { | 807 } else { |
| 820 if (handler_to_overwrite >= 0) { | 808 if (handler_to_overwrite >= 0) { |
| 821 handlers.Set(handler_to_overwrite, code); | 809 handlers.Set(handler_to_overwrite, code); |
| 822 if (!map.is_identical_to(maps.at(handler_to_overwrite))) { | 810 if (!map.is_identical_to(maps.at(handler_to_overwrite))) { |
| 823 maps.Set(handler_to_overwrite, map); | 811 maps.Set(handler_to_overwrite, map); |
| 824 } | 812 } |
| 825 } else { | 813 } else { |
| 826 maps.Add(map); | 814 maps.Add(map); |
| 827 handlers.Add(code); | 815 handlers.Add(code); |
| 828 } | 816 } |
| 829 | 817 |
| 830 if (UseVector()) { | 818 ConfigureVectorState(name, &maps, &handlers); |
| 831 ConfigureVectorState(name, &maps, &handlers); | |
| 832 } else { | |
| 833 ic = PropertyICCompiler::ComputePolymorphic(kind(), &maps, &handlers, | |
| 834 number_of_valid_maps, name, | |
| 835 extra_ic_state()); | |
| 836 } | |
| 837 } | 819 } |
| 838 | 820 |
| 839 if (!UseVector()) set_target(*ic); | 821 if (!UseVector()) set_target(*ic); |
| 840 return true; | 822 return true; |
| 841 } | 823 } |
| 842 | 824 |
| 843 | 825 |
| 844 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { | 826 void IC::UpdateMonomorphicIC(Handle<Code> handler, Handle<Name> name) { |
| 845 DCHECK(handler->is_handler()); | 827 DCHECK(handler->is_handler()); |
| 846 if (UseVector()) { | 828 ConfigureVectorState(name, receiver_map(), handler); |
| 847 ConfigureVectorState(name, receiver_map(), handler); | |
| 848 } else { | |
| 849 Handle<Code> ic = PropertyICCompiler::ComputeMonomorphic( | |
| 850 kind(), name, receiver_map(), handler, extra_ic_state()); | |
| 851 set_target(*ic); | |
| 852 } | |
| 853 } | 829 } |
| 854 | 830 |
| 855 | 831 |
| 856 void IC::CopyICToMegamorphicCache(Handle<Name> name) { | 832 void IC::CopyICToMegamorphicCache(Handle<Name> name) { |
| 857 MapHandleList maps; | 833 MapHandleList maps; |
| 858 CodeHandleList handlers; | 834 CodeHandleList handlers; |
| 859 TargetMaps(&maps); | 835 TargetMaps(&maps); |
| 860 if (!target()->FindHandlers(&handlers, maps.length())) return; | 836 if (!target()->FindHandlers(&handlers, maps.length())) return; |
| 861 for (int i = 0; i < maps.length(); i++) { | 837 for (int i = 0; i < maps.length(); i++) { |
| 862 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); | 838 UpdateMegamorphicCache(*maps.at(i), *name, *handlers.at(i)); |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 966 default: | 942 default: |
| 967 UNREACHABLE(); | 943 UNREACHABLE(); |
| 968 } | 944 } |
| 969 return Handle<Code>(); | 945 return Handle<Code>(); |
| 970 } | 946 } |
| 971 | 947 |
| 972 | 948 |
| 973 Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate, | 949 Handle<Code> KeyedStoreIC::initialize_stub(Isolate* isolate, |
| 974 LanguageMode language_mode, | 950 LanguageMode language_mode, |
| 975 State initialization_state) { | 951 State initialization_state) { |
| 976 if (FLAG_vector_stores && initialization_state != MEGAMORPHIC) { | 952 if (initialization_state != MEGAMORPHIC) { |
| 977 VectorKeyedStoreICTrampolineStub stub(isolate, StoreICState(language_mode)); | 953 VectorKeyedStoreICTrampolineStub stub(isolate, StoreICState(language_mode)); |
| 978 return stub.GetCode(); | 954 return stub.GetCode(); |
| 979 } | 955 } |
| 980 | 956 |
| 981 return KeyedStoreICInitializeStubHelper(isolate, language_mode, | 957 return KeyedStoreICInitializeStubHelper(isolate, language_mode, |
| 982 initialization_state); | 958 initialization_state); |
| 983 } | 959 } |
| 984 | 960 |
| 985 | 961 |
| 986 Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code( | 962 Handle<Code> KeyedStoreIC::initialize_stub_in_optimized_code( |
| 987 Isolate* isolate, LanguageMode language_mode, State initialization_state) { | 963 Isolate* isolate, LanguageMode language_mode, State initialization_state) { |
| 988 if (FLAG_vector_stores && initialization_state != MEGAMORPHIC) { | 964 if (initialization_state != MEGAMORPHIC) { |
| 989 VectorKeyedStoreICStub stub(isolate, StoreICState(language_mode)); | 965 VectorKeyedStoreICStub stub(isolate, StoreICState(language_mode)); |
| 990 return stub.GetCode(); | 966 return stub.GetCode(); |
| 991 } | 967 } |
| 992 | 968 |
| 993 return KeyedStoreICInitializeStubHelper(isolate, language_mode, | 969 return KeyedStoreICInitializeStubHelper(isolate, language_mode, |
| 994 initialization_state); | 970 initialization_state); |
| 995 } | 971 } |
| 996 | 972 |
| 997 | 973 |
| 998 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate, | 974 Handle<Code> KeyedStoreIC::ChooseMegamorphicStub(Isolate* isolate, |
| (...skipping 614 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1613 return ic; | 1589 return ic; |
| 1614 } | 1590 } |
| 1615 | 1591 |
| 1616 | 1592 |
| 1617 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, | 1593 Handle<Code> StoreIC::initialize_stub(Isolate* isolate, |
| 1618 LanguageMode language_mode, | 1594 LanguageMode language_mode, |
| 1619 State initialization_state) { | 1595 State initialization_state) { |
| 1620 DCHECK(initialization_state == UNINITIALIZED || | 1596 DCHECK(initialization_state == UNINITIALIZED || |
| 1621 initialization_state == PREMONOMORPHIC || | 1597 initialization_state == PREMONOMORPHIC || |
| 1622 initialization_state == MEGAMORPHIC); | 1598 initialization_state == MEGAMORPHIC); |
| 1623 if (FLAG_vector_stores) { | 1599 VectorStoreICTrampolineStub stub(isolate, StoreICState(language_mode)); |
| 1624 VectorStoreICTrampolineStub stub(isolate, StoreICState(language_mode)); | 1600 return stub.GetCode(); |
| 1625 return stub.GetCode(); | |
| 1626 } | |
| 1627 | |
| 1628 return StoreICInitializeStubHelper( | |
| 1629 isolate, ComputeExtraICState(language_mode), initialization_state); | |
| 1630 } | 1601 } |
| 1631 | 1602 |
| 1632 | 1603 |
| 1633 Handle<Code> StoreIC::initialize_stub_in_optimized_code( | 1604 Handle<Code> StoreIC::initialize_stub_in_optimized_code( |
| 1634 Isolate* isolate, LanguageMode language_mode, State initialization_state) { | 1605 Isolate* isolate, LanguageMode language_mode, State initialization_state) { |
| 1635 DCHECK(initialization_state == UNINITIALIZED || | 1606 DCHECK(initialization_state == UNINITIALIZED || |
| 1636 initialization_state == PREMONOMORPHIC || | 1607 initialization_state == PREMONOMORPHIC || |
| 1637 initialization_state == MEGAMORPHIC); | 1608 initialization_state == MEGAMORPHIC); |
| 1638 if (FLAG_vector_stores && initialization_state != MEGAMORPHIC) { | 1609 if (initialization_state != MEGAMORPHIC) { |
| 1639 VectorStoreICStub stub(isolate, StoreICState(language_mode)); | 1610 VectorStoreICStub stub(isolate, StoreICState(language_mode)); |
| 1640 return stub.GetCode(); | 1611 return stub.GetCode(); |
| 1641 } | 1612 } |
| 1642 | 1613 |
| 1643 return StoreICInitializeStubHelper( | 1614 return StoreICInitializeStubHelper( |
| 1644 isolate, ComputeExtraICState(language_mode), initialization_state); | 1615 isolate, ComputeExtraICState(language_mode), initialization_state); |
| 1645 } | 1616 } |
| 1646 | 1617 |
| 1647 | 1618 |
| 1648 Handle<Code> StoreIC::megamorphic_stub() { | 1619 Handle<Code> StoreIC::megamorphic_stub() { |
| (...skipping 26 matching lines...) Expand all Loading... |
| 1675 ExtraICState state = ComputeExtraICState(language_mode); | 1646 ExtraICState state = ComputeExtraICState(language_mode); |
| 1676 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); | 1647 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); |
| 1677 } | 1648 } |
| 1678 | 1649 |
| 1679 | 1650 |
| 1680 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, | 1651 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, |
| 1681 JSReceiver::StoreFromKeyed store_mode) { | 1652 JSReceiver::StoreFromKeyed store_mode) { |
| 1682 if (state() == UNINITIALIZED) { | 1653 if (state() == UNINITIALIZED) { |
| 1683 // This is the first time we execute this inline cache. Set the target to | 1654 // This is the first time we execute this inline cache. Set the target to |
| 1684 // the pre monomorphic stub to delay setting the monomorphic state. | 1655 // the pre monomorphic stub to delay setting the monomorphic state. |
| 1685 if (FLAG_vector_stores) { | 1656 ConfigureVectorState(PREMONOMORPHIC); |
| 1686 ConfigureVectorState(PREMONOMORPHIC); | |
| 1687 } else { | |
| 1688 set_target(*pre_monomorphic_stub()); | |
| 1689 } | |
| 1690 TRACE_IC("StoreIC", lookup->name()); | 1657 TRACE_IC("StoreIC", lookup->name()); |
| 1691 return; | 1658 return; |
| 1692 } | 1659 } |
| 1693 | 1660 |
| 1694 bool use_ic = LookupForWrite(lookup, value, store_mode); | 1661 bool use_ic = LookupForWrite(lookup, value, store_mode); |
| 1695 if (!use_ic) { | 1662 if (!use_ic) { |
| 1696 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); | 1663 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); |
| 1697 } | 1664 } |
| 1698 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); | 1665 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); |
| 1699 | 1666 |
| (...skipping 175 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1875 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type"); | 1842 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-NORMAL target type"); |
| 1876 return megamorphic_stub(); | 1843 return megamorphic_stub(); |
| 1877 } | 1844 } |
| 1878 | 1845 |
| 1879 MapHandleList target_receiver_maps; | 1846 MapHandleList target_receiver_maps; |
| 1880 TargetMaps(&target_receiver_maps); | 1847 TargetMaps(&target_receiver_maps); |
| 1881 if (target_receiver_maps.length() == 0) { | 1848 if (target_receiver_maps.length() == 0) { |
| 1882 Handle<Map> monomorphic_map = | 1849 Handle<Map> monomorphic_map = |
| 1883 ComputeTransitionedMap(receiver_map, store_mode); | 1850 ComputeTransitionedMap(receiver_map, store_mode); |
| 1884 store_mode = GetNonTransitioningStoreMode(store_mode); | 1851 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1885 if (FLAG_vector_stores) { | 1852 Handle<Code> handler = |
| 1886 Handle<Code> handler = | 1853 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler( |
| 1887 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler( | 1854 monomorphic_map, language_mode(), store_mode); |
| 1888 monomorphic_map, language_mode(), store_mode); | 1855 ConfigureVectorState(Handle<Name>::null(), monomorphic_map, handler); |
| 1889 ConfigureVectorState(Handle<Name>::null(), monomorphic_map, handler); | 1856 return null_handle; |
| 1890 return null_handle; | |
| 1891 } | |
| 1892 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | |
| 1893 monomorphic_map, language_mode(), store_mode); | |
| 1894 } | 1857 } |
| 1895 | 1858 |
| 1896 // There are several special cases where an IC that is MONOMORPHIC can still | 1859 // There are several special cases where an IC that is MONOMORPHIC can still |
| 1897 // transition to a different GetNonTransitioningStoreMode IC that handles a | 1860 // transition to a different GetNonTransitioningStoreMode IC that handles a |
| 1898 // superset of the original IC. Handle those here if the receiver map hasn't | 1861 // superset of the original IC. Handle those here if the receiver map hasn't |
| 1899 // changed or it has transitioned to a more general kind. | 1862 // changed or it has transitioned to a more general kind. |
| 1900 KeyedAccessStoreMode old_store_mode = | 1863 KeyedAccessStoreMode old_store_mode = GetKeyedAccessStoreMode(); |
| 1901 FLAG_vector_stores | |
| 1902 ? GetKeyedAccessStoreMode() | |
| 1903 : KeyedStoreIC::GetKeyedAccessStoreMode(target()->extra_ic_state()); | |
| 1904 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); | 1864 Handle<Map> previous_receiver_map = target_receiver_maps.at(0); |
| 1905 if (state() == MONOMORPHIC) { | 1865 if (state() == MONOMORPHIC) { |
| 1906 Handle<Map> transitioned_receiver_map = receiver_map; | 1866 Handle<Map> transitioned_receiver_map = receiver_map; |
| 1907 if (IsTransitionStoreMode(store_mode)) { | 1867 if (IsTransitionStoreMode(store_mode)) { |
| 1908 transitioned_receiver_map = | 1868 transitioned_receiver_map = |
| 1909 ComputeTransitionedMap(receiver_map, store_mode); | 1869 ComputeTransitionedMap(receiver_map, store_mode); |
| 1910 } | 1870 } |
| 1911 if ((receiver_map.is_identical_to(previous_receiver_map) && | 1871 if ((receiver_map.is_identical_to(previous_receiver_map) && |
| 1912 IsTransitionStoreMode(store_mode)) || | 1872 IsTransitionStoreMode(store_mode)) || |
| 1913 IsTransitionOfMonomorphicTarget(*previous_receiver_map, | 1873 IsTransitionOfMonomorphicTarget(*previous_receiver_map, |
| 1914 *transitioned_receiver_map)) { | 1874 *transitioned_receiver_map)) { |
| 1915 // If the "old" and "new" maps are in the same elements map family, or | 1875 // If the "old" and "new" maps are in the same elements map family, or |
| 1916 // if they at least come from the same origin for a transitioning store, | 1876 // if they at least come from the same origin for a transitioning store, |
| 1917 // stay MONOMORPHIC and use the map for the most generic ElementsKind. | 1877 // stay MONOMORPHIC and use the map for the most generic ElementsKind. |
| 1918 store_mode = GetNonTransitioningStoreMode(store_mode); | 1878 store_mode = GetNonTransitioningStoreMode(store_mode); |
| 1919 if (FLAG_vector_stores) { | 1879 Handle<Code> handler = |
| 1920 Handle<Code> handler = | 1880 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler( |
| 1921 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler( | 1881 transitioned_receiver_map, language_mode(), store_mode); |
| 1922 transitioned_receiver_map, language_mode(), store_mode); | 1882 ConfigureVectorState(Handle<Name>::null(), transitioned_receiver_map, |
| 1923 ConfigureVectorState(Handle<Name>::null(), transitioned_receiver_map, | 1883 handler); |
| 1924 handler); | 1884 return null_handle; |
| 1925 return null_handle; | |
| 1926 } | |
| 1927 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | |
| 1928 transitioned_receiver_map, language_mode(), store_mode); | |
| 1929 } else if (receiver_map.is_identical_to(previous_receiver_map) && | 1885 } else if (receiver_map.is_identical_to(previous_receiver_map) && |
| 1930 old_store_mode == STANDARD_STORE && | 1886 old_store_mode == STANDARD_STORE && |
| 1931 (store_mode == STORE_AND_GROW_NO_TRANSITION || | 1887 (store_mode == STORE_AND_GROW_NO_TRANSITION || |
| 1932 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || | 1888 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS || |
| 1933 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { | 1889 store_mode == STORE_NO_TRANSITION_HANDLE_COW)) { |
| 1934 // A "normal" IC that handles stores can switch to a version that can | 1890 // A "normal" IC that handles stores can switch to a version that can |
| 1935 // grow at the end of the array, handle OOB accesses or copy COW arrays | 1891 // grow at the end of the array, handle OOB accesses or copy COW arrays |
| 1936 // and still stay MONOMORPHIC. | 1892 // and still stay MONOMORPHIC. |
| 1937 if (FLAG_vector_stores) { | 1893 Handle<Code> handler = |
| 1938 Handle<Code> handler = | 1894 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler( |
| 1939 PropertyICCompiler::ComputeKeyedStoreMonomorphicHandler( | 1895 receiver_map, language_mode(), store_mode); |
| 1940 receiver_map, language_mode(), store_mode); | 1896 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); |
| 1941 ConfigureVectorState(Handle<Name>::null(), receiver_map, handler); | 1897 return null_handle; |
| 1942 return null_handle; | |
| 1943 } | |
| 1944 return PropertyICCompiler::ComputeKeyedStoreMonomorphic( | |
| 1945 receiver_map, language_mode(), store_mode); | |
| 1946 } | 1898 } |
| 1947 } | 1899 } |
| 1948 | 1900 |
| 1949 DCHECK(state() != GENERIC); | 1901 DCHECK(state() != GENERIC); |
| 1950 | 1902 |
| 1951 bool map_added = | 1903 bool map_added = |
| 1952 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); | 1904 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); |
| 1953 | 1905 |
| 1954 if (IsTransitionStoreMode(store_mode)) { | 1906 if (IsTransitionStoreMode(store_mode)) { |
| 1955 Handle<Map> transitioned_receiver_map = | 1907 Handle<Map> transitioned_receiver_map = |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1994 } | 1946 } |
| 1995 } | 1947 } |
| 1996 if (external_arrays != 0 && | 1948 if (external_arrays != 0 && |
| 1997 external_arrays != target_receiver_maps.length()) { | 1949 external_arrays != target_receiver_maps.length()) { |
| 1998 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 1950 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 1999 "unsupported combination of external and normal arrays"); | 1951 "unsupported combination of external and normal arrays"); |
| 2000 return megamorphic_stub(); | 1952 return megamorphic_stub(); |
| 2001 } | 1953 } |
| 2002 } | 1954 } |
| 2003 | 1955 |
| 2004 if (FLAG_vector_stores) { | 1956 MapHandleList transitioned_maps(target_receiver_maps.length()); |
| 2005 MapHandleList transitioned_maps(target_receiver_maps.length()); | 1957 CodeHandleList handlers(target_receiver_maps.length()); |
| 2006 CodeHandleList handlers(target_receiver_maps.length()); | 1958 PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers( |
| 2007 PropertyICCompiler::ComputeKeyedStorePolymorphicHandlers( | 1959 &target_receiver_maps, &transitioned_maps, &handlers, store_mode, |
| 2008 &target_receiver_maps, &transitioned_maps, &handlers, store_mode, | 1960 language_mode()); |
| 2009 language_mode()); | 1961 ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers); |
| 2010 ConfigureVectorState(&target_receiver_maps, &transitioned_maps, &handlers); | 1962 return null_handle; |
| 2011 return null_handle; | |
| 2012 } | |
| 2013 | |
| 2014 return PropertyICCompiler::ComputeKeyedStorePolymorphic( | |
| 2015 &target_receiver_maps, store_mode, language_mode()); | |
| 2016 } | 1963 } |
| 2017 | 1964 |
| 2018 | 1965 |
| 2019 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( | 1966 Handle<Map> KeyedStoreIC::ComputeTransitionedMap( |
| 2020 Handle<Map> map, KeyedAccessStoreMode store_mode) { | 1967 Handle<Map> map, KeyedAccessStoreMode store_mode) { |
| 2021 switch (store_mode) { | 1968 switch (store_mode) { |
| 2022 case STORE_TRANSITION_TO_OBJECT: | 1969 case STORE_TRANSITION_TO_OBJECT: |
| 2023 case STORE_AND_GROW_TRANSITION_TO_OBJECT: { | 1970 case STORE_AND_GROW_TRANSITION_TO_OBJECT: { |
| 2024 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind()) | 1971 ElementsKind kind = IsFastHoleyElementsKind(map->elements_kind()) |
| 2025 ? FAST_HOLEY_ELEMENTS | 1972 ? FAST_HOLEY_ELEMENTS |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2099 Heap* heap = receiver->GetHeap(); | 2046 Heap* heap = receiver->GetHeap(); |
| 2100 if (receiver->elements()->map() == heap->fixed_cow_array_map()) { | 2047 if (receiver->elements()->map() == heap->fixed_cow_array_map()) { |
| 2101 return STORE_NO_TRANSITION_HANDLE_COW; | 2048 return STORE_NO_TRANSITION_HANDLE_COW; |
| 2102 } else { | 2049 } else { |
| 2103 return STANDARD_STORE; | 2050 return STANDARD_STORE; |
| 2104 } | 2051 } |
| 2105 } | 2052 } |
| 2106 } | 2053 } |
| 2107 | 2054 |
| 2108 | 2055 |
| 2109 void KeyedStoreIC::ValidateStoreMode(Handle<Code> stub) { | |
| 2110 #ifdef DEBUG | |
| 2111 DCHECK(!FLAG_vector_stores); | |
| 2112 if (stub.is_null() || *stub == *megamorphic_stub() || *stub == *slow_stub()) { | |
| 2113 return; | |
| 2114 } | |
| 2115 | |
| 2116 // Query the keyed store mode. | |
| 2117 ExtraICState state = stub->extra_ic_state(); | |
| 2118 KeyedAccessStoreMode stub_mode = GetKeyedAccessStoreMode(state); | |
| 2119 | |
| 2120 MapHandleList map_list; | |
| 2121 stub->FindAllMaps(&map_list); | |
| 2122 CodeHandleList list; | |
| 2123 stub->FindHandlers(&list, map_list.length()); | |
| 2124 for (int i = 0; i < list.length(); i++) { | |
| 2125 Handle<Code> handler = list.at(i); | |
| 2126 CHECK(handler->is_handler()); | |
| 2127 CodeStub::Major major_key = CodeStub::MajorKeyFromKey(handler->stub_key()); | |
| 2128 uint32_t minor_key = CodeStub::MinorKeyFromKey(handler->stub_key()); | |
| 2129 // Ensure that we only see handlers we know have the store mode embedded. | |
| 2130 CHECK(major_key == CodeStub::KeyedStoreSloppyArguments || | |
| 2131 major_key == CodeStub::StoreFastElement || | |
| 2132 major_key == CodeStub::StoreElement || | |
| 2133 major_key == CodeStub::ElementsTransitionAndStore || | |
| 2134 *handler == *isolate()->builtins()->KeyedStoreIC_Slow()); | |
| 2135 // Ensure that the store mode matches that of the IC. | |
| 2136 CHECK(major_key == CodeStub::NoCache || | |
| 2137 stub_mode == CommonStoreModeBits::decode(minor_key)); | |
| 2138 // The one exception is the keyed store slow builtin, which doesn't include | |
| 2139 // store mode. | |
| 2140 CHECK(major_key != CodeStub::NoCache || | |
| 2141 *handler == *isolate()->builtins()->KeyedStoreIC_Slow()); | |
| 2142 } | |
| 2143 #endif // DEBUG | |
| 2144 } | |
| 2145 | |
| 2146 | |
| 2147 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, | 2056 MaybeHandle<Object> KeyedStoreIC::Store(Handle<Object> object, |
| 2148 Handle<Object> key, | 2057 Handle<Object> key, |
| 2149 Handle<Object> value) { | 2058 Handle<Object> value) { |
| 2150 // TODO(verwaest): Let SetProperty do the migration, since storing a property | 2059 // TODO(verwaest): Let SetProperty do the migration, since storing a property |
| 2151 // might deprecate the current map again, if value does not fit. | 2060 // might deprecate the current map again, if value does not fit. |
| 2152 if (MigrateDeprecated(object)) { | 2061 if (MigrateDeprecated(object)) { |
| 2153 Handle<Object> result; | 2062 Handle<Object> result; |
| 2154 ASSIGN_RETURN_ON_EXCEPTION( | 2063 ASSIGN_RETURN_ON_EXCEPTION( |
| 2155 isolate(), result, Runtime::SetObjectProperty(isolate(), object, key, | 2064 isolate(), result, Runtime::SetObjectProperty(isolate(), object, key, |
| 2156 value, language_mode()), | 2065 value, language_mode()), |
| (...skipping 10 matching lines...) Expand all Loading... |
| 2167 | 2076 |
| 2168 uint32_t index; | 2077 uint32_t index; |
| 2169 if ((key->IsInternalizedString() && | 2078 if ((key->IsInternalizedString() && |
| 2170 !String::cast(*key)->AsArrayIndex(&index)) || | 2079 !String::cast(*key)->AsArrayIndex(&index)) || |
| 2171 key->IsSymbol()) { | 2080 key->IsSymbol()) { |
| 2172 ASSIGN_RETURN_ON_EXCEPTION( | 2081 ASSIGN_RETURN_ON_EXCEPTION( |
| 2173 isolate(), store_handle, | 2082 isolate(), store_handle, |
| 2174 StoreIC::Store(object, Handle<Name>::cast(key), value, | 2083 StoreIC::Store(object, Handle<Name>::cast(key), value, |
| 2175 JSReceiver::MAY_BE_STORE_FROM_KEYED), | 2084 JSReceiver::MAY_BE_STORE_FROM_KEYED), |
| 2176 Object); | 2085 Object); |
| 2177 if (FLAG_vector_stores) { | 2086 if (!is_vector_set()) { |
| 2178 if (!is_vector_set()) { | 2087 ConfigureVectorState(MEGAMORPHIC); |
| 2179 ConfigureVectorState(MEGAMORPHIC); | 2088 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 2180 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 2089 "unhandled internalized string key"); |
| 2181 "unhandled internalized string key"); | 2090 TRACE_IC("StoreIC", key); |
| 2182 TRACE_IC("StoreIC", key); | |
| 2183 } | |
| 2184 } else { | |
| 2185 if (!is_target_set()) { | |
| 2186 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | |
| 2187 "unhandled internalized string key"); | |
| 2188 TRACE_IC("StoreIC", key); | |
| 2189 set_target(*stub); | |
| 2190 } | |
| 2191 } | 2091 } |
| 2192 return store_handle; | 2092 return store_handle; |
| 2193 } | 2093 } |
| 2194 | 2094 |
| 2195 bool use_ic = | 2095 bool use_ic = |
| 2196 FLAG_use_ic && !object->IsStringWrapper() && | 2096 FLAG_use_ic && !object->IsStringWrapper() && |
| 2197 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && | 2097 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && |
| 2198 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); | 2098 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); |
| 2199 if (use_ic && !object->IsSmi()) { | 2099 if (use_ic && !object->IsSmi()) { |
| 2200 // Don't use ICs for maps of the objects in Array's prototype chain. We | 2100 // Don't use ICs for maps of the objects in Array's prototype chain. We |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2237 if (!old_receiver_map.is_null()) { | 2137 if (!old_receiver_map.is_null()) { |
| 2238 if (sloppy_arguments_elements) { | 2138 if (sloppy_arguments_elements) { |
| 2239 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); | 2139 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "arguments receiver"); |
| 2240 } else if (key_is_valid_index) { | 2140 } else if (key_is_valid_index) { |
| 2241 // We should go generic if receiver isn't a dictionary, but our | 2141 // We should go generic if receiver isn't a dictionary, but our |
| 2242 // prototype chain does have dictionary elements. This ensures that | 2142 // prototype chain does have dictionary elements. This ensures that |
| 2243 // other non-dictionary receivers in the polymorphic case benefit | 2143 // other non-dictionary receivers in the polymorphic case benefit |
| 2244 // from fast path keyed stores. | 2144 // from fast path keyed stores. |
| 2245 if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly()) { | 2145 if (!old_receiver_map->DictionaryElementsInPrototypeChainOnly()) { |
| 2246 stub = StoreElementStub(old_receiver_map, store_mode); | 2146 stub = StoreElementStub(old_receiver_map, store_mode); |
| 2247 | |
| 2248 // Validate that the store_mode in the stub can also be derived | |
| 2249 // from peeking in the code bits of the handlers. | |
| 2250 if (!FLAG_vector_stores) ValidateStoreMode(stub); | |
| 2251 } else { | 2147 } else { |
| 2252 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 2148 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 2253 "dictionary or proxy prototype"); | 2149 "dictionary or proxy prototype"); |
| 2254 } | 2150 } |
| 2255 } else { | 2151 } else { |
| 2256 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); | 2152 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); |
| 2257 } | 2153 } |
| 2258 } else { | 2154 } else { |
| 2259 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); | 2155 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); |
| 2260 } | 2156 } |
| 2261 } | 2157 } |
| 2262 | 2158 |
| 2263 if (FLAG_vector_stores) { | 2159 if (!is_vector_set() || stub.is_null()) { |
| 2264 if (!is_vector_set() || stub.is_null()) { | |
| 2265 Code* megamorphic = *megamorphic_stub(); | |
| 2266 if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { | |
| 2267 ConfigureVectorState(MEGAMORPHIC); | |
| 2268 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | |
| 2269 *stub == megamorphic ? "set generic" : "slow stub"); | |
| 2270 } | |
| 2271 } | |
| 2272 } else { | |
| 2273 DCHECK(!is_target_set()); | |
| 2274 Code* megamorphic = *megamorphic_stub(); | 2160 Code* megamorphic = *megamorphic_stub(); |
| 2275 if (*stub == megamorphic) { | 2161 if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { |
| 2276 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "set generic"); | 2162 ConfigureVectorState(MEGAMORPHIC); |
| 2277 } else if (*stub == *slow_stub()) { | 2163 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 2278 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "slow stub"); | 2164 *stub == megamorphic ? "set generic" : "slow stub"); |
| 2279 } | |
| 2280 | |
| 2281 DCHECK(!stub.is_null()); | |
| 2282 if (!AddressIsDeoptimizedCode()) { | |
| 2283 set_target(*stub); | |
| 2284 } | 2165 } |
| 2285 } | 2166 } |
| 2286 TRACE_IC("StoreIC", key); | 2167 TRACE_IC("StoreIC", key); |
| 2287 | 2168 |
| 2288 return store_handle; | 2169 return store_handle; |
| 2289 } | 2170 } |
| 2290 | 2171 |
| 2291 | 2172 |
| 2292 void CallIC::HandleMiss(Handle<Object> function) { | 2173 void CallIC::HandleMiss(Handle<Object> function) { |
| 2293 Handle<Object> name = isolate()->factory()->empty_string(); | 2174 Handle<Object> name = isolate()->factory()->empty_string(); |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2429 | 2310 |
| 2430 // Used from ic-<arch>.cc. | 2311 // Used from ic-<arch>.cc. |
| 2431 RUNTIME_FUNCTION(Runtime_StoreIC_Miss) { | 2312 RUNTIME_FUNCTION(Runtime_StoreIC_Miss) { |
| 2432 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2313 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2433 HandleScope scope(isolate); | 2314 HandleScope scope(isolate); |
| 2434 Handle<Object> receiver = args.at<Object>(0); | 2315 Handle<Object> receiver = args.at<Object>(0); |
| 2435 Handle<Name> key = args.at<Name>(1); | 2316 Handle<Name> key = args.at<Name>(1); |
| 2436 Handle<Object> value = args.at<Object>(2); | 2317 Handle<Object> value = args.at<Object>(2); |
| 2437 Handle<Object> result; | 2318 Handle<Object> result; |
| 2438 | 2319 |
| 2439 if (FLAG_vector_stores) { | 2320 DCHECK(args.length() == 5 || args.length() == 6); |
| 2440 DCHECK(args.length() == 5 || args.length() == 6); | 2321 Handle<Smi> slot = args.at<Smi>(3); |
| 2441 Handle<Smi> slot = args.at<Smi>(3); | 2322 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); |
| 2442 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); | 2323 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); |
| 2443 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); | 2324 if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) { |
| 2444 if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) { | 2325 StoreICNexus nexus(vector, vector_slot); |
| 2445 StoreICNexus nexus(vector, vector_slot); | 2326 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2446 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | |
| 2447 ic.UpdateState(receiver, key); | |
| 2448 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 2449 ic.Store(receiver, key, value)); | |
| 2450 } else { | |
| 2451 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, | |
| 2452 vector->GetKind(vector_slot)); | |
| 2453 KeyedStoreICNexus nexus(vector, vector_slot); | |
| 2454 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | |
| 2455 ic.UpdateState(receiver, key); | |
| 2456 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 2457 ic.Store(receiver, key, value)); | |
| 2458 } | |
| 2459 } else { | |
| 2460 DCHECK(args.length() == 3); | |
| 2461 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | |
| 2462 ic.UpdateState(receiver, key); | 2327 ic.UpdateState(receiver, key); |
| 2463 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 2328 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2464 ic.Store(receiver, key, value)); | 2329 ic.Store(receiver, key, value)); |
| 2330 } else { |
| 2331 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, |
| 2332 vector->GetKind(vector_slot)); |
| 2333 KeyedStoreICNexus nexus(vector, vector_slot); |
| 2334 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2335 ic.UpdateState(receiver, key); |
| 2336 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2337 ic.Store(receiver, key, value)); |
| 2465 } | 2338 } |
| 2466 return *result; | 2339 return *result; |
| 2467 } | 2340 } |
| 2468 | 2341 |
| 2469 | 2342 |
| 2470 RUNTIME_FUNCTION(Runtime_StoreIC_MissFromStubFailure) { | 2343 RUNTIME_FUNCTION(Runtime_StoreIC_MissFromStubFailure) { |
| 2471 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2344 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2472 HandleScope scope(isolate); | 2345 HandleScope scope(isolate); |
| 2473 Handle<Object> receiver = args.at<Object>(0); | 2346 Handle<Object> receiver = args.at<Object>(0); |
| 2474 Handle<Name> key = args.at<Name>(1); | 2347 Handle<Name> key = args.at<Name>(1); |
| 2475 Handle<Object> value = args.at<Object>(2); | 2348 Handle<Object> value = args.at<Object>(2); |
| 2476 Handle<Object> result; | 2349 Handle<Object> result; |
| 2477 | 2350 |
| 2478 if (FLAG_vector_stores) { | 2351 int length = args.length(); |
| 2479 int length = args.length(); | 2352 DCHECK(length == 5 || length == 6); |
| 2480 DCHECK(length == 5 || length == 6); | 2353 // We might have slot and vector, for a normal miss (slot(3), vector(4)). |
| 2481 // We might have slot and vector, for a normal miss (slot(3), vector(4)). | 2354 // Or, map and vector for a transitioning store miss (map(3), vector(4)). |
| 2482 // Or, map and vector for a transitioning store miss (map(3), vector(4)). | 2355 // In this case, we need to recover the slot from a virtual register. |
| 2483 // In this case, we need to recover the slot from a virtual register. | 2356 // If length == 6, then a map is included (map(3), slot(4), vector(5)). |
| 2484 // If length == 6, then a map is included (map(3), slot(4), vector(5)). | 2357 Handle<Smi> slot; |
| 2485 Handle<Smi> slot; | 2358 Handle<TypeFeedbackVector> vector; |
| 2486 Handle<TypeFeedbackVector> vector; | 2359 if (length == 5) { |
| 2487 if (length == 5) { | 2360 if (args.at<Object>(3)->IsMap()) { |
| 2488 if (args.at<Object>(3)->IsMap()) { | 2361 vector = args.at<TypeFeedbackVector>(4); |
| 2489 vector = args.at<TypeFeedbackVector>(4); | 2362 slot = handle( |
| 2490 slot = handle( | 2363 *reinterpret_cast<Smi**>(isolate->virtual_slot_register_address()), |
| 2491 *reinterpret_cast<Smi**>(isolate->virtual_slot_register_address()), | 2364 isolate); |
| 2492 isolate); | |
| 2493 } else { | |
| 2494 vector = args.at<TypeFeedbackVector>(4); | |
| 2495 slot = args.at<Smi>(3); | |
| 2496 } | |
| 2497 } else { | 2365 } else { |
| 2498 vector = args.at<TypeFeedbackVector>(5); | 2366 vector = args.at<TypeFeedbackVector>(4); |
| 2499 slot = args.at<Smi>(4); | 2367 slot = args.at<Smi>(3); |
| 2500 } | |
| 2501 | |
| 2502 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); | |
| 2503 if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) { | |
| 2504 StoreICNexus nexus(vector, vector_slot); | |
| 2505 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | |
| 2506 ic.UpdateState(receiver, key); | |
| 2507 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 2508 ic.Store(receiver, key, value)); | |
| 2509 } else { | |
| 2510 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, | |
| 2511 vector->GetKind(vector_slot)); | |
| 2512 KeyedStoreICNexus nexus(vector, vector_slot); | |
| 2513 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | |
| 2514 ic.UpdateState(receiver, key); | |
| 2515 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 2516 ic.Store(receiver, key, value)); | |
| 2517 } | 2368 } |
| 2518 } else { | 2369 } else { |
| 2519 DCHECK(args.length() == 3 || args.length() == 4); | 2370 vector = args.at<TypeFeedbackVector>(5); |
| 2520 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2371 slot = args.at<Smi>(4); |
| 2372 } |
| 2373 |
| 2374 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); |
| 2375 if (vector->GetKind(vector_slot) == FeedbackVectorSlotKind::STORE_IC) { |
| 2376 StoreICNexus nexus(vector, vector_slot); |
| 2377 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2521 ic.UpdateState(receiver, key); | 2378 ic.UpdateState(receiver, key); |
| 2522 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 2379 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2523 ic.Store(receiver, key, value)); | 2380 ic.Store(receiver, key, value)); |
| 2381 } else { |
| 2382 DCHECK_EQ(FeedbackVectorSlotKind::KEYED_STORE_IC, |
| 2383 vector->GetKind(vector_slot)); |
| 2384 KeyedStoreICNexus nexus(vector, vector_slot); |
| 2385 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2386 ic.UpdateState(receiver, key); |
| 2387 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2388 ic.Store(receiver, key, value)); |
| 2524 } | 2389 } |
| 2525 return *result; | 2390 return *result; |
| 2526 } | 2391 } |
| 2527 | 2392 |
| 2528 | 2393 |
| 2529 // Used from ic-<arch>.cc. | 2394 // Used from ic-<arch>.cc. |
| 2530 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) { | 2395 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Miss) { |
| 2531 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2396 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2532 HandleScope scope(isolate); | 2397 HandleScope scope(isolate); |
| 2533 Handle<Object> receiver = args.at<Object>(0); | 2398 Handle<Object> receiver = args.at<Object>(0); |
| 2534 Handle<Object> key = args.at<Object>(1); | 2399 Handle<Object> key = args.at<Object>(1); |
| 2535 Handle<Object> value = args.at<Object>(2); | 2400 Handle<Object> value = args.at<Object>(2); |
| 2536 Handle<Object> result; | 2401 Handle<Object> result; |
| 2537 | 2402 |
| 2538 if (FLAG_vector_stores) { | 2403 DCHECK(args.length() == 5); |
| 2539 DCHECK(args.length() == 5); | 2404 Handle<Smi> slot = args.at<Smi>(3); |
| 2540 Handle<Smi> slot = args.at<Smi>(3); | 2405 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); |
| 2541 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); | 2406 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); |
| 2542 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); | 2407 KeyedStoreICNexus nexus(vector, vector_slot); |
| 2543 KeyedStoreICNexus nexus(vector, vector_slot); | 2408 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2544 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2409 ic.UpdateState(receiver, key); |
| 2545 ic.UpdateState(receiver, key); | 2410 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2546 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 2411 ic.Store(receiver, key, value)); |
| 2547 ic.Store(receiver, key, value)); | |
| 2548 } else { | |
| 2549 DCHECK(args.length() == 3); | |
| 2550 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | |
| 2551 ic.UpdateState(receiver, key); | |
| 2552 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | |
| 2553 ic.Store(receiver, key, value)); | |
| 2554 } | |
| 2555 return *result; | 2412 return *result; |
| 2556 } | 2413 } |
| 2557 | 2414 |
| 2558 | 2415 |
| 2559 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure) { | 2416 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_MissFromStubFailure) { |
| 2560 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2417 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2561 HandleScope scope(isolate); | 2418 HandleScope scope(isolate); |
| 2562 Handle<Object> receiver = args.at<Object>(0); | 2419 Handle<Object> receiver = args.at<Object>(0); |
| 2563 Handle<Object> key = args.at<Object>(1); | 2420 Handle<Object> key = args.at<Object>(1); |
| 2564 Handle<Object> value = args.at<Object>(2); | 2421 Handle<Object> value = args.at<Object>(2); |
| 2565 Handle<Object> result; | 2422 Handle<Object> result; |
| 2566 | 2423 |
| 2567 if (FLAG_vector_stores) { | 2424 DCHECK(args.length() == 5); |
| 2568 DCHECK(args.length() == 5); | 2425 Handle<Smi> slot = args.at<Smi>(3); |
| 2569 Handle<Smi> slot = args.at<Smi>(3); | 2426 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); |
| 2570 Handle<TypeFeedbackVector> vector = args.at<TypeFeedbackVector>(4); | 2427 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); |
| 2571 FeedbackVectorSlot vector_slot = vector->ToSlot(slot->value()); | 2428 KeyedStoreICNexus nexus(vector, vector_slot); |
| 2572 KeyedStoreICNexus nexus(vector, vector_slot); | 2429 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2573 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2430 ic.UpdateState(receiver, key); |
| 2574 ic.UpdateState(receiver, key); | 2431 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 2575 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 2432 ic.Store(receiver, key, value)); |
| 2576 ic.Store(receiver, key, value)); | |
| 2577 } else { | |
| 2578 DCHECK(args.length() == 3); | |
| 2579 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
| 2580 ic.UpdateState(receiver, key); | |
| 2581 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | |
| 2582 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); | |
| 2583 } | |
| 2584 return *result; | 2433 return *result; |
| 2585 } | 2434 } |
| 2586 | 2435 |
| 2587 | 2436 |
| 2588 RUNTIME_FUNCTION(Runtime_StoreIC_Slow) { | 2437 RUNTIME_FUNCTION(Runtime_StoreIC_Slow) { |
| 2589 HandleScope scope(isolate); | 2438 HandleScope scope(isolate); |
| 2590 DCHECK(args.length() == (FLAG_vector_stores ? 5 : 3)); | 2439 DCHECK(args.length() == 5); |
| 2591 Handle<Object> object = args.at<Object>(0); | 2440 Handle<Object> object = args.at<Object>(0); |
| 2592 Handle<Object> key = args.at<Object>(1); | 2441 Handle<Object> key = args.at<Object>(1); |
| 2593 Handle<Object> value = args.at<Object>(2); | 2442 Handle<Object> value = args.at<Object>(2); |
| 2594 LanguageMode language_mode; | 2443 LanguageMode language_mode; |
| 2595 if (FLAG_vector_stores) { | 2444 StoreICNexus nexus(isolate); |
| 2596 StoreICNexus nexus(isolate); | 2445 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2597 StoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2446 language_mode = ic.language_mode(); |
| 2598 language_mode = ic.language_mode(); | |
| 2599 } else { | |
| 2600 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | |
| 2601 language_mode = ic.language_mode(); | |
| 2602 } | |
| 2603 Handle<Object> result; | 2447 Handle<Object> result; |
| 2604 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2448 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 2605 isolate, result, | 2449 isolate, result, |
| 2606 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); | 2450 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); |
| 2607 return *result; | 2451 return *result; |
| 2608 } | 2452 } |
| 2609 | 2453 |
| 2610 | 2454 |
| 2611 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) { | 2455 RUNTIME_FUNCTION(Runtime_KeyedStoreIC_Slow) { |
| 2612 HandleScope scope(isolate); | 2456 HandleScope scope(isolate); |
| 2613 DCHECK(args.length() == (FLAG_vector_stores ? 5 : 3)); | 2457 DCHECK(args.length() == 5); |
| 2614 Handle<Object> object = args.at<Object>(0); | 2458 Handle<Object> object = args.at<Object>(0); |
| 2615 Handle<Object> key = args.at<Object>(1); | 2459 Handle<Object> key = args.at<Object>(1); |
| 2616 Handle<Object> value = args.at<Object>(2); | 2460 Handle<Object> value = args.at<Object>(2); |
| 2617 LanguageMode language_mode; | 2461 LanguageMode language_mode; |
| 2618 if (FLAG_vector_stores) { | 2462 KeyedStoreICNexus nexus(isolate); |
| 2619 KeyedStoreICNexus nexus(isolate); | 2463 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); |
| 2620 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate, &nexus); | 2464 language_mode = ic.language_mode(); |
| 2621 language_mode = ic.language_mode(); | |
| 2622 } else { | |
| 2623 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate); | |
| 2624 language_mode = ic.language_mode(); | |
| 2625 } | |
| 2626 Handle<Object> result; | 2465 Handle<Object> result; |
| 2627 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2466 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 2628 isolate, result, | 2467 isolate, result, |
| 2629 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); | 2468 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); |
| 2630 return *result; | 2469 return *result; |
| 2631 } | 2470 } |
| 2632 | 2471 |
| 2633 | 2472 |
| 2634 RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) { | 2473 RUNTIME_FUNCTION(Runtime_ElementsTransitionAndStoreIC_Miss) { |
| 2635 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2474 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2636 HandleScope scope(isolate); | 2475 HandleScope scope(isolate); |
| 2637 // Without vector stores, length == 4. | 2476 // Length == 5 or 6, depending on whether the vector slot |
| 2638 // With vector stores, length == 5 or 6, depending on whether the vector slot | |
| 2639 // is passed in a virtual register or not. | 2477 // is passed in a virtual register or not. |
| 2640 DCHECK(!FLAG_vector_stores || args.length() == 5 || args.length() == 6); | 2478 DCHECK(args.length() == 5 || args.length() == 6); |
| 2641 Handle<Object> object = args.at<Object>(0); | 2479 Handle<Object> object = args.at<Object>(0); |
| 2642 Handle<Object> key = args.at<Object>(1); | 2480 Handle<Object> key = args.at<Object>(1); |
| 2643 Handle<Object> value = args.at<Object>(2); | 2481 Handle<Object> value = args.at<Object>(2); |
| 2644 Handle<Map> map = args.at<Map>(3); | 2482 Handle<Map> map = args.at<Map>(3); |
| 2645 LanguageMode language_mode; | 2483 LanguageMode language_mode; |
| 2646 if (FLAG_vector_stores) { | 2484 KeyedStoreICNexus nexus(isolate); |
| 2647 KeyedStoreICNexus nexus(isolate); | 2485 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2648 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2486 language_mode = ic.language_mode(); |
| 2649 language_mode = ic.language_mode(); | |
| 2650 } else { | |
| 2651 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | |
| 2652 language_mode = ic.language_mode(); | |
| 2653 } | |
| 2654 if (object->IsJSObject()) { | 2487 if (object->IsJSObject()) { |
| 2655 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), | 2488 JSObject::TransitionElementsKind(Handle<JSObject>::cast(object), |
| 2656 map->elements_kind()); | 2489 map->elements_kind()); |
| 2657 } | 2490 } |
| 2658 Handle<Object> result; | 2491 Handle<Object> result; |
| 2659 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2492 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 2660 isolate, result, | 2493 isolate, result, |
| 2661 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); | 2494 Runtime::SetObjectProperty(isolate, object, key, value, language_mode)); |
| 2662 return *result; | 2495 return *result; |
| 2663 } | 2496 } |
| (...skipping 481 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3145 KeyedLoadICNexus nexus(vector, vector_slot); | 2978 KeyedLoadICNexus nexus(vector, vector_slot); |
| 3146 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2979 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 3147 ic.UpdateState(receiver, key); | 2980 ic.UpdateState(receiver, key); |
| 3148 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2981 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 3149 } | 2982 } |
| 3150 | 2983 |
| 3151 return *result; | 2984 return *result; |
| 3152 } | 2985 } |
| 3153 } // namespace internal | 2986 } // namespace internal |
| 3154 } // namespace v8 | 2987 } // namespace v8 |
| OLD | NEW |