| 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/api-arguments.h" | 9 #include "src/api-arguments.h" |
| 10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
| (...skipping 555 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 566 | 566 |
| 567 | 567 |
| 568 static bool MigrateDeprecated(Handle<Object> object) { | 568 static bool MigrateDeprecated(Handle<Object> object) { |
| 569 if (!object->IsJSObject()) return false; | 569 if (!object->IsJSObject()) return false; |
| 570 Handle<JSObject> receiver = Handle<JSObject>::cast(object); | 570 Handle<JSObject> receiver = Handle<JSObject>::cast(object); |
| 571 if (!receiver->map()->is_deprecated()) return false; | 571 if (!receiver->map()->is_deprecated()) return false; |
| 572 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); | 572 JSObject::MigrateInstance(Handle<JSObject>::cast(object)); |
| 573 return true; | 573 return true; |
| 574 } | 574 } |
| 575 | 575 |
| 576 | 576 void IC::ConfigureVectorState(IC::State new_state, Handle<Object> key) { |
| 577 void IC::ConfigureVectorState(IC::State new_state) { | |
| 578 DCHECK(UseVector()); | 577 DCHECK(UseVector()); |
| 579 if (new_state == PREMONOMORPHIC) { | 578 if (new_state == PREMONOMORPHIC) { |
| 580 nexus()->ConfigurePremonomorphic(); | 579 nexus()->ConfigurePremonomorphic(); |
| 581 } else if (new_state == MEGAMORPHIC) { | 580 } else if (new_state == MEGAMORPHIC) { |
| 582 nexus()->ConfigureMegamorphic(); | 581 if (kind() == Code::LOAD_IC || kind() == Code::STORE_IC) { |
| 582 nexus()->ConfigureMegamorphic(); |
| 583 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 584 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 585 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); |
| 586 } else { |
| 587 DCHECK(kind() == Code::KEYED_STORE_IC); |
| 588 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
| 589 nexus->ConfigureMegamorphicKeyed(key->IsName() ? PROPERTY : ELEMENT); |
| 590 } |
| 583 } else { | 591 } else { |
| 584 UNREACHABLE(); | 592 UNREACHABLE(); |
| 585 } | 593 } |
| 586 | 594 |
| 587 vector_set_ = true; | 595 vector_set_ = true; |
| 588 OnTypeFeedbackChanged(isolate(), get_host()); | 596 OnTypeFeedbackChanged(isolate(), get_host()); |
| 589 } | 597 } |
| 590 | 598 |
| 591 | 599 |
| 592 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, | 600 void IC::ConfigureVectorState(Handle<Name> name, Handle<Map> map, |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name); | 663 return TypeError(MessageTemplate::kNonObjectPropertyLoad, object, name); |
| 656 } | 664 } |
| 657 | 665 |
| 658 // Check if the name is trivially convertible to an index and get | 666 // Check if the name is trivially convertible to an index and get |
| 659 // the element or char if so. | 667 // the element or char if so. |
| 660 uint32_t index; | 668 uint32_t index; |
| 661 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { | 669 if (kind() == Code::KEYED_LOAD_IC && name->AsArrayIndex(&index)) { |
| 662 // Rewrite to the generic keyed load stub. | 670 // Rewrite to the generic keyed load stub. |
| 663 if (FLAG_use_ic) { | 671 if (FLAG_use_ic) { |
| 664 DCHECK(UseVector()); | 672 DCHECK(UseVector()); |
| 665 ConfigureVectorState(MEGAMORPHIC); | 673 ConfigureVectorState(MEGAMORPHIC, name); |
| 666 TRACE_IC("LoadIC", name); | 674 TRACE_IC("LoadIC", name); |
| 667 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); | 675 TRACE_GENERIC_IC(isolate(), "LoadIC", "name as array index"); |
| 668 } | 676 } |
| 669 Handle<Object> result; | 677 Handle<Object> result; |
| 670 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, | 678 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
| 671 Object::GetElement(isolate(), object, index), | 679 Object::GetElement(isolate(), object, index), |
| 672 Object); | 680 Object); |
| 673 return result; | 681 return result; |
| 674 } | 682 } |
| 675 | 683 |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 846 case PROTOTYPE_FAILURE: | 854 case PROTOTYPE_FAILURE: |
| 847 case MONOMORPHIC: | 855 case MONOMORPHIC: |
| 848 case POLYMORPHIC: | 856 case POLYMORPHIC: |
| 849 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { | 857 if (!target()->is_keyed_stub() || state() == PROTOTYPE_FAILURE) { |
| 850 if (UpdatePolymorphicIC(name, code)) break; | 858 if (UpdatePolymorphicIC(name, code)) break; |
| 851 // For keyed stubs, we can't know whether old handlers were for the | 859 // For keyed stubs, we can't know whether old handlers were for the |
| 852 // same key. | 860 // same key. |
| 853 CopyICToMegamorphicCache(name); | 861 CopyICToMegamorphicCache(name); |
| 854 } | 862 } |
| 855 if (UseVector()) { | 863 if (UseVector()) { |
| 856 ConfigureVectorState(MEGAMORPHIC); | 864 ConfigureVectorState(MEGAMORPHIC, name); |
| 857 } else { | 865 } else { |
| 858 set_target(*megamorphic_stub()); | 866 set_target(*megamorphic_stub()); |
| 859 } | 867 } |
| 860 // Fall through. | 868 // Fall through. |
| 861 case MEGAMORPHIC: | 869 case MEGAMORPHIC: |
| 862 UpdateMegamorphicCache(*receiver_map(), *name, *code); | 870 UpdateMegamorphicCache(*receiver_map(), *name, *code); |
| 863 // Indicate that we've handled this case. | 871 // Indicate that we've handled this case. |
| 864 if (UseVector()) { | 872 if (UseVector()) { |
| 865 vector_set_ = true; | 873 vector_set_ = true; |
| 866 } else { | 874 } else { |
| (...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 } | 1013 } |
| 1006 } | 1014 } |
| 1007 return true; | 1015 return true; |
| 1008 } | 1016 } |
| 1009 | 1017 |
| 1010 | 1018 |
| 1011 void LoadIC::UpdateCaches(LookupIterator* lookup) { | 1019 void LoadIC::UpdateCaches(LookupIterator* lookup) { |
| 1012 if (state() == UNINITIALIZED) { | 1020 if (state() == UNINITIALIZED) { |
| 1013 // This is the first time we execute this inline cache. Set the target to | 1021 // This is the first time we execute this inline cache. Set the target to |
| 1014 // the pre monomorphic stub to delay setting the monomorphic state. | 1022 // the pre monomorphic stub to delay setting the monomorphic state. |
| 1015 ConfigureVectorState(PREMONOMORPHIC); | 1023 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
| 1016 TRACE_IC("LoadIC", lookup->name()); | 1024 TRACE_IC("LoadIC", lookup->name()); |
| 1017 return; | 1025 return; |
| 1018 } | 1026 } |
| 1019 | 1027 |
| 1020 Handle<Code> code; | 1028 Handle<Code> code; |
| 1021 if (lookup->state() == LookupIterator::JSPROXY || | 1029 if (lookup->state() == LookupIterator::JSPROXY || |
| 1022 lookup->state() == LookupIterator::ACCESS_CHECK) { | 1030 lookup->state() == LookupIterator::ACCESS_CHECK) { |
| 1023 code = slow_stub(); | 1031 code = slow_stub(); |
| 1024 } else if (!lookup->IsFound()) { | 1032 } else if (!lookup->IsFound()) { |
| 1025 if (kind() == Code::LOAD_IC) { | 1033 if (kind() == Code::LOAD_IC) { |
| (...skipping 352 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1378 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { | 1386 if (object->IsJSObject() || (object->IsString() && key->IsNumber())) { |
| 1379 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); | 1387 Handle<HeapObject> receiver = Handle<HeapObject>::cast(object); |
| 1380 if (object->IsString() || key->IsSmi()) stub = LoadElementStub(receiver); | 1388 if (object->IsString() || key->IsSmi()) stub = LoadElementStub(receiver); |
| 1381 } | 1389 } |
| 1382 } | 1390 } |
| 1383 | 1391 |
| 1384 DCHECK(UseVector()); | 1392 DCHECK(UseVector()); |
| 1385 if (!is_vector_set() || stub.is_null()) { | 1393 if (!is_vector_set() || stub.is_null()) { |
| 1386 Code* generic = *megamorphic_stub(); | 1394 Code* generic = *megamorphic_stub(); |
| 1387 if (!stub.is_null() && *stub == generic) { | 1395 if (!stub.is_null() && *stub == generic) { |
| 1388 ConfigureVectorState(MEGAMORPHIC); | 1396 ConfigureVectorState(MEGAMORPHIC, key); |
| 1389 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); | 1397 TRACE_GENERIC_IC(isolate(), "KeyedLoadIC", "set generic"); |
| 1390 } | 1398 } |
| 1391 | 1399 |
| 1392 TRACE_IC("LoadIC", key); | 1400 TRACE_IC("LoadIC", key); |
| 1393 } | 1401 } |
| 1394 | 1402 |
| 1395 if (!load_handle.is_null()) return load_handle; | 1403 if (!load_handle.is_null()) return load_handle; |
| 1396 | 1404 |
| 1397 Handle<Object> result; | 1405 Handle<Object> result; |
| 1398 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, | 1406 ASSIGN_RETURN_ON_EXCEPTION(isolate(), result, |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1472 | 1480 |
| 1473 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, | 1481 MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name, |
| 1474 Handle<Object> value, | 1482 Handle<Object> value, |
| 1475 JSReceiver::StoreFromKeyed store_mode) { | 1483 JSReceiver::StoreFromKeyed store_mode) { |
| 1476 // Check if the name is trivially convertible to an index and set the element. | 1484 // Check if the name is trivially convertible to an index and set the element. |
| 1477 uint32_t index; | 1485 uint32_t index; |
| 1478 if (kind() == Code::KEYED_STORE_IC && name->AsArrayIndex(&index)) { | 1486 if (kind() == Code::KEYED_STORE_IC && name->AsArrayIndex(&index)) { |
| 1479 // Rewrite to the generic keyed store stub. | 1487 // Rewrite to the generic keyed store stub. |
| 1480 if (FLAG_use_ic) { | 1488 if (FLAG_use_ic) { |
| 1481 if (UseVector()) { | 1489 if (UseVector()) { |
| 1482 ConfigureVectorState(MEGAMORPHIC); | 1490 ConfigureVectorState(MEGAMORPHIC, name); |
| 1483 } else if (!AddressIsDeoptimizedCode()) { | 1491 } else if (!AddressIsDeoptimizedCode()) { |
| 1484 set_target(*megamorphic_stub()); | 1492 set_target(*megamorphic_stub()); |
| 1485 } | 1493 } |
| 1486 TRACE_IC("StoreIC", name); | 1494 TRACE_IC("StoreIC", name); |
| 1487 TRACE_GENERIC_IC(isolate(), "StoreIC", "name as array index"); | 1495 TRACE_GENERIC_IC(isolate(), "StoreIC", "name as array index"); |
| 1488 } | 1496 } |
| 1489 Handle<Object> result; | 1497 Handle<Object> result; |
| 1490 ASSIGN_RETURN_ON_EXCEPTION( | 1498 ASSIGN_RETURN_ON_EXCEPTION( |
| 1491 isolate(), result, | 1499 isolate(), result, |
| 1492 Object::SetElement(isolate(), object, index, value, language_mode()), | 1500 Object::SetElement(isolate(), object, index, value, language_mode()), |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1646 ExtraICState state = ComputeExtraICState(language_mode); | 1654 ExtraICState state = ComputeExtraICState(language_mode); |
| 1647 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); | 1655 return PropertyICCompiler::ComputeStore(isolate, PREMONOMORPHIC, state); |
| 1648 } | 1656 } |
| 1649 | 1657 |
| 1650 | 1658 |
| 1651 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, | 1659 void StoreIC::UpdateCaches(LookupIterator* lookup, Handle<Object> value, |
| 1652 JSReceiver::StoreFromKeyed store_mode) { | 1660 JSReceiver::StoreFromKeyed store_mode) { |
| 1653 if (state() == UNINITIALIZED) { | 1661 if (state() == UNINITIALIZED) { |
| 1654 // This is the first time we execute this inline cache. Set the target to | 1662 // This is the first time we execute this inline cache. Set the target to |
| 1655 // the pre monomorphic stub to delay setting the monomorphic state. | 1663 // the pre monomorphic stub to delay setting the monomorphic state. |
| 1656 ConfigureVectorState(PREMONOMORPHIC); | 1664 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
| 1657 TRACE_IC("StoreIC", lookup->name()); | 1665 TRACE_IC("StoreIC", lookup->name()); |
| 1658 return; | 1666 return; |
| 1659 } | 1667 } |
| 1660 | 1668 |
| 1661 bool use_ic = LookupForWrite(lookup, value, store_mode); | 1669 bool use_ic = LookupForWrite(lookup, value, store_mode); |
| 1662 if (!use_ic) { | 1670 if (!use_ic) { |
| 1663 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); | 1671 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); |
| 1664 } | 1672 } |
| 1665 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); | 1673 Handle<Code> code = use_ic ? ComputeHandler(lookup, value) : slow_stub(); |
| 1666 | 1674 |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2072 uint32_t index; | 2080 uint32_t index; |
| 2073 if ((key->IsInternalizedString() && | 2081 if ((key->IsInternalizedString() && |
| 2074 !String::cast(*key)->AsArrayIndex(&index)) || | 2082 !String::cast(*key)->AsArrayIndex(&index)) || |
| 2075 key->IsSymbol()) { | 2083 key->IsSymbol()) { |
| 2076 ASSIGN_RETURN_ON_EXCEPTION( | 2084 ASSIGN_RETURN_ON_EXCEPTION( |
| 2077 isolate(), store_handle, | 2085 isolate(), store_handle, |
| 2078 StoreIC::Store(object, Handle<Name>::cast(key), value, | 2086 StoreIC::Store(object, Handle<Name>::cast(key), value, |
| 2079 JSReceiver::MAY_BE_STORE_FROM_KEYED), | 2087 JSReceiver::MAY_BE_STORE_FROM_KEYED), |
| 2080 Object); | 2088 Object); |
| 2081 if (!is_vector_set()) { | 2089 if (!is_vector_set()) { |
| 2082 ConfigureVectorState(MEGAMORPHIC); | 2090 ConfigureVectorState(MEGAMORPHIC, key); |
| 2083 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 2091 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 2084 "unhandled internalized string key"); | 2092 "unhandled internalized string key"); |
| 2085 TRACE_IC("StoreIC", key); | 2093 TRACE_IC("StoreIC", key); |
| 2086 } | 2094 } |
| 2087 return store_handle; | 2095 return store_handle; |
| 2088 } | 2096 } |
| 2089 | 2097 |
| 2090 bool use_ic = | 2098 bool use_ic = |
| 2091 FLAG_use_ic && !object->IsStringWrapper() && | 2099 FLAG_use_ic && !object->IsStringWrapper() && |
| 2092 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && | 2100 !object->IsAccessCheckNeeded() && !object->IsJSGlobalProxy() && |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2147 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); | 2155 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-smi-like key"); |
| 2148 } | 2156 } |
| 2149 } else { | 2157 } else { |
| 2150 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); | 2158 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", "non-JSObject receiver"); |
| 2151 } | 2159 } |
| 2152 } | 2160 } |
| 2153 | 2161 |
| 2154 if (!is_vector_set() || stub.is_null()) { | 2162 if (!is_vector_set() || stub.is_null()) { |
| 2155 Code* megamorphic = *megamorphic_stub(); | 2163 Code* megamorphic = *megamorphic_stub(); |
| 2156 if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { | 2164 if (!stub.is_null() && (*stub == megamorphic || *stub == *slow_stub())) { |
| 2157 ConfigureVectorState(MEGAMORPHIC); | 2165 ConfigureVectorState(MEGAMORPHIC, key); |
| 2158 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", | 2166 TRACE_GENERIC_IC(isolate(), "KeyedStoreIC", |
| 2159 *stub == megamorphic ? "set generic" : "slow stub"); | 2167 *stub == megamorphic ? "set generic" : "slow stub"); |
| 2160 } | 2168 } |
| 2161 } | 2169 } |
| 2162 TRACE_IC("StoreIC", key); | 2170 TRACE_IC("StoreIC", key); |
| 2163 | 2171 |
| 2164 return store_handle; | 2172 return store_handle; |
| 2165 } | 2173 } |
| 2166 | 2174 |
| 2167 | 2175 |
| (...skipping 790 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2958 KeyedLoadICNexus nexus(vector, vector_slot); | 2966 KeyedLoadICNexus nexus(vector, vector_slot); |
| 2959 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); | 2967 KeyedLoadIC ic(IC::EXTRA_CALL_FRAME, isolate, &nexus); |
| 2960 ic.UpdateState(receiver, key); | 2968 ic.UpdateState(receiver, key); |
| 2961 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); | 2969 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, ic.Load(receiver, key)); |
| 2962 } | 2970 } |
| 2963 | 2971 |
| 2964 return *result; | 2972 return *result; |
| 2965 } | 2973 } |
| 2966 } // namespace internal | 2974 } // namespace internal |
| 2967 } // namespace v8 | 2975 } // namespace v8 |
| OLD | NEW |