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 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
54 } | 54 } |
55 | 55 |
56 void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, | 56 void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, |
57 Node* feedback, Label* if_handler, | 57 Node* feedback, Label* if_handler, |
58 Variable* var_handler, | 58 Variable* var_handler, |
59 Label* if_miss, | 59 Label* if_miss, |
60 int unroll_count) { | 60 int unroll_count) { |
61 Comment("HandlePolymorphicCase"); | 61 Comment("HandlePolymorphicCase"); |
62 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 62 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
63 | 63 |
| 64 // Deferred so the unrolled case can omit frame construction in bytecode |
| 65 // handler. |
| 66 Label loop(this, Label::kDeferred); |
| 67 |
64 // Iterate {feedback} array. | 68 // Iterate {feedback} array. |
65 const int kEntrySize = 2; | 69 const int kEntrySize = 2; |
66 | 70 |
67 for (int i = 0; i < unroll_count; i++) { | 71 for (int i = 0; i < unroll_count; i++) { |
68 Label next_entry(this); | 72 Label next_entry(this); |
69 Node* cached_map = | 73 Node* cached_map = |
70 LoadWeakCellValue(LoadFixedArrayElement(feedback, i * kEntrySize)); | 74 LoadWeakCellValue(LoadFixedArrayElement(feedback, i * kEntrySize)); |
71 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 75 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
72 | 76 |
73 // Found, now call handler. | 77 // Found, now call handler. |
74 Node* handler = LoadFixedArrayElement(feedback, i * kEntrySize + 1); | 78 Node* handler = LoadFixedArrayElement(feedback, i * kEntrySize + 1); |
75 var_handler->Bind(handler); | 79 var_handler->Bind(handler); |
76 Goto(if_handler); | 80 Goto(if_handler); |
77 | 81 |
78 Bind(&next_entry); | 82 Bind(&next_entry); |
79 } | 83 } |
| 84 Goto(&loop); |
80 | 85 |
81 // Loop from {unroll_count}*kEntrySize to {length}. | 86 // Loop from {unroll_count}*kEntrySize to {length}. |
| 87 Bind(&loop); |
82 Node* init = IntPtrConstant(unroll_count * kEntrySize); | 88 Node* init = IntPtrConstant(unroll_count * kEntrySize); |
83 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); | 89 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); |
84 BuildFastLoop( | 90 BuildFastLoop( |
85 init, length, | 91 init, length, |
86 [this, receiver_map, feedback, if_handler, var_handler](Node* index) { | 92 [this, receiver_map, feedback, if_handler, var_handler](Node* index) { |
87 Node* cached_map = | 93 Node* cached_map = |
88 LoadWeakCellValue(LoadFixedArrayElement(feedback, index)); | 94 LoadWeakCellValue(LoadFixedArrayElement(feedback, index)); |
89 | 95 |
90 Label next_entry(this); | 96 Label next_entry(this); |
91 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 97 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 | 140 |
135 Bind(&next_entry); | 141 Bind(&next_entry); |
136 }, | 142 }, |
137 kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); | 143 kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); |
138 // The loop falls through if no handler was found. | 144 // The loop falls through if no handler was found. |
139 Goto(if_miss); | 145 Goto(if_miss); |
140 } | 146 } |
141 | 147 |
142 void AccessorAssembler::HandleLoadICHandlerCase( | 148 void AccessorAssembler::HandleLoadICHandlerCase( |
143 const LoadICParameters* p, Node* handler, Label* miss, | 149 const LoadICParameters* p, Node* handler, Label* miss, |
144 ElementSupport support_elements) { | 150 ExitPoint* exit_point, ElementSupport support_elements) { |
145 Comment("have_handler"); | 151 Comment("have_handler"); |
146 ExitPoint direct_exit(this); | |
147 | 152 |
148 Variable var_holder(this, MachineRepresentation::kTagged, p->receiver); | 153 Variable var_holder(this, MachineRepresentation::kTagged, p->receiver); |
149 Variable var_smi_handler(this, MachineRepresentation::kTagged, handler); | 154 Variable var_smi_handler(this, MachineRepresentation::kTagged, handler); |
150 | 155 |
151 Variable* vars[] = {&var_holder, &var_smi_handler}; | 156 Variable* vars[] = {&var_holder, &var_smi_handler}; |
152 Label if_smi_handler(this, 2, vars); | 157 Label if_smi_handler(this, 2, vars); |
153 Label try_proto_handler(this, Label::kDeferred), | 158 Label try_proto_handler(this, Label::kDeferred), |
154 call_handler(this, Label::kDeferred); | 159 call_handler(this, Label::kDeferred); |
155 | 160 |
156 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); | 161 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); |
157 | 162 |
158 // |handler| is a Smi, encoding what to do. See SmiHandler methods | 163 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
159 // for the encoding format. | 164 // for the encoding format. |
160 Bind(&if_smi_handler); | 165 Bind(&if_smi_handler); |
161 { | 166 { |
162 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), | 167 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), |
163 miss, &direct_exit, support_elements); | 168 miss, exit_point, support_elements); |
164 } | 169 } |
165 | 170 |
166 Bind(&try_proto_handler); | 171 Bind(&try_proto_handler); |
167 { | 172 { |
168 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); | 173 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); |
169 HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler, | 174 HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler, |
170 &if_smi_handler, miss, &direct_exit, false); | 175 &if_smi_handler, miss, exit_point, false); |
171 } | 176 } |
172 | 177 |
173 Bind(&call_handler); | 178 Bind(&call_handler); |
174 { | 179 { |
175 typedef LoadWithVectorDescriptor Descriptor; | 180 typedef LoadWithVectorDescriptor Descriptor; |
176 TailCallStub(Descriptor(isolate()), handler, p->context, p->receiver, | 181 exit_point->ReturnCallStub(Descriptor(isolate()), handler, p->context, |
177 p->name, p->slot, p->vector); | 182 p->receiver, p->name, p->slot, p->vector); |
178 } | 183 } |
179 } | 184 } |
180 | 185 |
181 void AccessorAssembler::HandleLoadField(Node* holder, Node* handler_word, | 186 void AccessorAssembler::HandleLoadField(Node* holder, Node* handler_word, |
182 Variable* var_double_value, | 187 Variable* var_double_value, |
183 Label* rebox_double, | 188 Label* rebox_double, |
184 ExitPoint* exit_point) { | 189 ExitPoint* exit_point) { |
185 Comment("field_load"); | 190 Comment("field_load"); |
186 Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word); | 191 Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word); |
187 | 192 |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), | 271 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), |
267 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), | 272 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), |
268 miss); | 273 miss); |
269 exit_point->Return(UndefinedConstant()); | 274 exit_point->Return(UndefinedConstant()); |
270 } | 275 } |
271 | 276 |
272 Bind(&property); | 277 Bind(&property); |
273 Comment("property_load"); | 278 Comment("property_load"); |
274 } | 279 } |
275 | 280 |
276 Label constant(this, Label::kDeferred), field(this), | 281 Label constant(this), field(this), normal(this, Label::kDeferred); |
277 normal(this, Label::kDeferred); | |
278 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), | 282 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), |
279 &field); | 283 &field); |
280 | 284 |
281 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForConstants)), | 285 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForConstants)), |
282 &constant, &normal); | 286 &constant, &normal); |
283 | 287 |
284 Bind(&field); | 288 Bind(&field); |
285 HandleLoadField(holder, handler_word, &var_double_value, &rebox_double, | 289 HandleLoadField(holder, handler_word, &var_double_value, &rebox_double, |
286 exit_point); | 290 exit_point); |
287 | 291 |
(...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 var_transition.Bind(transition); | 661 var_transition.Bind(transition); |
658 Goto(&if_transition); | 662 Goto(&if_transition); |
659 } | 663 } |
660 | 664 |
661 Bind(&if_transition); | 665 Bind(&if_transition); |
662 { | 666 { |
663 Node* holder = p->receiver; | 667 Node* holder = p->receiver; |
664 Node* transition = var_transition.value(); | 668 Node* transition = var_transition.value(); |
665 Node* handler_word = SmiUntag(smi_handler); | 669 Node* handler_word = SmiUntag(smi_handler); |
666 | 670 |
667 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(transition)), miss); | 671 GotoIf(IsDeprecatedMap(transition), miss); |
668 | 672 |
669 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word); | 673 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word); |
670 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kStoreNormal)), | 674 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kStoreNormal)), |
671 &if_store_normal); | 675 &if_store_normal); |
672 GotoIf(WordEqual(handler_kind, | 676 GotoIf(WordEqual(handler_kind, |
673 IntPtrConstant(StoreHandler::kTransitionToConstant)), | 677 IntPtrConstant(StoreHandler::kTransitionToConstant)), |
674 &if_transition_to_constant); | 678 &if_transition_to_constant); |
675 | 679 |
676 // Handle transitioning field stores. | 680 // Handle transitioning field stores. |
677 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition, | 681 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition, |
(...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1315 Bind(&return_undefined); | 1319 Bind(&return_undefined); |
1316 Return(UndefinedConstant()); | 1320 Return(UndefinedConstant()); |
1317 } | 1321 } |
1318 } | 1322 } |
1319 | 1323 |
1320 void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, | 1324 void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, |
1321 Node* instance_type, Node* key, | 1325 Node* instance_type, Node* key, |
1322 const LoadICParameters* p, | 1326 const LoadICParameters* p, |
1323 Label* slow, | 1327 Label* slow, |
1324 UseStubCache use_stub_cache) { | 1328 UseStubCache use_stub_cache) { |
| 1329 ExitPoint direct_exit(this); |
| 1330 |
1325 Comment("key is unique name"); | 1331 Comment("key is unique name"); |
1326 Label if_found_on_receiver(this), if_property_dictionary(this), | 1332 Label if_found_on_receiver(this), if_property_dictionary(this), |
1327 lookup_prototype_chain(this); | 1333 lookup_prototype_chain(this); |
1328 Variable var_details(this, MachineRepresentation::kWord32); | 1334 Variable var_details(this, MachineRepresentation::kWord32); |
1329 Variable var_value(this, MachineRepresentation::kTagged); | 1335 Variable var_value(this, MachineRepresentation::kTagged); |
1330 | 1336 |
1331 // Receivers requiring non-standard accesses (interceptors, access | 1337 // Receivers requiring non-standard accesses (interceptors, access |
1332 // checks, strings and string wrappers, proxies) are handled in the runtime. | 1338 // checks, strings and string wrappers, proxies) are handled in the runtime. |
1333 GotoIf(Int32LessThanOrEqual(instance_type, | 1339 GotoIf(Int32LessThanOrEqual(instance_type, |
1334 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 1340 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
(...skipping 26 matching lines...) Expand all Loading... |
1361 } | 1367 } |
1362 | 1368 |
1363 if (use_stub_cache == kUseStubCache) { | 1369 if (use_stub_cache == kUseStubCache) { |
1364 Bind(&stub_cache); | 1370 Bind(&stub_cache); |
1365 Comment("stub cache probe for fast property load"); | 1371 Comment("stub cache probe for fast property load"); |
1366 Variable var_handler(this, MachineRepresentation::kTagged); | 1372 Variable var_handler(this, MachineRepresentation::kTagged); |
1367 Label found_handler(this, &var_handler), stub_cache_miss(this); | 1373 Label found_handler(this, &var_handler), stub_cache_miss(this); |
1368 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key, | 1374 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key, |
1369 &found_handler, &var_handler, &stub_cache_miss); | 1375 &found_handler, &var_handler, &stub_cache_miss); |
1370 Bind(&found_handler); | 1376 Bind(&found_handler); |
1371 { HandleLoadICHandlerCase(p, var_handler.value(), slow); } | 1377 { HandleLoadICHandlerCase(p, var_handler.value(), slow, &direct_exit); } |
1372 | 1378 |
1373 Bind(&stub_cache_miss); | 1379 Bind(&stub_cache_miss); |
1374 { | 1380 { |
1375 // TODO(jkummerow): Check if the property exists on the prototype | 1381 // TODO(jkummerow): Check if the property exists on the prototype |
1376 // chain. If it doesn't, then there's no point in missing. | 1382 // chain. If it doesn't, then there's no point in missing. |
1377 Comment("KeyedLoadGeneric_miss"); | 1383 Comment("KeyedLoadGeneric_miss"); |
1378 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 1384 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
1379 p->name, p->slot, p->vector); | 1385 p->name, p->slot, p->vector); |
1380 } | 1386 } |
1381 } | 1387 } |
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1569 | 1575 |
1570 Bind(&miss); | 1576 Bind(&miss); |
1571 { | 1577 { |
1572 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 1578 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
1573 Goto(if_miss); | 1579 Goto(if_miss); |
1574 } | 1580 } |
1575 } | 1581 } |
1576 | 1582 |
1577 //////////////////// Entry points into private implementation (one per stub). | 1583 //////////////////// Entry points into private implementation (one per stub). |
1578 | 1584 |
| 1585 void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p, |
| 1586 ExitPoint* exit_point) { |
| 1587 // Must be kept in sync with LoadIC. |
| 1588 |
| 1589 // This function is hand-tuned to omit frame construction for common cases, |
| 1590 // e.g.: monomorphic field and constant loads through smi handlers. |
| 1591 // Polymorphic ICs with a hit in the first two entries also omit frames. |
| 1592 // TODO(jgruber): Frame omission is fragile and can be affected by minor |
| 1593 // changes in control flow and logic. We currently have no way of ensuring |
| 1594 // that no frame is constructed, so it's easy to break this optimization by |
| 1595 // accident. |
| 1596 Label stub_call(this, Label::kDeferred), miss(this, Label::kDeferred); |
| 1597 |
| 1598 // Inlined fast path. |
| 1599 { |
| 1600 Comment("LoadIC_BytecodeHandler_fast"); |
| 1601 |
| 1602 Node* recv_map = LoadReceiverMap(p->receiver); |
| 1603 GotoIf(IsDeprecatedMap(recv_map), &miss); |
| 1604 |
| 1605 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1606 Label try_polymorphic(this), if_handler(this, &var_handler); |
| 1607 |
| 1608 Node* feedback = |
| 1609 TryMonomorphicCase(p->slot, p->vector, recv_map, &if_handler, |
| 1610 &var_handler, &try_polymorphic); |
| 1611 |
| 1612 Bind(&if_handler); |
| 1613 HandleLoadICHandlerCase(p, var_handler.value(), &miss, exit_point); |
| 1614 |
| 1615 Bind(&try_polymorphic); |
| 1616 { |
| 1617 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
| 1618 &stub_call); |
| 1619 HandlePolymorphicCase(recv_map, feedback, &if_handler, &var_handler, |
| 1620 &miss, 2); |
| 1621 } |
| 1622 } |
| 1623 |
| 1624 Bind(&stub_call); |
| 1625 { |
| 1626 Comment("LoadIC_BytecodeHandler_noninlined"); |
| 1627 |
| 1628 // Call into the stub that implements the non-inlined parts of LoadIC. |
| 1629 Callable ic = CodeFactory::LoadICInOptimizedCode_Noninlined(isolate()); |
| 1630 Node* code_target = HeapConstant(ic.code()); |
| 1631 exit_point->ReturnCallStub(ic.descriptor(), code_target, p->context, |
| 1632 p->receiver, p->name, p->slot, p->vector); |
| 1633 } |
| 1634 |
| 1635 Bind(&miss); |
| 1636 { |
| 1637 Comment("LoadIC_BytecodeHandler_miss"); |
| 1638 |
| 1639 exit_point->ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, |
| 1640 p->receiver, p->name, p->slot, p->vector); |
| 1641 } |
| 1642 } |
| 1643 |
1579 void AccessorAssembler::LoadIC(const LoadICParameters* p) { | 1644 void AccessorAssembler::LoadIC(const LoadICParameters* p) { |
| 1645 // Must be kept in sync with LoadIC_BytecodeHandler. |
| 1646 |
| 1647 ExitPoint direct_exit(this); |
| 1648 |
1580 Variable var_handler(this, MachineRepresentation::kTagged); | 1649 Variable var_handler(this, MachineRepresentation::kTagged); |
1581 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), | 1650 Label if_handler(this, &var_handler), non_inlined(this, Label::kDeferred), |
1582 try_megamorphic(this, Label::kDeferred), | 1651 try_polymorphic(this), miss(this, Label::kDeferred); |
1583 try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred); | |
1584 | 1652 |
1585 Node* receiver_map = LoadReceiverMap(p->receiver); | 1653 Node* receiver_map = LoadReceiverMap(p->receiver); |
1586 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1654 GotoIf(IsDeprecatedMap(receiver_map), &miss); |
1587 | 1655 |
1588 // Check monomorphic case. | 1656 // Check monomorphic case. |
1589 Node* feedback = | 1657 Node* feedback = |
1590 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1658 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
1591 &var_handler, &try_polymorphic); | 1659 &var_handler, &try_polymorphic); |
1592 Bind(&if_handler); | 1660 Bind(&if_handler); |
1593 { HandleLoadICHandlerCase(p, var_handler.value(), &miss); } | 1661 HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit); |
1594 | 1662 |
1595 Bind(&try_polymorphic); | 1663 Bind(&try_polymorphic); |
1596 { | 1664 { |
1597 // Check polymorphic case. | 1665 // Check polymorphic case. |
1598 Comment("LoadIC_try_polymorphic"); | 1666 Comment("LoadIC_try_polymorphic"); |
1599 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | 1667 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
1600 &try_megamorphic); | 1668 &non_inlined); |
1601 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, | 1669 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
1602 &miss, 2); | 1670 &miss, 2); |
1603 } | 1671 } |
1604 | 1672 |
1605 Bind(&try_megamorphic); | 1673 Bind(&non_inlined); |
| 1674 LoadIC_Noninlined(p, receiver_map, feedback, &var_handler, &if_handler, &miss, |
| 1675 &direct_exit); |
| 1676 |
| 1677 Bind(&miss); |
| 1678 direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, |
| 1679 p->name, p->slot, p->vector); |
| 1680 } |
| 1681 |
| 1682 void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p, |
| 1683 Node* receiver_map, Node* feedback, |
| 1684 Variable* var_handler, |
| 1685 Label* if_handler, Label* miss, |
| 1686 ExitPoint* exit_point) { |
| 1687 Label try_uninitialized(this, Label::kDeferred); |
| 1688 |
| 1689 // Neither deprecated map nor monomorphic. These cases are handled in the |
| 1690 // bytecode handler. |
| 1691 CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map))); |
| 1692 CSA_ASSERT(this, |
| 1693 WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(feedback))); |
| 1694 CSA_ASSERT(this, WordNotEqual(LoadMap(feedback), FixedArrayMapConstant())); |
| 1695 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
| 1696 |
1606 { | 1697 { |
1607 // Check megamorphic case. | 1698 // Check megamorphic case. |
1608 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 1699 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
1609 &try_uninitialized); | 1700 &try_uninitialized); |
1610 | 1701 |
1611 TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name, | 1702 TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name, |
1612 &if_handler, &var_handler, &miss); | 1703 if_handler, var_handler, miss); |
1613 } | 1704 } |
| 1705 |
1614 Bind(&try_uninitialized); | 1706 Bind(&try_uninitialized); |
1615 { | 1707 { |
1616 // Check uninitialized case. | 1708 // Check uninitialized case. |
1617 GotoIfNot( | 1709 GotoIfNot( |
1618 WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)), | 1710 WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)), |
1619 &miss); | 1711 miss); |
1620 TailCallStub(CodeFactory::LoadIC_Uninitialized(isolate()), p->context, | 1712 exit_point->ReturnCallStub(CodeFactory::LoadIC_Uninitialized(isolate()), |
1621 p->receiver, p->name, p->slot, p->vector); | 1713 p->context, p->receiver, p->name, p->slot, |
1622 } | 1714 p->vector); |
1623 Bind(&miss); | |
1624 { | |
1625 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, | |
1626 p->slot, p->vector); | |
1627 } | 1715 } |
1628 } | 1716 } |
1629 | 1717 |
1630 void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) { | 1718 void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) { |
1631 Label miss(this); | 1719 Label miss(this); |
1632 Node* receiver = p->receiver; | 1720 Node* receiver = p->receiver; |
1633 GotoIf(TaggedIsSmi(receiver), &miss); | 1721 GotoIf(TaggedIsSmi(receiver), &miss); |
1634 Node* receiver_map = LoadMap(receiver); | 1722 Node* receiver_map = LoadMap(receiver); |
1635 Node* instance_type = LoadMapInstanceType(receiver_map); | 1723 Node* instance_type = LoadMapInstanceType(receiver_map); |
1636 | 1724 |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1760 void AccessorAssembler::LoadGlobalIC_MissCase(const LoadICParameters* p, | 1848 void AccessorAssembler::LoadGlobalIC_MissCase(const LoadICParameters* p, |
1761 ExitPoint* exit_point) { | 1849 ExitPoint* exit_point) { |
1762 Comment("LoadGlobalIC_MissCase"); | 1850 Comment("LoadGlobalIC_MissCase"); |
1763 | 1851 |
1764 exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, | 1852 exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, |
1765 p->name, p->slot, p->vector); | 1853 p->name, p->slot, p->vector); |
1766 } | 1854 } |
1767 | 1855 |
1768 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, | 1856 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, |
1769 TypeofMode typeof_mode) { | 1857 TypeofMode typeof_mode) { |
| 1858 // Must be kept in sync with Interpreter::BuildLoadGlobal. |
| 1859 |
1770 ExitPoint direct_exit(this); | 1860 ExitPoint direct_exit(this); |
1771 | 1861 |
1772 Label try_handler(this), miss(this); | 1862 Label try_handler(this), miss(this); |
1773 LoadGlobalIC_TryPropertyCellCase(p->vector, p->slot, &direct_exit, | 1863 LoadGlobalIC_TryPropertyCellCase(p->vector, p->slot, &direct_exit, |
1774 &try_handler, &miss); | 1864 &try_handler, &miss); |
1775 | 1865 |
1776 Bind(&try_handler); | 1866 Bind(&try_handler); |
1777 LoadGlobalIC_TryHandlerCase(p, typeof_mode, &direct_exit, &miss); | 1867 LoadGlobalIC_TryHandlerCase(p, typeof_mode, &direct_exit, &miss); |
1778 | 1868 |
1779 Bind(&miss); | 1869 Bind(&miss); |
1780 LoadGlobalIC_MissCase(p, &direct_exit); | 1870 LoadGlobalIC_MissCase(p, &direct_exit); |
1781 } | 1871 } |
1782 | 1872 |
1783 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { | 1873 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { |
| 1874 ExitPoint direct_exit(this); |
| 1875 |
1784 Variable var_handler(this, MachineRepresentation::kTagged); | 1876 Variable var_handler(this, MachineRepresentation::kTagged); |
1785 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), | 1877 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), |
1786 try_megamorphic(this, Label::kDeferred), | 1878 try_megamorphic(this, Label::kDeferred), |
1787 try_polymorphic_name(this, Label::kDeferred), | 1879 try_polymorphic_name(this, Label::kDeferred), |
1788 miss(this, Label::kDeferred); | 1880 miss(this, Label::kDeferred); |
1789 | 1881 |
1790 Node* receiver_map = LoadReceiverMap(p->receiver); | 1882 Node* receiver_map = LoadReceiverMap(p->receiver); |
1791 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1883 GotoIf(IsDeprecatedMap(receiver_map), &miss); |
1792 | 1884 |
1793 // Check monomorphic case. | 1885 // Check monomorphic case. |
1794 Node* feedback = | 1886 Node* feedback = |
1795 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1887 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
1796 &var_handler, &try_polymorphic); | 1888 &var_handler, &try_polymorphic); |
1797 Bind(&if_handler); | 1889 Bind(&if_handler); |
1798 { HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements); } | 1890 { |
| 1891 HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit, |
| 1892 kSupportElements); |
| 1893 } |
1799 | 1894 |
1800 Bind(&try_polymorphic); | 1895 Bind(&try_polymorphic); |
1801 { | 1896 { |
1802 // Check polymorphic case. | 1897 // Check polymorphic case. |
1803 Comment("KeyedLoadIC_try_polymorphic"); | 1898 Comment("KeyedLoadIC_try_polymorphic"); |
1804 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | 1899 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
1805 &try_megamorphic); | 1900 &try_megamorphic); |
1806 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, | 1901 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
1807 &miss, 2); | 1902 &miss, 2); |
1808 } | 1903 } |
1809 | 1904 |
1810 Bind(&try_megamorphic); | 1905 Bind(&try_megamorphic); |
1811 { | 1906 { |
1812 // Check megamorphic case. | 1907 // Check megamorphic case. |
1813 Comment("KeyedLoadIC_try_megamorphic"); | 1908 Comment("KeyedLoadIC_try_megamorphic"); |
1814 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 1909 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
1815 &try_polymorphic_name); | 1910 &try_polymorphic_name); |
1816 // TODO(jkummerow): Inline this? Or some of it? | 1911 // TODO(jkummerow): Inline this? Or some of it? |
1817 TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context, | 1912 TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context, |
1818 p->receiver, p->name, p->slot, p->vector); | 1913 p->receiver, p->name, p->slot, p->vector); |
1819 } | 1914 } |
1820 Bind(&try_polymorphic_name); | 1915 Bind(&try_polymorphic_name); |
1821 { | 1916 { |
1822 // We might have a name in feedback, and a fixed array in the next slot. | 1917 // We might have a name in feedback, and a fixed array in the next slot. |
1823 Comment("KeyedLoadIC_try_polymorphic_name"); | 1918 Comment("KeyedLoadIC_try_polymorphic_name"); |
1824 GotoIfNot(WordEqual(feedback, p->name), &miss); | 1919 GotoIfNot(WordEqual(feedback, p->name), &miss); |
1825 // If the name comparison succeeded, we know we have a fixed array with | 1920 // If the name comparison succeeded, we know we have a fixed array with |
1826 // at least one map/handler pair. | 1921 // at least one map/handler pair. |
1827 Node* offset = ElementOffsetFromIndex( | 1922 Node* array = |
1828 p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS, | 1923 LoadFixedArrayElement(p->vector, p->slot, kPointerSize, SMI_PARAMETERS); |
1829 FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag); | |
1830 Node* array = Load(MachineType::AnyTagged(), p->vector, offset); | |
1831 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss, | 1924 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss, |
1832 1); | 1925 1); |
1833 } | 1926 } |
1834 Bind(&miss); | 1927 Bind(&miss); |
1835 { | 1928 { |
1836 Comment("KeyedLoadIC_miss"); | 1929 Comment("KeyedLoadIC_miss"); |
1837 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 1930 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
1838 p->name, p->slot, p->vector); | 1931 p->name, p->slot, p->vector); |
1839 } | 1932 } |
1840 } | 1933 } |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1874 p->name); | 1967 p->name); |
1875 } | 1968 } |
1876 } | 1969 } |
1877 | 1970 |
1878 void AccessorAssembler::StoreIC(const StoreICParameters* p) { | 1971 void AccessorAssembler::StoreIC(const StoreICParameters* p) { |
1879 Variable var_handler(this, MachineRepresentation::kTagged); | 1972 Variable var_handler(this, MachineRepresentation::kTagged); |
1880 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), | 1973 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), |
1881 try_megamorphic(this, Label::kDeferred), miss(this, Label::kDeferred); | 1974 try_megamorphic(this, Label::kDeferred), miss(this, Label::kDeferred); |
1882 | 1975 |
1883 Node* receiver_map = LoadReceiverMap(p->receiver); | 1976 Node* receiver_map = LoadReceiverMap(p->receiver); |
1884 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1977 GotoIf(IsDeprecatedMap(receiver_map), &miss); |
1885 | 1978 |
1886 // Check monomorphic case. | 1979 // Check monomorphic case. |
1887 Node* feedback = | 1980 Node* feedback = |
1888 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1981 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
1889 &var_handler, &try_polymorphic); | 1982 &var_handler, &try_polymorphic); |
1890 Bind(&if_handler); | 1983 Bind(&if_handler); |
1891 { | 1984 { |
1892 Comment("StoreIC_if_handler"); | 1985 Comment("StoreIC_if_handler"); |
1893 HandleStoreICHandlerCase(p, var_handler.value(), &miss); | 1986 HandleStoreICHandlerCase(p, var_handler.value(), &miss); |
1894 } | 1987 } |
(...skipping 30 matching lines...) Expand all Loading... |
1925 Label miss(this, Label::kDeferred); | 2018 Label miss(this, Label::kDeferred); |
1926 { | 2019 { |
1927 Variable var_handler(this, MachineRepresentation::kTagged); | 2020 Variable var_handler(this, MachineRepresentation::kTagged); |
1928 | 2021 |
1929 Label if_handler(this, &var_handler), | 2022 Label if_handler(this, &var_handler), |
1930 try_polymorphic(this, Label::kDeferred), | 2023 try_polymorphic(this, Label::kDeferred), |
1931 try_megamorphic(this, Label::kDeferred), | 2024 try_megamorphic(this, Label::kDeferred), |
1932 try_polymorphic_name(this, Label::kDeferred); | 2025 try_polymorphic_name(this, Label::kDeferred); |
1933 | 2026 |
1934 Node* receiver_map = LoadReceiverMap(p->receiver); | 2027 Node* receiver_map = LoadReceiverMap(p->receiver); |
1935 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 2028 GotoIf(IsDeprecatedMap(receiver_map), &miss); |
1936 | 2029 |
1937 // Check monomorphic case. | 2030 // Check monomorphic case. |
1938 Node* feedback = | 2031 Node* feedback = |
1939 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 2032 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
1940 &var_handler, &try_polymorphic); | 2033 &var_handler, &try_polymorphic); |
1941 Bind(&if_handler); | 2034 Bind(&if_handler); |
1942 { | 2035 { |
1943 Comment("KeyedStoreIC_if_handler"); | 2036 Comment("KeyedStoreIC_if_handler"); |
1944 HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements); | 2037 HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements); |
1945 } | 2038 } |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2006 p->context, p->receiver, p->name, p->value, p->slot, p->vector); | 2099 p->context, p->receiver, p->name, p->value, p->slot, p->vector); |
2007 } | 2100 } |
2008 | 2101 |
2009 Bind(&try_polymorphic_name); | 2102 Bind(&try_polymorphic_name); |
2010 { | 2103 { |
2011 // We might have a name in feedback, and a fixed array in the next slot. | 2104 // We might have a name in feedback, and a fixed array in the next slot. |
2012 Comment("KeyedStoreIC_try_polymorphic_name"); | 2105 Comment("KeyedStoreIC_try_polymorphic_name"); |
2013 GotoIfNot(WordEqual(feedback, p->name), &miss); | 2106 GotoIfNot(WordEqual(feedback, p->name), &miss); |
2014 // If the name comparison succeeded, we know we have a FixedArray with | 2107 // If the name comparison succeeded, we know we have a FixedArray with |
2015 // at least one map/handler pair. | 2108 // at least one map/handler pair. |
2016 Node* offset = ElementOffsetFromIndex( | 2109 Node* array = LoadFixedArrayElement(p->vector, p->slot, kPointerSize, |
2017 p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS, | 2110 SMI_PARAMETERS); |
2018 FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag); | |
2019 Node* array = Load(MachineType::AnyTagged(), p->vector, offset); | |
2020 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, | 2111 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, |
2021 &miss, 1); | 2112 &miss, 1); |
2022 } | 2113 } |
2023 } | 2114 } |
2024 Bind(&miss); | 2115 Bind(&miss); |
2025 { | 2116 { |
2026 Comment("KeyedStoreIC_miss"); | 2117 Comment("KeyedStoreIC_miss"); |
2027 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, | 2118 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, |
2028 p->vector, p->receiver, p->name); | 2119 p->vector, p->receiver, p->name); |
2029 } | 2120 } |
2030 } | 2121 } |
2031 | 2122 |
2032 //////////////////// Public methods. | 2123 //////////////////// Public methods. |
2033 | 2124 |
2034 void AccessorAssembler::GenerateLoadIC() { | 2125 void AccessorAssembler::GenerateLoadIC() { |
2035 typedef LoadWithVectorDescriptor Descriptor; | 2126 typedef LoadWithVectorDescriptor Descriptor; |
2036 | 2127 |
2037 Node* receiver = Parameter(Descriptor::kReceiver); | 2128 Node* receiver = Parameter(Descriptor::kReceiver); |
2038 Node* name = Parameter(Descriptor::kName); | 2129 Node* name = Parameter(Descriptor::kName); |
2039 Node* slot = Parameter(Descriptor::kSlot); | 2130 Node* slot = Parameter(Descriptor::kSlot); |
2040 Node* vector = Parameter(Descriptor::kVector); | 2131 Node* vector = Parameter(Descriptor::kVector); |
2041 Node* context = Parameter(Descriptor::kContext); | 2132 Node* context = Parameter(Descriptor::kContext); |
2042 | 2133 |
2043 LoadICParameters p(context, receiver, name, slot, vector); | 2134 LoadICParameters p(context, receiver, name, slot, vector); |
2044 LoadIC(&p); | 2135 LoadIC(&p); |
2045 } | 2136 } |
2046 | 2137 |
| 2138 void AccessorAssembler::GenerateLoadIC_Noninlined() { |
| 2139 typedef LoadWithVectorDescriptor Descriptor; |
| 2140 |
| 2141 Node* receiver = Parameter(Descriptor::kReceiver); |
| 2142 Node* name = Parameter(Descriptor::kName); |
| 2143 Node* slot = Parameter(Descriptor::kSlot); |
| 2144 Node* vector = Parameter(Descriptor::kVector); |
| 2145 Node* context = Parameter(Descriptor::kContext); |
| 2146 |
| 2147 ExitPoint direct_exit(this); |
| 2148 Variable var_handler(this, MachineRepresentation::kTagged); |
| 2149 Label if_handler(this, &var_handler), miss(this, Label::kDeferred); |
| 2150 |
| 2151 Node* receiver_map = LoadReceiverMap(receiver); |
| 2152 Node* feedback = LoadFixedArrayElement(vector, slot, 0, SMI_PARAMETERS); |
| 2153 |
| 2154 LoadICParameters p(context, receiver, name, slot, vector); |
| 2155 LoadIC_Noninlined(&p, receiver_map, feedback, &var_handler, &if_handler, |
| 2156 &miss, &direct_exit); |
| 2157 |
| 2158 Bind(&if_handler); |
| 2159 HandleLoadICHandlerCase(&p, var_handler.value(), &miss, &direct_exit); |
| 2160 |
| 2161 Bind(&miss); |
| 2162 direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, |
| 2163 slot, vector); |
| 2164 } |
| 2165 |
2047 void AccessorAssembler::GenerateLoadIC_Uninitialized() { | 2166 void AccessorAssembler::GenerateLoadIC_Uninitialized() { |
2048 typedef LoadWithVectorDescriptor Descriptor; | 2167 typedef LoadWithVectorDescriptor Descriptor; |
2049 | 2168 |
2050 Node* receiver = Parameter(Descriptor::kReceiver); | 2169 Node* receiver = Parameter(Descriptor::kReceiver); |
2051 Node* name = Parameter(Descriptor::kName); | 2170 Node* name = Parameter(Descriptor::kName); |
2052 Node* slot = Parameter(Descriptor::kSlot); | 2171 Node* slot = Parameter(Descriptor::kSlot); |
2053 Node* vector = Parameter(Descriptor::kVector); | 2172 Node* vector = Parameter(Descriptor::kVector); |
2054 Node* context = Parameter(Descriptor::kContext); | 2173 Node* context = Parameter(Descriptor::kContext); |
2055 | 2174 |
2056 LoadICParameters p(context, receiver, name, slot, vector); | 2175 LoadICParameters p(context, receiver, name, slot, vector); |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2228 Node* context = Parameter(Descriptor::kContext); | 2347 Node* context = Parameter(Descriptor::kContext); |
2229 Node* vector = LoadFeedbackVectorForStub(); | 2348 Node* vector = LoadFeedbackVectorForStub(); |
2230 | 2349 |
2231 Callable callable = | 2350 Callable callable = |
2232 CodeFactory::KeyedStoreICInOptimizedCode(isolate(), language_mode); | 2351 CodeFactory::KeyedStoreICInOptimizedCode(isolate(), language_mode); |
2233 TailCallStub(callable, context, receiver, name, value, slot, vector); | 2352 TailCallStub(callable, context, receiver, name, value, slot, vector); |
2234 } | 2353 } |
2235 | 2354 |
2236 } // namespace internal | 2355 } // namespace internal |
2237 } // namespace v8 | 2356 } // namespace v8 |
OLD | NEW |