| 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-arguments-inl.h" | 8 #include "src/api-arguments-inl.h" |
| 9 #include "src/api.h" | 9 #include "src/api.h" |
| 10 #include "src/arguments.h" | 10 #include "src/arguments.h" |
| (...skipping 549 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); | 560 LoadICNexus* nexus = casted_nexus<LoadICNexus>(); |
| 561 nexus->ConfigureMonomorphic(map, handler); | 561 nexus->ConfigureMonomorphic(map, handler); |
| 562 } else if (kind() == Code::LOAD_GLOBAL_IC) { | 562 } else if (kind() == Code::LOAD_GLOBAL_IC) { |
| 563 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); | 563 LoadGlobalICNexus* nexus = casted_nexus<LoadGlobalICNexus>(); |
| 564 nexus->ConfigureHandlerMode(Handle<Code>::cast(handler)); | 564 nexus->ConfigureHandlerMode(Handle<Code>::cast(handler)); |
| 565 } else if (kind() == Code::KEYED_LOAD_IC) { | 565 } else if (kind() == Code::KEYED_LOAD_IC) { |
| 566 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); | 566 KeyedLoadICNexus* nexus = casted_nexus<KeyedLoadICNexus>(); |
| 567 nexus->ConfigureMonomorphic(name, map, handler); | 567 nexus->ConfigureMonomorphic(name, map, handler); |
| 568 } else if (kind() == Code::STORE_IC) { | 568 } else if (kind() == Code::STORE_IC) { |
| 569 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); | 569 StoreICNexus* nexus = casted_nexus<StoreICNexus>(); |
| 570 nexus->ConfigureMonomorphic(map, handler); | 570 nexus->ConfigureMonomorphic(map, Handle<Code>::cast(handler)); |
| 571 } else { | 571 } else { |
| 572 DCHECK(kind() == Code::KEYED_STORE_IC); | 572 DCHECK(kind() == Code::KEYED_STORE_IC); |
| 573 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); | 573 KeyedStoreICNexus* nexus = casted_nexus<KeyedStoreICNexus>(); |
| 574 nexus->ConfigureMonomorphic(name, map, handler); | 574 nexus->ConfigureMonomorphic(name, map, Handle<Code>::cast(handler)); |
| 575 } | 575 } |
| 576 | 576 |
| 577 vector_set_ = true; | 577 vector_set_ = true; |
| 578 OnTypeFeedbackChanged(isolate(), get_host()); | 578 OnTypeFeedbackChanged(isolate(), get_host()); |
| 579 } | 579 } |
| 580 | 580 |
| 581 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, | 581 void IC::ConfigureVectorState(Handle<Name> name, MapHandleList* maps, |
| 582 List<Handle<Object>>* handlers) { | 582 List<Handle<Object>>* handlers) { |
| 583 DCHECK(UseVector()); | 583 DCHECK(UseVector()); |
| 584 if (kind() == Code::LOAD_IC) { | 584 if (kind() == Code::LOAD_IC) { |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 MapHandleList map_list; | 783 MapHandleList map_list; |
| 784 map_list.Add(handle(target_map)); | 784 map_list.Add(handle(target_map)); |
| 785 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list); | 785 transitioned_map = source_map->FindElementsKindTransitionedMap(&map_list); |
| 786 } | 786 } |
| 787 return transitioned_map == target_map; | 787 return transitioned_map == target_map; |
| 788 } | 788 } |
| 789 | 789 |
| 790 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { | 790 void IC::PatchCache(Handle<Name> name, Handle<Object> handler) { |
| 791 DCHECK(IsHandler(*handler)); | 791 DCHECK(IsHandler(*handler)); |
| 792 // Currently only LoadIC and KeyedLoadIC support non-code handlers. | 792 // Currently only LoadIC and KeyedLoadIC support non-code handlers. |
| 793 DCHECK_IMPLIES(!handler->IsCode(), kind() == Code::LOAD_IC || | 793 DCHECK_IMPLIES(!handler->IsCode(), |
| 794 kind() == Code::KEYED_LOAD_IC || | 794 kind() == Code::LOAD_IC || kind() == Code::KEYED_LOAD_IC); |
| 795 kind() == Code::STORE_IC || | |
| 796 kind() == Code::KEYED_STORE_IC); | |
| 797 switch (state()) { | 795 switch (state()) { |
| 798 case UNINITIALIZED: | 796 case UNINITIALIZED: |
| 799 case PREMONOMORPHIC: | 797 case PREMONOMORPHIC: |
| 800 UpdateMonomorphicIC(handler, name); | 798 UpdateMonomorphicIC(handler, name); |
| 801 break; | 799 break; |
| 802 case RECOMPUTE_HANDLER: | 800 case RECOMPUTE_HANDLER: |
| 803 case MONOMORPHIC: | 801 case MONOMORPHIC: |
| 804 if (kind() == Code::LOAD_GLOBAL_IC) { | 802 if (kind() == Code::LOAD_GLOBAL_IC) { |
| 805 UpdateMonomorphicIC(handler, name); | 803 UpdateMonomorphicIC(handler, name); |
| 806 break; | 804 break; |
| (...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1005 return isolate()->store_stub_cache(); | 1003 return isolate()->store_stub_cache(); |
| 1006 | 1004 |
| 1007 default: | 1005 default: |
| 1008 break; | 1006 break; |
| 1009 } | 1007 } |
| 1010 UNREACHABLE(); | 1008 UNREACHABLE(); |
| 1011 return nullptr; | 1009 return nullptr; |
| 1012 } | 1010 } |
| 1013 | 1011 |
| 1014 void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) { | 1012 void IC::UpdateMegamorphicCache(Map* map, Name* name, Object* handler) { |
| 1015 if (FLAG_store_ic_smi_handlers && handler->IsSmi() && | |
| 1016 (kind() == Code::STORE_IC || kind() == Code::KEYED_STORE_IC)) { | |
| 1017 // TODO(ishell, jkummerow): Implement data handlers support in | |
| 1018 // KeyedStoreIC_Megamorphic. | |
| 1019 Handle<Map> map_handle(map, isolate()); | |
| 1020 Handle<Name> name_handle(name, isolate()); | |
| 1021 int config = Smi::cast(handler)->value(); | |
| 1022 int value_index = StoreHandler::DescriptorValueIndexBits::decode(config); | |
| 1023 int descriptor = (value_index - DescriptorArray::kDescriptorValue - | |
| 1024 DescriptorArray::kFirstIndex) / | |
| 1025 DescriptorArray::kDescriptorSize; | |
| 1026 | |
| 1027 PropertyDetails details = | |
| 1028 map->instance_descriptors()->GetDetails(descriptor); | |
| 1029 DCHECK_EQ(DATA, details.type()); | |
| 1030 DCHECK_EQ(name, map->instance_descriptors()->GetKey(descriptor)); | |
| 1031 Representation representation = details.representation(); | |
| 1032 FieldIndex index = FieldIndex::ForDescriptor(map, descriptor); | |
| 1033 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub); | |
| 1034 StoreFieldStub stub(isolate(), index, representation); | |
| 1035 Code* handler = *stub.GetCode(); | |
| 1036 stub_cache()->Set(*name_handle, *map_handle, handler); | |
| 1037 return; | |
| 1038 } | |
| 1039 stub_cache()->Set(name, map, handler); | 1013 stub_cache()->Set(name, map, handler); |
| 1040 } | 1014 } |
| 1041 | 1015 |
| 1042 Handle<Object> IC::ComputeHandler(LookupIterator* lookup, | 1016 Handle<Object> IC::ComputeHandler(LookupIterator* lookup, |
| 1043 Handle<Object> value) { | 1017 Handle<Object> value) { |
| 1044 // Try to find a globally shared handler stub. | 1018 // Try to find a globally shared handler stub. |
| 1045 Handle<Object> handler = GetMapIndependentHandler(lookup); | 1019 Handle<Object> handler = GetMapIndependentHandler(lookup); |
| 1046 if (!handler.is_null()) { | 1020 if (!handler.is_null()) { |
| 1047 DCHECK(IC::IsHandler(*handler)); | 1021 DCHECK(IC::IsHandler(*handler)); |
| 1048 return handler; | 1022 return handler; |
| (...skipping 611 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1660 // the pre monomorphic stub to delay setting the monomorphic state. | 1634 // the pre monomorphic stub to delay setting the monomorphic state. |
| 1661 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); | 1635 ConfigureVectorState(PREMONOMORPHIC, Handle<Object>()); |
| 1662 TRACE_IC("StoreIC", lookup->name()); | 1636 TRACE_IC("StoreIC", lookup->name()); |
| 1663 return; | 1637 return; |
| 1664 } | 1638 } |
| 1665 | 1639 |
| 1666 bool use_ic = LookupForWrite(lookup, value, store_mode); | 1640 bool use_ic = LookupForWrite(lookup, value, store_mode); |
| 1667 if (!use_ic) { | 1641 if (!use_ic) { |
| 1668 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); | 1642 TRACE_GENERIC_IC(isolate(), "StoreIC", "LookupForWrite said 'false'"); |
| 1669 } | 1643 } |
| 1670 Handle<Object> handler = use_ic ? ComputeHandler(lookup, value) | 1644 Handle<Code> code = |
| 1671 : Handle<Object>::cast(slow_stub()); | 1645 use_ic ? Handle<Code>::cast(ComputeHandler(lookup, value)) : slow_stub(); |
| 1672 | 1646 |
| 1673 PatchCache(lookup->name(), handler); | 1647 PatchCache(lookup->name(), code); |
| 1674 TRACE_IC("StoreIC", lookup->name()); | 1648 TRACE_IC("StoreIC", lookup->name()); |
| 1675 } | 1649 } |
| 1676 | 1650 |
| 1677 | 1651 |
| 1678 static Handle<Code> PropertyCellStoreHandler( | 1652 static Handle<Code> PropertyCellStoreHandler( |
| 1679 Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder, | 1653 Isolate* isolate, Handle<JSObject> receiver, Handle<JSGlobalObject> holder, |
| 1680 Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) { | 1654 Handle<Name> name, Handle<PropertyCell> cell, PropertyCellType type) { |
| 1681 auto constant_type = Nothing<PropertyCellConstantType>(); | 1655 auto constant_type = Nothing<PropertyCellConstantType>(); |
| 1682 if (type == PropertyCellType::kConstantType) { | 1656 if (type == PropertyCellType::kConstantType) { |
| 1683 constant_type = Just(cell->GetConstantType()); | 1657 constant_type = Just(cell->GetConstantType()); |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1782 if (holder->IsJSGlobalObject()) { | 1756 if (holder->IsJSGlobalObject()) { |
| 1783 break; // Custom-compiled handler. | 1757 break; // Custom-compiled handler. |
| 1784 } | 1758 } |
| 1785 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal); | 1759 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreNormal); |
| 1786 DCHECK(holder.is_identical_to(receiver)); | 1760 DCHECK(holder.is_identical_to(receiver)); |
| 1787 return isolate()->builtins()->StoreIC_Normal(); | 1761 return isolate()->builtins()->StoreIC_Normal(); |
| 1788 } | 1762 } |
| 1789 | 1763 |
| 1790 // -------------- Fields -------------- | 1764 // -------------- Fields -------------- |
| 1791 if (lookup->property_details().type() == DATA) { | 1765 if (lookup->property_details().type() == DATA) { |
| 1792 if (FLAG_store_ic_smi_handlers) { | 1766 bool use_stub = true; |
| 1793 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldDH); | 1767 if (lookup->representation().IsHeapObject()) { |
| 1794 int descriptor = lookup->GetFieldDescriptorIndex(); | 1768 // Only use a generic stub if no types need to be tracked. |
| 1795 FieldIndex index = lookup->GetFieldIndex(); | 1769 Handle<FieldType> field_type = lookup->GetFieldType(); |
| 1796 return StoreHandler::StoreField(isolate(), descriptor, index, | 1770 use_stub = !field_type->IsClass(); |
| 1797 lookup->representation()); | 1771 } |
| 1798 } else { | 1772 if (use_stub) { |
| 1799 bool use_stub = true; | 1773 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub); |
| 1800 if (lookup->representation().IsHeapObject()) { | 1774 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), |
| 1801 // Only use a generic stub if no types need to be tracked. | 1775 lookup->representation()); |
| 1802 Handle<FieldType> field_type = lookup->GetFieldType(); | 1776 return stub.GetCode(); |
| 1803 use_stub = !field_type->IsClass(); | |
| 1804 } | |
| 1805 if (use_stub) { | |
| 1806 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreFieldStub); | |
| 1807 StoreFieldStub stub(isolate(), lookup->GetFieldIndex(), | |
| 1808 lookup->representation()); | |
| 1809 return stub.GetCode(); | |
| 1810 } | |
| 1811 } | 1777 } |
| 1812 break; // Custom-compiled handler. | 1778 break; // Custom-compiled handler. |
| 1813 } | 1779 } |
| 1814 | 1780 |
| 1815 // -------------- Constant properties -------------- | 1781 // -------------- Constant properties -------------- |
| 1816 DCHECK(lookup->property_details().type() == DATA_CONSTANT); | 1782 DCHECK(lookup->property_details().type() == DATA_CONSTANT); |
| 1817 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); | 1783 TRACE_GENERIC_IC(isolate(), "StoreIC", "constant property"); |
| 1818 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); | 1784 TRACE_HANDLER_STATS(isolate(), StoreIC_SlowStub); |
| 1819 return slow_stub(); | 1785 return slow_stub(); |
| 1820 } | 1786 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1918 isolate(), receiver, Handle<JSGlobalObject>::cast(holder), | 1884 isolate(), receiver, Handle<JSGlobalObject>::cast(holder), |
| 1919 lookup->name(), cell, updated_type); | 1885 lookup->name(), cell, updated_type); |
| 1920 return code; | 1886 return code; |
| 1921 } | 1887 } |
| 1922 | 1888 |
| 1923 // -------------- Fields -------------- | 1889 // -------------- Fields -------------- |
| 1924 if (lookup->property_details().type() == DATA) { | 1890 if (lookup->property_details().type() == DATA) { |
| 1925 #ifdef DEBUG | 1891 #ifdef DEBUG |
| 1926 bool use_stub = true; | 1892 bool use_stub = true; |
| 1927 if (lookup->representation().IsHeapObject()) { | 1893 if (lookup->representation().IsHeapObject()) { |
| 1928 DCHECK(!FLAG_store_ic_smi_handlers); | |
| 1929 // Only use a generic stub if no types need to be tracked. | 1894 // Only use a generic stub if no types need to be tracked. |
| 1930 Handle<FieldType> field_type = lookup->GetFieldType(); | 1895 Handle<FieldType> field_type = lookup->GetFieldType(); |
| 1931 use_stub = !field_type->IsClass(); | 1896 use_stub = !field_type->IsClass(); |
| 1932 } | 1897 } |
| 1933 DCHECK(!use_stub); | 1898 DCHECK(!use_stub); |
| 1934 #endif | 1899 #endif |
| 1935 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField); | 1900 TRACE_HANDLER_STATS(isolate(), StoreIC_StoreField); |
| 1936 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); | 1901 NamedStoreHandlerCompiler compiler(isolate(), receiver_map(), holder); |
| 1937 return compiler.CompileStoreField(lookup); | 1902 return compiler.CompileStoreField(lookup); |
| 1938 } | 1903 } |
| (...skipping 1061 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3000 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); | 2965 DCHECK_EQ(LookupIterator::INTERCEPTOR, it.state()); |
| 3001 it.Next(); | 2966 it.Next(); |
| 3002 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, | 2967 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, result, |
| 3003 Object::GetProperty(&it)); | 2968 Object::GetProperty(&it)); |
| 3004 } | 2969 } |
| 3005 | 2970 |
| 3006 return *result; | 2971 return *result; |
| 3007 } | 2972 } |
| 3008 } // namespace internal | 2973 } // namespace internal |
| 3009 } // namespace v8 | 2974 } // namespace v8 |
| OLD | NEW |