Chromium Code Reviews| 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" |
| 11 #include "src/ic/stub-cache.h" | 11 #include "src/ic/stub-cache.h" |
| 12 #include "src/objects-inl.h" | 12 #include "src/objects-inl.h" |
| 13 | 13 |
| 14 namespace v8 { | 14 namespace v8 { |
| 15 namespace internal { | 15 namespace internal { |
| 16 | 16 |
| 17 using compiler::CodeAssemblerState; | 17 using compiler::CodeAssemblerState; |
| 18 using compiler::Node; | 18 using compiler::Node; |
| 19 | 19 |
| 20 //////////////////// Private helpers. | 20 //////////////////// Private helpers. |
| 21 | 21 |
| 22 Node* AccessorAssembler::LoadFeedbackSlot(Node* vector, Node* slot, | |
|
rmcilroy
2017/03/06 09:06:36
Nit - I think we have something similar in Intepre
jgruber
2017/03/07 09:40:56
I didn't find a similar function in InterpreterAss
| |
| 23 int additional_offset) { | |
| 24 int32_t header_size = | |
| 25 FixedArray::kHeaderSize - kHeapObjectTag + additional_offset; | |
| 26 | |
| 27 // Adding |header_size| with a separate IntPtrAdd rather than passing it | |
| 28 // into ElementOffsetFromIndex() allows it to be folded into a single | |
| 29 // [base, index, offset] indirect memory access on x64. | |
| 30 Node* offset = | |
| 31 ElementOffsetFromIndex(slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS); | |
| 32 return Load(MachineType::AnyTagged(), vector, | |
| 33 IntPtrAdd(offset, IntPtrConstant(header_size))); | |
| 34 } | |
| 35 | |
| 22 Node* AccessorAssembler::TryMonomorphicCase(Node* slot, Node* vector, | 36 Node* AccessorAssembler::TryMonomorphicCase(Node* slot, Node* vector, |
| 23 Node* receiver_map, | 37 Node* receiver_map, |
| 24 Label* if_handler, | 38 Label* if_handler, |
| 25 Variable* var_handler, | 39 Variable* var_handler, |
| 26 Label* if_miss) { | 40 Label* if_miss) { |
| 27 Comment("TryMonomorphicCase"); | 41 Comment("TryMonomorphicCase"); |
| 28 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 42 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
| 29 | 43 |
| 30 // TODO(ishell): add helper class that hides offset computations for a series | 44 // TODO(ishell): add helper class that hides offset computations for a series |
| 31 // of loads. | 45 // of loads. |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 54 } | 68 } |
| 55 | 69 |
| 56 void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, | 70 void AccessorAssembler::HandlePolymorphicCase(Node* receiver_map, |
| 57 Node* feedback, Label* if_handler, | 71 Node* feedback, Label* if_handler, |
| 58 Variable* var_handler, | 72 Variable* var_handler, |
| 59 Label* if_miss, | 73 Label* if_miss, |
| 60 int unroll_count) { | 74 int unroll_count) { |
| 61 Comment("HandlePolymorphicCase"); | 75 Comment("HandlePolymorphicCase"); |
| 62 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 76 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
| 63 | 77 |
| 78 // Deferred so the unrolled case can omit frame construction in bytecode | |
| 79 // handler. | |
| 80 Label loop(this, Label::kDeferred); | |
| 81 | |
| 64 // Iterate {feedback} array. | 82 // Iterate {feedback} array. |
| 65 const int kEntrySize = 2; | 83 const int kEntrySize = 2; |
| 66 | 84 |
| 67 for (int i = 0; i < unroll_count; i++) { | 85 for (int i = 0; i < unroll_count; i++) { |
| 68 Label next_entry(this); | 86 Label next_entry(this); |
| 69 Node* cached_map = | 87 Node* cached_map = |
| 70 LoadWeakCellValue(LoadFixedArrayElement(feedback, i * kEntrySize)); | 88 LoadWeakCellValue(LoadFixedArrayElement(feedback, i * kEntrySize)); |
| 71 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 89 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
| 72 | 90 |
| 73 // Found, now call handler. | 91 // Found, now call handler. |
| 74 Node* handler = LoadFixedArrayElement(feedback, i * kEntrySize + 1); | 92 Node* handler = LoadFixedArrayElement(feedback, i * kEntrySize + 1); |
| 75 var_handler->Bind(handler); | 93 var_handler->Bind(handler); |
| 76 Goto(if_handler); | 94 Goto(if_handler); |
| 77 | 95 |
| 78 Bind(&next_entry); | 96 Bind(&next_entry); |
| 79 } | 97 } |
| 98 Goto(&loop); | |
| 80 | 99 |
| 81 // Loop from {unroll_count}*kEntrySize to {length}. | 100 // Loop from {unroll_count}*kEntrySize to {length}. |
| 101 Bind(&loop); | |
| 82 Node* init = IntPtrConstant(unroll_count * kEntrySize); | 102 Node* init = IntPtrConstant(unroll_count * kEntrySize); |
| 83 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); | 103 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); |
| 84 BuildFastLoop( | 104 BuildFastLoop( |
| 85 init, length, | 105 init, length, |
| 86 [this, receiver_map, feedback, if_handler, var_handler](Node* index) { | 106 [this, receiver_map, feedback, if_handler, var_handler](Node* index) { |
| 87 Node* cached_map = | 107 Node* cached_map = |
| 88 LoadWeakCellValue(LoadFixedArrayElement(feedback, index)); | 108 LoadWeakCellValue(LoadFixedArrayElement(feedback, index)); |
| 89 | 109 |
| 90 Label next_entry(this); | 110 Label next_entry(this); |
| 91 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 111 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 134 | 154 |
| 135 Bind(&next_entry); | 155 Bind(&next_entry); |
| 136 }, | 156 }, |
| 137 kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); | 157 kEntrySize, INTPTR_PARAMETERS, IndexAdvanceMode::kPost); |
| 138 // The loop falls through if no handler was found. | 158 // The loop falls through if no handler was found. |
| 139 Goto(if_miss); | 159 Goto(if_miss); |
| 140 } | 160 } |
| 141 | 161 |
| 142 void AccessorAssembler::HandleLoadICHandlerCase( | 162 void AccessorAssembler::HandleLoadICHandlerCase( |
| 143 const LoadICParameters* p, Node* handler, Label* miss, | 163 const LoadICParameters* p, Node* handler, Label* miss, |
| 144 ElementSupport support_elements) { | 164 ExitPoint* exit_point, ElementSupport support_elements) { |
| 145 Comment("have_handler"); | 165 Comment("have_handler"); |
| 146 ExitPoint direct_exit(this); | |
| 147 | 166 |
| 148 Variable var_holder(this, MachineRepresentation::kTagged, p->receiver); | 167 Variable var_holder(this, MachineRepresentation::kTagged, p->receiver); |
| 149 Variable var_smi_handler(this, MachineRepresentation::kTagged, handler); | 168 Variable var_smi_handler(this, MachineRepresentation::kTagged, handler); |
| 150 | 169 |
| 151 Variable* vars[] = {&var_holder, &var_smi_handler}; | 170 Variable* vars[] = {&var_holder, &var_smi_handler}; |
| 152 Label if_smi_handler(this, 2, vars); | 171 Label if_smi_handler(this, 2, vars); |
| 153 Label try_proto_handler(this, Label::kDeferred), | 172 Label try_proto_handler(this, Label::kDeferred), |
| 154 call_handler(this, Label::kDeferred); | 173 call_handler(this, Label::kDeferred); |
| 155 | 174 |
| 156 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); | 175 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); |
| 157 | 176 |
| 158 // |handler| is a Smi, encoding what to do. See SmiHandler methods | 177 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
| 159 // for the encoding format. | 178 // for the encoding format. |
| 160 Bind(&if_smi_handler); | 179 Bind(&if_smi_handler); |
| 161 { | 180 { |
| 162 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), | 181 HandleLoadICSmiHandlerCase(p, var_holder.value(), var_smi_handler.value(), |
| 163 miss, &direct_exit, support_elements); | 182 miss, exit_point, support_elements); |
| 164 } | 183 } |
| 165 | 184 |
| 166 Bind(&try_proto_handler); | 185 Bind(&try_proto_handler); |
| 167 { | 186 { |
| 168 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); | 187 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); |
| 169 HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler, | 188 HandleLoadICProtoHandlerCase(p, handler, &var_holder, &var_smi_handler, |
| 170 &if_smi_handler, miss, &direct_exit, false); | 189 &if_smi_handler, miss, exit_point, false); |
| 171 } | 190 } |
| 172 | 191 |
| 173 Bind(&call_handler); | 192 Bind(&call_handler); |
| 174 { | 193 { |
| 175 typedef LoadWithVectorDescriptor Descriptor; | 194 typedef LoadWithVectorDescriptor Descriptor; |
| 176 TailCallStub(Descriptor(isolate()), handler, p->context, p->receiver, | 195 exit_point->ReturnCallStub(Descriptor(isolate()), handler, p->context, |
| 177 p->name, p->slot, p->vector); | 196 p->receiver, p->name, p->slot, p->vector); |
| 178 } | 197 } |
| 179 } | 198 } |
| 180 | 199 |
| 181 void AccessorAssembler::HandleLoadField(Node* holder, Node* handler_word, | 200 void AccessorAssembler::HandleLoadField(Node* holder, Node* handler_word, |
| 182 Variable* var_double_value, | 201 Variable* var_double_value, |
| 183 Label* rebox_double, | 202 Label* rebox_double, |
| 184 ExitPoint* exit_point) { | 203 ExitPoint* exit_point) { |
| 185 Comment("field_load"); | 204 Comment("field_load"); |
| 186 Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word); | 205 Node* offset = DecodeWord<LoadHandler::FieldOffsetBits>(handler_word); |
| 187 | 206 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 266 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), | 285 WordEqual(LoadObjectField(protector_cell, PropertyCell::kValueOffset), |
| 267 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), | 286 SmiConstant(Smi::FromInt(Isolate::kProtectorValid))), |
| 268 miss); | 287 miss); |
| 269 exit_point->Return(UndefinedConstant()); | 288 exit_point->Return(UndefinedConstant()); |
| 270 } | 289 } |
| 271 | 290 |
| 272 Bind(&property); | 291 Bind(&property); |
| 273 Comment("property_load"); | 292 Comment("property_load"); |
| 274 } | 293 } |
| 275 | 294 |
| 276 Label constant(this, Label::kDeferred), field(this), | 295 Label constant(this), field(this), normal(this, Label::kDeferred); |
| 277 normal(this, Label::kDeferred); | |
| 278 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), | 296 GotoIf(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForFields)), |
| 279 &field); | 297 &field); |
| 280 | 298 |
| 281 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForConstants)), | 299 Branch(WordEqual(handler_kind, IntPtrConstant(LoadHandler::kForConstants)), |
| 282 &constant, &normal); | 300 &constant, &normal); |
| 283 | 301 |
| 284 Bind(&field); | 302 Bind(&field); |
| 285 HandleLoadField(holder, handler_word, &var_double_value, &rebox_double, | 303 HandleLoadField(holder, handler_word, &var_double_value, &rebox_double, |
| 286 exit_point); | 304 exit_point); |
| 287 | 305 |
| (...skipping 369 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 657 var_transition.Bind(transition); | 675 var_transition.Bind(transition); |
| 658 Goto(&if_transition); | 676 Goto(&if_transition); |
| 659 } | 677 } |
| 660 | 678 |
| 661 Bind(&if_transition); | 679 Bind(&if_transition); |
| 662 { | 680 { |
| 663 Node* holder = p->receiver; | 681 Node* holder = p->receiver; |
| 664 Node* transition = var_transition.value(); | 682 Node* transition = var_transition.value(); |
| 665 Node* handler_word = SmiUntag(smi_handler); | 683 Node* handler_word = SmiUntag(smi_handler); |
| 666 | 684 |
| 667 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(transition)), miss); | 685 GotoIf(IsDeprecatedMap(transition), miss); |
| 668 | 686 |
| 669 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word); | 687 Node* handler_kind = DecodeWord<StoreHandler::KindBits>(handler_word); |
| 670 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kStoreNormal)), | 688 GotoIf(WordEqual(handler_kind, IntPtrConstant(StoreHandler::kStoreNormal)), |
| 671 &if_store_normal); | 689 &if_store_normal); |
| 672 GotoIf(WordEqual(handler_kind, | 690 GotoIf(WordEqual(handler_kind, |
| 673 IntPtrConstant(StoreHandler::kTransitionToConstant)), | 691 IntPtrConstant(StoreHandler::kTransitionToConstant)), |
| 674 &if_transition_to_constant); | 692 &if_transition_to_constant); |
| 675 | 693 |
| 676 // Handle transitioning field stores. | 694 // Handle transitioning field stores. |
| 677 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition, | 695 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition, |
| (...skipping 637 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1315 Bind(&return_undefined); | 1333 Bind(&return_undefined); |
| 1316 Return(UndefinedConstant()); | 1334 Return(UndefinedConstant()); |
| 1317 } | 1335 } |
| 1318 } | 1336 } |
| 1319 | 1337 |
| 1320 void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, | 1338 void AccessorAssembler::GenericPropertyLoad(Node* receiver, Node* receiver_map, |
| 1321 Node* instance_type, Node* key, | 1339 Node* instance_type, Node* key, |
| 1322 const LoadICParameters* p, | 1340 const LoadICParameters* p, |
| 1323 Label* slow, | 1341 Label* slow, |
| 1324 UseStubCache use_stub_cache) { | 1342 UseStubCache use_stub_cache) { |
| 1343 ExitPoint direct_exit(this); | |
| 1344 | |
| 1325 Comment("key is unique name"); | 1345 Comment("key is unique name"); |
| 1326 Label if_found_on_receiver(this), if_property_dictionary(this), | 1346 Label if_found_on_receiver(this), if_property_dictionary(this), |
| 1327 lookup_prototype_chain(this); | 1347 lookup_prototype_chain(this); |
| 1328 Variable var_details(this, MachineRepresentation::kWord32); | 1348 Variable var_details(this, MachineRepresentation::kWord32); |
| 1329 Variable var_value(this, MachineRepresentation::kTagged); | 1349 Variable var_value(this, MachineRepresentation::kTagged); |
| 1330 | 1350 |
| 1331 // Receivers requiring non-standard accesses (interceptors, access | 1351 // Receivers requiring non-standard accesses (interceptors, access |
| 1332 // checks, strings and string wrappers, proxies) are handled in the runtime. | 1352 // checks, strings and string wrappers, proxies) are handled in the runtime. |
| 1333 GotoIf(Int32LessThanOrEqual(instance_type, | 1353 GotoIf(Int32LessThanOrEqual(instance_type, |
| 1334 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), | 1354 Int32Constant(LAST_SPECIAL_RECEIVER_TYPE)), |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 1361 } | 1381 } |
| 1362 | 1382 |
| 1363 if (use_stub_cache == kUseStubCache) { | 1383 if (use_stub_cache == kUseStubCache) { |
| 1364 Bind(&stub_cache); | 1384 Bind(&stub_cache); |
| 1365 Comment("stub cache probe for fast property load"); | 1385 Comment("stub cache probe for fast property load"); |
| 1366 Variable var_handler(this, MachineRepresentation::kTagged); | 1386 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1367 Label found_handler(this, &var_handler), stub_cache_miss(this); | 1387 Label found_handler(this, &var_handler), stub_cache_miss(this); |
| 1368 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key, | 1388 TryProbeStubCache(isolate()->load_stub_cache(), receiver, key, |
| 1369 &found_handler, &var_handler, &stub_cache_miss); | 1389 &found_handler, &var_handler, &stub_cache_miss); |
| 1370 Bind(&found_handler); | 1390 Bind(&found_handler); |
| 1371 { HandleLoadICHandlerCase(p, var_handler.value(), slow); } | 1391 { HandleLoadICHandlerCase(p, var_handler.value(), slow, &direct_exit); } |
| 1372 | 1392 |
| 1373 Bind(&stub_cache_miss); | 1393 Bind(&stub_cache_miss); |
| 1374 { | 1394 { |
| 1375 // TODO(jkummerow): Check if the property exists on the prototype | 1395 // TODO(jkummerow): Check if the property exists on the prototype |
| 1376 // chain. If it doesn't, then there's no point in missing. | 1396 // chain. If it doesn't, then there's no point in missing. |
| 1377 Comment("KeyedLoadGeneric_miss"); | 1397 Comment("KeyedLoadGeneric_miss"); |
| 1378 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 1398 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
| 1379 p->name, p->slot, p->vector); | 1399 p->name, p->slot, p->vector); |
| 1380 } | 1400 } |
| 1381 } | 1401 } |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1569 | 1589 |
| 1570 Bind(&miss); | 1590 Bind(&miss); |
| 1571 { | 1591 { |
| 1572 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); | 1592 IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); |
| 1573 Goto(if_miss); | 1593 Goto(if_miss); |
| 1574 } | 1594 } |
| 1575 } | 1595 } |
| 1576 | 1596 |
| 1577 //////////////////// Entry points into private implementation (one per stub). | 1597 //////////////////// Entry points into private implementation (one per stub). |
| 1578 | 1598 |
| 1599 void AccessorAssembler::LoadIC_BytecodeHandler(const LoadICParameters* p, | |
| 1600 ExitPoint* exit_point) { | |
| 1601 // Must be kept in sync with LoadIC. | |
| 1602 | |
| 1603 // This function is hand-tuned to omit frame construction for common cases, | |
| 1604 // e.g.: monomorphic field and constant loads through smi handlers. | |
| 1605 // Polymorphic ICs with a hit in the first two entries also omit frames. | |
|
rmcilroy
2017/03/06 09:06:36
Out of interest, any reason only the first two ent
jgruber
2017/03/07 09:40:56
I reused the existing HandlePolymorphicCase. My as
| |
| 1606 // TODO(jgruber): Frame omission is fragile and can be affected by minor | |
| 1607 // changes in control flow and logic. We currently have no way of ensuring | |
| 1608 // that no frame is constructed, so it's easy to break this optimization by | |
| 1609 // accident. | |
|
rmcilroy
2017/03/06 09:06:36
There was a way to check this in Hydrogen code stu
jgruber
2017/03/07 09:40:56
Acknowledged. No idea how hard this would be, mayb
| |
| 1610 Label stub_call(this, Label::kDeferred), miss(this, Label::kDeferred); | |
| 1611 | |
| 1612 // Inlined fast path. | |
| 1613 { | |
| 1614 Comment("LoadIC_BytecodeHandler_fast"); | |
| 1615 | |
| 1616 Node* recv_map = LoadReceiverMap(p->receiver); | |
| 1617 GotoIf(IsDeprecatedMap(recv_map), &miss); | |
| 1618 | |
| 1619 Variable var_handler(this, MachineRepresentation::kTagged); | |
| 1620 Label try_polymorphic(this), if_handler(this, &var_handler); | |
| 1621 | |
| 1622 Node* feedback = | |
| 1623 TryMonomorphicCase(p->slot, p->vector, recv_map, &if_handler, | |
| 1624 &var_handler, &try_polymorphic); | |
| 1625 | |
| 1626 Bind(&if_handler); | |
| 1627 HandleLoadICHandlerCase(p, var_handler.value(), &miss, exit_point); | |
| 1628 | |
| 1629 Bind(&try_polymorphic); | |
| 1630 { | |
| 1631 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | |
| 1632 &stub_call); | |
| 1633 HandlePolymorphicCase(recv_map, feedback, &if_handler, &var_handler, | |
| 1634 &miss, 2); | |
| 1635 } | |
| 1636 } | |
| 1637 | |
| 1638 Bind(&stub_call); | |
| 1639 { | |
| 1640 Comment("LoadIC_BytecodeHandler_noninlined"); | |
| 1641 | |
| 1642 // Call into the stub that implements the non-inlined parts of LoadIC. | |
| 1643 Callable ic = CodeFactory::LoadICInOptimizedCode_Noninlined(isolate()); | |
| 1644 Node* code_target = HeapConstant(ic.code()); | |
| 1645 exit_point->ReturnCallStub(ic.descriptor(), code_target, p->context, | |
| 1646 p->receiver, p->name, p->slot, p->vector); | |
| 1647 } | |
| 1648 | |
| 1649 Bind(&miss); | |
| 1650 { | |
| 1651 Comment("LoadIC_BytecodeHandler_miss"); | |
| 1652 | |
| 1653 exit_point->ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, | |
| 1654 p->receiver, p->name, p->slot, p->vector); | |
| 1655 } | |
| 1656 } | |
| 1657 | |
| 1579 void AccessorAssembler::LoadIC(const LoadICParameters* p) { | 1658 void AccessorAssembler::LoadIC(const LoadICParameters* p) { |
| 1659 // Must be kept in sync with LoadIC_BytecodeHandler. | |
| 1660 | |
| 1661 ExitPoint direct_exit(this); | |
| 1662 | |
| 1580 Variable var_handler(this, MachineRepresentation::kTagged); | 1663 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1581 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), | 1664 Label if_handler(this, &var_handler), non_inlined(this, Label::kDeferred), |
| 1582 try_megamorphic(this, Label::kDeferred), | 1665 try_polymorphic(this), miss(this, Label::kDeferred); |
| 1583 try_uninitialized(this, Label::kDeferred), miss(this, Label::kDeferred); | |
| 1584 | 1666 |
| 1585 Node* receiver_map = LoadReceiverMap(p->receiver); | 1667 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1586 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1668 GotoIf(IsDeprecatedMap(receiver_map), &miss); |
| 1587 | 1669 |
| 1588 // Check monomorphic case. | 1670 // Check monomorphic case. |
| 1589 Node* feedback = | 1671 Node* feedback = |
| 1590 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1672 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1591 &var_handler, &try_polymorphic); | 1673 &var_handler, &try_polymorphic); |
| 1592 Bind(&if_handler); | 1674 Bind(&if_handler); |
| 1593 { HandleLoadICHandlerCase(p, var_handler.value(), &miss); } | 1675 HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit); |
| 1594 | 1676 |
| 1595 Bind(&try_polymorphic); | 1677 Bind(&try_polymorphic); |
| 1596 { | 1678 { |
| 1597 // Check polymorphic case. | 1679 // Check polymorphic case. |
| 1598 Comment("LoadIC_try_polymorphic"); | 1680 Comment("LoadIC_try_polymorphic"); |
| 1599 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | 1681 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
| 1600 &try_megamorphic); | 1682 &non_inlined); |
| 1601 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, | 1683 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
| 1602 &miss, 2); | 1684 &miss, 2); |
| 1603 } | 1685 } |
| 1604 | 1686 |
| 1605 Bind(&try_megamorphic); | 1687 Bind(&non_inlined); |
| 1688 LoadIC_Noninlined(p, receiver_map, feedback, &var_handler, &if_handler, &miss, | |
| 1689 &direct_exit); | |
| 1690 | |
| 1691 Bind(&miss); | |
| 1692 direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, | |
| 1693 p->name, p->slot, p->vector); | |
| 1694 } | |
| 1695 | |
| 1696 void AccessorAssembler::LoadIC_Noninlined(const LoadICParameters* p, | |
| 1697 Node* receiver_map, Node* feedback, | |
| 1698 Variable* var_handler, | |
| 1699 Label* if_handler, Label* miss, | |
| 1700 ExitPoint* exit_point) { | |
| 1701 Label try_uninitialized(this, Label::kDeferred); | |
| 1702 | |
| 1703 // Neither deprecated map nor monomorphic. These cases are handled in the | |
| 1704 // bytecode handler. | |
| 1705 CSA_ASSERT(this, Word32BinaryNot(IsDeprecatedMap(receiver_map))); | |
| 1706 CSA_ASSERT(this, | |
| 1707 WordNotEqual(receiver_map, LoadWeakCellValueUnchecked(feedback))); | |
| 1708 CSA_ASSERT(this, WordNotEqual(LoadMap(feedback), FixedArrayMapConstant())); | |
| 1709 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | |
| 1710 | |
| 1606 { | 1711 { |
| 1607 // Check megamorphic case. | 1712 // Check megamorphic case. |
| 1608 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 1713 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| 1609 &try_uninitialized); | 1714 &try_uninitialized); |
| 1610 | 1715 |
| 1611 TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name, | 1716 TryProbeStubCache(isolate()->load_stub_cache(), p->receiver, p->name, |
| 1612 &if_handler, &var_handler, &miss); | 1717 if_handler, var_handler, miss); |
| 1613 } | 1718 } |
| 1719 | |
| 1614 Bind(&try_uninitialized); | 1720 Bind(&try_uninitialized); |
| 1615 { | 1721 { |
| 1616 // Check uninitialized case. | 1722 // Check uninitialized case. |
| 1617 GotoIfNot( | 1723 GotoIfNot( |
| 1618 WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)), | 1724 WordEqual(feedback, LoadRoot(Heap::kuninitialized_symbolRootIndex)), |
| 1619 &miss); | 1725 miss); |
| 1620 TailCallStub(CodeFactory::LoadIC_Uninitialized(isolate()), p->context, | 1726 exit_point->ReturnCallStub(CodeFactory::LoadIC_Uninitialized(isolate()), |
| 1621 p->receiver, p->name, p->slot, p->vector); | 1727 p->context, p->receiver, p->name, p->slot, |
| 1622 } | 1728 p->vector); |
| 1623 Bind(&miss); | |
| 1624 { | |
| 1625 TailCallRuntime(Runtime::kLoadIC_Miss, p->context, p->receiver, p->name, | |
| 1626 p->slot, p->vector); | |
| 1627 } | 1729 } |
| 1628 } | 1730 } |
| 1629 | 1731 |
| 1630 void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) { | 1732 void AccessorAssembler::LoadIC_Uninitialized(const LoadICParameters* p) { |
| 1631 Label miss(this); | 1733 Label miss(this); |
| 1632 Node* receiver = p->receiver; | 1734 Node* receiver = p->receiver; |
| 1633 GotoIf(TaggedIsSmi(receiver), &miss); | 1735 GotoIf(TaggedIsSmi(receiver), &miss); |
| 1634 Node* receiver_map = LoadMap(receiver); | 1736 Node* receiver_map = LoadMap(receiver); |
| 1635 Node* instance_type = LoadMapInstanceType(receiver_map); | 1737 Node* instance_type = LoadMapInstanceType(receiver_map); |
| 1636 | 1738 |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1760 void AccessorAssembler::LoadGlobalIC_MissCase(const LoadICParameters* p, | 1862 void AccessorAssembler::LoadGlobalIC_MissCase(const LoadICParameters* p, |
| 1761 ExitPoint* exit_point) { | 1863 ExitPoint* exit_point) { |
| 1762 Comment("LoadGlobalIC_MissCase"); | 1864 Comment("LoadGlobalIC_MissCase"); |
| 1763 | 1865 |
| 1764 exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, | 1866 exit_point->ReturnCallRuntime(Runtime::kLoadGlobalIC_Miss, p->context, |
| 1765 p->name, p->slot, p->vector); | 1867 p->name, p->slot, p->vector); |
| 1766 } | 1868 } |
| 1767 | 1869 |
| 1768 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, | 1870 void AccessorAssembler::LoadGlobalIC(const LoadICParameters* p, |
| 1769 TypeofMode typeof_mode) { | 1871 TypeofMode typeof_mode) { |
| 1872 // Must be kept in sync with Interpreter::BuildLoadGlobal. | |
| 1873 | |
| 1770 ExitPoint direct_exit(this); | 1874 ExitPoint direct_exit(this); |
| 1771 | 1875 |
| 1772 Label try_handler(this), miss(this); | 1876 Label try_handler(this), miss(this); |
| 1773 LoadGlobalIC_TryPropertyCellCase(p->vector, p->slot, &direct_exit, | 1877 LoadGlobalIC_TryPropertyCellCase(p->vector, p->slot, &direct_exit, |
| 1774 &try_handler, &miss); | 1878 &try_handler, &miss); |
| 1775 | 1879 |
| 1776 Bind(&try_handler); | 1880 Bind(&try_handler); |
| 1777 LoadGlobalIC_TryHandlerCase(p, typeof_mode, &direct_exit, &miss); | 1881 LoadGlobalIC_TryHandlerCase(p, typeof_mode, &direct_exit, &miss); |
| 1778 | 1882 |
| 1779 Bind(&miss); | 1883 Bind(&miss); |
| 1780 LoadGlobalIC_MissCase(p, &direct_exit); | 1884 LoadGlobalIC_MissCase(p, &direct_exit); |
| 1781 } | 1885 } |
| 1782 | 1886 |
| 1783 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { | 1887 void AccessorAssembler::KeyedLoadIC(const LoadICParameters* p) { |
| 1888 ExitPoint direct_exit(this); | |
| 1889 | |
| 1784 Variable var_handler(this, MachineRepresentation::kTagged); | 1890 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1785 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), | 1891 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), |
| 1786 try_megamorphic(this, Label::kDeferred), | 1892 try_megamorphic(this, Label::kDeferred), |
| 1787 try_polymorphic_name(this, Label::kDeferred), | 1893 try_polymorphic_name(this, Label::kDeferred), |
| 1788 miss(this, Label::kDeferred); | 1894 miss(this, Label::kDeferred); |
| 1789 | 1895 |
| 1790 Node* receiver_map = LoadReceiverMap(p->receiver); | 1896 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1791 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1897 GotoIf(IsDeprecatedMap(receiver_map), &miss); |
| 1792 | 1898 |
| 1793 // Check monomorphic case. | 1899 // Check monomorphic case. |
| 1794 Node* feedback = | 1900 Node* feedback = |
| 1795 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1901 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1796 &var_handler, &try_polymorphic); | 1902 &var_handler, &try_polymorphic); |
| 1797 Bind(&if_handler); | 1903 Bind(&if_handler); |
| 1798 { HandleLoadICHandlerCase(p, var_handler.value(), &miss, kSupportElements); } | 1904 { |
| 1905 HandleLoadICHandlerCase(p, var_handler.value(), &miss, &direct_exit, | |
| 1906 kSupportElements); | |
| 1907 } | |
| 1799 | 1908 |
| 1800 Bind(&try_polymorphic); | 1909 Bind(&try_polymorphic); |
| 1801 { | 1910 { |
| 1802 // Check polymorphic case. | 1911 // Check polymorphic case. |
| 1803 Comment("KeyedLoadIC_try_polymorphic"); | 1912 Comment("KeyedLoadIC_try_polymorphic"); |
| 1804 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), | 1913 GotoIfNot(WordEqual(LoadMap(feedback), FixedArrayMapConstant()), |
| 1805 &try_megamorphic); | 1914 &try_megamorphic); |
| 1806 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, | 1915 HandlePolymorphicCase(receiver_map, feedback, &if_handler, &var_handler, |
| 1807 &miss, 2); | 1916 &miss, 2); |
| 1808 } | 1917 } |
| 1809 | 1918 |
| 1810 Bind(&try_megamorphic); | 1919 Bind(&try_megamorphic); |
| 1811 { | 1920 { |
| 1812 // Check megamorphic case. | 1921 // Check megamorphic case. |
| 1813 Comment("KeyedLoadIC_try_megamorphic"); | 1922 Comment("KeyedLoadIC_try_megamorphic"); |
| 1814 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 1923 GotoIfNot(WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| 1815 &try_polymorphic_name); | 1924 &try_polymorphic_name); |
| 1816 // TODO(jkummerow): Inline this? Or some of it? | 1925 // TODO(jkummerow): Inline this? Or some of it? |
| 1817 TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context, | 1926 TailCallStub(CodeFactory::KeyedLoadIC_Megamorphic(isolate()), p->context, |
| 1818 p->receiver, p->name, p->slot, p->vector); | 1927 p->receiver, p->name, p->slot, p->vector); |
| 1819 } | 1928 } |
| 1820 Bind(&try_polymorphic_name); | 1929 Bind(&try_polymorphic_name); |
| 1821 { | 1930 { |
| 1822 // We might have a name in feedback, and a fixed array in the next slot. | 1931 // We might have a name in feedback, and a fixed array in the next slot. |
| 1823 Comment("KeyedLoadIC_try_polymorphic_name"); | 1932 Comment("KeyedLoadIC_try_polymorphic_name"); |
| 1824 GotoIfNot(WordEqual(feedback, p->name), &miss); | 1933 GotoIfNot(WordEqual(feedback, p->name), &miss); |
| 1825 // If the name comparison succeeded, we know we have a fixed array with | 1934 // If the name comparison succeeded, we know we have a fixed array with |
| 1826 // at least one map/handler pair. | 1935 // at least one map/handler pair. |
| 1827 Node* offset = ElementOffsetFromIndex( | 1936 Node* array = LoadFeedbackSlot(p->vector, p->slot, kPointerSize); |
| 1828 p->slot, FAST_HOLEY_ELEMENTS, 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, | 1937 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss, |
| 1832 1); | 1938 1); |
| 1833 } | 1939 } |
| 1834 Bind(&miss); | 1940 Bind(&miss); |
| 1835 { | 1941 { |
| 1836 Comment("KeyedLoadIC_miss"); | 1942 Comment("KeyedLoadIC_miss"); |
| 1837 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, | 1943 TailCallRuntime(Runtime::kKeyedLoadIC_Miss, p->context, p->receiver, |
| 1838 p->name, p->slot, p->vector); | 1944 p->name, p->slot, p->vector); |
| 1839 } | 1945 } |
| 1840 } | 1946 } |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1874 p->name); | 1980 p->name); |
| 1875 } | 1981 } |
| 1876 } | 1982 } |
| 1877 | 1983 |
| 1878 void AccessorAssembler::StoreIC(const StoreICParameters* p) { | 1984 void AccessorAssembler::StoreIC(const StoreICParameters* p) { |
| 1879 Variable var_handler(this, MachineRepresentation::kTagged); | 1985 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1880 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), | 1986 Label if_handler(this, &var_handler), try_polymorphic(this, Label::kDeferred), |
| 1881 try_megamorphic(this, Label::kDeferred), miss(this, Label::kDeferred); | 1987 try_megamorphic(this, Label::kDeferred), miss(this, Label::kDeferred); |
| 1882 | 1988 |
| 1883 Node* receiver_map = LoadReceiverMap(p->receiver); | 1989 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1884 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 1990 GotoIf(IsDeprecatedMap(receiver_map), &miss); |
| 1885 | 1991 |
| 1886 // Check monomorphic case. | 1992 // Check monomorphic case. |
| 1887 Node* feedback = | 1993 Node* feedback = |
| 1888 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1994 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1889 &var_handler, &try_polymorphic); | 1995 &var_handler, &try_polymorphic); |
| 1890 Bind(&if_handler); | 1996 Bind(&if_handler); |
| 1891 { | 1997 { |
| 1892 Comment("StoreIC_if_handler"); | 1998 Comment("StoreIC_if_handler"); |
| 1893 HandleStoreICHandlerCase(p, var_handler.value(), &miss); | 1999 HandleStoreICHandlerCase(p, var_handler.value(), &miss); |
| 1894 } | 2000 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1925 Label miss(this, Label::kDeferred); | 2031 Label miss(this, Label::kDeferred); |
| 1926 { | 2032 { |
| 1927 Variable var_handler(this, MachineRepresentation::kTagged); | 2033 Variable var_handler(this, MachineRepresentation::kTagged); |
| 1928 | 2034 |
| 1929 Label if_handler(this, &var_handler), | 2035 Label if_handler(this, &var_handler), |
| 1930 try_polymorphic(this, Label::kDeferred), | 2036 try_polymorphic(this, Label::kDeferred), |
| 1931 try_megamorphic(this, Label::kDeferred), | 2037 try_megamorphic(this, Label::kDeferred), |
| 1932 try_polymorphic_name(this, Label::kDeferred); | 2038 try_polymorphic_name(this, Label::kDeferred); |
| 1933 | 2039 |
| 1934 Node* receiver_map = LoadReceiverMap(p->receiver); | 2040 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1935 GotoIf(IsSetWord32<Map::Deprecated>(LoadMapBitField3(receiver_map)), &miss); | 2041 GotoIf(IsDeprecatedMap(receiver_map), &miss); |
| 1936 | 2042 |
| 1937 // Check monomorphic case. | 2043 // Check monomorphic case. |
| 1938 Node* feedback = | 2044 Node* feedback = |
| 1939 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 2045 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1940 &var_handler, &try_polymorphic); | 2046 &var_handler, &try_polymorphic); |
| 1941 Bind(&if_handler); | 2047 Bind(&if_handler); |
| 1942 { | 2048 { |
| 1943 Comment("KeyedStoreIC_if_handler"); | 2049 Comment("KeyedStoreIC_if_handler"); |
| 1944 HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements); | 2050 HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements); |
| 1945 } | 2051 } |
| (...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); | 2112 p->context, p->receiver, p->name, p->value, p->slot, p->vector); |
| 2007 } | 2113 } |
| 2008 | 2114 |
| 2009 Bind(&try_polymorphic_name); | 2115 Bind(&try_polymorphic_name); |
| 2010 { | 2116 { |
| 2011 // We might have a name in feedback, and a fixed array in the next slot. | 2117 // We might have a name in feedback, and a fixed array in the next slot. |
| 2012 Comment("KeyedStoreIC_try_polymorphic_name"); | 2118 Comment("KeyedStoreIC_try_polymorphic_name"); |
| 2013 GotoIfNot(WordEqual(feedback, p->name), &miss); | 2119 GotoIfNot(WordEqual(feedback, p->name), &miss); |
| 2014 // If the name comparison succeeded, we know we have a FixedArray with | 2120 // If the name comparison succeeded, we know we have a FixedArray with |
| 2015 // at least one map/handler pair. | 2121 // at least one map/handler pair. |
| 2016 Node* offset = ElementOffsetFromIndex( | 2122 Node* array = LoadFeedbackSlot(p->vector, p->slot, kPointerSize); |
| 2017 p->slot, FAST_HOLEY_ELEMENTS, 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, | 2123 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, |
| 2021 &miss, 1); | 2124 &miss, 1); |
| 2022 } | 2125 } |
| 2023 } | 2126 } |
| 2024 Bind(&miss); | 2127 Bind(&miss); |
| 2025 { | 2128 { |
| 2026 Comment("KeyedStoreIC_miss"); | 2129 Comment("KeyedStoreIC_miss"); |
| 2027 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, | 2130 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, |
| 2028 p->vector, p->receiver, p->name); | 2131 p->vector, p->receiver, p->name); |
| 2029 } | 2132 } |
| 2030 } | 2133 } |
| 2031 | 2134 |
| 2032 //////////////////// Public methods. | 2135 //////////////////// Public methods. |
| 2033 | 2136 |
| 2034 void AccessorAssembler::GenerateLoadIC() { | 2137 void AccessorAssembler::GenerateLoadIC() { |
| 2035 typedef LoadWithVectorDescriptor Descriptor; | 2138 typedef LoadWithVectorDescriptor Descriptor; |
| 2036 | 2139 |
| 2037 Node* receiver = Parameter(Descriptor::kReceiver); | 2140 Node* receiver = Parameter(Descriptor::kReceiver); |
| 2038 Node* name = Parameter(Descriptor::kName); | 2141 Node* name = Parameter(Descriptor::kName); |
| 2039 Node* slot = Parameter(Descriptor::kSlot); | 2142 Node* slot = Parameter(Descriptor::kSlot); |
| 2040 Node* vector = Parameter(Descriptor::kVector); | 2143 Node* vector = Parameter(Descriptor::kVector); |
| 2041 Node* context = Parameter(Descriptor::kContext); | 2144 Node* context = Parameter(Descriptor::kContext); |
| 2042 | 2145 |
| 2043 LoadICParameters p(context, receiver, name, slot, vector); | 2146 LoadICParameters p(context, receiver, name, slot, vector); |
| 2044 LoadIC(&p); | 2147 LoadIC(&p); |
| 2045 } | 2148 } |
| 2046 | 2149 |
| 2150 void AccessorAssembler::GenerateLoadIC_Noninlined() { | |
| 2151 typedef LoadWithVectorDescriptor Descriptor; | |
| 2152 | |
| 2153 Node* receiver = Parameter(Descriptor::kReceiver); | |
| 2154 Node* name = Parameter(Descriptor::kName); | |
| 2155 Node* slot = Parameter(Descriptor::kSlot); | |
| 2156 Node* vector = Parameter(Descriptor::kVector); | |
| 2157 Node* context = Parameter(Descriptor::kContext); | |
| 2158 | |
| 2159 ExitPoint direct_exit(this); | |
| 2160 Variable var_handler(this, MachineRepresentation::kTagged); | |
| 2161 Label if_handler(this, &var_handler), miss(this, Label::kDeferred); | |
| 2162 | |
| 2163 Node* receiver_map = LoadReceiverMap(receiver); | |
| 2164 Node* feedback = LoadFeedbackSlot(vector, slot, 0); | |
| 2165 | |
| 2166 LoadICParameters p(context, receiver, name, slot, vector); | |
| 2167 LoadIC_Noninlined(&p, receiver_map, feedback, &var_handler, &if_handler, | |
| 2168 &miss, &direct_exit); | |
| 2169 | |
| 2170 Bind(&if_handler); | |
| 2171 HandleLoadICHandlerCase(&p, var_handler.value(), &miss, &direct_exit); | |
| 2172 | |
| 2173 Bind(&miss); | |
| 2174 direct_exit.ReturnCallRuntime(Runtime::kLoadIC_Miss, context, receiver, name, | |
| 2175 slot, vector); | |
| 2176 } | |
| 2177 | |
| 2047 void AccessorAssembler::GenerateLoadIC_Uninitialized() { | 2178 void AccessorAssembler::GenerateLoadIC_Uninitialized() { |
| 2048 typedef LoadWithVectorDescriptor Descriptor; | 2179 typedef LoadWithVectorDescriptor Descriptor; |
| 2049 | 2180 |
| 2050 Node* receiver = Parameter(Descriptor::kReceiver); | 2181 Node* receiver = Parameter(Descriptor::kReceiver); |
| 2051 Node* name = Parameter(Descriptor::kName); | 2182 Node* name = Parameter(Descriptor::kName); |
| 2052 Node* slot = Parameter(Descriptor::kSlot); | 2183 Node* slot = Parameter(Descriptor::kSlot); |
| 2053 Node* vector = Parameter(Descriptor::kVector); | 2184 Node* vector = Parameter(Descriptor::kVector); |
| 2054 Node* context = Parameter(Descriptor::kContext); | 2185 Node* context = Parameter(Descriptor::kContext); |
| 2055 | 2186 |
| 2056 LoadICParameters p(context, receiver, name, slot, vector); | 2187 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); | 2359 Node* context = Parameter(Descriptor::kContext); |
| 2229 Node* vector = LoadFeedbackVectorForStub(); | 2360 Node* vector = LoadFeedbackVectorForStub(); |
| 2230 | 2361 |
| 2231 Callable callable = | 2362 Callable callable = |
| 2232 CodeFactory::KeyedStoreICInOptimizedCode(isolate(), language_mode); | 2363 CodeFactory::KeyedStoreICInOptimizedCode(isolate(), language_mode); |
| 2233 TailCallStub(callable, context, receiver, name, value, slot, vector); | 2364 TailCallStub(callable, context, receiver, name, value, slot, vector); |
| 2234 } | 2365 } |
| 2235 | 2366 |
| 2236 } // namespace internal | 2367 } // namespace internal |
| 2237 } // namespace v8 | 2368 } // namespace v8 |
| OLD | NEW |