| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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/accessor-assembler.h" | 5 #include "src/ic/accessor-assembler.h" |
| 6 | 6 |
| 7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
| 8 #include "src/code-stubs.h" | 8 #include "src/code-stubs.h" |
| 9 #include "src/counters.h" | 9 #include "src/counters.h" |
| 10 #include "src/ic/handler-configuration.h" | 10 #include "src/ic/handler-configuration.h" |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 138 // The loop falls through if no handler was found. | 138 // The loop falls through if no handler was found. |
| 139 Goto(if_miss); | 139 Goto(if_miss); |
| 140 } | 140 } |
| 141 | 141 |
| 142 void AccessorAssembler::HandleLoadICHandlerCase( | 142 void AccessorAssembler::HandleLoadICHandlerCase( |
| 143 const LoadICParameters* p, Node* handler, Label* miss, | 143 const LoadICParameters* p, Node* handler, Label* miss, |
| 144 ElementSupport support_elements) { | 144 ElementSupport support_elements) { |
| 145 Comment("have_handler"); | 145 Comment("have_handler"); |
| 146 ExitPoint direct_exit(this); | 146 ExitPoint direct_exit(this); |
| 147 | 147 |
| 148 Variable var_holder(this, MachineRepresentation::kTagged); | 148 Variable var_holder(this, MachineRepresentation::kTagged, p->receiver); |
| 149 var_holder.Bind(p->receiver); | 149 Variable var_smi_handler(this, MachineRepresentation::kTagged, handler); |
| 150 Variable var_smi_handler(this, MachineRepresentation::kTagged); | |
| 151 var_smi_handler.Bind(handler); | |
| 152 | 150 |
| 153 Variable* vars[] = {&var_holder, &var_smi_handler}; | 151 Variable* vars[] = {&var_holder, &var_smi_handler}; |
| 154 Label if_smi_handler(this, 2, vars); | 152 Label if_smi_handler(this, 2, vars); |
| 155 Label try_proto_handler(this), call_handler(this); | 153 Label try_proto_handler(this, Label::kDeferred), |
| 154 call_handler(this, Label::kDeferred); |
| 156 | 155 |
| 157 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); | 156 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); |
| 158 | 157 |
| 159 // |handler| is a Smi, encoding what to do. See SmiHandler methods | 158 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
| 160 // for the encoding format. | 159 // for the encoding format. |
| 161 Bind(&if_smi_handler); | 160 Bind(&if_smi_handler); |
| 162 { | 161 { |
| 163 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), | 162 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), |
| 164 miss, &direct_exit, support_elements); | 163 miss, &direct_exit, support_elements); |
| 165 } | 164 } |
| (...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), | 266 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), |
| 268 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), | 267 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), |
| 269 miss); | 268 miss); |
| 270 exit_point->Return(UndefinedConstant()); | 269 exit_point->Return(UndefinedConstant()); |
| 271 } | 270 } |
| 272 | 271 |
| 273 Bind(&property); | 272 Bind(&property); |
| 274 Comment("property_load"); | 273 Comment("property_load"); |
| 275 } | 274 } |
| 276 | 275 |
| 277 Label constant(this), field(this), normal(this); | 276 Label constant(this, Label::kDeferred), field(this), |
| 277 normal(this, Label::kDeferred); |
| 278 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), | 278 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), |
| 279 &field); | 279 &field); |
| 280 | 280 |
| 281 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForConstants)), | 281 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForConstants)), |
| 282 &constant, &normal); | 282 &constant, &normal); |
| 283 | 283 |
| 284 Bind(&field); | 284 Bind(&field); |
| 285 HandleLoadField(holder, handler_word, &var_double_value, &rebox_double, | 285 HandleLoadField(holder, handler_word, &var_double_value, &rebox_double, |
| 286 exit_point); | 286 exit_point); |
| 287 | 287 |
| 288 Bind(&constant); | 288 Bind(&constant); |
| 289 { | 289 { |
| 290 Comment("constant_load"); | 290 Comment("constant_load"); |
| 291 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); | 291 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); |
| 292 Node* descriptor = DecodeWord<LoadHandler::DescriptorBits>(handler_word); | 292 Node* descriptor = DecodeWord<LoadHandler::DescriptorBits>(handler_word); |
| 293 Node* scaled_descriptor = | 293 Node* scaled_descriptor = |
| 294 IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize)); | 294 IntPtrMul(descriptor, IntPtrConstant(DescriptorArray::kEntrySize)); |
| 295 Node* value_index = | 295 Node* value_index = |
| 296 IntPtrAdd(scaled_descriptor, | 296 IntPtrAdd(scaled_descriptor, |
| 297 IntPtrConstant(DescriptorArray::kFirstIndex + | 297 IntPtrConstant(DescriptorArray::kFirstIndex + |
| 298 DescriptorArray::kEntryValueIndex)); | 298 DescriptorArray::kEntryValueIndex)); |
| 299 CSA_ASSERT(this, | 299 CSA_ASSERT(this, |
| 300 UintPtrLessThan(descriptor, | 300 UintPtrLessThan(descriptor, |
| 301 LoadAndUntagFixedArrayBaseLength(descriptors))); | 301 LoadAndUntagFixedArrayBaseLength(descriptors))); |
| 302 Node* value = LoadFixedArrayElement(descriptors, value_index); | 302 Node* value = LoadFixedArrayElement(descriptors, value_index); |
| 303 | 303 |
| 304 Label if_accessor_info(this); | 304 Label if_accessor_info(this, Label::kDeferred); |
| 305 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), | 305 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), |
| 306 &if_accessor_info); | 306 &if_accessor_info); |
| 307 exit_point->Return(value); | 307 exit_point->Return(value); |
| 308 | 308 |
| 309 Bind(&if_accessor_info); | 309 Bind(&if_accessor_info); |
| 310 Callable callable = CodeFactory::ApiGetter(isolate()); | 310 Callable callable = CodeFactory::ApiGetter(isolate()); |
| 311 exit_point->ReturnCallStub(callable, p->context, p->receiver, holder, | 311 exit_point->ReturnCallStub(callable, p->context, p->receiver, holder, |
| 312 value); | 312 value); |
| 313 } | 313 } |
| 314 | 314 |
| (...skipping 1217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1532 { | 1532 { |
| 1533 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 1533 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
| 1534 Goto(if_miss); | 1534 Goto(if_miss); |
| 1535 } | 1535 } |
| 1536 } | 1536 } |
| 1537 | 1537 |
| 1538 //////////////////// Entry points into private implementation (one per stub). | 1538 //////////////////// Entry points into private implementation (one per stub). |
| 1539 | 1539 |
| 1540 void AccessorAssembler::LoadIC(const LoadICParameters* p) { | 1540 void AccessorAssembler::LoadIC(const LoadICParameters* p) { |
| 1541 Variable var_handler(this, MachineRepresentation::kTagged); | 1541 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1542 // TODO(ishell): defer blocks when it works. | 1542 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), |
| 1543 Label if_handler(this, &var_handler), try_polymorphic(this), | 1543 try_megamorphic(this, Label::kDeferred), |
| 1544 try_megamorphic(this /*, Label::kDeferred*/), | 1544 try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred); |
| 1545 try_uninitialized(this /*, Label::kDeferred*/), | |
| 1546 miss(this /*, Label::kDeferred*/); | |
| 1547 | 1545 |
| 1548 Node* receiver_map = LoadReceiverMap(p->receiver); | 1546 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1549 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1547 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); |
| 1550 | 1548 |
| 1551 // Check monomorphic case. | 1549 // Check monomorphic case. |
| 1552 Node* feedback = | 1550 Node* feedback = |
| 1553 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1551 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1554 &var_handler, &try_polymorphic); | 1552 &var_handler, &try_polymorphic); |
| 1555 Bind(&if_handler); | 1553 Bind(&if_handler); |
| 1556 { HandleLoadICHandlerCase(p, var_handler.value(), &miss); } | 1554 { HandleLoadICHandlerCase(p, var_handler.value(), &miss); } |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1738 | 1736 |
| 1739 Bind(&try_handler); | 1737 Bind(&try_handler); |
| 1740 LoadGlobalIC_TryHandlerCase(p, typeof_mode, &direct_exit, &miss); | 1738 LoadGlobalIC_TryHandlerCase(p, typeof_mode, &direct_exit, &miss); |
| 1741 | 1739 |
| 1742 Bind(&miss); | 1740 Bind(&miss); |
| 1743 LoadGlobalIC_MissCase(p, &direct_exit); | 1741 LoadGlobalIC_MissCase(p, &direct_exit); |
| 1744 } | 1742 } |
| 1745 | 1743 |
| 1746 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { | 1744 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { |
| 1747 Variable var_handler(this, MachineRepresentation::kTagged); | 1745 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1748 // TODO(ishell): defer blocks when it works. | 1746 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), |
| 1749 Label if_handler(this, &var_handler), try_polymorphic(this), | 1747 try_megamorphic(this, Label::kDeferred), |
| 1750 try_megamorphic(this /*, Label::kDeferred*/), | 1748 try_polymorphic_name(this, Label::kDeferred), |
| 1751 try_polymorphic_name(this /*, Label::kDeferred*/), | 1749 miss(this, Label::kDeferred); |
| 1752 miss(this /*, Label::kDeferred*/); | |
| 1753 | 1750 |
| 1754 Node* receiver_map = LoadReceiverMap(p->receiver); | 1751 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1755 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1752 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); |
| 1756 | 1753 |
| 1757 // Check monomorphic case. | 1754 // Check monomorphic case. |
| 1758 Node* feedback = | 1755 Node* feedback = |
| 1759 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1756 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1760 &var_handler, &try_polymorphic); | 1757 &var_handler, &try_polymorphic); |
| 1761 Bind(&if_handler); | 1758 Bind(&if_handler); |
| 1762 { HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements); } | 1759 { HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements); } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1834 Comment("KeyedLoadGeneric_slow"); | 1831 Comment("KeyedLoadGeneric_slow"); |
| 1835 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); | 1832 IncrementCounter(isolate()->counters()->ic_keyed_load_generic_slow(), 1); |
| 1836 // TODO(jkummerow): Should we use the GetProperty TF stub instead? | 1833 // TODO(jkummerow): Should we use the GetProperty TF stub instead? |
| 1837 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, | 1834 TailCallRuntime(Runtime::kKeyedGetProperty, p->context, p->receiver, |
| 1838 p->name); | 1835 p->name); |
| 1839 } | 1836 } |
| 1840 } | 1837 } |
| 1841 | 1838 |
| 1842 void AccessorAssembler::StoreIC(const StoreICParameters* p) { | 1839 void AccessorAssembler::StoreIC(const StoreICParameters* p) { |
| 1843 Variable var_handler(this, MachineRepresentation::kTagged); | 1840 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1844 // TODO(ishell): defer blocks when it works. | 1841 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), |
| 1845 Label if_handler(this, &var_handler), try_polymorphic(this), | 1842 try_megamorphic(this, Label::kDeferred), miss(this, Label::kDeferred); |
| 1846 try_megamorphic(this /*, Label::kDeferred*/), | |
| 1847 miss(this /*, Label::kDeferred*/); | |
| 1848 | 1843 |
| 1849 Node* receiver_map = LoadReceiverMap(p->receiver); | 1844 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1850 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1845 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); |
| 1851 | 1846 |
| 1852 // Check monomorphic case. | 1847 // Check monomorphic case. |
| 1853 Node* feedback = | 1848 Node* feedback = |
| 1854 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1849 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1855 &var_handler, &try_polymorphic); | 1850 &var_handler, &try_polymorphic); |
| 1856 Bind(&if_handler); | 1851 Bind(&if_handler); |
| 1857 { | 1852 { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1881 } | 1876 } |
| 1882 Bind(&miss); | 1877 Bind(&miss); |
| 1883 { | 1878 { |
| 1884 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, | 1879 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, |
| 1885 p->vector, p->receiver, p->name); | 1880 p->vector, p->receiver, p->name); |
| 1886 } | 1881 } |
| 1887 } | 1882 } |
| 1888 | 1883 |
| 1889 void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p, | 1884 void AccessorAssembler::KeyedStoreIC(const StoreICParameters* p, |
| 1890 LanguageMode language_mode) { | 1885 LanguageMode language_mode) { |
| 1891 // TODO(ishell): defer blocks when it works. | 1886 Label miss(this, Label::kDeferred); |
| 1892 Label miss(this /*, Label::kDeferred*/); | |
| 1893 { | 1887 { |
| 1894 Variable var_handler(this, MachineRepresentation::kTagged); | 1888 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1895 | 1889 |
| 1896 // TODO(ishell): defer blocks when it works. | 1890 Label if_handler(this, &var_handler), |
| 1897 Label if_handler(this, &var_handler), try_polymorphic(this), | 1891 try_polymorphic(this, Label::kDeferred), |
| 1898 try_megamorphic(this /*, Label::kDeferred*/), | 1892 try_megamorphic(this, Label::kDeferred), |
| 1899 try_polymorphic_name(this /*, Label::kDeferred*/); | 1893 try_polymorphic_name(this, Label::kDeferred); |
| 1900 | 1894 |
| 1901 Node* receiver_map = LoadReceiverMap(p->receiver); | 1895 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1902 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1896 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); |
| 1903 | 1897 |
| 1904 // Check monomorphic case. | 1898 // Check monomorphic case. |
| 1905 Node* feedback = | 1899 Node* feedback = |
| 1906 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1900 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1907 &var_handler, &try_polymorphic); | 1901 &var_handler, &try_polymorphic); |
| 1908 Bind(&if_handler); | 1902 Bind(&if_handler); |
| 1909 { | 1903 { |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2191 Node* slot = Parameter(Descriptor::kSlot); | 2185 Node* slot = Parameter(Descriptor::kSlot); |
| 2192 Node* context = Parameter(Descriptor::kContext); | 2186 Node* context = Parameter(Descriptor::kContext); |
| 2193 Node* vector = LoadFeedbackVectorForStub(); | 2187 Node* vector = LoadFeedbackVectorForStub(); |
| 2194 | 2188 |
| 2195 StoreICParameters p(context, receiver, name, value, slot, vector); | 2189 StoreICParameters p(context, receiver, name, value, slot, vector); |
| 2196 KeyedStoreIC(&p, language_mode); | 2190 KeyedStoreIC(&p, language_mode); |
| 2197 } | 2191 } |
| 2198 | 2192 |
| 2199 } // namespace internal | 2193 } // namespace internal |
| 2200 } // namespace v8 | 2194 } // namespace v8 |
| OLD | NEW |