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

Side by Side Diff: src/builtins/builtins-string.cc

Issue 2358263002: [builtins] migrate C++ String Iterator builtins to baseline TurboFan (Closed)
Patch Set: Adapt arguments for TFJ builtins Created 4 years, 2 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
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/builtins/builtins.h" 5 #include "src/builtins/builtins.h"
6 #include "src/builtins/builtins-utils.h" 6 #include "src/builtins/builtins-utils.h"
7 7
8 #include "src/code-factory.h" 8 #include "src/code-factory.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 598 matching lines...) Expand 10 before | Expand all | Expand 10 after
609 typedef compiler::Node Node; 609 typedef compiler::Node Node;
610 610
611 Node* receiver = assembler->Parameter(0); 611 Node* receiver = assembler->Parameter(0);
612 Node* context = assembler->Parameter(3); 612 Node* context = assembler->Parameter(3);
613 613
614 Node* result = assembler->ToThisValue( 614 Node* result = assembler->ToThisValue(
615 context, receiver, PrimitiveType::kString, "String.prototype.valueOf"); 615 context, receiver, PrimitiveType::kString, "String.prototype.valueOf");
616 assembler->Return(result); 616 assembler->Return(result);
617 } 617 }
618 618
619 BUILTIN(StringPrototypeIterator) { 619 void Builtins::Generate_StringPrototypeIterator(CodeStubAssembler* assembler) {
620 HandleScope scope(isolate); 620 typedef CodeStubAssembler::Label Label;
621 TO_THIS_STRING(object, "String.prototype[Symbol.iterator]"); 621 typedef compiler::Node Node;
622 622 typedef CodeStubAssembler::Variable Variable;
623 Handle<String> string; 623
624 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string, 624 Variable var_string(assembler, MachineRepresentation::kTagged);
625 Object::ToString(isolate, object)); 625 Variable var_index(assembler, MachineRepresentation::kTagged);
626 626
627 return *isolate->factory()->NewJSStringIterator(string); 627 Variable* loop_inputs[] = {&var_string, &var_index};
628 Label loop(assembler, 2, loop_inputs);
629 Label allocate_iterator(assembler);
630
631 Node* receiver = assembler->Parameter(0);
632 Node* context = assembler->Parameter(3);
633
634 Node* string = assembler->ToThisString(context, receiver,
635 "String.prototype[Symbol.iterator]");
636 var_string.Bind(string);
637 var_index.Bind(assembler->SmiConstant(Smi::FromInt(0)));
638
639 assembler->Goto(&loop);
640 assembler->Bind(&loop);
641 {
642 // Load the instance type of the {string}.
643 Node* string_instance_type = assembler->LoadInstanceType(string);
644
645 // Check if the {string} is a SeqString.
646 Label if_stringisnotsequential(assembler);
647 assembler->Branch(assembler->Word32Equal(
648 assembler->Word32And(string_instance_type,
649 assembler->Int32Constant(
650 kStringRepresentationMask)),
651 assembler->Int32Constant(kSeqStringTag)),
652 &allocate_iterator, &if_stringisnotsequential);
653
654 assembler->Bind(&if_stringisnotsequential);
655 {
656 // Check if the {string} is a ConsString.
657 Label if_stringiscons(assembler), if_stringisnotcons(assembler);
658 assembler->Branch(
659 assembler->Word32Equal(
660 assembler->Word32And(
661 string_instance_type,
662 assembler->Int32Constant(kStringRepresentationMask)),
663 assembler->Int32Constant(kConsStringTag)),
664 &if_stringiscons, &if_stringisnotcons);
665
666 assembler->Bind(&if_stringiscons);
667 {
668 // Flatten cons-string and finish.
669 var_string.Bind(assembler->CallRuntime(
670 Runtime::kFlattenString, assembler->NoContextConstant(), string));
671 assembler->Goto(&allocate_iterator);
672 }
673
674 assembler->Bind(&if_stringisnotcons);
675 {
676 // Check if the {string} is an ExternalString.
677 Label if_stringisnotexternal(assembler);
678 assembler->Branch(
679 assembler->Word32Equal(
680 assembler->Word32And(
681 string_instance_type,
682 assembler->Int32Constant(kStringRepresentationMask)),
683 assembler->Int32Constant(kExternalStringTag)),
684 &allocate_iterator, &if_stringisnotexternal);
685
686 assembler->Bind(&if_stringisnotexternal);
687 {
688 // The {string} is a SlicedString, continue with its parent.
689 Node* index = var_index.value();
690 Node* string_offset =
691 assembler->LoadObjectField(string, SlicedString::kOffsetOffset);
692 Node* string_parent =
693 assembler->LoadObjectField(string, SlicedString::kParentOffset);
694 var_index.Bind(assembler->SmiAdd(index, string_offset));
695 var_string.Bind(string_parent);
696 assembler->Goto(&loop);
697 }
698 }
699 }
700 }
701
702 assembler->Bind(&allocate_iterator);
703 {
704 Node* native_context = assembler->LoadNativeContext(context);
705 Node* map = assembler->LoadFixedArrayElement(
706 native_context,
707 assembler->IntPtrConstant(Context::STRING_ITERATOR_MAP_INDEX), 0,
708 CodeStubAssembler::INTPTR_PARAMETERS);
709 Node* iterator = assembler->Allocate(JSStringIterator::kSize);
710 assembler->StoreMapNoWriteBarrier(iterator, map);
711 assembler->StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset,
712 Heap::kEmptyFixedArrayRootIndex);
713 assembler->StoreObjectFieldRoot(iterator, JSObject::kElementsOffset,
714 Heap::kEmptyFixedArrayRootIndex);
715 assembler->StoreObjectFieldNoWriteBarrier(
716 iterator, JSStringIterator::kStringOffset, var_string.value());
717
718 assembler->StoreObjectFieldNoWriteBarrier(
719 iterator, JSStringIterator::kNextIndexOffset, var_index.value());
720 assembler->Return(iterator);
721 }
628 } 722 }
629 723
630 BUILTIN(StringIteratorPrototypeNext) { 724 namespace {
631 HandleScope scope(isolate); 725
632 726 // Return the |word32| codepoint at {index}. Supports SeqStrings and
633 if (!args.receiver()->IsJSStringIterator()) { 727 // ExternalStrings.
634 Handle<String> reason = isolate->factory()->NewStringFromAsciiChecked( 728 compiler::Node* LoadSurrogatePairInternal(CodeStubAssembler* assembler,
635 "String Iterator.prototype.next"); 729 compiler::Node* string,
636 THROW_NEW_ERROR_RETURN_FAILURE( 730 compiler::Node* length,
637 isolate, 731 compiler::Node* index,
638 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, reason)); 732 UnicodeEncoding encoding) {
639 } 733 typedef CodeStubAssembler::Label Label;
640 Handle<JSStringIterator> iterator = 734 typedef compiler::Node Node;
641 Handle<JSStringIterator>::cast(args.receiver()); 735 typedef CodeStubAssembler::Variable Variable;
642 Handle<String> string(iterator->string()); 736 Label handle_surrogate_pair(assembler), return_result(assembler);
643 737 Variable var_result(assembler, MachineRepresentation::kWord32);
644 int position = iterator->index(); 738 Variable var_trail(assembler, MachineRepresentation::kWord16);
645 int length = string->length(); 739 var_result.Bind(assembler->Int32Constant(0));
646 740 var_trail.Bind(assembler->Int32Constant(0));
647 if (position < length) { 741
648 uint16_t lead = string->Get(position); 742 Node* string_instance_type = assembler->LoadInstanceType(string);
649 if (lead >= 0xD800 && lead <= 0xDBFF && position + 1 < length) { 743
650 uint16_t trail = string->Get(position + 1); 744 Label if_stringissequential(assembler), if_stringisexternal(assembler);
651 if (V8_LIKELY(trail >= 0xDC00 && trail <= 0xDFFF)) { 745 assembler->Branch(assembler->Word32Equal(
652 // Return surrogate pair code units 746 assembler->Word32And(string_instance_type,
653 iterator->set_index(position + 2); 747 assembler->Int32Constant(
654 Handle<String> value = 748 kStringRepresentationMask)),
655 isolate->factory()->NewSurrogatePairString(lead, trail); 749 assembler->Int32Constant(kSeqStringTag)),
656 return *isolate->factory()->NewJSIteratorResult(value, false); 750 &if_stringissequential, &if_stringisexternal);
657 } 751
658 } 752 assembler->Bind(&if_stringissequential);
659 753 {
660 // Return single code unit 754 Label if_stringisonebyte(assembler), if_stringistwobyte(assembler);
661 iterator->set_index(position + 1); 755 assembler->Branch(
662 Handle<String> value = 756 assembler->Word32Equal(
663 isolate->factory()->LookupSingleCharacterStringFromCode(lead); 757 assembler->Word32And(string_instance_type,
664 return *isolate->factory()->NewJSIteratorResult(value, false); 758 assembler->Int32Constant(kStringEncodingMask)),
665 } 759 assembler->Int32Constant(kOneByteStringTag)),
666 760 &if_stringisonebyte, &if_stringistwobyte);
667 iterator->set_string(isolate->heap()->empty_string()); 761
668 762 assembler->Bind(&if_stringisonebyte);
669 return *isolate->factory()->NewJSIteratorResult( 763 {
670 isolate->factory()->undefined_value(), true); 764 var_result.Bind(assembler->Load(
765 MachineType::Uint8(), string,
766 assembler->IntPtrAdd(
767 index, assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
768 kHeapObjectTag))));
769 assembler->Goto(&return_result);
770 }
771
772 assembler->Bind(&if_stringistwobyte);
773 {
774 Node* lead = assembler->Load(
775 MachineType::Uint16(), string,
776 assembler->IntPtrAdd(
777 assembler->WordShl(index, assembler->IntPtrConstant(1)),
778 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
779 kHeapObjectTag)));
780 var_result.Bind(lead);
781 Node* next_pos = assembler->Int32Add(index, assembler->Int32Constant(1));
782
783 Label if_isdoublecodeunit(assembler);
784 assembler->GotoIf(assembler->Int32GreaterThanOrEqual(next_pos, length),
785 &return_result);
786 assembler->GotoIf(
787 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xD800)),
788 &return_result);
789 assembler->Branch(
790 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xDC00)),
791 &if_isdoublecodeunit, &return_result);
792
793 assembler->Bind(&if_isdoublecodeunit);
794 {
795 Node* trail = assembler->Load(
796 MachineType::Uint16(), string,
797 assembler->IntPtrAdd(
798 assembler->WordShl(next_pos, assembler->IntPtrConstant(1)),
799 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
800 kHeapObjectTag)));
801 assembler->GotoIf(
802 assembler->Uint32LessThan(trail, assembler->Int32Constant(0xDC00)),
803 &return_result);
804 assembler->GotoIf(assembler->Uint32GreaterThanOrEqual(
805 trail, assembler->Int32Constant(0xE000)),
806 &return_result);
807
808 var_trail.Bind(trail);
809 assembler->Goto(&handle_surrogate_pair);
810 }
811 }
812 }
813
814 assembler->Bind(&if_stringisexternal);
815 {
816 assembler->Assert(assembler->Word32Equal(
817 assembler->Word32And(
818 string_instance_type,
819 assembler->Int32Constant(kStringRepresentationMask)),
820 assembler->Int32Constant(kExternalStringTag)));
821 Label if_stringisshort(assembler), if_stringisnotshort(assembler);
822
823 assembler->Branch(assembler->Word32Equal(
824 assembler->Word32And(string_instance_type,
825 assembler->Int32Constant(
826 kShortExternalStringMask)),
827 assembler->Int32Constant(0)),
828 &if_stringisshort, &if_stringisnotshort);
829
830 assembler->Bind(&if_stringisshort);
831 {
832 // Load the actual resource data from the {string}.
833 Node* string_resource_data = assembler->LoadObjectField(
834 string, ExternalString::kResourceDataOffset, MachineType::Pointer());
835
836 Label if_stringistwobyte(assembler), if_stringisonebyte(assembler);
837 assembler->Branch(assembler->Word32Equal(
838 assembler->Word32And(
839 string_instance_type,
840 assembler->Int32Constant(kStringEncodingMask)),
841 assembler->Int32Constant(kTwoByteStringTag)),
842 &if_stringistwobyte, &if_stringisonebyte);
843
844 assembler->Bind(&if_stringisonebyte);
845 {
846 var_result.Bind(
847 assembler->Load(MachineType::Uint8(), string_resource_data, index));
848 assembler->Goto(&return_result);
849 }
850
851 assembler->Bind(&if_stringistwobyte);
852 {
853 Label if_isdoublecodeunit(assembler);
854 Node* lead = assembler->Load(
855 MachineType::Uint16(), string_resource_data,
856 assembler->WordShl(index, assembler->IntPtrConstant(1)));
857 var_result.Bind(lead);
858 Node* next_pos =
859 assembler->Int32Add(index, assembler->Int32Constant(1));
860
861 assembler->GotoIf(assembler->Int32GreaterThanOrEqual(next_pos, length),
862 &return_result);
863 assembler->GotoIf(
864 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xD800)),
865 &return_result);
866 assembler->Branch(
867 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xDC00)),
868 &if_isdoublecodeunit, &return_result);
869
870 assembler->Bind(&if_isdoublecodeunit);
871 {
872 Node* trail = assembler->Load(
873 MachineType::Uint16(), string,
874 assembler->IntPtrAdd(
875 assembler->WordShl(next_pos, assembler->IntPtrConstant(1)),
876 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
877 kHeapObjectTag)));
878 assembler->GotoIf(assembler->Uint32LessThan(
879 trail, assembler->Int32Constant(0xDC00)),
880 &return_result);
881 assembler->GotoIf(assembler->Uint32GreaterThanOrEqual(
882 trail, assembler->Int32Constant(0xE000)),
883 &return_result);
884
885 var_trail.Bind(trail);
886 assembler->Goto(&handle_surrogate_pair);
887 }
888 }
889 }
890
891 assembler->Bind(&if_stringisnotshort);
892 {
893 Label if_isdoublecodeunit(assembler);
894 Node* lead = assembler->SmiToWord32(assembler->CallRuntime(
895 Runtime::kExternalStringGetChar, assembler->NoContextConstant(),
896 string, assembler->SmiTag(index)));
897 var_result.Bind(lead);
898 Node* next_pos = assembler->Int32Add(index, assembler->Int32Constant(1));
899
900 assembler->GotoIf(assembler->Int32GreaterThanOrEqual(next_pos, length),
901 &return_result);
902 assembler->GotoIf(
903 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xD800)),
904 &return_result);
905 assembler->Branch(assembler->Uint32GreaterThanOrEqual(
906 lead, assembler->Int32Constant(0xDC00)),
907 &return_result, &if_isdoublecodeunit);
908
909 assembler->Bind(&if_isdoublecodeunit);
910 {
911 Node* trail = assembler->SmiToWord32(assembler->CallRuntime(
912 Runtime::kExternalStringGetChar, assembler->NoContextConstant(),
913 string, assembler->SmiTag(next_pos)));
914 assembler->GotoIf(
915 assembler->Uint32LessThan(trail, assembler->Int32Constant(0xDC00)),
916 &return_result);
917 assembler->GotoIf(assembler->Uint32GreaterThanOrEqual(
918 trail, assembler->Int32Constant(0xE000)),
919 &return_result);
920 var_trail.Bind(trail);
921 assembler->Goto(&handle_surrogate_pair);
922 }
923 }
924 }
925
926 assembler->Bind(&handle_surrogate_pair);
927 {
928 Node* lead = var_result.value();
929 Node* trail = var_trail.value();
930 #ifdef ENABLE_SLOW_DCHECKS
931 // Check that this path is only taken if a surrogate pair is found
932 assembler->Assert(assembler->Uint32GreaterThanOrEqual(
933 lead, assembler->Int32Constant(0xD800)));
934 assembler->Assert(
935 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xDC00)));
936 assembler->Assert(assembler->Uint32GreaterThanOrEqual(
937 trail, assembler->Int32Constant(0xDC00)));
938 assembler->Assert(
939 assembler->Uint32LessThan(trail, assembler->Int32Constant(0xE000)));
940 #endif
941
942 switch (encoding) {
943 case UnicodeEncoding::UTF16:
944 var_result.Bind(assembler->WordOr(
945 assembler->WordShl(trail, assembler->Int32Constant(16)), lead));
946 break;
947
948 case UnicodeEncoding::UTF32: {
949 // Convert UTF16 surrogate pair into |word32| code point, encoded as
950 // UTF32.
951 Node* surrogate_offset =
952 assembler->Int32Constant(0x10000 - (0xD800 << 10) - 0xDC00);
953
954 // (lead << 10) + trail + SURROGATE_OFFSET
955 var_result.Bind(assembler->Int32Add(
956 assembler->WordShl(lead, assembler->Int32Constant(10)),
957 assembler->Int32Add(trail, surrogate_offset)));
958 break;
959 }
960 }
961 assembler->Goto(&return_result);
962 }
963
964 assembler->Bind(&return_result);
965 return var_result.value();
671 } 966 }
672 967
968 compiler::Node* LoadSurrogatePairAt(CodeStubAssembler* assembler,
969 compiler::Node* string,
970 compiler::Node* length,
971 compiler::Node* index) {
972 return LoadSurrogatePairInternal(assembler, string, length, index,
973 UnicodeEncoding::UTF16);
974 }
975
976 } // namespace
977
978 void Builtins::Generate_StringIteratorPrototypeNext(
979 CodeStubAssembler* assembler) {
980 typedef CodeStubAssembler::Label Label;
981 typedef compiler::Node Node;
982 typedef CodeStubAssembler::Variable Variable;
983
984 Variable var_value(assembler, MachineRepresentation::kTagged);
985 Variable var_done(assembler, MachineRepresentation::kTagged);
986
987 var_value.Bind(assembler->UndefinedConstant());
988 var_done.Bind(assembler->BooleanConstant(true));
989
990 Label throw_bad_receiver(assembler), next_codepoint(assembler),
991 return_result(assembler);
992
993 Node* iterator = assembler->Parameter(0);
994 Node* context = assembler->Parameter(3);
995
996 assembler->GotoIf(assembler->WordIsSmi(iterator), &throw_bad_receiver);
997 assembler->GotoUnless(
998 assembler->WordEqual(assembler->LoadInstanceType(iterator),
999 assembler->Int32Constant(JS_STRING_ITERATOR_TYPE)),
1000 &throw_bad_receiver);
1001
1002 Node* string =
1003 assembler->LoadObjectField(iterator, JSStringIterator::kStringOffset);
1004 Node* position =
1005 assembler->LoadObjectField(iterator, JSStringIterator::kNextIndexOffset);
1006 Node* length = assembler->LoadObjectField(string, String::kLengthOffset);
1007
1008 assembler->Branch(assembler->SmiLessThan(position, length), &next_codepoint,
1009 &return_result);
1010
1011 assembler->Bind(&next_codepoint);
1012 {
1013 Node* ch =
1014 LoadSurrogatePairAt(assembler, string, assembler->SmiUntag(length),
1015 assembler->SmiUntag(position));
1016 Node* value = assembler->StringFromCodePoint(ch, UnicodeEncoding::UTF16);
1017 var_value.Bind(value);
1018 Node* length = assembler->LoadObjectField(value, String::kLengthOffset);
1019 assembler->StoreObjectFieldNoWriteBarrier(
1020 iterator, JSStringIterator::kNextIndexOffset,
1021 assembler->SmiAdd(position, length));
1022 var_done.Bind(assembler->BooleanConstant(false));
1023 assembler->Goto(&return_result);
1024 }
1025
1026 assembler->Bind(&return_result);
1027 {
1028 Node* native_context = assembler->LoadNativeContext(context);
1029 Node* map = assembler->LoadFixedArrayElement(
1030 native_context,
1031 assembler->IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0,
1032 CodeStubAssembler::INTPTR_PARAMETERS);
1033 Node* result = assembler->Allocate(JSIteratorResult::kSize);
1034 assembler->StoreMapNoWriteBarrier(result, map);
1035 assembler->StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
1036 Heap::kEmptyFixedArrayRootIndex);
1037 assembler->StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
1038 Heap::kEmptyFixedArrayRootIndex);
1039 assembler->StoreObjectFieldNoWriteBarrier(
1040 result, JSIteratorResult::kValueOffset, var_value.value());
1041 assembler->StoreObjectFieldNoWriteBarrier(
1042 result, JSIteratorResult::kDoneOffset, var_done.value());
1043 assembler->Return(result);
1044 }
1045
1046 assembler->Bind(&throw_bad_receiver);
1047 {
1048 // The {receiver} is not a valid JSGeneratorObject.
1049 Node* result = assembler->CallRuntime(
1050 Runtime::kThrowIncompatibleMethodReceiver, context,
1051 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
1052 "String Iterator.prototype.next", TENURED)),
1053 iterator);
1054 assembler->Return(result); // Never reached.
1055 }
1056 }
1057
673 } // namespace internal 1058 } // namespace internal
674 } // namespace v8 1059 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698