| 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/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 783 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 794 switch (state()) { | 794 switch (state()) { |
| 795 case UNINITIALIZED: | 795 case UNINITIALIZED: |
| 796 case PREMONOMORPHIC: | 796 case PREMONOMORPHIC: |
| 797 UpdateMonomorphicIC(code, name); | 797 UpdateMonomorphicIC(code, name); |
| 798 break; | 798 break; |
| 799 case PROTOTYPE_FAILURE: | 799 case PROTOTYPE_FAILURE: |
| 800 case MONOMORPHIC: | 800 case MONOMORPHIC: |
| 801 case POLYMORPHIC: | 801 case POLYMORPHIC: |
| 802 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { | 802 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { |
| 803 if (UpdatePolymorphicIC(name, code)) break; | 803 if (UpdatePolymorphicIC(name, code)) break; |
| 804 // For keyed stubs, we can't know whether old handlers were for the |
| 805 // same key. |
| 804 CopyICToMegamorphicCache(name); | 806 CopyICToMegamorphicCache(name); |
| 805 } | 807 } |
| 806 set_target(*megamorphic_stub()); | 808 set_target(*megamorphic_stub()); |
| 807 // Fall through. | 809 // Fall through. |
| 808 case MEGAMORPHIC: | 810 case MEGAMORPHIC: |
| 809 UpdateMegamorphicCache(*receiver_type(), *name, *code); | 811 UpdateMegamorphicCache(*receiver_type(), *name, *code); |
| 812 // Indicate that we've handled this case. |
| 813 target_set_ = true; |
| 810 break; | 814 break; |
| 811 case DEBUG_STUB: | 815 case DEBUG_STUB: |
| 812 break; | 816 break; |
| 813 case DEFAULT: | 817 case DEFAULT: |
| 818 UNREACHABLE(); |
| 819 break; |
| 814 case GENERIC: | 820 case GENERIC: |
| 815 UNREACHABLE(); | 821 // The generic keyed store stub re-uses store handlers, which can miss. |
| 822 // That's ok, no reason to do anything. |
| 823 DCHECK(target()->kind() == Code::KEYED_STORE_IC); |
| 816 break; | 824 break; |
| 817 } | 825 } |
| 818 } | 826 } |
| 819 | 827 |
| 820 | 828 |
| 821 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, | 829 Handle<Code> LoadIC::initialize_stub(Isolate* isolate, |
| 822 ExtraICState extra_state) { | 830 ExtraICState extra_state) { |
| 823 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); | 831 return PropertyICCompiler::ComputeLoad(isolate, UNINITIALIZED, extra_state); |
| 824 } | 832 } |
| 825 | 833 |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 887 } else { | 895 } else { |
| 888 code = ComputeHandler(lookup); | 896 code = ComputeHandler(lookup); |
| 889 } | 897 } |
| 890 | 898 |
| 891 PatchCache(lookup->name(), code); | 899 PatchCache(lookup->name(), code); |
| 892 TRACE_IC("LoadIC", lookup->name()); | 900 TRACE_IC("LoadIC", lookup->name()); |
| 893 } | 901 } |
| 894 | 902 |
| 895 | 903 |
| 896 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { | 904 void IC::UpdateMegamorphicCache(HeapType* type, Name* name, Code* code) { |
| 897 if (kind() == Code::KEYED_LOAD_IC || kind() == Code::KEYED_STORE_IC) return; | 905 // Megamorphic state isn't implemented for keyed loads currently. |
| 906 if (kind() == Code::KEYED_LOAD_IC) return; |
| 898 Map* map = *TypeToMap(type, isolate()); | 907 Map* map = *TypeToMap(type, isolate()); |
| 899 isolate()->stub_cache()->Set(name, map, code); | 908 isolate()->stub_cache()->Set(name, map, code); |
| 900 } | 909 } |
| 901 | 910 |
| 902 | 911 |
| 903 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { | 912 Handle<Code> IC::ComputeHandler(LookupIterator* lookup, Handle<Object> value) { |
| 904 bool receiver_is_holder = | 913 bool receiver_is_holder = |
| 905 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); | 914 lookup->GetReceiver().is_identical_to(lookup->GetHolder<JSObject>()); |
| 906 CacheHolderFlag flag; | 915 CacheHolderFlag flag; |
| 907 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( | 916 Handle<Map> stub_holder_map = IC::GetHandlerCacheHolder( |
| (...skipping 450 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 } | 1367 } |
| 1359 | 1368 |
| 1360 | 1369 |
| 1361 Handle<Code> StoreIC::megamorphic_stub() { | 1370 Handle<Code> StoreIC::megamorphic_stub() { |
| 1362 if (kind() == Code::STORE_IC) { | 1371 if (kind() == Code::STORE_IC) { |
| 1363 return PropertyICCompiler::ComputeStore(isolate(), MEGAMORPHIC, | 1372 return PropertyICCompiler::ComputeStore(isolate(), MEGAMORPHIC, |
| 1364 extra_ic_state()); | 1373 extra_ic_state()); |
| 1365 } else { | 1374 } else { |
| 1366 DCHECK(kind() == Code::KEYED_STORE_IC); | 1375 DCHECK(kind() == Code::KEYED_STORE_IC); |
| 1367 if (strict_mode() == STRICT) { | 1376 if (strict_mode() == STRICT) { |
| 1368 return isolate()->builtins()->KeyedStoreIC_Generic_Strict(); | 1377 return isolate()->builtins()->KeyedStoreIC_Megamorphic_Strict(); |
| 1369 } else { | 1378 } else { |
| 1370 return isolate()->builtins()->KeyedStoreIC_Generic(); | 1379 return isolate()->builtins()->KeyedStoreIC_Megamorphic(); |
| 1371 } | 1380 } |
| 1372 } | 1381 } |
| 1373 } | 1382 } |
| 1374 | 1383 |
| 1375 | 1384 |
| 1376 Handle<Code> StoreIC::generic_stub() const { | 1385 Handle<Code> StoreIC::generic_stub() const { |
| 1377 if (kind() == Code::STORE_IC) { | 1386 if (kind() == Code::STORE_IC) { |
| 1378 return PropertyICCompiler::ComputeStore(isolate(), GENERIC, | 1387 return PropertyICCompiler::ComputeStore(isolate(), GENERIC, |
| 1379 extra_ic_state()); | 1388 extra_ic_state()); |
| 1380 } else { | 1389 } else { |
| (...skipping 425 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1806 | 1815 |
| 1807 Handle<Object> store_handle; | 1816 Handle<Object> store_handle; |
| 1808 Handle<Code> stub = generic_stub(); | 1817 Handle<Code> stub = generic_stub(); |
| 1809 | 1818 |
| 1810 if (key->IsInternalizedString()) { | 1819 if (key->IsInternalizedString()) { |
| 1811 ASSIGN_RETURN_ON_EXCEPTION( | 1820 ASSIGN_RETURN_ON_EXCEPTION( |
| 1812 isolate(), store_handle, | 1821 isolate(), store_handle, |
| 1813 StoreIC::Store(object, Handle<String>::cast(key), value, | 1822 StoreIC::Store(object, Handle<String>::cast(key), value, |
| 1814 JSReceiver::MAY_BE_STORE_FROM_KEYED), | 1823 JSReceiver::MAY_BE_STORE_FROM_KEYED), |
| 1815 Object); | 1824 Object); |
| 1816 // TODO(jkummerow): Ideally we'd wrap this in "if (!is_target_set())", | 1825 if (!is_target_set()) { |
| 1817 // but doing so causes Hydrogen crashes. Needs investigation. | 1826 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 1818 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 1827 "unhandled internalized string key"); |
| 1819 "unhandled internalized string key"); | 1828 TRACE_IC("StoreIC", key); |
| 1820 TRACE_IC("StoreIC", key); | 1829 set_target(*stub); |
| 1821 set_target(*stub); | 1830 } |
| 1822 return store_handle; | 1831 return store_handle; |
| 1823 } | 1832 } |
| 1824 | 1833 |
| 1825 bool use_ic = | 1834 bool use_ic = |
| 1826 FLAG_use_ic && !object->IsStringWrapper() && | 1835 FLAG_use_ic && !object->IsStringWrapper() && |
| 1827 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && | 1836 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && |
| 1828 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); | 1837 !(object->IsJSObject() && JSObject::cast(*object)->map()->is_observed()); |
| 1829 if (use_ic && !object->IsSmi()) { | 1838 if (use_ic && !object->IsSmi()) { |
| 1830 // Don't use ICs for maps of the objects in Array's prototype chain. We | 1839 // Don't use ICs for maps of the objects in Array's prototype chain. We |
| 1831 // expect to be able to trap element sets to objects with those maps in | 1840 // expect to be able to trap element sets to objects with those maps in |
| (...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2081 } | 2090 } |
| 2082 | 2091 |
| 2083 | 2092 |
| 2084 // Used from ic-<arch>.cc. | 2093 // Used from ic-<arch>.cc. |
| 2085 RUNTIME_FUNCTION(StoreIC_Miss) { | 2094 RUNTIME_FUNCTION(StoreIC_Miss) { |
| 2086 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2095 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2087 HandleScope scope(isolate); | 2096 HandleScope scope(isolate); |
| 2088 DCHECK(args.length() == 3); | 2097 DCHECK(args.length() == 3); |
| 2089 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); | 2098 StoreIC ic(IC::NO_EXTRA_FRAME, isolate); |
| 2090 Handle<Object> receiver = args.at<Object>(0); | 2099 Handle<Object> receiver = args.at<Object>(0); |
| 2091 Handle<String> key = args.at<String>(1); | 2100 Handle<Name> key = args.at<Name>(1); |
| 2092 ic.UpdateState(receiver, key); | 2101 ic.UpdateState(receiver, key); |
| 2093 Handle<Object> result; | 2102 Handle<Object> result; |
| 2094 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2103 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 2095 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); | 2104 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); |
| 2096 return *result; | 2105 return *result; |
| 2097 } | 2106 } |
| 2098 | 2107 |
| 2099 | 2108 |
| 2100 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { | 2109 RUNTIME_FUNCTION(StoreIC_MissFromStubFailure) { |
| 2101 TimerEventScope<TimerEventIcMiss> timer(isolate); | 2110 TimerEventScope<TimerEventIcMiss> timer(isolate); |
| 2102 HandleScope scope(isolate); | 2111 HandleScope scope(isolate); |
| 2103 DCHECK(args.length() == 3 || args.length() == 4); | 2112 DCHECK(args.length() == 3 || args.length() == 4); |
| 2104 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); | 2113 StoreIC ic(IC::EXTRA_CALL_FRAME, isolate); |
| 2105 Handle<Object> receiver = args.at<Object>(0); | 2114 Handle<Object> receiver = args.at<Object>(0); |
| 2106 Handle<String> key = args.at<String>(1); | 2115 Handle<Name> key = args.at<Name>(1); |
| 2107 ic.UpdateState(receiver, key); | 2116 ic.UpdateState(receiver, key); |
| 2108 Handle<Object> result; | 2117 Handle<Object> result; |
| 2109 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 2118 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( |
| 2110 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); | 2119 isolate, result, ic.Store(receiver, key, args.at<Object>(2))); |
| 2111 return *result; | 2120 return *result; |
| 2112 } | 2121 } |
| 2113 | 2122 |
| 2114 | 2123 |
| 2115 // Used from ic-<arch>.cc. | 2124 // Used from ic-<arch>.cc. |
| 2116 RUNTIME_FUNCTION(KeyedStoreIC_Miss) { | 2125 RUNTIME_FUNCTION(KeyedStoreIC_Miss) { |
| (...skipping 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2664 static const Address IC_utilities[] = { | 2673 static const Address IC_utilities[] = { |
| 2665 #define ADDR(name) FUNCTION_ADDR(name), | 2674 #define ADDR(name) FUNCTION_ADDR(name), |
| 2666 IC_UTIL_LIST(ADDR) NULL | 2675 IC_UTIL_LIST(ADDR) NULL |
| 2667 #undef ADDR | 2676 #undef ADDR |
| 2668 }; | 2677 }; |
| 2669 | 2678 |
| 2670 | 2679 |
| 2671 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } | 2680 Address IC::AddressFromUtilityId(IC::UtilityId id) { return IC_utilities[id]; } |
| 2672 } | 2681 } |
| 2673 } // namespace v8::internal | 2682 } // namespace v8::internal |
| OLD | NEW |