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 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(const StoreICParameters* p, | 475 void AccessorAssemblerImpl::HandleStoreICHandlerCase( |
| 476 Node* handler, | 476 const StoreICParameters* p, Node* handler, Label* miss, |
| 477 Label* miss) { | 477 ElementSupport support_elements) { |
| 478 Label if_smi_handler(this); | 478 Label if_smi_handler(this), if_nonsmi_handler(this); |
| 479 Label try_proto_handler(this), call_handler(this); | 479 Label if_proto_handler(this), if_element_handler(this), call_handler(this); |
| 480 | 480 |
| 481 Branch(TaggedIsSmi(handler), &if_smi_handler, &try_proto_handler); | 481 Branch(TaggedIsSmi(handler), &if_smi_handler, &if_nonsmi_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(&try_proto_handler); | 494 Bind(&if_nonsmi_handler); |
| 495 { | 495 { |
| 496 GotoIf(IsCodeMap(LoadMap(handler)), &call_handler); | 496 Node* handler_map = LoadMap(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 { | |
| 497 HandleStoreICProtoHandler(p, handler, miss); | 510 HandleStoreICProtoHandler(p, handler, miss); |
| 498 } | 511 } |
| 499 | 512 |
| 500 // |handler| is a heap object. Must be code, call it. | 513 // |handler| is a heap object. Must be code, call it. |
| 501 Bind(&call_handler); | 514 Bind(&call_handler); |
| 502 { | 515 { |
| 503 StoreWithVectorDescriptor descriptor(isolate()); | 516 StoreWithVectorDescriptor descriptor(isolate()); |
| 504 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, | 517 TailCallStub(descriptor, handler, p->context, p->receiver, p->name, |
| 505 p->value, p->slot, p->vector); | 518 p->value, p->slot, p->vector); |
| 506 } | 519 } |
| 507 } | 520 } |
| 508 | 521 |
| 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 | |
| 509 void AccessorAssemblerImpl::HandleStoreICProtoHandler( | 539 void AccessorAssemblerImpl::HandleStoreICProtoHandler( |
| 510 const StoreICParameters* p, Node* handler, Label* miss) { | 540 const StoreICParameters* p, Node* handler, Label* miss) { |
| 511 // IC dispatchers rely on these assumptions to be held. | 541 // IC dispatchers rely on these assumptions to be held. |
| 512 STATIC_ASSERT(FixedArray::kLengthOffset == | 542 STATIC_ASSERT(FixedArray::kLengthOffset == |
| 513 StoreHandler::kTransitionCellOffset); | 543 StoreHandler::kTransitionCellOffset); |
| 514 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex), | 544 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kSmiHandlerIndex), |
| 515 StoreHandler::kSmiHandlerOffset); | 545 StoreHandler::kSmiHandlerOffset); |
| 516 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex), | 546 DCHECK_EQ(FixedArray::OffsetOfElementAt(StoreHandler::kValidityCellIndex), |
| 517 StoreHandler::kValidityCellOffset); | 547 StoreHandler::kValidityCellOffset); |
| 518 | 548 |
| (...skipping 980 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1499 | 1529 |
| 1500 Node* receiver_map = LoadReceiverMap(p->receiver); | 1530 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1501 | 1531 |
| 1502 // Check monomorphic case. | 1532 // Check monomorphic case. |
| 1503 Node* feedback = | 1533 Node* feedback = |
| 1504 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1534 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1505 &var_handler, &try_polymorphic); | 1535 &var_handler, &try_polymorphic); |
| 1506 Bind(&if_handler); | 1536 Bind(&if_handler); |
| 1507 { | 1537 { |
| 1508 Comment("KeyedStoreIC_if_handler"); | 1538 Comment("KeyedStoreIC_if_handler"); |
| 1509 HandleStoreICHandlerCase(p, var_handler.value(), &miss); | 1539 HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements); |
| 1510 } | 1540 } |
| 1511 | 1541 |
| 1512 Bind(&try_polymorphic); | 1542 Bind(&try_polymorphic); |
| 1513 { | 1543 { |
| 1514 // CheckPolymorphic case. | 1544 // CheckPolymorphic case. |
| 1515 Comment("KeyedStoreIC_try_polymorphic"); | 1545 Comment("KeyedStoreIC_try_polymorphic"); |
| 1516 GotoUnless( | 1546 GotoUnless( |
| 1517 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | 1547 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), |
| 1518 &try_megamorphic); | 1548 &try_megamorphic); |
| 1519 Label if_transition_handler(this); | 1549 Label if_transition_handler(this); |
| 1520 Variable var_transition_map_cell(this, MachineRepresentation::kTagged); | 1550 Variable var_transition_map_cell(this, MachineRepresentation::kTagged); |
| 1521 HandleKeyedStorePolymorphicCase(receiver_map, feedback, &if_handler, | 1551 HandleKeyedStorePolymorphicCase(receiver_map, feedback, &if_handler, |
| 1522 &var_handler, &if_transition_handler, | 1552 &var_handler, &if_transition_handler, |
| 1523 &var_transition_map_cell, &miss); | 1553 &var_transition_map_cell, &miss); |
| 1524 Bind(&if_transition_handler); | 1554 Bind(&if_transition_handler); |
| 1525 Comment("KeyedStoreIC_polymorphic_transition"); | 1555 Comment("KeyedStoreIC_polymorphic_transition"); |
| 1526 Node* transition_map = | 1556 { |
| 1527 LoadWeakCellValue(var_transition_map_cell.value(), &miss); | 1557 Node* handler = var_handler.value(); |
| 1528 StoreTransitionDescriptor descriptor(isolate()); | 1558 CSA_ASSERT(this, IsTuple2Map(LoadMap(handler))); |
| 1529 TailCallStub(descriptor, var_handler.value(), p->context, p->receiver, | 1559 |
| 1530 p->name, transition_map, p->value, p->slot, p->vector); | 1560 // Check validity cell. |
| 1561 // HandleStoreICElementHandlerCase(p, handler, miss); | |
|
Jakob Kummerow
2016/11/28 18:48:05
leftover?
Igor Sheludko
2016/11/28 22:25:54
Done.
| |
| 1562 | |
| 1563 Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset); | |
| 1564 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); | |
| 1565 GotoIf(WordNotEqual(cell_value, | |
| 1566 SmiConstant(Smi::FromInt(Map::kPrototypeChainValid))), | |
| 1567 &miss); | |
| 1568 | |
| 1569 Node* code_handler = LoadObjectField(handler, Tuple2::kValue2Offset); | |
| 1570 CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler))); | |
| 1571 | |
| 1572 Node* transition_map = | |
| 1573 LoadWeakCellValue(var_transition_map_cell.value(), &miss); | |
| 1574 StoreTransitionDescriptor descriptor(isolate()); | |
| 1575 TailCallStub(descriptor, code_handler, p->context, p->receiver, p->name, | |
| 1576 transition_map, p->value, p->slot, p->vector); | |
| 1577 } | |
| 1531 } | 1578 } |
| 1532 | 1579 |
| 1533 Bind(&try_megamorphic); | 1580 Bind(&try_megamorphic); |
| 1534 { | 1581 { |
| 1535 // Check megamorphic case. | 1582 // Check megamorphic case. |
| 1536 Comment("KeyedStoreIC_try_megamorphic"); | 1583 Comment("KeyedStoreIC_try_megamorphic"); |
| 1537 GotoUnless( | 1584 GotoUnless( |
| 1538 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | 1585 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), |
| 1539 &try_polymorphic_name); | 1586 &try_polymorphic_name); |
| 1540 TailCallStub( | 1587 TailCallStub( |
| (...skipping 226 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1767 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( | 1814 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( |
| 1768 CodeAssemblerState* state, LanguageMode language_mode) { | 1815 CodeAssemblerState* state, LanguageMode language_mode) { |
| 1769 AccessorAssemblerImpl assembler(state); | 1816 AccessorAssemblerImpl assembler(state); |
| 1770 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); | 1817 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); |
| 1771 } | 1818 } |
| 1772 | 1819 |
| 1773 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE | 1820 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE |
| 1774 | 1821 |
| 1775 } // namespace internal | 1822 } // namespace internal |
| 1776 } // namespace v8 | 1823 } // namespace v8 |
| OLD | NEW |