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/keyed-store-generic.h" | 5 #include "src/ic/keyed-store-generic.h" |
6 | 6 |
7 #include "src/code-factory.h" | 7 #include "src/code-factory.h" |
8 #include "src/code-stub-assembler.h" | 8 #include "src/code-stub-assembler.h" |
9 #include "src/contexts.h" | 9 #include "src/contexts.h" |
10 #include "src/ic/accessor-assembler-impl.h" | 10 #include "src/ic/accessor-assembler-impl.h" |
(...skipping 443 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
454 | 454 |
455 Bind(&if_bump_length_with_gap); | 455 Bind(&if_bump_length_with_gap); |
456 { | 456 { |
457 StoreElementWithCapacity(receiver, receiver_map, elements, elements_kind, | 457 StoreElementWithCapacity(receiver, receiver_map, elements, elements_kind, |
458 intptr_index, value, context, slow, | 458 intptr_index, value, context, slow, |
459 kBumpLengthWithGap); | 459 kBumpLengthWithGap); |
460 } | 460 } |
461 | 461 |
462 // Out-of-capacity accesses (index >= capacity) jump here. Additionally, | 462 // Out-of-capacity accesses (index >= capacity) jump here. Additionally, |
463 // an ElementsKind transition might be necessary. | 463 // an ElementsKind transition might be necessary. |
| 464 // The index can also be negative at this point! Jump to the runtime in that |
| 465 // case to convert it to a named property. |
464 Bind(&if_grow); | 466 Bind(&if_grow); |
465 { | 467 { |
466 Comment("Grow backing store"); | 468 Comment("Grow backing store"); |
467 // TODO(jkummerow): Support inline backing store growth. | 469 // TODO(jkummerow): Support inline backing store growth. |
468 Goto(slow); | 470 Goto(slow); |
469 } | 471 } |
470 | 472 |
471 // Any ElementsKind > LAST_FAST_ELEMENTS_KIND jumps here for further dispatch. | 473 // Any ElementsKind > LAST_FAST_ELEMENTS_KIND jumps here for further dispatch. |
472 Bind(&if_nonfast); | 474 Bind(&if_nonfast); |
473 { | 475 { |
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
720 type, p->receiver); | 722 type, p->receiver); |
721 } else { | 723 } else { |
722 DCHECK_EQ(SLOPPY, language_mode); | 724 DCHECK_EQ(SLOPPY, language_mode); |
723 Return(p->value); | 725 Return(p->value); |
724 } | 726 } |
725 } | 727 } |
726 | 728 |
727 Bind(&stub_cache); | 729 Bind(&stub_cache); |
728 { | 730 { |
729 Comment("stub cache probe"); | 731 Comment("stub cache probe"); |
| 732 // The stub cache lookup is opportunistic: if we find a handler, use it; |
| 733 // otherwise take the slow path. Since this is a generic stub, compiling |
| 734 // a handler (as KeyedStoreIC_Miss would do) is probably a waste of time. |
730 Variable var_handler(this, MachineRepresentation::kTagged); | 735 Variable var_handler(this, MachineRepresentation::kTagged); |
731 Label found_handler(this, &var_handler), stub_cache_miss(this); | 736 Label found_handler(this, &var_handler); |
732 TryProbeStubCache(isolate()->store_stub_cache(), receiver, p->name, | 737 TryProbeStubCache(isolate()->store_stub_cache(), receiver, p->name, |
733 &found_handler, &var_handler, &stub_cache_miss); | 738 &found_handler, &var_handler, slow); |
734 Bind(&found_handler); | 739 Bind(&found_handler); |
735 { | 740 { |
736 Comment("KeyedStoreGeneric found handler"); | 741 Comment("KeyedStoreGeneric found handler"); |
737 HandleStoreICHandlerCase(p, var_handler.value(), slow); | 742 HandleStoreICHandlerCase(p, var_handler.value(), slow); |
738 } | 743 } |
739 Bind(&stub_cache_miss); | |
740 { | |
741 Comment("KeyedStoreGeneric_miss"); | |
742 TailCallRuntime(Runtime::kKeyedStoreIC_Miss, p->context, p->value, | |
743 p->slot, p->vector, p->receiver, p->name); | |
744 } | |
745 } | 744 } |
746 } | 745 } |
747 | 746 |
748 void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) { | 747 void KeyedStoreGenericAssembler::KeyedStoreGeneric(LanguageMode language_mode) { |
749 typedef StoreWithVectorDescriptor Descriptor; | 748 typedef StoreWithVectorDescriptor Descriptor; |
750 | 749 |
751 Node* receiver = Parameter(Descriptor::kReceiver); | 750 Node* receiver = Parameter(Descriptor::kReceiver); |
752 Node* name = Parameter(Descriptor::kName); | 751 Node* name = Parameter(Descriptor::kName); |
753 Node* value = Parameter(Descriptor::kValue); | 752 Node* value = Parameter(Descriptor::kValue); |
754 Node* slot = Parameter(Descriptor::kSlot); | 753 Node* slot = Parameter(Descriptor::kSlot); |
755 Node* vector = Parameter(Descriptor::kVector); | 754 Node* vector = Parameter(Descriptor::kVector); |
756 Node* context = Parameter(Descriptor::kContext); | 755 Node* context = Parameter(Descriptor::kContext); |
757 | 756 |
758 Variable var_index(this, MachineType::PointerRepresentation()); | 757 Variable var_index(this, MachineType::PointerRepresentation()); |
| 758 Variable var_unique(this, MachineRepresentation::kTagged); |
| 759 var_unique.Bind(name); // Dummy initialization. |
759 Label if_index(this), if_unique_name(this), slow(this); | 760 Label if_index(this), if_unique_name(this), slow(this); |
760 | 761 |
761 GotoIf(TaggedIsSmi(receiver), &slow); | 762 GotoIf(TaggedIsSmi(receiver), &slow); |
762 Node* receiver_map = LoadMap(receiver); | 763 Node* receiver_map = LoadMap(receiver); |
763 Node* instance_type = LoadMapInstanceType(receiver_map); | 764 Node* instance_type = LoadMapInstanceType(receiver_map); |
764 // Receivers requiring non-standard element accesses (interceptors, access | 765 // Receivers requiring non-standard element accesses (interceptors, access |
765 // checks, strings and string wrappers, proxies) are handled in the runtime. | 766 // checks, strings and string wrappers, proxies) are handled in the runtime. |
766 GotoIf(Int32LessThanOrEqual(instance_type, | 767 GotoIf(Int32LessThanOrEqual(instance_type, |
767 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), | 768 Int32Constant(LAST_CUSTOM_ELEMENTS_RECEIVER)), |
768 &slow); | 769 &slow); |
769 | 770 |
770 TryToName(name, &if_index, &var_index, &if_unique_name, &slow); | 771 TryToName(name, &if_index, &var_index, &if_unique_name, &var_unique, &slow); |
771 | 772 |
772 Bind(&if_index); | 773 Bind(&if_index); |
773 { | 774 { |
774 Comment("integer index"); | 775 Comment("integer index"); |
775 EmitGenericElementStore(receiver, receiver_map, instance_type, | 776 EmitGenericElementStore(receiver, receiver_map, instance_type, |
776 var_index.value(), value, context, &slow); | 777 var_index.value(), value, context, &slow); |
777 } | 778 } |
778 | 779 |
779 Bind(&if_unique_name); | 780 Bind(&if_unique_name); |
780 { | 781 { |
781 Comment("key is unique name"); | 782 Comment("key is unique name"); |
782 KeyedStoreGenericAssembler::StoreICParameters p(context, receiver, name, | 783 StoreICParameters p(context, receiver, var_unique.value(), value, slot, |
783 value, slot, vector); | 784 vector); |
784 EmitGenericPropertyStore(receiver, receiver_map, &p, &slow, language_mode); | 785 EmitGenericPropertyStore(receiver, receiver_map, &p, &slow, language_mode); |
785 } | 786 } |
786 | 787 |
787 Bind(&slow); | 788 Bind(&slow); |
788 { | 789 { |
789 Comment("KeyedStoreGeneric_slow"); | 790 Comment("KeyedStoreGeneric_slow"); |
790 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value, | 791 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value, |
791 SmiConstant(language_mode)); | 792 SmiConstant(language_mode)); |
792 } | 793 } |
793 } | 794 } |
794 | 795 |
795 } // namespace internal | 796 } // namespace internal |
796 } // namespace v8 | 797 } // namespace v8 |
OLD | NEW |