Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(89)

Side by Side Diff: src/ic.cc

Issue 12221064: Implement many KeyedStoreStubs using Crankshaft (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Rebase Created 7 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« src/ic.h ('K') | « src/ic.h ('k') | src/runtime.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2012 the V8 project authors. All rights reserved. 1 // Copyright 2012 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 1343 matching lines...) Expand 10 before | Expand all | Expand 10 after
1354 if (state == UNINITIALIZED) { 1354 if (state == UNINITIALIZED) {
1355 stub = string_stub(); 1355 stub = string_stub();
1356 } 1356 }
1357 } else if (object->IsJSObject()) { 1357 } else if (object->IsJSObject()) {
1358 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1358 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1359 if (receiver->elements()->map() == 1359 if (receiver->elements()->map() ==
1360 isolate()->heap()->non_strict_arguments_elements_map()) { 1360 isolate()->heap()->non_strict_arguments_elements_map()) {
1361 stub = non_strict_arguments_stub(); 1361 stub = non_strict_arguments_stub();
1362 } else if (receiver->HasIndexedInterceptor()) { 1362 } else if (receiver->HasIndexedInterceptor()) {
1363 stub = indexed_interceptor_stub(); 1363 stub = indexed_interceptor_stub();
1364 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { 1364 } else if (!key->ToSmi()->IsFailure() &&
1365 (target() != *non_strict_arguments_stub())) {
1365 stub = LoadElementStub(receiver); 1366 stub = LoadElementStub(receiver);
1366 } 1367 }
1367 } 1368 }
1368 } else { 1369 } else {
1369 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic"); 1370 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "force generic");
1370 } 1371 }
1371 ASSERT(!stub.is_null()); 1372 ASSERT(!stub.is_null());
1372 set_target(*stub); 1373 set_target(*stub);
1373 TRACE_IC("KeyedLoadIC", key, state, target()); 1374 TRACE_IC("KeyedLoadIC", key, state, target());
1374 } 1375 }
(...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after
1648 KeyedAccessStoreMode store_mode, 1649 KeyedAccessStoreMode store_mode,
1649 StrictModeFlag strict_mode) { 1650 StrictModeFlag strict_mode) {
1650 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS 1651 // Don't handle megamorphic property accesses for INTERCEPTORS or CALLBACKS
1651 // via megamorphic stubs, since they don't have a map in their relocation info 1652 // via megamorphic stubs, since they don't have a map in their relocation info
1652 // and so the stubs can't be harvested for the object needed for a map check. 1653 // and so the stubs can't be harvested for the object needed for a map check.
1653 if (target()->type() != Code::NORMAL) { 1654 if (target()->type() != Code::NORMAL) {
1654 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type"); 1655 TRACE_GENERIC_IC(isolate(), "KeyedIC", "non-NORMAL target type");
1655 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub(); 1656 return strict_mode == kStrictMode ? generic_stub_strict() : generic_stub();
1656 } 1657 }
1657 1658
1658 if ((store_mode == STORE_NO_TRANSITION_HANDLE_COW ||
1659 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS)) {
1660 // TODO(danno): We'll soon handle MONOMORPHIC ICs that also support
1661 // copying COW arrays and silently ignoring some OOB stores into external
1662 // arrays, but for now use the generic.
1663 TRACE_GENERIC_IC(isolate(), "KeyedIC", "COW/OOB external array");
1664 return strict_mode == kStrictMode
1665 ? generic_stub_strict()
1666 : generic_stub();
1667 }
1668
1669 State ic_state = target()->ic_state(); 1659 State ic_state = target()->ic_state();
1670 Handle<Map> receiver_map(receiver->map()); 1660 Handle<Map> receiver_map(receiver->map());
1671 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) { 1661 if (ic_state == UNINITIALIZED || ic_state == PREMONOMORPHIC) {
1672 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state 1662 // Optimistically assume that ICs that haven't reached the MONOMORPHIC state
1673 // yet will do so and stay there. 1663 // yet will do so and stay there.
1674 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode); 1664 Handle<Map> monomorphic_map = ComputeTransitionedMap(receiver, store_mode);
1675 store_mode = GetNonTransitioningStoreMode(store_mode); 1665 store_mode = GetNonTransitioningStoreMode(store_mode);
1676 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1666 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1677 monomorphic_map, strict_mode, store_mode); 1667 monomorphic_map, strict_mode, store_mode);
1678 } 1668 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1711 transitioned_kind); 1701 transitioned_kind);
1712 Map* transitioned_previous_map = more_general_transition 1702 Map* transitioned_previous_map = more_general_transition
1713 ? previous_receiver_map->LookupElementsTransitionMap(transitioned_kind) 1703 ? previous_receiver_map->LookupElementsTransitionMap(transitioned_kind)
1714 : NULL; 1704 : NULL;
1715 if (transitioned_previous_map == *transitioned_receiver_map) { 1705 if (transitioned_previous_map == *transitioned_receiver_map) {
1716 // Element family is the same, use the "worst" case map. 1706 // Element family is the same, use the "worst" case map.
1717 store_mode = GetNonTransitioningStoreMode(store_mode); 1707 store_mode = GetNonTransitioningStoreMode(store_mode);
1718 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1708 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1719 transitioned_receiver_map, strict_mode, store_mode); 1709 transitioned_receiver_map, strict_mode, store_mode);
1720 } else if (*previous_receiver_map == receiver->map()) { 1710 } else if (*previous_receiver_map == receiver->map()) {
1721 if (IsGrowStoreMode(store_mode)) { 1711 if (IsGrowStoreMode(store_mode) ||
1712 store_mode == STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS ||
1713 store_mode == STORE_NO_TRANSITION_HANDLE_COW) {
1722 // A "normal" IC that handles stores can switch to a version that can 1714 // A "normal" IC that handles stores can switch to a version that can
1723 // grow at the end of the array and still stay MONOMORPHIC. 1715 // grow at the end of the array, handle OOB accesses or copy COW arrays
1716 // and still stay MONOMORPHIC.
1724 return isolate()->stub_cache()->ComputeKeyedStoreElement( 1717 return isolate()->stub_cache()->ComputeKeyedStoreElement(
1725 receiver_map, strict_mode, store_mode); 1718 receiver_map, strict_mode, store_mode);
1726 } 1719 }
1727 } 1720 }
1728 } 1721 }
1729 1722
1730 ASSERT(ic_state != GENERIC); 1723 ASSERT(ic_state != GENERIC);
1731 1724
1732 bool map_added = 1725 bool map_added =
1733 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map); 1726 AddOneReceiverMapIfMissing(&target_receiver_maps, receiver_map);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
1812 return JSArray::cast(*receiver)->length()->IsSmi() && 1805 return JSArray::cast(*receiver)->length()->IsSmi() &&
1813 index >= Smi::cast(JSArray::cast(*receiver)->length())->value(); 1806 index >= Smi::cast(JSArray::cast(*receiver)->length())->value();
1814 } 1807 }
1815 return index >= receiver->elements()->length(); 1808 return index >= receiver->elements()->length();
1816 } 1809 }
1817 1810
1818 1811
1819 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver, 1812 KeyedAccessStoreMode KeyedStoreIC::GetStoreMode(Handle<JSObject> receiver,
1820 Handle<Object> key, 1813 Handle<Object> key,
1821 Handle<Object> value) { 1814 Handle<Object> value) {
1822 ASSERT(key->IsSmi()); 1815 ASSERT(!key->ToSmi()->IsFailure());
1823 int index = Smi::cast(*key)->value(); 1816 Smi* smi_key = NULL;
1817 key->ToSmi()->To<Smi>(&smi_key);
Jakob Kummerow 2013/03/11 16:36:07 nit: drop the "<Smi>", just "...->To(&smi_key)".
danno 2013/03/13 15:36:26 Done.
1818 int index = smi_key->value();
1824 bool oob_access = IsOutOfBoundsAccess(receiver, index); 1819 bool oob_access = IsOutOfBoundsAccess(receiver, index);
1825 bool allow_growth = receiver->IsJSArray() && oob_access; 1820 bool allow_growth = receiver->IsJSArray() && oob_access;
1826 if (allow_growth) { 1821 if (allow_growth) {
1827 // Handle growing array in stub if necessary. 1822 // Handle growing array in stub if necessary.
1828 if (receiver->HasFastSmiElements()) { 1823 if (receiver->HasFastSmiElements()) {
1829 if (value->IsHeapNumber()) { 1824 if (value->IsHeapNumber()) {
1830 if (receiver->HasFastHoleyElements()) { 1825 if (receiver->HasFastHoleyElements()) {
1831 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE; 1826 return STORE_AND_GROW_TRANSITION_HOLEY_SMI_TO_DOUBLE;
1832 } else { 1827 } else {
1833 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE; 1828 return STORE_AND_GROW_TRANSITION_SMI_TO_DOUBLE;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1871 if (receiver->HasFastHoleyElements()) { 1866 if (receiver->HasFastHoleyElements()) {
1872 return STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT; 1867 return STORE_TRANSITION_HOLEY_DOUBLE_TO_OBJECT;
1873 } else { 1868 } else {
1874 return STORE_TRANSITION_DOUBLE_TO_OBJECT; 1869 return STORE_TRANSITION_DOUBLE_TO_OBJECT;
1875 } 1870 }
1876 } 1871 }
1877 } 1872 }
1878 if (!FLAG_trace_external_array_abuse && 1873 if (!FLAG_trace_external_array_abuse &&
1879 receiver->map()->has_external_array_elements() && oob_access) { 1874 receiver->map()->has_external_array_elements() && oob_access) {
1880 return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS; 1875 return STORE_NO_TRANSITION_IGNORE_OUT_OF_BOUNDS;
1876 }
1877 Heap* heap = receiver->GetHeap();
1878 if (receiver->elements()->map() == heap->fixed_cow_array_map()) {
1879 return STORE_NO_TRANSITION_HANDLE_COW;
1881 } else { 1880 } else {
1882 return STANDARD_STORE; 1881 return STANDARD_STORE;
1883 } 1882 }
1884 } 1883 }
1885 } 1884 }
1886 1885
1887 1886
1888 MaybeObject* KeyedStoreIC::Store(State state, 1887 MaybeObject* KeyedStoreIC::Store(State state,
1889 StrictModeFlag strict_mode, 1888 StrictModeFlag strict_mode,
1890 Handle<Object> object, 1889 Handle<Object> object,
(...skipping 21 matching lines...) Expand all
1912 if (use_ic) { 1911 if (use_ic) {
1913 Handle<Code> stub = (strict_mode == kStrictMode) 1912 Handle<Code> stub = (strict_mode == kStrictMode)
1914 ? generic_stub_strict() 1913 ? generic_stub_strict()
1915 : generic_stub(); 1914 : generic_stub();
1916 if (miss_mode != MISS_FORCE_GENERIC) { 1915 if (miss_mode != MISS_FORCE_GENERIC) {
1917 if (object->IsJSObject()) { 1916 if (object->IsJSObject()) {
1918 Handle<JSObject> receiver = Handle<JSObject>::cast(object); 1917 Handle<JSObject> receiver = Handle<JSObject>::cast(object);
1919 if (receiver->elements()->map() == 1918 if (receiver->elements()->map() ==
1920 isolate()->heap()->non_strict_arguments_elements_map()) { 1919 isolate()->heap()->non_strict_arguments_elements_map()) {
1921 stub = non_strict_arguments_stub(); 1920 stub = non_strict_arguments_stub();
1922 } else if (key->IsSmi() && (target() != *non_strict_arguments_stub())) { 1921 } else if (!key->ToSmi()->IsFailure() &&
1922 (target() != *non_strict_arguments_stub())) {
1923 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value); 1923 KeyedAccessStoreMode store_mode = GetStoreMode(receiver, key, value);
1924 stub = StoreElementStub(receiver, store_mode, strict_mode); 1924 stub = StoreElementStub(receiver, store_mode, strict_mode);
1925 } else {
1926 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "key not a number");
1925 } 1927 }
1928 } else {
1929 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "not an object");
1926 } 1930 }
1927 } else { 1931 } else {
1928 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic"); 1932 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "force generic");
1929 } 1933 }
1930 ASSERT(!stub.is_null()); 1934 ASSERT(!stub.is_null());
1931 set_target(*stub); 1935 set_target(*stub);
1932 TRACE_IC("KeyedStoreIC", key, state, target()); 1936 TRACE_IC("KeyedStoreIC", key, state, target());
1933 } 1937 }
1934 1938
1935 return Runtime::SetObjectProperty( 1939 return Runtime::SetObjectProperty(
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
2073 args.at<Object>(0), 2077 args.at<Object>(0),
2074 args.at<Object>(1), 2078 args.at<Object>(1),
2075 MISS_FORCE_GENERIC); 2079 MISS_FORCE_GENERIC);
2076 } 2080 }
2077 2081
2078 2082
2079 // Used from ic-<arch>.cc. 2083 // Used from ic-<arch>.cc.
2080 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) { 2084 RUNTIME_FUNCTION(MaybeObject*, StoreIC_Miss) {
2081 HandleScope scope(isolate); 2085 HandleScope scope(isolate);
2082 ASSERT(args.length() == 3); 2086 ASSERT(args.length() == 3);
2083 StoreIC ic(isolate); 2087 StoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2084 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2088 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2085 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2089 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2086 return ic.Store(state, 2090 return ic.Store(state,
2087 Code::GetStrictMode(extra_ic_state), 2091 Code::GetStrictMode(extra_ic_state),
2088 args.at<Object>(0), 2092 args.at<Object>(0),
2089 args.at<String>(1), 2093 args.at<String>(1),
2090 args.at<Object>(2)); 2094 args.at<Object>(2));
2091 } 2095 }
2092 2096
2093 2097
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
2149 2153
2150 // Return the stored value. 2154 // Return the stored value.
2151 return value; 2155 return value;
2152 } 2156 }
2153 2157
2154 2158
2155 // Used from ic-<arch>.cc. 2159 // Used from ic-<arch>.cc.
2156 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) { 2160 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Miss) {
2157 HandleScope scope(isolate); 2161 HandleScope scope(isolate);
2158 ASSERT(args.length() == 3); 2162 ASSERT(args.length() == 3);
2159 KeyedStoreIC ic(isolate); 2163 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2160 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2164 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2161 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2165 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2162 return ic.Store(state, 2166 return ic.Store(state,
2167 Code::GetStrictMode(extra_ic_state),
2168 args.at<Object>(0),
2169 args.at<Object>(1),
2170 args.at<Object>(2),
2171 MISS);
2172 }
2173
2174
2175 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissFromStubFailure) {
2176 HandleScope scope(isolate);
2177 ASSERT(args.length() == 3);
2178 KeyedStoreIC ic(IC::EXTRA_CALL_FRAME, isolate);
2179 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2180 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2181 return ic.Store(state,
2163 Code::GetStrictMode(extra_ic_state), 2182 Code::GetStrictMode(extra_ic_state),
2164 args.at<Object>(0), 2183 args.at<Object>(0),
2165 args.at<Object>(1), 2184 args.at<Object>(1),
2166 args.at<Object>(2), 2185 args.at<Object>(2),
2167 MISS); 2186 MISS);
2168 } 2187 }
2169 2188
2170 2189
2171 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) { 2190 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_Slow) {
2172 NoHandleAllocation na(isolate); 2191 NoHandleAllocation na(isolate);
2173 ASSERT(args.length() == 3); 2192 ASSERT(args.length() == 3);
2174 KeyedStoreIC ic(isolate); 2193 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2175 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2194 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2176 Handle<Object> object = args.at<Object>(0); 2195 Handle<Object> object = args.at<Object>(0);
2177 Handle<Object> key = args.at<Object>(1); 2196 Handle<Object> key = args.at<Object>(1);
2178 Handle<Object> value = args.at<Object>(2); 2197 Handle<Object> value = args.at<Object>(2);
2179 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state); 2198 StrictModeFlag strict_mode = Code::GetStrictMode(extra_ic_state);
2180 return Runtime::SetObjectProperty(isolate, 2199 return Runtime::SetObjectProperty(isolate,
2181 object, 2200 object,
2182 key, 2201 key,
2183 value, 2202 value,
2184 NONE, 2203 NONE,
2185 strict_mode); 2204 strict_mode);
2186 } 2205 }
2187 2206
2188 2207
2189 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) { 2208 RUNTIME_FUNCTION(MaybeObject*, KeyedStoreIC_MissForceGeneric) {
2190 HandleScope scope(isolate); 2209 HandleScope scope(isolate);
2191 ASSERT(args.length() == 3); 2210 ASSERT(args.length() == 3);
2192 KeyedStoreIC ic(isolate); 2211 KeyedStoreIC ic(IC::NO_EXTRA_FRAME, isolate);
2193 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]); 2212 IC::State state = IC::StateFrom(ic.target(), args[0], args[1]);
2194 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state(); 2213 Code::ExtraICState extra_ic_state = ic.target()->extra_ic_state();
2195 return ic.Store(state, 2214 return ic.Store(state,
2196 Code::GetStrictMode(extra_ic_state), 2215 Code::GetStrictMode(extra_ic_state),
2197 args.at<Object>(0), 2216 args.at<Object>(0),
2198 args.at<Object>(1), 2217 args.at<Object>(1),
2199 args.at<Object>(2), 2218 args.at<Object>(2),
2200 MISS_FORCE_GENERIC); 2219 MISS_FORCE_GENERIC);
2201 } 2220 }
2202 2221
(...skipping 540 matching lines...) Expand 10 before | Expand all | Expand 10 after
2743 #undef ADDR 2762 #undef ADDR
2744 }; 2763 };
2745 2764
2746 2765
2747 Address IC::AddressFromUtilityId(IC::UtilityId id) { 2766 Address IC::AddressFromUtilityId(IC::UtilityId id) {
2748 return IC_utilities[id]; 2767 return IC_utilities[id];
2749 } 2768 }
2750 2769
2751 2770
2752 } } // namespace v8::internal 2771 } } // namespace v8::internal
OLDNEW
« src/ic.h ('K') | « src/ic.h ('k') | src/runtime.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698