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

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

Issue 2358263002: [builtins] migrate C++ String Iterator builtins to baseline TurboFan (Closed)
Patch Set: v6 (fix toString() behaviour in S.p[@@iterator]) Created 4 years, 3 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 | « src/builtins/builtins.h ('k') | src/objects-debug.cc » ('j') | 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/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::kWord32);
626 626
627 return *isolate->factory()->NewJSStringIterator(string); 627 Variable* loop_inputs[] = {&var_string, &var_index};
628 } 628 Label loop(assembler, 2, loop_inputs);
629 629 Label allocate_iterator(assembler);
630 BUILTIN(StringIteratorPrototypeNext) { 630
631 HandleScope scope(isolate); 631 Node* receiver = assembler->Parameter(0);
632 632 Node* context = assembler->Parameter(3);
633 if (!args.receiver()->IsJSStringIterator()) { 633
634 Handle<String> reason = isolate->factory()->NewStringFromAsciiChecked( 634 Node* string = assembler->ToThisString(context, receiver,
635 "String Iterator.prototype.next"); 635 "String.prototype[Symbol.iterator]");
636 THROW_NEW_ERROR_RETURN_FAILURE( 636 var_string.Bind(string);
637 isolate, 637 var_index.Bind(assembler->Int32Constant(0));
638 NewTypeError(MessageTemplate::kIncompatibleMethodReceiver, reason)); 638
639 } 639 assembler->Goto(&loop);
640 Handle<JSStringIterator> iterator = 640 assembler->Bind(&loop);
641 Handle<JSStringIterator>::cast(args.receiver()); 641 {
642 Handle<String> string(iterator->string()); 642 // Load the instance type of the {string}.
643 643 Node* string_instance_type = assembler->LoadInstanceType(string);
644 int position = iterator->index(); 644
645 int length = string->length(); 645 // Check if the {string} is a SeqString.
646 646 Label if_stringisnotsequential(assembler);
647 if (position < length) { 647 assembler->Branch(assembler->Word32Equal(
648 uint16_t lead = string->Get(position); 648 assembler->Word32And(string_instance_type,
649 if (lead >= 0xD800 && lead <= 0xDBFF && position + 1 < length) { 649 assembler->Int32Constant(
650 uint16_t trail = string->Get(position + 1); 650 kStringRepresentationMask)),
651 if (V8_LIKELY(trail >= 0xDC00 && trail <= 0xDFFF)) { 651 assembler->Int32Constant(kSeqStringTag)),
652 // Return surrogate pair code units 652 &allocate_iterator, &if_stringisnotsequential);
653 iterator->set_index(position + 2); 653
654 Handle<String> value = 654 assembler->Bind(&if_stringisnotsequential);
655 isolate->factory()->NewSurrogatePairString(lead, trail); 655 {
656 return *isolate->factory()->NewJSIteratorResult(value, false); 656 // Check if the {string} is a ConsString.
657 } 657 Label if_stringiscons(assembler), if_stringisnotcons(assembler);
658 } 658 assembler->Branch(
659 659 assembler->Word32Equal(
660 // Return single code unit 660 assembler->Word32And(
661 iterator->set_index(position + 1); 661 string_instance_type,
662 Handle<String> value = 662 assembler->Int32Constant(kStringRepresentationMask)),
663 isolate->factory()->LookupSingleCharacterStringFromCode(lead); 663 assembler->Int32Constant(kConsStringTag)),
664 return *isolate->factory()->NewJSIteratorResult(value, false); 664 &if_stringiscons, &if_stringisnotcons);
665 } 665
666 666 assembler->Bind(&if_stringiscons);
667 iterator->set_string(isolate->heap()->empty_string()); 667 {
668 668 // Flatten cons-string and finish.
669 return *isolate->factory()->NewJSIteratorResult( 669 var_string.Bind(assembler->CallRuntime(
670 isolate->factory()->undefined_value(), true); 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 = assembler->LoadAndUntagObjectField(
691 string, SlicedString::kOffsetOffset);
692 Node* string_parent =
693 assembler->LoadObjectField(string, SlicedString::kParentOffset);
694 var_index.Bind(assembler->IntPtrAdd(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* index = assembler->Int32Constant(Context::STRING_ITERATOR_MAP_INDEX);
706 Node* map = assembler->LoadFixedArrayElement(
707 native_context, index, 0, CodeStubAssembler::INTPTR_PARAMETERS);
708 Node* iterator = assembler->Allocate(JSStringIterator::kSize);
709 assembler->StoreMapNoWriteBarrier(iterator, map);
710 assembler->StoreObjectFieldRoot(iterator, JSValue::kPropertiesOffset,
711 Heap::kEmptyFixedArrayRootIndex);
712 assembler->StoreObjectFieldRoot(iterator, JSObject::kElementsOffset,
713 Heap::kEmptyFixedArrayRootIndex);
714 assembler->StoreObjectField(iterator, JSStringIterator::kStringOffset,
Benedikt Meurer 2016/09/23 18:14:53 This doesn't need a write barrier, since the objec
caitp 2016/09/23 19:14:16 Done.
715 var_string.value());
716
717 assembler->StoreObjectField(iterator, JSStringIterator::kNextIndexOffset,
Benedikt Meurer 2016/09/23 18:14:53 This doesn't need a write barrier, you can safely
caitp 2016/09/23 19:14:16 Done.
718 assembler->SmiFromWord32(var_index.value()));
719 assembler->Return(iterator);
720 }
721 }
722
723 namespace {
724
725 enum class UnicodeEncoding {
726 UTF16, // high 16bits trail surrogate, low 16bits lead surrogate
727 UTF32
728 };
729
730 // Return the |String| containing a single {codepoint}, which may be encoded
731 // as one of the following: a single UTF16 code unit, a |word32| with the
732 // high 16 bits set to the trailing surrogate, and low 16 bits set to the lead
733 // surrogate, or a single UTF32-encoded codepoint.
734 static compiler::Node* CreateStringFromCodePointInternal(
Benedikt Meurer 2016/09/23 03:46:24 You don't need static inside an anonymous namespac
caitp 2016/09/23 10:14:28 The UnicodeEncoding thing is there to control how
caitp 2016/09/23 19:14:16 The UnicodeEncoding thing is there to control how
Benedikt Meurer 2016/09/26 04:15:40 Acknowledged.
735 CodeStubAssembler* assembler, compiler::Node* codepoint,
736 UnicodeEncoding encoding) {
737 typedef CodeStubAssembler::Label Label;
738 typedef compiler::Node Node;
739 typedef CodeStubAssembler::Variable Variable;
740
741 Variable var_result(assembler, MachineRepresentation::kTagged);
742 var_result.Bind(assembler->EmptyStringConstant());
743
744 Label if_isonebyte(assembler), if_istwobyte(assembler),
745 return_result(assembler);
746
747 assembler->Branch(
748 assembler->Uint32LessThan(codepoint, assembler->Int32Constant(0x100)),
749 &if_isonebyte, &if_istwobyte);
750
751 assembler->Bind(&if_isonebyte);
752 {
753 Node* value = assembler->AllocateSeqOneByteString(1);
754 assembler->StoreNoWriteBarrier(
755 MachineRepresentation::kWord8, value,
756 assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
757 kHeapObjectTag),
758 codepoint);
759 var_result.Bind(value);
760 assembler->Goto(&return_result);
761 }
762
763 assembler->Bind(&if_istwobyte);
764 {
765 Label if_isdouble(assembler), if_issingle(assembler);
766 assembler->Branch(
767 assembler->Uint32LessThan(codepoint, assembler->Int32Constant(0x10000)),
768 &if_issingle, &if_isdouble);
769
770 assembler->Bind(&if_issingle);
771 {
772 Node* value = assembler->AllocateSeqTwoByteString(1);
773 assembler->StoreNoWriteBarrier(
774 MachineRepresentation::kWord16, value,
775 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
776 kHeapObjectTag),
777 codepoint);
778 var_result.Bind(value);
779 assembler->Goto(&return_result);
780 }
781
782 assembler->Bind(&if_isdouble);
783 {
784 switch (encoding) {
785 case UnicodeEncoding::UTF16:
786 break;
787 case UnicodeEncoding::UTF32: {
788 // Convert UTF32 to UTF16 code units, and store as a 32 bit word.
789 Node* lead_offset =
caitp 2016/09/23 19:14:16 This code here in particular should be very useful
790 assembler->Int32Constant(0xD800 - (0x10000 >> 10));
791
792 Node* lead = assembler->Int32Add(
793 assembler->WordShr(codepoint, assembler->Int32Constant(10)),
794 lead_offset);
795
796 Node* trail = assembler->Int32Add(
797 assembler->Word32And(codepoint, assembler->Int32Constant(0x3FF)),
798 assembler->Int32Constant(0xDC00));
799
800 codepoint = assembler->Word32Or(
801 assembler->WordShl(trail, assembler->Int32Constant(16)), lead);
802 }
803 default:
804 UNREACHABLE();
805 }
806
807 Node* value = assembler->AllocateSeqTwoByteString(2);
808 assembler->StoreNoWriteBarrier(
809 MachineRepresentation::kWord32, value,
810 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
811 kHeapObjectTag),
812 codepoint);
813 var_result.Bind(value);
814 assembler->Goto(&return_result);
815 }
816 }
817
818 assembler->Bind(&return_result);
819 return var_result.value();
820 }
821
822 static compiler::Node* CreateStringFromSurrogatePair(
823 CodeStubAssembler* assembler, compiler::Node* code_units) {
824 return CreateStringFromCodePointInternal(assembler, code_units,
825 UnicodeEncoding::UTF16);
826 }
827
828 // Return the |word32| codepoint at {index}. Supports SeqStrings and
829 // ExternalStrings.
830 static compiler::Node* LoadSurrogatePairInternal(CodeStubAssembler* assembler,
831 compiler::Node* string,
832 compiler::Node* length,
833 compiler::Node* index,
834 UnicodeEncoding encoding) {
835 typedef CodeStubAssembler::Label Label;
836 typedef compiler::Node Node;
837 typedef CodeStubAssembler::Variable Variable;
838 Label handle_surrogate_pair(assembler), return_result(assembler);
839 Variable var_result(assembler, MachineRepresentation::kWord32);
840 Variable var_trail(assembler, MachineRepresentation::kWord16);
841 var_result.Bind(assembler->Int32Constant(0));
842 var_trail.Bind(assembler->Int32Constant(0));
843
844 Node* string_instance_type = assembler->LoadInstanceType(string);
845
846 Label if_stringissequential(assembler), if_stringisexternal(assembler);
847 assembler->Branch(assembler->Word32Equal(
848 assembler->Word32And(string_instance_type,
849 assembler->Int32Constant(
850 kStringRepresentationMask)),
851 assembler->Int32Constant(kSeqStringTag)),
852 &if_stringissequential, &if_stringisexternal);
853
854 assembler->Bind(&if_stringissequential);
855 {
856 Label if_stringisonebyte(assembler), if_stringistwobyte(assembler);
857 assembler->Branch(
858 assembler->Word32Equal(
859 assembler->Word32And(string_instance_type,
860 assembler->Int32Constant(kStringEncodingMask)),
861 assembler->Int32Constant(kOneByteStringTag)),
862 &if_stringisonebyte, &if_stringistwobyte);
863
864 assembler->Bind(&if_stringisonebyte);
865 {
866 var_result.Bind(assembler->Load(
867 MachineType::Uint8(), string,
868 assembler->IntPtrAdd(
869 index, assembler->IntPtrConstant(SeqOneByteString::kHeaderSize -
870 kHeapObjectTag))));
871 assembler->Goto(&return_result);
872 }
873
874 assembler->Bind(&if_stringistwobyte);
875 {
876 Node* lead = assembler->Load(
877 MachineType::Uint16(), string,
878 assembler->IntPtrAdd(
879 assembler->WordShl(index, assembler->IntPtrConstant(1)),
880 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
881 kHeapObjectTag)));
882 var_result.Bind(lead);
883 Node* next_pos = assembler->Int32Add(index, assembler->Int32Constant(1));
884
885 Label if_isdoublecodeunit(assembler);
886 assembler->GotoIf(assembler->Int32GreaterThanOrEqual(next_pos, length),
887 &return_result);
888 assembler->GotoIf(
889 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xD800)),
890 &return_result);
891 assembler->Branch(
892 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xDC00)),
893 &if_isdoublecodeunit, &return_result);
894
895 assembler->Bind(&if_isdoublecodeunit);
896 {
897 Node* trail = assembler->Load(
898 MachineType::Uint16(), string,
899 assembler->IntPtrAdd(
900 assembler->WordShl(next_pos, assembler->IntPtrConstant(1)),
901 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
902 kHeapObjectTag)));
903 assembler->GotoIf(
904 assembler->Uint32LessThan(trail, assembler->Int32Constant(0xDC00)),
905 &return_result);
906 assembler->GotoIf(assembler->Uint32GreaterThanOrEqual(
907 trail, assembler->Int32Constant(0xE000)),
908 &return_result);
909
910 var_trail.Bind(trail);
911 assembler->Goto(&handle_surrogate_pair);
912 }
913 }
914 }
915
916 assembler->Bind(&if_stringisexternal);
917 {
918 assembler->Assert(assembler->Word32Equal(
919 assembler->Word32And(
920 string_instance_type,
921 assembler->Int32Constant(kStringRepresentationMask)),
922 assembler->Int32Constant(kExternalStringTag)));
923 Label if_stringisshort(assembler), if_stringisnotshort(assembler);
924
925 assembler->Branch(assembler->Word32Equal(
926 assembler->Word32And(string_instance_type,
927 assembler->Int32Constant(
928 kShortExternalStringMask)),
929 assembler->Int32Constant(0)),
930 &if_stringisshort, &if_stringisnotshort);
931
932 assembler->Bind(&if_stringisshort);
933 {
934 // Load the actual resource data from the {string}.
935 Node* string_resource_data = assembler->LoadObjectField(
936 string, ExternalString::kResourceDataOffset, MachineType::Pointer());
937
938 Label if_stringistwobyte(assembler), if_stringisonebyte(assembler);
939 assembler->Branch(assembler->Word32Equal(
940 assembler->Word32And(
941 string_instance_type,
942 assembler->Int32Constant(kStringEncodingMask)),
943 assembler->Int32Constant(kTwoByteStringTag)),
944 &if_stringistwobyte, &if_stringisonebyte);
945
946 assembler->Bind(&if_stringisonebyte);
947 {
948 var_result.Bind(
949 assembler->Load(MachineType::Uint8(), string_resource_data, index));
950 assembler->Goto(&return_result);
951 }
952
953 assembler->Bind(&if_stringistwobyte);
954 {
955 Label if_isdoublecodeunit(assembler);
956 Node* lead = assembler->Load(
957 MachineType::Uint16(), string_resource_data,
958 assembler->WordShl(index, assembler->IntPtrConstant(1)));
959 var_result.Bind(lead);
960 Node* next_pos =
961 assembler->Int32Add(index, assembler->Int32Constant(1));
962
963 assembler->GotoIf(assembler->Int32GreaterThanOrEqual(next_pos, length),
964 &return_result);
965 assembler->GotoIf(
966 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xD800)),
967 &return_result);
968 assembler->Branch(
969 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xDC00)),
970 &if_isdoublecodeunit, &return_result);
971
972 assembler->Bind(&if_isdoublecodeunit);
973 {
974 Node* trail = assembler->Load(
975 MachineType::Uint16(), string,
976 assembler->IntPtrAdd(
977 assembler->WordShl(next_pos, assembler->IntPtrConstant(1)),
978 assembler->IntPtrConstant(SeqTwoByteString::kHeaderSize -
979 kHeapObjectTag)));
980 assembler->GotoIf(assembler->Uint32LessThan(
981 trail, assembler->Int32Constant(0xDC00)),
982 &return_result);
983 assembler->GotoIf(assembler->Uint32GreaterThanOrEqual(
984 trail, assembler->Int32Constant(0xE000)),
985 &return_result);
986
987 var_trail.Bind(trail);
988 assembler->Goto(&handle_surrogate_pair);
989 }
990 }
991 }
992
993 assembler->Bind(&if_stringisnotshort);
994 {
995 Label if_isdoublecodeunit(assembler);
996 Node* lead = assembler->SmiToWord32(assembler->CallRuntime(
997 Runtime::kExternalStringGetChar, assembler->NoContextConstant(),
998 string, assembler->SmiTag(index)));
999 var_result.Bind(lead);
1000 Node* next_pos = assembler->Int32Add(index, assembler->Int32Constant(1));
1001
1002 assembler->GotoIf(assembler->Int32GreaterThanOrEqual(next_pos, length),
1003 &return_result);
1004 assembler->GotoIf(
1005 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xD800)),
1006 &return_result);
1007 assembler->Branch(assembler->Uint32GreaterThanOrEqual(
1008 lead, assembler->Int32Constant(0xDC00)),
1009 &return_result, &if_isdoublecodeunit);
1010
1011 assembler->Bind(&if_isdoublecodeunit);
1012 {
1013 Node* trail = assembler->SmiToWord32(assembler->CallRuntime(
1014 Runtime::kExternalStringGetChar, assembler->NoContextConstant(),
1015 string, assembler->SmiTag(next_pos)));
1016 assembler->GotoIf(
1017 assembler->Uint32LessThan(trail, assembler->Int32Constant(0xDC00)),
1018 &return_result);
1019 assembler->GotoIf(assembler->Uint32GreaterThanOrEqual(
1020 trail, assembler->Int32Constant(0xE000)),
1021 &return_result);
1022 var_trail.Bind(trail);
1023 assembler->Goto(&handle_surrogate_pair);
1024 }
1025 }
1026 }
1027
1028 assembler->Bind(&handle_surrogate_pair);
1029 {
1030 Node* lead = var_result.value();
1031 Node* trail = var_trail.value();
1032 #ifdef ENABLE_SLOW_DCHECKS
1033 // Check that this path is only taken if a surrogate pair is found
1034 assembler->Assert(assembler->Uint32GreaterThanOrEqual(
1035 lead, assembler->Int32Constant(0xD800)));
1036 assembler->Assert(
1037 assembler->Uint32LessThan(lead, assembler->Int32Constant(0xDC00)));
1038 assembler->Assert(assembler->Uint32GreaterThanOrEqual(
1039 trail, assembler->Int32Constant(0xDC00)));
1040 assembler->Assert(
1041 assembler->Uint32LessThan(trail, assembler->Int32Constant(0xE000)));
1042 #endif
1043
1044 switch (encoding) {
1045 case UnicodeEncoding::UTF16:
1046 var_result.Bind(assembler->WordOr(
1047 assembler->WordShl(trail, assembler->Int32Constant(16)), lead));
1048 break;
1049
1050 case UnicodeEncoding::UTF32: {
1051 // Convert UTF16 surrogate pair into |word32| code point, encoded as
1052 // UTF32.
1053 Node* surrogate_offset =
1054 assembler->Int32Constant(0x10000 - (0xD800 << 10) - 0xDC00);
1055
1056 // (lead << 10) + trail + SURROGATE_OFFSET
1057 var_result.Bind(assembler->Int32Add(
1058 assembler->WordShl(lead, assembler->Int32Constant(10)),
1059 assembler->Int32Add(trail, surrogate_offset)));
1060 break;
1061 }
1062 }
1063 assembler->Goto(&return_result);
1064 }
1065
1066 assembler->Bind(&return_result);
1067 return var_result.value();
1068 }
1069
1070 static compiler::Node* LoadSurrogatePairAt(CodeStubAssembler* assembler,
1071 compiler::Node* string,
1072 compiler::Node* length,
1073 compiler::Node* index) {
1074 return LoadSurrogatePairInternal(assembler, string, length, index,
1075 UnicodeEncoding::UTF16);
1076 }
1077
1078 } // namespace
1079
1080 void Builtins::Generate_StringIteratorPrototypeNext(
1081 CodeStubAssembler* assembler) {
1082 typedef CodeStubAssembler::Label Label;
1083 typedef compiler::Node Node;
1084 typedef CodeStubAssembler::Variable Variable;
1085
1086 Variable var_value(assembler, MachineRepresentation::kTagged);
1087 Variable var_done(assembler, MachineRepresentation::kTagged);
1088
1089 var_value.Bind(assembler->UndefinedConstant());
1090 var_done.Bind(assembler->BooleanConstant(true));
1091
1092 Label throw_bad_receiver(assembler), next_codepoint(assembler),
1093 return_result(assembler);
1094
1095 Node* iterator = assembler->Parameter(0);
1096 Node* context = assembler->Parameter(3);
1097
1098 assembler->GotoIf(assembler->WordIsSmi(iterator), &throw_bad_receiver);
1099 assembler->GotoUnless(
1100 assembler->WordEqual(assembler->LoadInstanceType(iterator),
1101 assembler->Int32Constant(JS_STRING_ITERATOR_TYPE)),
1102 &throw_bad_receiver);
1103
1104 Node* string =
1105 assembler->LoadObjectField(iterator, JSStringIterator::kStringOffset);
1106 Node* position = assembler->LoadAndUntagObjectField(
1107 iterator, JSStringIterator::kNextIndexOffset);
1108 Node* length =
1109 assembler->LoadAndUntagObjectField(string, String::kLengthOffset);
1110
1111 assembler->Branch(assembler->Int32LessThan(position, length), &next_codepoint,
1112 &return_result);
1113
1114 assembler->Bind(&next_codepoint);
1115 {
1116 Node* ch = LoadSurrogatePairAt(assembler, string, length, position);
1117 Node* value = CreateStringFromSurrogatePair(assembler, ch);
1118 var_value.Bind(value);
1119 Node* length =
1120 assembler->LoadAndUntagObjectField(value, String::kLengthOffset);
1121 assembler->StoreObjectFieldNoWriteBarrier(
1122 iterator, JSStringIterator::kNextIndexOffset,
1123 assembler->SmiFromWord32(assembler->Int32Add(position, length)));
1124 var_done.Bind(assembler->BooleanConstant(false));
1125 assembler->Goto(&return_result);
1126 }
1127
1128 assembler->Bind(&return_result);
1129 {
1130 Node* native_context = assembler->LoadNativeContext(context);
1131 Node* map = assembler->LoadFixedArrayElement(
1132 native_context,
1133 assembler->IntPtrConstant(Context::ITERATOR_RESULT_MAP_INDEX), 0,
1134 CodeStubAssembler::INTPTR_PARAMETERS);
1135 Node* result = assembler->Allocate(JSIteratorResult::kSize);
1136 assembler->StoreMapNoWriteBarrier(result, map);
1137 assembler->StoreObjectFieldRoot(result, JSIteratorResult::kPropertiesOffset,
1138 Heap::kEmptyFixedArrayRootIndex);
1139 assembler->StoreObjectFieldRoot(result, JSIteratorResult::kElementsOffset,
1140 Heap::kEmptyFixedArrayRootIndex);
1141 assembler->StoreObjectField(result, JSIteratorResult::kValueOffset,
Benedikt Meurer 2016/09/23 18:14:53 You can skip write barrier for these two stores be
caitp 2016/09/23 19:14:16 Done.
1142 var_value.value());
1143 assembler->StoreObjectField(result, JSIteratorResult::kDoneOffset,
1144 var_done.value());
1145 assembler->Return(result);
1146 }
1147
1148 assembler->Bind(&throw_bad_receiver);
1149 {
1150 // The {receiver} is not a valid JSGeneratorObject.
1151 Node* result = assembler->CallRuntime(
1152 Runtime::kThrowIncompatibleMethodReceiver, context,
1153 assembler->HeapConstant(assembler->factory()->NewStringFromAsciiChecked(
1154 "String Iterator.prototype.next", TENURED)),
1155 iterator);
1156 assembler->Return(result); // Never reached.
1157 }
671 } 1158 }
672 1159
673 } // namespace internal 1160 } // namespace internal
674 } // namespace v8 1161 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins.h ('k') | src/objects-debug.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698