| 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 #include "src/ic/accessor-assembler-impl.h" | 6 #include "src/ic/accessor-assembler-impl.h" |
| 7 | 7 |
| 8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
| 9 #include "src/code-stubs.h" | 9 #include "src/code-stubs.h" |
| 10 #include "src/ic/handler-configuration.h" | 10 #include "src/ic/handler-configuration.h" |
| (...skipping 454 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 465 Variable var_smi_handler(this, MachineRepresentation::kTagged); | 465 Variable var_smi_handler(this, MachineRepresentation::kTagged); |
| 466 Label if_smi_handler(this); | 466 Label if_smi_handler(this); |
| 467 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, | 467 HandleLoadICProtoHandlerCase(&p, handler, &var_holder, &var_smi_handler, |
| 468 &if_smi_handler, miss, | 468 &if_smi_handler, miss, |
| 469 throw_reference_error_if_nonexistent); | 469 throw_reference_error_if_nonexistent); |
| 470 Bind(&if_smi_handler); | 470 Bind(&if_smi_handler); |
| 471 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), | 471 HandleLoadICSmiHandlerCase(&p, var_holder.value(), var_smi_handler.value(), |
| 472 miss, kOnlyProperties); | 472 miss, kOnlyProperties); |
| 473 } | 473 } |
| 474 | 474 |
| 475 void AccessorAssemblerImpl::HandleStoreICHandlerCase( | 475 void AccessorAssemblerImpl::HandleStoreICHandlerCase(const StoreICParameters* p, |
| 476 const StoreICParameters* p, Node* handler, Label* miss, | 476 Node* handler, |
| 477 ElementSupport support_elements) { | 477 Label* miss) { |
| 478 Label if_smi_handler(this), if_nonsmi_handler(this); | 478 Label if_smi_handler(this); |
| 479 Label if_proto_handler(this), if_element_handler(this), call_handler(this); | 479 Label try_proto_handler(this), call_handler(this); |
| 480 | 480 |
| 481 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_handler); | 481 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); |
| 482 | 482 |
| 483 // |handler| is a Smi, encoding what to do. See SmiHandler methods | 483 // |handler| is a Smi, encoding what to do. See SmiHandler methods |
| 484 // for the encoding format. | 484 // for the encoding format. |
| 485 Bind(&if_smi_handler); | 485 Bind(&if_smi_handler); |
| 486 { | 486 { |
| 487 Node* holder = p->receiver; | 487 Node* holder = p->receiver; |
| 488 Node* handler_word = SmiUntag(handler); | 488 Node* handler_word = SmiUntag(handler); |
| 489 | 489 |
| 490 // Handle non-transitioning field stores. | 490 // Handle non-transitioning field stores. |
| 491 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, nullptr, miss); | 491 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, nullptr, miss); |
| 492 } | 492 } |
| 493 | 493 |
| 494 Bind(&if_nonsmi_handler); | 494 Bind(&try_proto_handler); |
| 495 { | 495 { |
| 496 Node* handler_map = LoadMap(handler); | 496 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); |
| 497 if (support_elements == kSupportElements) { | |
| 498 GotoIf(IsTuple2Map(handler_map), &if_element_handler); | |
| 499 } | |
| 500 Branch(IsCodeMap(handler_map), &call_handler, &if_proto_handler); | |
| 501 } | |
| 502 | |
| 503 if (support_elements == kSupportElements) { | |
| 504 Bind(&if_element_handler); | |
| 505 { HandleStoreICElementHandlerCase(p, handler, miss); } | |
| 506 } | |
| 507 | |
| 508 Bind(&if_proto_handler); | |
| 509 { | |
| 510 HandleStoreICProtoHandler(p, handler, miss); | 497 HandleStoreICProtoHandler(p, handler, miss); |
| 511 } | 498 } |
| 512 | 499 |
| 513 // |handler| is a heap object. Must be code, call it. | 500 // |handler| is a heap object. Must be code, call it. |
| 514 Bind(&call_handler); | 501 Bind(&call_handler); |
| 515 { | 502 { |
| 516 StoreWithVectorDescriptor descriptor(isolate()); | 503 StoreWithVectorDescriptor descriptor(isolate()); |
| 517 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, | 504 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, |
| 518 p->value, p->slot, p->vector); | 505 p->value, p->slot, p->vector); |
| 519 } | 506 } |
| 520 } | 507 } |
| 521 | 508 |
| 522 void AccessorAssemblerImpl::HandleStoreICElementHandlerCase( | |
| 523 const StoreICParameters* p, Node* handler, Label* miss) { | |
| 524 Comment("HandleStoreICElementHandlerCase"); | |
| 525 Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset); | |
| 526 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); | |
| 527 GotoIf(WordNotEqual(cell_value, | |
| 528 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), | |
| 529 miss); | |
| 530 | |
| 531 Node* code_handler = LoadObjectField(handler, Tuple2::kValue2Offset); | |
| 532 CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler))); | |
| 533 | |
| 534 StoreWithVectorDescriptor descriptor(isolate()); | |
| 535 TailCallStub(descriptor, code_handler, p->context, p->receiver, p->name, | |
| 536 p->value, p->slot, p->vector); | |
| 537 } | |
| 538 | |
| 539 void AccessorAssemblerImpl::HandleStoreICProtoHandler( | 509 void AccessorAssemblerImpl::HandleStoreICProtoHandler( |
| 540 const StoreICParameters* p, Node* handler, Label* miss) { | 510 const StoreICParameters* p, Node* handler, Label* miss) { |
| 541 // IC dispatchers rely on these assumptions to be held. | 511 // IC dispatchers rely on these assumptions to be held. |
| 542 STATIC_ASSERT(FixedArray::kLengthOffset == | 512 STATIC_ASSERT(FixedArray::kLengthOffset == |
| 543 StoreHandler::kTransitionCellOffset); | 513 StoreHandler::kTransitionCellOffset); |
| 544 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex), | 514 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex), |
| 545 StoreHandler::kSmiHandlerOffset); | 515 StoreHandler::kSmiHandlerOffset); |
| 546 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex), | 516 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex), |
| 547 StoreHandler::kValidityCellOffset); | 517 StoreHandler::kValidityCellOffset); |
| 548 | 518 |
| (...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1529 | 1499 |
| 1530 Node* receiver_map = LoadReceiverMap(p->receiver); | 1500 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1531 | 1501 |
| 1532 // Check monomorphic case. | 1502 // Check monomorphic case. |
| 1533 Node* feedback = | 1503 Node* feedback = |
| 1534 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1504 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1535 &var_handler, &try_polymorphic); | 1505 &var_handler, &try_polymorphic); |
| 1536 Bind(&if_handler); | 1506 Bind(&if_handler); |
| 1537 { | 1507 { |
| 1538 Comment("KeyedStoreIC_if_handler"); | 1508 Comment("KeyedStoreIC_if_handler"); |
| 1539 HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements); | 1509 HandleStoreICHandlerCase(p, var_handler.value(), &miss); |
| 1540 } | 1510 } |
| 1541 | 1511 |
| 1542 Bind(&try_polymorphic); | 1512 Bind(&try_polymorphic); |
| 1543 { | 1513 { |
| 1544 // CheckPolymorphic case. | 1514 // CheckPolymorphic case. |
| 1545 Comment("KeyedStoreIC_try_polymorphic"); | 1515 Comment("KeyedStoreIC_try_polymorphic"); |
| 1546 GotoUnless( | 1516 GotoUnless( |
| 1547 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 1517 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| 1548 &try_megamorphic); | 1518 &try_megamorphic); |
| 1549 Label if_transition_handler(this); | 1519 Label if_transition_handler(this); |
| 1550 Variable var_transition_map_cell(this, MachineRepresentation::kTagged); | 1520 Variable var_transition_map_cell(this, MachineRepresentation::kTagged); |
| 1551 HandleKeyedStorePolymorphicCase(receiver_map, feedback, &if_handler, | 1521 HandleKeyedStorePolymorphicCase(receiver_map, feedback, &if_handler, |
| 1552 &var_handler, &if_transition_handler, | 1522 &var_handler, &if_transition_handler, |
| 1553 &var_transition_map_cell, &miss); | 1523 &var_transition_map_cell, &miss); |
| 1554 Bind(&if_transition_handler); | 1524 Bind(&if_transition_handler); |
| 1555 Comment("KeyedStoreIC_polymorphic_transition"); | 1525 Comment("KeyedStoreIC_polymorphic_transition"); |
| 1556 { | 1526 Node* transition_map = |
| 1557 Node* handler = var_handler.value(); | 1527 LoadWeakCellValue(var_transition_map_cell.value(), &miss); |
| 1558 CSA_ASSERT(this, IsTuple2Map(LoadMap(handler))); | 1528 StoreTransitionDescriptor descriptor(isolate()); |
| 1559 | 1529 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, |
| 1560 // Check validity cell. | 1530 p->name, transition_map, p->value, p->slot, p->vector); |
| 1561 Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset); | |
| 1562 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); | |
| 1563 GotoIf(WordNotEqual(cell_value, | |
| 1564 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), | |
| 1565 &miss); | |
| 1566 | |
| 1567 Node* code_handler = LoadObjectField(handler, Tuple2::kValue2Offset); | |
| 1568 CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler))); | |
| 1569 | |
| 1570 Node* transition_map = | |
| 1571 LoadWeakCellValue(var_transition_map_cell.value(), &miss); | |
| 1572 StoreTransitionDescriptor descriptor(isolate()); | |
| 1573 TailCallStub(descriptor, code_handler, p->context, p->receiver, p->name, | |
| 1574 transition_map, p->value, p->slot, p->vector); | |
| 1575 } | |
| 1576 } | 1531 } |
| 1577 | 1532 |
| 1578 Bind(&try_megamorphic); | 1533 Bind(&try_megamorphic); |
| 1579 { | 1534 { |
| 1580 // Check megamorphic case. | 1535 // Check megamorphic case. |
| 1581 Comment("KeyedStoreIC_try_megamorphic"); | 1536 Comment("KeyedStoreIC_try_megamorphic"); |
| 1582 GotoUnless( | 1537 GotoUnless( |
| 1583 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 1538 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| 1584 &try_polymorphic_name); | 1539 &try_polymorphic_name); |
| 1585 TailCallStub( | 1540 TailCallStub( |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1812 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( | 1767 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( |
| 1813 CodeAssemblerState* state, LanguageMode language_mode) { | 1768 CodeAssemblerState* state, LanguageMode language_mode) { |
| 1814 AccessorAssemblerImpl assembler(state); | 1769 AccessorAssemblerImpl assembler(state); |
| 1815 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); | 1770 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); |
| 1816 } | 1771 } |
| 1817 | 1772 |
| 1818 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE | 1773 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE |
| 1819 | 1774 |
| 1820 } // namespace internal | 1775 } // namespace internal |
| 1821 } // namespace v8 | 1776 } // namespace v8 |
| OLD | NEW |