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

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

Issue 2696993002: [stubs] KeyedStoreGeneric: overwrite existing fast properties directly (Closed)
Patch Set: address comments 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 // Ignore FLAG_track_fields etc. and always emit code for all checks,
616 // because this builtin is part of the snapshot and therefore should
617 // be flag independent.
618 GotoIf(Word32Equal(representation, Int32Constant(Representation::kSmi)),
619 &r_smi);
620 GotoIf(Word32Equal(representation, Int32Constant(Representation::kDouble)),
621 &r_double);
622 GotoIf(
623 Word32Equal(representation, Int32Constant(Representation::kHeapObject)),
624 &r_heapobject);
625 GotoIf(Word32Equal(representation, Int32Constant(Representation::kNone)),
626 bailout);
627 CSA_ASSERT(this, Word32Equal(representation,
628 Int32Constant(Representation::kTagged)));
629 Goto(&all_fine);
630
631 Bind(&r_smi);
632 { Branch(TaggedIsSmi(value), &all_fine, bailout); }
633
634 Bind(&r_double);
635 {
636 GotoIf(TaggedIsSmi(value), &all_fine);
637 Node* value_map = LoadMap(value);
638 // While supporting mutable HeapNumbers would be straightforward, such
639 // objects should not end up here anyway.
640 CSA_ASSERT(this,
641 WordNotEqual(value_map,
642 LoadRoot(Heap::kMutableHeapNumberMapRootIndex)));
643 Branch(IsHeapNumberMap(value_map), &all_fine, bailout);
644 }
645
646 Bind(&r_heapobject);
647 {
648 GotoIf(TaggedIsSmi(value), bailout);
649 Node* field_type =
650 LoadValueByKeyIndex<DescriptorArray>(descriptors, name_index);
651 intptr_t kNoneType = reinterpret_cast<intptr_t>(FieldType::None());
652 intptr_t kAnyType = reinterpret_cast<intptr_t>(FieldType::Any());
653 // FieldType::None can't hold any value.
654 GotoIf(WordEqual(field_type, IntPtrConstant(kNoneType)), bailout);
655 // FieldType::Any can hold any value.
656 GotoIf(WordEqual(field_type, IntPtrConstant(kAnyType)), &all_fine);
657 CSA_ASSERT(this, IsWeakCell(field_type));
658 // Cleared WeakCells count as FieldType::None, which can't hold any value.
659 field_type = LoadWeakCellValue(field_type, bailout);
660 // FieldType::Class(...) performs a map check.
661 CSA_ASSERT(this, IsMap(field_type));
662 Branch(WordEqual(LoadMap(value), field_type), &all_fine, bailout);
663 }
664
665 Bind(&all_fine);
666 }
667
668 void KeyedStoreGenericAssembler::OverwriteExistingFastProperty(
669 Node* object, Node* object_map, Node* properties, Node* descriptors,
670 Node* descriptor_name_index, Node* details, Node* value, Label* slow) {
671 // Properties in descriptors can't be overwritten without map transition.
672 GotoIf(Word32NotEqual(DecodeWord32<PropertyDetails::LocationField>(details),
673 Int32Constant(kField)),
674 slow);
675
676 if (FLAG_track_constant_fields) {
677 // TODO(ishell): Taking the slow path is not necessary if new and old
678 // values are identical.
679 GotoIf(Word32Equal(DecodeWord32<PropertyDetails::ConstnessField>(details),
680 Int32Constant(kConst)),
681 slow);
682 }
683
684 Label done(this);
685 Node* representation =
686 DecodeWord32<PropertyDetails::RepresentationField>(details);
687
688 CheckFieldType(descriptors, descriptor_name_index, representation, value,
689 slow);
690 Node* field_index =
691 DecodeWordFromWord32<PropertyDetails::FieldIndexField>(details);
692 Node* inobject_properties = LoadMapInobjectProperties(object_map);
693
694 Label inobject(this), backing_store(this);
695 Branch(UintPtrLessThan(field_index, inobject_properties), &inobject,
696 &backing_store);
697
698 Bind(&inobject);
699 {
700 Node* field_offset =
701 IntPtrMul(IntPtrSub(LoadMapInstanceSize(object_map),
702 IntPtrSub(inobject_properties, field_index)),
703 IntPtrConstant(kPointerSize));
704 Label tagged_rep(this), double_rep(this);
705 Branch(Word32Equal(representation, Int32Constant(Representation::kDouble)),
706 &double_rep, &tagged_rep);
707 Bind(&double_rep);
708 {
709 Node* double_value = ChangeNumberToFloat64(value);
710 if (FLAG_unbox_double_fields) {
711 StoreObjectFieldNoWriteBarrier(object, field_offset, double_value,
712 MachineRepresentation::kFloat64);
713 } else {
714 Node* mutable_heap_number = LoadObjectField(object, field_offset);
715 StoreHeapNumberValue(mutable_heap_number, double_value);
716 }
717 Goto(&done);
718 }
719
720 Bind(&tagged_rep);
721 {
722 StoreObjectField(object, field_offset, value);
723 Goto(&done);
724 }
725 }
726
727 Bind(&backing_store);
728 {
729 Node* backing_store_index = IntPtrSub(field_index, inobject_properties);
730 Label tagged_rep(this), double_rep(this);
731 Branch(Word32Equal(representation, Int32Constant(Representation::kDouble)),
732 &double_rep, &tagged_rep);
733 Bind(&double_rep);
734 {
735 Node* double_value = ChangeNumberToFloat64(value);
736 Node* mutable_heap_number =
737 LoadFixedArrayElement(properties, backing_store_index);
738 StoreHeapNumberValue(mutable_heap_number, double_value);
739 Goto(&done);
740 }
741 Bind(&tagged_rep);
742 {
743 StoreFixedArrayElement(properties, backing_store_index, value);
744 Goto(&done);
745 }
746 }
747 Bind(&done);
748 }
749
602 void KeyedStoreGenericAssembler::EmitGenericPropertyStore( 750 void KeyedStoreGenericAssembler::EmitGenericPropertyStore(
603 Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow, 751 Node* receiver, Node* receiver_map, const StoreICParameters* p, Label* slow,
604 LanguageMode language_mode) { 752 LanguageMode language_mode) {
605 Variable var_accessor_pair(this, MachineRepresentation::kTagged); 753 Variable var_accessor_pair(this, MachineRepresentation::kTagged);
606 Variable var_accessor_holder(this, MachineRepresentation::kTagged); 754 Variable var_accessor_holder(this, MachineRepresentation::kTagged);
607 Label stub_cache(this), fast_properties(this), dictionary_properties(this), 755 Label stub_cache(this), fast_properties(this), dictionary_properties(this),
608 accessor(this), readonly(this); 756 accessor(this), readonly(this);
609 Node* properties = LoadProperties(receiver); 757 Node* properties = LoadProperties(receiver);
610 Node* properties_map = LoadMap(properties); 758 Node* properties_map = LoadMap(properties);
611 Branch(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)), 759 Branch(WordEqual(properties_map, LoadRoot(Heap::kHashTableMapRootIndex)),
612 &dictionary_properties, &fast_properties); 760 &dictionary_properties, &fast_properties);
613 761
614 Bind(&fast_properties); 762 Bind(&fast_properties);
615 { 763 {
616 // TODO(jkummerow): Does it make sense to support some cases here inline? 764 Comment("fast property store");
617 // Maybe overwrite existing writable properties? 765 Node* bitfield3 = LoadMapBitField3(receiver_map);
618 // Maybe support map transitions? 766 Node* descriptors = LoadMapDescriptors(receiver_map);
619 Goto(&stub_cache); 767 Label descriptor_found(this);
768 Variable var_name_index(this, MachineType::PointerRepresentation());
769 // TODO(jkummerow): Maybe look for existing map transitions?
770 Label* notfound = &stub_cache;
771 DescriptorLookup(p->name, descriptors, bitfield3, &descriptor_found,
772 &var_name_index, notfound);
773
774 Bind(&descriptor_found);
775 {
776 Node* name_index = var_name_index.value();
777 Node* details =
778 LoadDetailsByKeyIndex<DescriptorArray>(descriptors, name_index);
779 Label data_property(this);
780 JumpIfDataProperty(details, &data_property, &readonly);
781
782 // Accessor case.
783 // TODO(jkummerow): Implement a trimmed-down LoadAccessorFromFastObject.
784 Variable var_details(this, MachineRepresentation::kWord32);
785 LoadPropertyFromFastObject(receiver, receiver_map, descriptors,
786 name_index, &var_details, &var_accessor_pair);
787 var_accessor_holder.Bind(receiver);
788 Goto(&accessor);
789
790 Bind(&data_property);
791 {
792 OverwriteExistingFastProperty(receiver, receiver_map, properties,
793 descriptors, name_index, details,
794 p->value, slow);
795 Return(p->value);
796 }
797 }
620 } 798 }
621 799
622 Bind(&dictionary_properties); 800 Bind(&dictionary_properties);
623 { 801 {
624 Comment("dictionary property store"); 802 Comment("dictionary property store");
625 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out 803 // We checked for LAST_CUSTOM_ELEMENTS_RECEIVER before, which rules out
626 // seeing global objects here (which would need special handling). 804 // seeing global objects here (which would need special handling).
627 805
628 Variable var_name_index(this, MachineType::PointerRepresentation()); 806 Variable var_name_index(this, MachineType::PointerRepresentation());
629 Label dictionary_found(this, &var_name_index), not_found(this); 807 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); 947 Bind(&slow);
770 { 948 {
771 Comment("KeyedStoreGeneric_slow"); 949 Comment("KeyedStoreGeneric_slow");
772 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value, 950 TailCallRuntime(Runtime::kSetProperty, context, receiver, name, value,
773 SmiConstant(language_mode)); 951 SmiConstant(language_mode));
774 } 952 }
775 } 953 }
776 954
777 } // namespace internal 955 } // namespace internal
778 } // namespace v8 956 } // 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