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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
73 | 73 |
74 Bind(&next_entry); | 74 Bind(&next_entry); |
75 } | 75 } |
76 | 76 |
77 // Loop from {unroll_count}*kEntrySize to {length}. | 77 // Loop from {unroll_count}*kEntrySize to {length}. |
78 Node* init = IntPtrConstant(unroll_count * kEntrySize); | 78 Node* init = IntPtrConstant(unroll_count * kEntrySize); |
79 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); | 79 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); |
80 BuildFastLoop( | 80 BuildFastLoop( |
81 MachineType::PointerRepresentation(), init, length, | 81 MachineType::PointerRepresentation(), init, length, |
82 [this, receiver_map, feedback, if_handler, var_handler](Node* index) { | 82 [this, receiver_map, feedback, if_handler, var_handler](Node* index) { |
83 Node* cached_map = LoadWeakCellValue( | 83 Node* cached_map = |
84 LoadFixedArrayElement(feedback, index, 0, INTPTR_PARAMETERS)); | 84 LoadWeakCellValue(LoadFixedArrayElement(feedback, index)); |
85 | 85 |
86 Label next_entry(this); | 86 Label next_entry(this); |
87 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 87 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
88 | 88 |
89 // Found, now call handler. | 89 // Found, now call handler. |
90 Node* handler = LoadFixedArrayElement(feedback, index, kPointerSize, | 90 Node* handler = LoadFixedArrayElement(feedback, index, kPointerSize); |
91 INTPTR_PARAMETERS); | |
92 var_handler->Bind(handler); | 91 var_handler->Bind(handler); |
93 Goto(if_handler); | 92 Goto(if_handler); |
94 | 93 |
95 Bind(&next_entry); | 94 Bind(&next_entry); |
96 }, | 95 }, |
97 kEntrySize, IndexAdvanceMode::kPost); | 96 kEntrySize, IndexAdvanceMode::kPost); |
98 // The loop falls through if no handler was found. | 97 // The loop falls through if no handler was found. |
99 Goto(if_miss); | 98 Goto(if_miss); |
100 } | 99 } |
101 | 100 |
102 void AccessorAssemblerImpl::HandleKeyedStorePolymorphicCase( | 101 void AccessorAssemblerImpl::HandleKeyedStorePolymorphicCase( |
103 Node* receiver_map, Node* feedback, Label* if_handler, | 102 Node* receiver_map, Node* feedback, Label* if_handler, |
104 Variable* var_handler, Label* if_transition_handler, | 103 Variable* var_handler, Label* if_transition_handler, |
105 Variable* var_transition_map_cell, Label* if_miss) { | 104 Variable* var_transition_map_cell, Label* if_miss) { |
106 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); | 105 DCHECK_EQ(MachineRepresentation::kTagged, var_handler->rep()); |
107 DCHECK_EQ(MachineRepresentation::kTagged, var_transition_map_cell->rep()); | 106 DCHECK_EQ(MachineRepresentation::kTagged, var_transition_map_cell->rep()); |
108 | 107 |
109 const int kEntrySize = 3; | 108 const int kEntrySize = 3; |
110 | 109 |
111 Node* init = IntPtrConstant(0); | 110 Node* init = IntPtrConstant(0); |
112 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); | 111 Node* length = LoadAndUntagFixedArrayBaseLength(feedback); |
113 BuildFastLoop(MachineType::PointerRepresentation(), init, length, | 112 BuildFastLoop(MachineType::PointerRepresentation(), init, length, |
114 [this, receiver_map, feedback, if_handler, var_handler, | 113 [this, receiver_map, feedback, if_handler, var_handler, |
115 if_transition_handler, var_transition_map_cell](Node* index) { | 114 if_transition_handler, var_transition_map_cell](Node* index) { |
116 Node* cached_map = LoadWeakCellValue(LoadFixedArrayElement( | 115 Node* cached_map = |
117 feedback, index, 0, INTPTR_PARAMETERS)); | 116 LoadWeakCellValue(LoadFixedArrayElement(feedback, index)); |
118 Label next_entry(this); | 117 Label next_entry(this); |
119 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); | 118 GotoIf(WordNotEqual(receiver_map, cached_map), &next_entry); |
120 | 119 |
121 Node* maybe_transition_map_cell = LoadFixedArrayElement( | 120 Node* maybe_transition_map_cell = |
122 feedback, index, kPointerSize, INTPTR_PARAMETERS); | 121 LoadFixedArrayElement(feedback, index, kPointerSize); |
123 | 122 |
124 var_handler->Bind(LoadFixedArrayElement( | 123 var_handler->Bind( |
125 feedback, index, 2 * kPointerSize, INTPTR_PARAMETERS)); | 124 LoadFixedArrayElement(feedback, index, 2 * kPointerSize)); |
126 GotoIf(WordEqual(maybe_transition_map_cell, | 125 GotoIf(WordEqual(maybe_transition_map_cell, |
127 LoadRoot(Heap::kUndefinedValueRootIndex)), | 126 LoadRoot(Heap::kUndefinedValueRootIndex)), |
128 if_handler); | 127 if_handler); |
129 var_transition_map_cell->Bind(maybe_transition_map_cell); | 128 var_transition_map_cell->Bind(maybe_transition_map_cell); |
130 Goto(if_transition_handler); | 129 Goto(if_transition_handler); |
131 | 130 |
132 Bind(&next_entry); | 131 Bind(&next_entry); |
133 }, | 132 }, |
134 kEntrySize, IndexAdvanceMode::kPost); | 133 kEntrySize, IndexAdvanceMode::kPost); |
135 // The loop falls through if no handler was found. | 134 // The loop falls through if no handler was found. |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
279 | 278 |
280 Bind(&constant); | 279 Bind(&constant); |
281 { | 280 { |
282 Comment("constant_load"); | 281 Comment("constant_load"); |
283 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); | 282 Node* descriptors = LoadMapDescriptors(LoadMap(holder)); |
284 Node* descriptor = | 283 Node* descriptor = |
285 DecodeWord<LoadHandler::DescriptorValueIndexBits>(handler_word); | 284 DecodeWord<LoadHandler::DescriptorValueIndexBits>(handler_word); |
286 CSA_ASSERT(this, | 285 CSA_ASSERT(this, |
287 UintPtrLessThan(descriptor, | 286 UintPtrLessThan(descriptor, |
288 LoadAndUntagFixedArrayBaseLength(descriptors))); | 287 LoadAndUntagFixedArrayBaseLength(descriptors))); |
289 Node* value = | 288 Node* value = LoadFixedArrayElement(descriptors, descriptor); |
290 LoadFixedArrayElement(descriptors, descriptor, 0, INTPTR_PARAMETERS); | |
291 | 289 |
292 Label if_accessor_info(this); | 290 Label if_accessor_info(this); |
293 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), | 291 GotoIf(IsSetWord<LoadHandler::IsAccessorInfoBits>(handler_word), |
294 &if_accessor_info); | 292 &if_accessor_info); |
295 Return(value); | 293 Return(value); |
296 | 294 |
297 Bind(&if_accessor_info); | 295 Bind(&if_accessor_info); |
298 Callable callable = CodeFactory::ApiGetter(isolate()); | 296 Callable callable = CodeFactory::ApiGetter(isolate()); |
299 TailCallStub(callable, p->context, p->receiver, holder, value); | 297 TailCallStub(callable, p->context, p->receiver, holder, value); |
300 } | 298 } |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 Context::SECURITY_TOKEN_INDEX); | 413 Context::SECURITY_TOKEN_INDEX); |
416 Node* current_token = | 414 Node* current_token = |
417 LoadContextElement(native_context, Context::SECURITY_TOKEN_INDEX); | 415 LoadContextElement(native_context, Context::SECURITY_TOKEN_INDEX); |
418 Branch(WordEqual(expected_token, current_token), &can_access, miss); | 416 Branch(WordEqual(expected_token, current_token), &can_access, miss); |
419 } | 417 } |
420 Bind(&can_access); | 418 Bind(&can_access); |
421 | 419 |
422 BuildFastLoop( | 420 BuildFastLoop( |
423 MachineType::PointerRepresentation(), start_index.value(), handler_length, | 421 MachineType::PointerRepresentation(), start_index.value(), handler_length, |
424 [this, p, handler, miss](Node* current) { | 422 [this, p, handler, miss](Node* current) { |
425 Node* prototype_cell = | 423 Node* prototype_cell = LoadFixedArrayElement(handler, current); |
426 LoadFixedArrayElement(handler, current, 0, INTPTR_PARAMETERS); | |
427 CheckPrototype(prototype_cell, p->name, miss); | 424 CheckPrototype(prototype_cell, p->name, miss); |
428 }, | 425 }, |
429 1, IndexAdvanceMode::kPost); | 426 1, IndexAdvanceMode::kPost); |
430 | 427 |
431 Node* maybe_holder_cell = | 428 Node* maybe_holder_cell = |
432 LoadFixedArrayElement(handler, LoadHandler::kHolderCellIndex); | 429 LoadFixedArrayElement(handler, LoadHandler::kHolderCellIndex); |
433 Label load_existent(this); | 430 Label load_existent(this); |
434 GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); | 431 GotoIf(WordNotEqual(maybe_holder_cell, NullConstant()), &load_existent); |
435 // This is a handler for a load of a non-existent value. | 432 // This is a handler for a load of a non-existent value. |
436 if (throw_reference_error_if_nonexistent) { | 433 if (throw_reference_error_if_nonexistent) { |
(...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 var_transition.Bind(transition); | 567 var_transition.Bind(transition); |
571 Goto(&if_transition); | 568 Goto(&if_transition); |
572 } | 569 } |
573 | 570 |
574 Bind(&array_handler); | 571 Bind(&array_handler); |
575 { | 572 { |
576 Node* length = SmiUntag(maybe_transition_cell); | 573 Node* length = SmiUntag(maybe_transition_cell); |
577 BuildFastLoop(MachineType::PointerRepresentation(), | 574 BuildFastLoop(MachineType::PointerRepresentation(), |
578 IntPtrConstant(StoreHandler::kFirstPrototypeIndex), length, | 575 IntPtrConstant(StoreHandler::kFirstPrototypeIndex), length, |
579 [this, p, handler, miss](Node* current) { | 576 [this, p, handler, miss](Node* current) { |
580 Node* prototype_cell = LoadFixedArrayElement( | 577 Node* prototype_cell = |
581 handler, current, 0, INTPTR_PARAMETERS); | 578 LoadFixedArrayElement(handler, current); |
582 CheckPrototype(prototype_cell, p->name, miss); | 579 CheckPrototype(prototype_cell, p->name, miss); |
583 }, | 580 }, |
584 1, IndexAdvanceMode::kPost); | 581 1, IndexAdvanceMode::kPost); |
585 | 582 |
586 Node* maybe_transition_cell = | 583 Node* maybe_transition_cell = |
587 LoadFixedArrayElement(handler, StoreHandler::kTransitionCellIndex); | 584 LoadFixedArrayElement(handler, StoreHandler::kTransitionCellIndex); |
588 Node* transition = LoadWeakCellValue(maybe_transition_cell, miss); | 585 Node* transition = LoadWeakCellValue(maybe_transition_cell, miss); |
589 var_transition.Bind(transition); | 586 var_transition.Bind(transition); |
590 Goto(&if_transition); | 587 Goto(&if_transition); |
591 } | 588 } |
(...skipping 14 matching lines...) Expand all Loading... |
606 // Handle transitioning field stores. | 603 // Handle transitioning field stores. |
607 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition, | 604 HandleStoreICSmiHandlerCase(handler_word, holder, p->value, transition, |
608 miss); | 605 miss); |
609 | 606 |
610 Bind(&if_transition_to_constant); | 607 Bind(&if_transition_to_constant); |
611 { | 608 { |
612 // Check that constant matches value. | 609 // Check that constant matches value. |
613 Node* value_index_in_descriptor = | 610 Node* value_index_in_descriptor = |
614 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); | 611 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); |
615 Node* descriptors = LoadMapDescriptors(transition); | 612 Node* descriptors = LoadMapDescriptors(transition); |
616 Node* constant = LoadFixedArrayElement( | 613 Node* constant = |
617 descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS); | 614 LoadFixedArrayElement(descriptors, value_index_in_descriptor); |
618 GotoIf(WordNotEqual(p->value, constant), miss); | 615 GotoIf(WordNotEqual(p->value, constant), miss); |
619 | 616 |
620 StoreMap(p->receiver, transition); | 617 StoreMap(p->receiver, transition); |
621 Return(p->value); | 618 Return(p->value); |
622 } | 619 } |
623 } | 620 } |
624 } | 621 } |
625 | 622 |
626 void AccessorAssemblerImpl::HandleStoreICSmiHandlerCase(Node* handler_word, | 623 void AccessorAssemblerImpl::HandleStoreICSmiHandlerCase(Node* handler_word, |
627 Node* holder, | 624 Node* holder, |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
680 Bind(&if_heap_object_field); | 677 Bind(&if_heap_object_field); |
681 { | 678 { |
682 Comment("store heap object field"); | 679 Comment("store heap object field"); |
683 // Generate full field type check here and then store value as Tagged. | 680 // Generate full field type check here and then store value as Tagged. |
684 Node* prepared_value = | 681 Node* prepared_value = |
685 PrepareValueForWrite(value, Representation::HeapObject(), miss); | 682 PrepareValueForWrite(value, Representation::HeapObject(), miss); |
686 Node* value_index_in_descriptor = | 683 Node* value_index_in_descriptor = |
687 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); | 684 DecodeWord<StoreHandler::DescriptorValueIndexBits>(handler_word); |
688 Node* descriptors = | 685 Node* descriptors = |
689 LoadMapDescriptors(transition ? transition : LoadMap(holder)); | 686 LoadMapDescriptors(transition ? transition : LoadMap(holder)); |
690 Node* maybe_field_type = LoadFixedArrayElement( | 687 Node* maybe_field_type = |
691 descriptors, value_index_in_descriptor, 0, INTPTR_PARAMETERS); | 688 LoadFixedArrayElement(descriptors, value_index_in_descriptor); |
692 Label do_store(this); | 689 Label do_store(this); |
693 GotoIf(TaggedIsSmi(maybe_field_type), &do_store); | 690 GotoIf(TaggedIsSmi(maybe_field_type), &do_store); |
694 // Check that value type matches the field type. | 691 // Check that value type matches the field type. |
695 { | 692 { |
696 Node* field_type = LoadWeakCellValue(maybe_field_type, miss); | 693 Node* field_type = LoadWeakCellValue(maybe_field_type, miss); |
697 Branch(WordEqual(LoadMap(prepared_value), field_type), &do_store, miss); | 694 Branch(WordEqual(LoadMap(prepared_value), field_type), &do_store, miss); |
698 } | 695 } |
699 Bind(&do_store); | 696 Bind(&do_store); |
700 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(), | 697 HandleStoreFieldAndReturn(handler_word, holder, Representation::Tagged(), |
701 prepared_value, transition, miss); | 698 prepared_value, transition, miss); |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
802 // FAST_DOUBLE_ELEMENTS | 799 // FAST_DOUBLE_ELEMENTS |
803 &if_fast_double, | 800 &if_fast_double, |
804 // FAST_HOLEY_DOUBLE_ELEMENTS | 801 // FAST_HOLEY_DOUBLE_ELEMENTS |
805 &if_fast_holey_double}; | 802 &if_fast_holey_double}; |
806 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, | 803 Switch(elements_kind, unimplemented_elements_kind, kinds, labels, |
807 arraysize(kinds)); | 804 arraysize(kinds)); |
808 | 805 |
809 Bind(&if_fast_packed); | 806 Bind(&if_fast_packed); |
810 { | 807 { |
811 Comment("fast packed elements"); | 808 Comment("fast packed elements"); |
812 Return(LoadFixedArrayElement(elements, intptr_index, 0, INTPTR_PARAMETERS)); | 809 Return(LoadFixedArrayElement(elements, intptr_index)); |
813 } | 810 } |
814 | 811 |
815 Bind(&if_fast_holey); | 812 Bind(&if_fast_holey); |
816 { | 813 { |
817 Comment("fast holey elements"); | 814 Comment("fast holey elements"); |
818 Node* element = | 815 Node* element = LoadFixedArrayElement(elements, intptr_index); |
819 LoadFixedArrayElement(elements, intptr_index, 0, INTPTR_PARAMETERS); | |
820 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); | 816 GotoIf(WordEqual(element, TheHoleConstant()), if_hole); |
821 Return(element); | 817 Return(element); |
822 } | 818 } |
823 | 819 |
824 Bind(&if_fast_double); | 820 Bind(&if_fast_double); |
825 { | 821 { |
826 Comment("packed double elements"); | 822 Comment("packed double elements"); |
827 var_double_value->Bind(LoadFixedDoubleArrayElement( | 823 var_double_value->Bind(LoadFixedDoubleArrayElement(elements, intptr_index, |
828 elements, intptr_index, MachineType::Float64(), 0, INTPTR_PARAMETERS)); | 824 MachineType::Float64())); |
829 Goto(rebox_double); | 825 Goto(rebox_double); |
830 } | 826 } |
831 | 827 |
832 Bind(&if_fast_holey_double); | 828 Bind(&if_fast_holey_double); |
833 { | 829 { |
834 Comment("holey double elements"); | 830 Comment("holey double elements"); |
835 Node* value = LoadFixedDoubleArrayElement(elements, intptr_index, | 831 Node* value = LoadFixedDoubleArrayElement(elements, intptr_index, |
836 MachineType::Float64(), 0, | 832 MachineType::Float64(), 0, |
837 INTPTR_PARAMETERS, if_hole); | 833 INTPTR_PARAMETERS, if_hole); |
838 var_double_value->Bind(value); | 834 var_double_value->Bind(value); |
(...skipping 17 matching lines...) Expand all Loading... |
856 Comment("dictionary elements"); | 852 Comment("dictionary elements"); |
857 GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), out_of_bounds); | 853 GotoIf(IntPtrLessThan(intptr_index, IntPtrConstant(0)), out_of_bounds); |
858 Variable var_entry(this, MachineType::PointerRepresentation()); | 854 Variable var_entry(this, MachineType::PointerRepresentation()); |
859 Label if_found(this); | 855 Label if_found(this); |
860 NumberDictionaryLookup<SeededNumberDictionary>( | 856 NumberDictionaryLookup<SeededNumberDictionary>( |
861 elements, intptr_index, &if_found, &var_entry, if_hole); | 857 elements, intptr_index, &if_found, &var_entry, if_hole); |
862 Bind(&if_found); | 858 Bind(&if_found); |
863 // Check that the value is a data property. | 859 // Check that the value is a data property. |
864 Node* details_index = EntryToIndex<SeededNumberDictionary>( | 860 Node* details_index = EntryToIndex<SeededNumberDictionary>( |
865 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); | 861 var_entry.value(), SeededNumberDictionary::kEntryDetailsIndex); |
866 Node* details = SmiToWord32( | 862 Node* details = SmiToWord32(LoadFixedArrayElement(elements, details_index)); |
867 LoadFixedArrayElement(elements, details_index, 0, INTPTR_PARAMETERS)); | |
868 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); | 863 Node* kind = DecodeWord32<PropertyDetails::KindField>(details); |
869 // TODO(jkummerow): Support accessors without missing? | 864 // TODO(jkummerow): Support accessors without missing? |
870 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); | 865 GotoUnless(Word32Equal(kind, Int32Constant(kData)), miss); |
871 // Finally, load the value. | 866 // Finally, load the value. |
872 Node* value_index = EntryToIndex<SeededNumberDictionary>( | 867 Node* value_index = EntryToIndex<SeededNumberDictionary>( |
873 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); | 868 var_entry.value(), SeededNumberDictionary::kEntryValueIndex); |
874 Return(LoadFixedArrayElement(elements, value_index, 0, INTPTR_PARAMETERS)); | 869 Return(LoadFixedArrayElement(elements, value_index)); |
875 } | 870 } |
876 | 871 |
877 Bind(&if_typed_array); | 872 Bind(&if_typed_array); |
878 { | 873 { |
879 Comment("typed elements"); | 874 Comment("typed elements"); |
880 // Check if buffer has been neutered. | 875 // Check if buffer has been neutered. |
881 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); | 876 Node* buffer = LoadObjectField(object, JSArrayBufferView::kBufferOffset); |
882 GotoIf(IsDetachedBuffer(buffer), miss); | 877 GotoIf(IsDetachedBuffer(buffer), miss); |
883 | 878 |
884 // Bounds check. | 879 // Bounds check. |
(...skipping 940 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1825 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( | 1820 void AccessorAssembler::GenerateKeyedStoreICTrampolineTF( |
1826 CodeAssemblerState* state, LanguageMode language_mode) { | 1821 CodeAssemblerState* state, LanguageMode language_mode) { |
1827 AccessorAssemblerImpl assembler(state); | 1822 AccessorAssemblerImpl assembler(state); |
1828 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); | 1823 assembler.GenerateKeyedStoreICTrampolineTF(language_mode); |
1829 } | 1824 } |
1830 | 1825 |
1831 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE | 1826 #undef ACCESSOR_ASSEMBLER_PUBLIC_INTERFACE |
1832 | 1827 |
1833 } // namespace internal | 1828 } // namespace internal |
1834 } // namespace v8 | 1829 } // namespace v8 |
OLD | NEW |