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 |