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