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 |