Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(311)

Side by Side Diff: src/ic/keyed-store-generic.cc

Issue 2696993002: [stubs] KeyedStoreGeneric: overwrite existing fast properties directly (Closed)
Patch Set: ready for review Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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.h" 10 #include "src/ic/accessor-assembler.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 Node* current_elements_kind, Node* context, 65 Node* current_elements_kind, Node* context,
66 ElementsKind packed_kind, 66 ElementsKind packed_kind,
67 ElementsKind packed_kind_2, Label* bailout); 67 ElementsKind packed_kind_2, Label* bailout);
68 68
69 void JumpIfDataProperty(Node* details, Label* writable, Label* readonly); 69 void JumpIfDataProperty(Node* details, Label* writable, Label* readonly);
70 void LookupPropertyOnPrototypeChain(Node* receiver_map, Node* name, 70 void LookupPropertyOnPrototypeChain(Node* receiver_map, Node* name,
71 Label* accessor, 71 Label* accessor,
72 Variable* var_accessor_pair, 72 Variable* var_accessor_pair,
73 Variable* var_accessor_holder, 73 Variable* var_accessor_holder,
74 Label* readonly, Label* bailout); 74 Label* readonly, Label* bailout);
75
76 void CheckFieldType(Node* descriptors, Node* name_index, Node* representation,
77 Node* value, Label* bailout);
78 void OverwriteExistingFastProperty(Node* object, Node* object_map,
79 Node* properties, Node* descriptors,
80 Node* descriptor_name_index, Node* details,
81 Node* value, Label* slow);
75 }; 82 };
76 83
77 void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state, 84 void KeyedStoreGenericGenerator::Generate(compiler::CodeAssemblerState* state,
78 LanguageMode language_mode) { 85 LanguageMode language_mode) {
79 KeyedStoreGenericAssembler assembler(state); 86 KeyedStoreGenericAssembler assembler(state);
80 assembler.KeyedStoreGeneric(language_mode); 87 assembler.KeyedStoreGeneric(language_mode);
81 } 88 }
82 89
83 void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements( 90 void KeyedStoreGenericAssembler::BranchIfPrototypesHaveNonFastElements(
84 Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) { 91 Node* receiver_map, Label* non_fast_elements, Label* only_fast_elements) {
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
537 &var_entry, &next_proto, bailout); 544 &var_entry, &next_proto, bailout);
538 Bind(&found_fast); 545 Bind(&found_fast);
539 { 546 {
540 Node* descriptors = var_meta_storage.value(); 547 Node* descriptors = var_meta_storage.value();
541 Node* name_index = var_entry.value(); 548 Node* name_index = var_entry.value();
542 Node* details = 549 Node* details =
543 LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index); 550 LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index);
544 JumpIfDataProperty(details, &ok_to_write, readonly); 551 JumpIfDataProperty(details, &ok_to_write, readonly);
545 552
546 // Accessor case. 553 // Accessor case.
554 // TODO(jkummerow): Implement a trimmed-down LoadAccessorFromFastObject.
547 Variable var_details(this, MachineRepresentation::kWord32); 555 Variable var_details(this, MachineRepresentation::kWord32);
548 LoadPropertyFromFastObject(holder, holder_map, descriptors, name_index, 556 LoadPropertyFromFastObject(holder, holder_map, descriptors, name_index,
549 &var_details, var_accessor_pair); 557 &var_details, var_accessor_pair);
550 var_accessor_holder->Bind(holder); 558 var_accessor_holder->Bind(holder);
551 Goto(accessor); 559 Goto(accessor);
552 } 560 }
553 561
554 Bind(&found_dict); 562 Bind(&found_dict);
555 { 563 {
556 Node* dictionary = var_meta_storage.value(); 564 Node* dictionary = var_meta_storage.value();
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
592 bailout); 600 bailout);
593 Node* proto = LoadMapPrototype(holder_map); 601 Node* proto = LoadMapPrototype(holder_map);
594 GotoIf(WordEqual(proto, NullConstant()), &ok_to_write); 602 GotoIf(WordEqual(proto, NullConstant()), &ok_to_write);
595 var_holder.Bind(proto); 603 var_holder.Bind(proto);
596 var_holder_map.Bind(LoadMap(proto)); 604 var_holder_map.Bind(LoadMap(proto));
597 Goto(&loop); 605 Goto(&loop);
598 } 606 }
599 Bind(&ok_to_write); 607 Bind(&ok_to_write);
600 } 608 }
601 609
610 void KeyedStoreGenericAssembler::CheckFieldType(Node* descriptors,
611 Node* name_index,
612 Node* representation,
613 Node* value, Label* bailout) {
614 Label r_smi(this), r_double(this), r_heapobject(this), all_fine(this);
615 if (FLAG_track_fields) {
616 GotoIf(Word32Equal(representation, Int32Constant(Representation::kSmi)),
617 &r_smi);
618 }
619 if (FLAG_track_double_fields) {
620 GotoIf(Word32Equal(representation, Int32Constant(Representation::kDouble)),
621 &r_double);
622 }
623 if (FLAG_track_heap_object_fields) {
624 GotoIf(
625 Word32Equal(representation, Int32Constant(Representation::kHeapObject)),
626 &r_heapobject);
627 }
628 if (FLAG_track_fields) {
629 GotoIf(Word32Equal(representation, Int32Constant(Representation::kNone)),
630 bailout);
631 }
Igor Sheludko 2017/02/16 16:04:37 CSA_ASSERT(representation == kTagged)?
Jakob Kummerow 2017/02/16 18:24:27 Done.
632 Goto(&all_fine);
633
634 Bind(&r_smi);
Igor Sheludko 2017/02/16 16:04:37 1) "if (FLAG_track_fields) {" or we will have an u
Jakob Kummerow 2017/02/16 18:24:27 I agree, but as discussed, that unfortunately does
635 { Branch(TaggedIsSmi(value), &all_fine, bailout); }
636
637 Bind(&r_double);
Igor Sheludko 2017/02/16 16:04:37 Same here.
638 {
639 GotoIf(TaggedIsSmi(value), &all_fine);
640 Node* value_map = LoadMap(value);
641 // While supporting mutable HeapNumbers would be straightforward, such
642 // objects should not end up here anyway.
643 CSA_ASSERT(this,
644 WordNotEqual(value_map,
645 LoadRoot(Heap::kMutableHeapNumberMapRootIndex)));
646 Branch(IsHeapNumberMap(value_map), &all_fine, bailout);
647 }
648
649 Bind(&r_heapobject);
Igor Sheludko 2017/02/16 16:04:37 Same here.
650 {
651 GotoIf(TaggedIsSmi(value), bailout);
652 Node* field_type =
653 LoadValueByKeyIndex<DescriptorArray>(descriptors, name_index);
654 intptr_t kNoneType = reinterpret_cast<intptr_t>(FieldType::None());
655 intptr_t kAnyType = reinterpret_cast<intptr_t>(FieldType::Any());
656 // FieldType::None can't hold any value.
657 GotoIf(WordEqual(field_type, IntPtrConstant(kNoneType)), bailout);
658 // FieldType::Any can hold any value.
659 GotoIf(WordEqual(field_type, IntPtrConstant(kAnyType)), &all_fine);
660 CSA_ASSERT(this, IsWeakCell(field_type));
661 // Cleared WeakCells count as FieldType::None, which can't hold any value.
662 field_type = LoadWeakCellValue(field_type, bailout);
663 // FieldType::Class(...) performs a map check.
664 CSA_ASSERT(this, IsMap(field_type));
665 Branch(WordEqual(LoadMap(value), field_type), &all_fine, bailout);
666 }
667
668 Bind(&all_fine);
669 }
670
671 void KeyedStoreGenericAssembler::OverwriteExistingFastProperty(
672 Node* object, Node* object_map, Node* properties, Node* descriptors,
673 Node* descriptor_name_index, Node* details, Node* value, Label* slow) {
674 // Properties in descriptors can't be overwritten without map transition.
675 GotoIf(Word32NotEqual(DecodeWord32<PropertyDetails::LocationField>(details),
676 Int32Constant(kField)),
677 slow);
678
679 if (FLAG_track_constant_fields) {
680 // TODO(ishell): Taking the slow path is not necessary if new and old
681 // values are identical.
682 GotoIf(Word32Equal(DecodeWord32<PropertyDetails::ConstnessField>(details),
683 Int32Constant(kConst)),
684 slow);
685 }
686
687 Label done(this);
688 Node* representation =
689 DecodeWord32<PropertyDetails::RepresentationField>(details);
690
691 CheckFieldType(descriptors, descriptor_name_index, representation, value,
692 slow);
693 Node* field_index =
694 DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details);
695 Node* inobject_properties = LoadMapInobjectProperties(object_map);
696
697 Label inobject(this), backing_store(this);
698 Branch(UintPtrLessThan(field_index, inobject_properties), &inobject,
699 &backing_store);
700
701 Bind(&inobject);
702 {
703 Node* field_offset =
704 IntPtrMul(IntPtrSub(LoadMapInstanceSize(object_map),
705 IntPtrSub(inobject_properties, field_index)),
706 IntPtrConstant(kPointerSize));
707 Label tagged_rep(this), double_rep(this);
708 Branch(Word32Equal(representation, Int32Constant(Representation::kDouble)),
709 &double_rep, &tagged_rep);
710 Bind(&double_rep);
711 {
712 Node* double_value = ChangeNumberToFloat64(value);
713 if (FLAG_unbox_double_fields) {
714 StoreObjectFieldNoWriteBarrier(object, field_offset, double_value,
715 MachineRepresentation::kFloat64);
716 } else {
717 Node* mutable_heap_number = LoadObjectField(object, field_offset);
718 StoreHeapNumberValue(mutable_heap_number, double_value);
719 }
720 Goto(&done);
721 }
722
723 Bind(&tagged_rep);
724 {
725 StoreObjectField(object, field_offset, value);
726 Goto(&done);
727 }
728 }
729
730 Bind(&backing_store);
731 {
732 Node* backing_store_index = IntPtrSub(field_index, inobject_properties);
733 Label tagged_rep(this), double_rep(this);
734 Branch(Word32Equal(representation, Int32Constant(Representation::kDouble)),
735 &double_rep, &tagged_rep);
736 Bind(&double_rep);
737 {
738 Node* double_value = ChangeNumberToFloat64(value);
739 Node* mutable_heap_number =
740 LoadFixedArrayElement(properties, backing_store_index);
741 StoreHeapNumberValue(mutable_heap_number, double_value);
742 Goto(&done);
743 }
744 Bind(&tagged_rep);
745 {
746 StoreFixedArrayElement(properties, backing_store_index, value);
747 Goto(&done);
748 }
749 }
750 Bind(&done);
751 }
752
602 void KeyedStoreGenericAssembler::EmitGenericPropertyStore( 753 void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
603 Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow, 754 Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow,
604 LanguageMode language_mode) { 755 LanguageMode language_mode) {
605 Variable var_accessor_pair(this, MachineRepresentation::kTagged); 756 Variable var_accessor_pair(this, MachineRepresentation::kTagged);
606 Variable var_accessor_holder(this, MachineRepresentation::kTagged); 757 Variable var_accessor_holder(this, MachineRepresentation::kTagged);
607 Label stub_cache(this), fast_properties(this), dictionary_properties(this), 758 Label stub_cache(this), fast_properties(this), dictionary_properties(this),
608 accessor(this), readonly(this); 759 accessor(this), readonly(this);
609 Node* properties = LoadProperties(receiver); 760 Node* properties = LoadProperties(receiver);
610 Node* properties_map = LoadMap(properties); 761 Node* properties_map = LoadMap(properties);
611 Branch(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), 762 Branch(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)),
612 &dictionary_properties, &fast_properties); 763 &dictionary_properties, &fast_properties);
613 764
614 Bind(&fast_properties); 765 Bind(&fast_properties);
615 { 766 {
616 // TODO(jkummerow): Does it make sense to support some cases here inline? 767 Comment("fast property store");
617 // Maybe overwrite existing writable properties? 768 Node* bitfield3 = LoadMapBitField3(receiver_map);
618 // Maybe support map transitions? 769 Node* descriptors = LoadMapDescriptors(receiver_map);
619 Goto(&stub_cache); 770 Label descriptor_found(this);
771 Variable var_name_index(this, MachineType::PointerRepresentation());
772 // TODO(jkummerow): Maybe look for existing map transitions?
773 Label* notfound = &stub_cache;
774 DescriptorLookup(p->name, descriptors, bitfield3, &descriptor_found,
775 &var_name_index, notfound);
776
777 Bind(&descriptor_found);
778 {
779 Node* name_index = var_name_index.value();
780 Node* details =
781 LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index);
782 Label data_property(this);
783 JumpIfDataProperty(details, &data_property, &readonly);
784
785 // Accessor case.
786 // TODO(jkummerow): Implement a trimmed-down LoadAccessorFromFastObject.
787 Variable var_details(this, MachineRepresentation::kWord32);
788 LoadPropertyFromFastObject(receiver, receiver_map, descriptors,
789 name_index, &var_details, &var_accessor_pair);
790 var_accessor_holder.Bind(receiver);
791 Goto(&accessor);
792
793 Bind(&data_property);
794 {
795 OverwriteExistingFastProperty(receiver, receiver_map, properties,
796 descriptors, name_index, details,
797 p->value, slow);
798 Return(p->value);
799 }
800 }
620 } 801 }
621 802
622 Bind(&dictionary_properties); 803 Bind(&dictionary_properties);
623 { 804 {
624 Comment("dictionary property store"); 805 Comment("dictionary property store");
625 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out 806 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
626 // seeing global objects here (which would need special handling). 807 // seeing global objects here (which would need special handling).
627 808
628 Variable var_name_index(this, MachineType::PointerRepresentation()); 809 Variable var_name_index(this, MachineType::PointerRepresentation());
629 Label dictionary_found(this, &var_name_index), not_found(this); 810 Label dictionary_found(this, &var_name_index), not_found(this);
(...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 Bind(&slow); 950 Bind(&slow);
770 { 951 {
771 Comment("KeyedStoreGeneric_slow"); 952 Comment("KeyedStoreGeneric_slow");
772 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value, 953 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value,
773 SmiConstant(language_mode)); 954 SmiConstant(language_mode));
774 } 955 }
775 } 956 }
776 957
777 } // namespace internal 958 } // namespace internal
778 } // namespace v8 959 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698