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 785 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 796 // Handled by if_fast_holey_double. | 796 // Handled by if_fast_holey_double. |
| 797 FAST_HOLEY_DOUBLE_ELEMENTS}; | 797 FAST_HOLEY_DOUBLE_ELEMENTS}; |
| 798 Label* labels[] = {// FAST_{SMI,}_ELEMENTS | 798 Label* labels[] = {// FAST_{SMI,}_ELEMENTS |
| 799 &if_fast_packed, &if_fast_packed, | 799 &if_fast_packed, &if_fast_packed, |
| 800 // FAST_HOLEY_{SMI,}_ELEMENTS | 800 // FAST_HOLEY_{SMI,}_ELEMENTS |
| 801 &if_fast_holey, &if_fast_holey, | 801 &if_fast_holey, &if_fast_holey, |
| 802 // FAST_DOUBLE_ELEMENTS | 802 // FAST_DOUBLE_ELEMENTS |
| 803 &if_fast_double, | 803 &if_fast_double, |
| 804 // FAST_HOLEY_DOUBLE_ELEMENTS | 804 // FAST_HOLEY_DOUBLE_ELEMENTS |
| 805 &if_fast_holey_double}; | 805 &if_fast_holey_double}; |
| 806 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, | 806 Switch(TruncateWordToWord32(elements_kind), unimplemented_elements_kind, |
| 807 arraysize(kinds)); | 807 kinds, labels, arraysize(kinds)); |
| 808 | 808 |
| 809 Bind(&if_fast_packed); | 809 Bind(&if_fast_packed); |
| 810 { | 810 { |
| 811 Comment("fast packed elements"); | 811 Comment("fast packed elements"); |
| 812 Return(LoadFixedArrayElement(elements, intptr_index, 0, INTPTR_PARAMETERS)); | 812 Return(LoadFixedArrayElement(elements, intptr_index, 0, INTPTR_PARAMETERS)); |
| 813 } | 813 } |
| 814 | 814 |
| 815 Bind(&if_fast_holey); | 815 Bind(&if_fast_holey); |
| 816 { | 816 { |
| 817 Comment("fast holey elements"); | 817 Comment("fast holey elements"); |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 874 Return(LoadFixedArrayElement(elements, value_index, 0, INTPTR_PARAMETERS)); | 874 Return(LoadFixedArrayElement(elements, value_index, 0, INTPTR_PARAMETERS)); |
| 875 } | 875 } |
| 876 | 876 |
| 877 Bind(&if_typed_array); | 877 Bind(&if_typed_array); |
| 878 { | 878 { |
| 879 Comment("typed elements"); | 879 Comment("typed elements"); |
| 880 // Check if buffer has been neutered. | 880 // Check if buffer has been neutered. |
| 881 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 881 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
| 882 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, | 882 Node* bitfield = LoadObjectField(buffer, JSArrayBuffer::kBitFieldOffset, |
| 883 MachineType::Uint32()); | 883 MachineType::Uint32()); |
| 884 Node* neutered_bit = | 884 GotoIf(IsSetWord32<JSArrayBuffer::WasNeutered>(bitfield), miss); |
|
Igor Sheludko
2016/12/07 10:20:42
Drive-by cleanup.
| |
| 885 Word32And(bitfield, Int32Constant(JSArrayBuffer::WasNeutered::kMask)); | |
| 886 GotoUnless(Word32Equal(neutered_bit, Int32Constant(0)), miss); | |
| 887 | 885 |
| 888 // Bounds check. | 886 // Bounds check. |
| 889 Node* length = | 887 Node* length = |
| 890 SmiUntag(LoadObjectField(object, JSTypedArray::kLengthOffset)); | 888 SmiUntag(LoadObjectField(object, JSTypedArray::kLengthOffset)); |
| 891 GotoUnless(UintPtrLessThan(intptr_index, length), out_of_bounds); | 889 GotoUnless(UintPtrLessThan(intptr_index, length), out_of_bounds); |
| 892 | 890 |
| 893 // Backing store = external_pointer + base_pointer. | 891 // Backing store = external_pointer + base_pointer. |
| 894 Node* external_pointer = | 892 Node* external_pointer = |
| 895 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, | 893 LoadObjectField(elements, FixedTypedArrayBase::kExternalPointerOffset, |
| 896 MachineType::Pointer()); | 894 MachineType::Pointer()); |
| 897 Node* base_pointer = | 895 Node* base_pointer = |
| 898 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset); | 896 LoadObjectField(elements, FixedTypedArrayBase::kBasePointerOffset, |
| 897 MachineType::Pointer()); | |
| 899 Node* backing_store = IntPtrAdd(external_pointer, base_pointer); | 898 Node* backing_store = IntPtrAdd(external_pointer, base_pointer); |
| 900 | 899 |
| 901 Label uint8_elements(this), int8_elements(this), uint16_elements(this), | 900 Label uint8_elements(this), int8_elements(this), uint16_elements(this), |
| 902 int16_elements(this), uint32_elements(this), int32_elements(this), | 901 int16_elements(this), uint32_elements(this), int32_elements(this), |
| 903 float32_elements(this), float64_elements(this); | 902 float32_elements(this), float64_elements(this); |
| 904 Label* elements_kind_labels[] = { | 903 Label* elements_kind_labels[] = { |
| 905 &uint8_elements, &uint8_elements, &int8_elements, | 904 &uint8_elements, &uint8_elements, &int8_elements, |
| 906 &uint16_elements, &int16_elements, &uint32_elements, | 905 &uint16_elements, &int16_elements, &uint32_elements, |
| 907 &int32_elements, &float32_elements, &float64_elements}; | 906 &int32_elements, &float32_elements, &float64_elements}; |
| 908 int32_t elements_kinds[] = { | 907 int32_t elements_kinds[] = { |
| 909 UINT8_ELEMENTS, UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS, | 908 UINT8_ELEMENTS, UINT8_CLAMPED_ELEMENTS, INT8_ELEMENTS, |
| 910 UINT16_ELEMENTS, INT16_ELEMENTS, UINT32_ELEMENTS, | 909 UINT16_ELEMENTS, INT16_ELEMENTS, UINT32_ELEMENTS, |
| 911 INT32_ELEMENTS, FLOAT32_ELEMENTS, FLOAT64_ELEMENTS}; | 910 INT32_ELEMENTS, FLOAT32_ELEMENTS, FLOAT64_ELEMENTS}; |
| 912 const size_t kTypedElementsKindCount = | 911 const size_t kTypedElementsKindCount = |
| 913 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - | 912 LAST_FIXED_TYPED_ARRAY_ELEMENTS_KIND - |
| 914 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1; | 913 FIRST_FIXED_TYPED_ARRAY_ELEMENTS_KIND + 1; |
| 915 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); | 914 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kinds)); |
| 916 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); | 915 DCHECK_EQ(kTypedElementsKindCount, arraysize(elements_kind_labels)); |
| 917 Switch(elements_kind, miss, elements_kinds, elements_kind_labels, | 916 Switch(TruncateWordToWord32(elements_kind), miss, elements_kinds, |
| 918 kTypedElementsKindCount); | 917 elements_kind_labels, kTypedElementsKindCount); |
| 919 Bind(&uint8_elements); | 918 Bind(&uint8_elements); |
| 920 { | 919 { |
| 921 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. | 920 Comment("UINT8_ELEMENTS"); // Handles UINT8_CLAMPED_ELEMENTS too. |
| 922 Return(SmiTag(Load(MachineType::Uint8(), backing_store, intptr_index))); | 921 Node* element = Load(MachineType::Uint8(), backing_store, intptr_index); |
| 922 Return(SmiFromWord32(element)); | |
| 923 } | 923 } |
| 924 Bind(&int8_elements); | 924 Bind(&int8_elements); |
| 925 { | 925 { |
| 926 Comment("INT8_ELEMENTS"); | 926 Comment("INT8_ELEMENTS"); |
| 927 Return(SmiTag(Load(MachineType::Int8(), backing_store, intptr_index))); | 927 Node* element = Load(MachineType::Int8(), backing_store, intptr_index); |
| 928 Return(SmiFromWord32(element)); | |
| 928 } | 929 } |
| 929 Bind(&uint16_elements); | 930 Bind(&uint16_elements); |
| 930 { | 931 { |
| 931 Comment("UINT16_ELEMENTS"); | 932 Comment("UINT16_ELEMENTS"); |
| 932 Node* index = WordShl(intptr_index, IntPtrConstant(1)); | 933 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
| 933 Return(SmiTag(Load(MachineType::Uint16(), backing_store, index))); | 934 Node* element = Load(MachineType::Uint16(), backing_store, index); |
| 935 Return(SmiFromWord32(element)); | |
| 934 } | 936 } |
| 935 Bind(&int16_elements); | 937 Bind(&int16_elements); |
| 936 { | 938 { |
| 937 Comment("INT16_ELEMENTS"); | 939 Comment("INT16_ELEMENTS"); |
| 938 Node* index = WordShl(intptr_index, IntPtrConstant(1)); | 940 Node* index = WordShl(intptr_index, IntPtrConstant(1)); |
| 939 Return(SmiTag(Load(MachineType::Int16(), backing_store, index))); | 941 Node* element = Load(MachineType::Int16(), backing_store, index); |
| 942 Return(SmiFromWord32(element)); | |
| 940 } | 943 } |
| 941 Bind(&uint32_elements); | 944 Bind(&uint32_elements); |
| 942 { | 945 { |
| 943 Comment("UINT32_ELEMENTS"); | 946 Comment("UINT32_ELEMENTS"); |
| 944 Node* index = WordShl(intptr_index, IntPtrConstant(2)); | 947 Node* index = WordShl(intptr_index, IntPtrConstant(2)); |
| 945 Node* element = Load(MachineType::Uint32(), backing_store, index); | 948 Node* element = Load(MachineType::Uint32(), backing_store, index); |
| 946 Return(ChangeUint32ToTagged(element)); | 949 Return(ChangeUint32ToTagged(element)); |
| 947 } | 950 } |
| 948 Bind(&int32_elements); | 951 Bind(&int32_elements); |
| 949 { | 952 { |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1027 // Compute the hash of the name (use entire hash field). | 1030 // Compute the hash of the name (use entire hash field). |
| 1028 Node* hash_field = LoadNameHashField(name); | 1031 Node* hash_field = LoadNameHashField(name); |
| 1029 CSA_ASSERT(this, | 1032 CSA_ASSERT(this, |
| 1030 Word32Equal(Word32And(hash_field, | 1033 Word32Equal(Word32And(hash_field, |
| 1031 Int32Constant(Name::kHashNotComputedMask)), | 1034 Int32Constant(Name::kHashNotComputedMask)), |
| 1032 Int32Constant(0))); | 1035 Int32Constant(0))); |
| 1033 | 1036 |
| 1034 // Using only the low bits in 64-bit mode is unlikely to increase the | 1037 // Using only the low bits in 64-bit mode is unlikely to increase the |
| 1035 // risk of collision even if the heap is spread over an area larger than | 1038 // risk of collision even if the heap is spread over an area larger than |
| 1036 // 4Gb (and not at all if it isn't). | 1039 // 4Gb (and not at all if it isn't). |
| 1037 Node* hash = Int32Add(hash_field, map); | 1040 Node* map32 = TruncateWordToWord32(BitcastTaggedToWord(map)); |
| 1041 Node* hash = Int32Add(hash_field, map32); | |
| 1038 // Base the offset on a simple combination of name and map. | 1042 // Base the offset on a simple combination of name and map. |
| 1039 hash = Word32Xor(hash, Int32Constant(StubCache::kPrimaryMagic)); | 1043 hash = Word32Xor(hash, Int32Constant(StubCache::kPrimaryMagic)); |
| 1040 uint32_t mask = (StubCache::kPrimaryTableSize - 1) | 1044 uint32_t mask = (StubCache::kPrimaryTableSize - 1) |
| 1041 << StubCache::kCacheIndexShift; | 1045 << StubCache::kCacheIndexShift; |
| 1042 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask))); | 1046 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask))); |
| 1043 } | 1047 } |
| 1044 | 1048 |
| 1045 Node* AccessorAssemblerImpl::StubCacheSecondaryOffset(Node* name, Node* seed) { | 1049 Node* AccessorAssemblerImpl::StubCacheSecondaryOffset(Node* name, Node* seed) { |
| 1046 // See v8::internal::StubCache::SecondaryOffset(). | 1050 // See v8::internal::StubCache::SecondaryOffset(). |
| 1047 | 1051 |
| 1048 // Use the seed from the primary cache in the secondary cache. | 1052 // Use the seed from the primary cache in the secondary cache. |
| 1049 Node* hash = Int32Sub(seed, name); | 1053 Node* name32 = TruncateWordToWord32(BitcastTaggedToWord(name)); |
| 1054 Node* hash = Int32Sub(TruncateWordToWord32(seed), name32); | |
| 1050 hash = Int32Add(hash, Int32Constant(StubCache::kSecondaryMagic)); | 1055 hash = Int32Add(hash, Int32Constant(StubCache::kSecondaryMagic)); |
| 1051 int32_t mask = (StubCache::kSecondaryTableSize - 1) | 1056 int32_t mask = (StubCache::kSecondaryTableSize - 1) |
| 1052 << StubCache::kCacheIndexShift; | 1057 << StubCache::kCacheIndexShift; |
| 1053 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask))); | 1058 return ChangeUint32ToWord(Word32And(hash, Int32Constant(mask))); |
| 1054 } | 1059 } |
| 1055 | 1060 |
| 1056 void AccessorAssemblerImpl::TryProbeStubCacheTable( | 1061 void AccessorAssemblerImpl::TryProbeStubCacheTable( |
| 1057 StubCache* stub_cache, StubCacheTable table_id, Node* entry_offset, | 1062 StubCache* stub_cache, StubCacheTable table_id, Node* entry_offset, |
| 1058 Node* name, Node* map, Label* if_handler, Variable* var_handler, | 1063 Node* name, Node* map, Label* if_handler, Variable* var_handler, |
| 1059 Label* if_miss) { | 1064 Label* if_miss) { |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1505 } | 1510 } |
| 1506 Bind(&miss); | 1511 Bind(&miss); |
| 1507 { | 1512 { |
| 1508 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, | 1513 TailCallRuntime(Runtime::kStoreIC_Miss, p->context, p->value, p->slot, |
| 1509 p->vector, p->receiver, p->name); | 1514 p->vector, p->receiver, p->name); |
| 1510 } | 1515 } |
| 1511 } | 1516 } |
| 1512 | 1517 |
| 1513 void AccessorAssemblerImpl::KeyedStoreIC(const StoreICParameters* p, | 1518 void AccessorAssemblerImpl::KeyedStoreIC(const StoreICParameters* p, |
| 1514 LanguageMode language_mode) { | 1519 LanguageMode language_mode) { |
| 1515 Variable var_handler(this, MachineRepresentation::kTagged); | 1520 // TODO(ishell): defer blocks when it works. |
| 1516 // This is to make |miss| label see the var_handler bound on all paths. | 1521 Label miss(this /*, Label::kDeferred*/); |
| 1517 var_handler.Bind(IntPtrConstant(0)); | 1522 { |
|
Igor Sheludko
2016/12/07 10:20:42
I moved |miss| label to outer scope to avoid this
| |
| 1523 Variable var_handler(this, MachineRepresentation::kTagged); | |
| 1518 | 1524 |
| 1519 // TODO(ishell): defer blocks when it works. | 1525 // TODO(ishell): defer blocks when it works. |
| 1520 Label if_handler(this, &var_handler), try_polymorphic(this), | 1526 Label if_handler(this, &var_handler), try_polymorphic(this), |
| 1521 try_megamorphic(this /*, Label::kDeferred*/), | 1527 try_megamorphic(this /*, Label::kDeferred*/), |
| 1522 try_polymorphic_name(this /*, Label::kDeferred*/), | 1528 try_polymorphic_name(this /*, Label::kDeferred*/); |
| 1523 miss(this /*, Label::kDeferred*/); | |
| 1524 | 1529 |
| 1525 Node* receiver_map = LoadReceiverMap(p->receiver); | 1530 Node* receiver_map = LoadReceiverMap(p->receiver); |
| 1526 | 1531 |
| 1527 // Check monomorphic case. | 1532 // Check monomorphic case. |
| 1528 Node* feedback = | 1533 Node* feedback = |
| 1529 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, | 1534 TryMonomorphicCase(p->slot, p->vector, receiver_map, &if_handler, |
| 1530 &var_handler, &try_polymorphic); | 1535 &var_handler, &try_polymorphic); |
| 1531 Bind(&if_handler); | 1536 Bind(&if_handler); |
| 1532 { | 1537 { |
| 1533 Comment("KeyedStoreIC_if_handler"); | 1538 Comment("KeyedStoreIC_if_handler"); |
| 1534 HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements); | 1539 HandleStoreICHandlerCase(p, var_handler.value(), &miss, kSupportElements); |
| 1535 } | 1540 } |
| 1536 | 1541 |
| 1537 Bind(&try_polymorphic); | 1542 Bind(&try_polymorphic); |
| 1538 { | |
| 1539 // CheckPolymorphic case. | |
| 1540 Comment("KeyedStoreIC_try_polymorphic"); | |
| 1541 GotoUnless( | |
| 1542 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | |
| 1543 &try_megamorphic); | |
| 1544 Label if_transition_handler(this); | |
| 1545 Variable var_transition_map_cell(this, MachineRepresentation::kTagged); | |
| 1546 HandleKeyedStorePolymorphicCase(receiver_map, feedback, &if_handler, | |
| 1547 &var_handler, &if_transition_handler, | |
| 1548 &var_transition_map_cell, &miss); | |
| 1549 Bind(&if_transition_handler); | |
| 1550 Comment("KeyedStoreIC_polymorphic_transition"); | |
| 1551 { | 1543 { |
| 1552 Node* handler = var_handler.value(); | 1544 // CheckPolymorphic case. |
| 1545 Comment("KeyedStoreIC_try_polymorphic"); | |
| 1546 GotoUnless( | |
| 1547 WordEqual(LoadMap(feedback), LoadRoot(Heap::kFixedArrayMapRootIndex)), | |
| 1548 &try_megamorphic); | |
| 1549 Label if_transition_handler(this); | |
| 1550 Variable var_transition_map_cell(this, MachineRepresentation::kTagged); | |
| 1551 HandleKeyedStorePolymorphicCase(receiver_map, feedback, &if_handler, | |
| 1552 &var_handler, &if_transition_handler, | |
| 1553 &var_transition_map_cell, &miss); | |
| 1554 Bind(&if_transition_handler); | |
| 1555 Comment("KeyedStoreIC_polymorphic_transition"); | |
| 1556 { | |
| 1557 Node* handler = var_handler.value(); | |
| 1553 | 1558 |
| 1554 Label call_handler(this); | 1559 Label call_handler(this); |
| 1555 Variable var_code_handler(this, MachineRepresentation::kTagged); | 1560 Variable var_code_handler(this, MachineRepresentation::kTagged); |
| 1556 var_code_handler.Bind(handler); | 1561 var_code_handler.Bind(handler); |
| 1557 GotoUnless(IsTuple2Map(LoadMap(handler)), &call_handler); | 1562 GotoUnless(IsTuple2Map(LoadMap(handler)), &call_handler); |
| 1558 { | 1563 { |
| 1559 CSA_ASSERT(this, IsTuple2Map(LoadMap(handler))); | 1564 CSA_ASSERT(this, IsTuple2Map(LoadMap(handler))); |
| 1560 | 1565 |
| 1561 // Check validity cell. | 1566 // Check validity cell. |
| 1562 Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset); | 1567 Node* validity_cell = LoadObjectField(handler, Tuple2::kValue1Offset); |
| 1563 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); | 1568 Node* cell_value = LoadObjectField(validity_cell, Cell::kValueOffset); |
| 1564 GotoIf(WordNotEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)), | 1569 GotoIf( |
| 1565 &miss); | 1570 WordNotEqual(cell_value, SmiConstant(Map::kPrototypeChainValid)), |
| 1571 &miss); | |
| 1566 | 1572 |
| 1567 var_code_handler.Bind(LoadObjectField(handler, Tuple2::kValue2Offset)); | 1573 var_code_handler.Bind( |
| 1568 Goto(&call_handler); | 1574 LoadObjectField(handler, Tuple2::kValue2Offset)); |
| 1569 } | 1575 Goto(&call_handler); |
| 1576 } | |
| 1570 | 1577 |
| 1571 Bind(&call_handler); | 1578 Bind(&call_handler); |
| 1572 { | 1579 { |
| 1573 Node* code_handler = var_code_handler.value(); | 1580 Node* code_handler = var_code_handler.value(); |
| 1574 CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler))); | 1581 CSA_ASSERT(this, IsCodeMap(LoadMap(code_handler))); |
| 1575 | 1582 |
| 1576 Node* transition_map = | 1583 Node* transition_map = |
| 1577 LoadWeakCellValue(var_transition_map_cell.value(), &miss); | 1584 LoadWeakCellValue(var_transition_map_cell.value(), &miss); |
| 1578 StoreTransitionDescriptor descriptor(isolate()); | 1585 StoreTransitionDescriptor descriptor(isolate()); |
| 1579 TailCallStub(descriptor, code_handler, p->context, p->receiver, p->name, | 1586 TailCallStub(descriptor, code_handler, p->context, p->receiver, |
| 1580 transition_map, p->value, p->slot, p->vector); | 1587 p->name, transition_map, p->value, p->slot, p->vector); |
| 1588 } | |
| 1581 } | 1589 } |
| 1582 } | 1590 } |
| 1591 | |
| 1592 Bind(&try_megamorphic); | |
| 1593 { | |
| 1594 // Check megamorphic case. | |
| 1595 Comment("KeyedStoreIC_try_megamorphic"); | |
| 1596 GotoUnless( | |
| 1597 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | |
| 1598 &try_polymorphic_name); | |
| 1599 TailCallStub( | |
| 1600 CodeFactory::KeyedStoreIC_Megamorphic(isolate(), language_mode), | |
| 1601 p->context, p->receiver, p->name, p->value, p->slot, p->vector); | |
| 1602 } | |
| 1603 | |
| 1604 Bind(&try_polymorphic_name); | |
| 1605 { | |
| 1606 // We might have a name in feedback, and a fixed array in the next slot. | |
| 1607 Comment("KeyedStoreIC_try_polymorphic_name"); | |
| 1608 GotoUnless(WordEqual(feedback, p->name), &miss); | |
| 1609 // If the name comparison succeeded, we know we have a FixedArray with | |
| 1610 // at least one map/handler pair. | |
| 1611 Node* offset = ElementOffsetFromIndex( | |
| 1612 p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS, | |
| 1613 FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag); | |
| 1614 Node* array = Load(MachineType::AnyTagged(), p->vector, offset); | |
| 1615 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, | |
| 1616 &miss, 1); | |
| 1617 } | |
| 1583 } | 1618 } |
| 1584 | |
| 1585 Bind(&try_megamorphic); | |
| 1586 { | |
| 1587 // Check megamorphic case. | |
| 1588 Comment("KeyedStoreIC_try_megamorphic"); | |
| 1589 GotoUnless( | |
| 1590 WordEqual(feedback, LoadRoot(Heap::kmegamorphic_symbolRootIndex)), | |
| 1591 &try_polymorphic_name); | |
| 1592 TailCallStub( | |
| 1593 CodeFactory::KeyedStoreIC_Megamorphic(isolate(), language_mode), | |
| 1594 p->context, p->receiver, p->name, p->value, p->slot, p->vector); | |
| 1595 } | |
| 1596 | |
| 1597 Bind(&try_polymorphic_name); | |
| 1598 { | |
| 1599 // We might have a name in feedback, and a fixed array in the next slot. | |
| 1600 Comment("KeyedStoreIC_try_polymorphic_name"); | |
| 1601 GotoUnless(WordEqual(feedback, p->name), &miss); | |
| 1602 // If the name comparison succeeded, we know we have a FixedArray with | |
| 1603 // at least one map/handler pair. | |
| 1604 Node* offset = ElementOffsetFromIndex( | |
| 1605 p->slot, FAST_HOLEY_ELEMENTS, SMI_PARAMETERS, | |
| 1606 FixedArray::kHeaderSize + kPointerSize - kHeapObjectTag); | |
| 1607 Node* array = Load(MachineType::AnyTagged(), p->vector, offset); | |
| 1608 HandlePolymorphicCase(receiver_map, array, &if_handler, &var_handler, &miss, | |
| 1609 1); | |
| 1610 } | |
| 1611 | |
| 1612 Bind(&miss); | 1619 Bind(&miss); |
| 1613 { | 1620 { |
| 1614 Comment("KeyedStoreIC_miss"); | 1621 Comment("KeyedStoreIC_miss"); |
| 1615 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, | 1622 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, p->slot, |
| 1616 p->vector, p->receiver, p->name); | 1623 p->vector, p->receiver, p->name); |
| 1617 } | 1624 } |
| 1618 } | 1625 } |
| 1619 | 1626 |
| 1620 //////////////////// Public methods. | 1627 //////////////////// Public methods. |
| 1621 | 1628 |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1819 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( | 1826 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( |
| 1820 CodeAssemblerState* state, LanguageMode language_mode) { | 1827 CodeAssemblerState* state, LanguageMode language_mode) { |
| 1821 AccessorAssemblerImpl assembler(state); | 1828 AccessorAssemblerImpl assembler(state); |
| 1822 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); | 1829 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); |
| 1823 } | 1830 } |
| 1824 | 1831 |
| 1825 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE | 1832 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE |
| 1826 | 1833 |
| 1827 } // namespace internal | 1834 } // namespace internal |
| 1828 } // namespace v8 | 1835 } // namespace v8 |
| OLD | NEW |