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 |