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

Side by Side Diff: src/runtime/runtime-regexp.cc

Issue 2415103002: [regexp] Turn last match info into a simple FixedArray (Closed)
Patch Set: Don't check instance type before map check 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
« no previous file with comments | « src/runtime/runtime.h ('k') | src/runtime/runtime-strings.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 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/runtime/runtime-utils.h" 5 #include "src/runtime/runtime-utils.h"
6 6
7 #include "src/arguments.h" 7 #include "src/arguments.h"
8 #include "src/conversions-inl.h" 8 #include "src/conversions-inl.h"
9 #include "src/isolate-inl.h" 9 #include "src/isolate-inl.h"
10 #include "src/messages.h" 10 #include "src/messages.h"
(...skipping 383 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 static const size_t kMaxRegexpIndicesListCapacity = 8 * KB; 394 static const size_t kMaxRegexpIndicesListCapacity = 8 * KB;
395 if (isolate->regexp_indices()->capacity() > kMaxRegexpIndicesListCapacity) { 395 if (isolate->regexp_indices()->capacity() > kMaxRegexpIndicesListCapacity) {
396 isolate->regexp_indices()->Clear(); // Throw away backing storage 396 isolate->regexp_indices()->Clear(); // Throw away backing storage
397 } 397 }
398 } 398 }
399 } // namespace 399 } // namespace
400 400
401 template <typename ResultSeqString> 401 template <typename ResultSeqString>
402 MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString( 402 MUST_USE_RESULT static Object* StringReplaceGlobalAtomRegExpWithString(
403 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> pattern_regexp, 403 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> pattern_regexp,
404 Handle<String> replacement, Handle<JSObject> last_match_info) { 404 Handle<String> replacement, Handle<RegExpMatchInfo> last_match_info) {
405 DCHECK(subject->IsFlat()); 405 DCHECK(subject->IsFlat());
406 DCHECK(replacement->IsFlat()); 406 DCHECK(replacement->IsFlat());
407 407
408 List<int>* indices = GetRewoundRegexpIndicesList(isolate); 408 List<int>* indices = GetRewoundRegexpIndicesList(isolate);
409 409
410 DCHECK_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag()); 410 DCHECK_EQ(JSRegExp::ATOM, pattern_regexp->TypeTag());
411 String* pattern = 411 String* pattern =
412 String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex)); 412 String::cast(pattern_regexp->DataAt(JSRegExp::kAtomPatternIndex));
413 int subject_len = subject->length(); 413 int subject_len = subject->length();
414 int pattern_len = pattern->length(); 414 int pattern_len = pattern->length();
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
472 indices->at(matches - 1) + pattern_len}; 472 indices->at(matches - 1) + pattern_len};
473 RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices); 473 RegExpImpl::SetLastMatchInfo(last_match_info, subject, 0, match_indices);
474 474
475 TruncateRegexpIndicesList(isolate); 475 TruncateRegexpIndicesList(isolate);
476 476
477 return *result; 477 return *result;
478 } 478 }
479 479
480 MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString( 480 MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithString(
481 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, 481 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
482 Handle<String> replacement, Handle<JSObject> last_match_info) { 482 Handle<String> replacement, Handle<RegExpMatchInfo> last_match_info) {
483 DCHECK(subject->IsFlat()); 483 DCHECK(subject->IsFlat());
484 DCHECK(replacement->IsFlat()); 484 DCHECK(replacement->IsFlat());
485 485
486 int capture_count = regexp->CaptureCount(); 486 int capture_count = regexp->CaptureCount();
487 int subject_length = subject->length(); 487 int subject_length = subject->length();
488 488
489 // CompiledReplacement uses zone allocation. 489 // CompiledReplacement uses zone allocation.
490 Zone zone(isolate->allocator()); 490 Zone zone(isolate->allocator());
491 CompiledReplacement compiled_replacement(&zone); 491 CompiledReplacement compiled_replacement(&zone);
492 bool simple_replace = 492 bool simple_replace =
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 554
555 RegExpImpl::SetLastMatchInfo(last_match_info, subject, capture_count, 555 RegExpImpl::SetLastMatchInfo(last_match_info, subject, capture_count,
556 global_cache.LastSuccessfulMatch()); 556 global_cache.LastSuccessfulMatch());
557 557
558 RETURN_RESULT_OR_FAILURE(isolate, builder.ToString()); 558 RETURN_RESULT_OR_FAILURE(isolate, builder.ToString());
559 } 559 }
560 560
561 template <typename ResultSeqString> 561 template <typename ResultSeqString>
562 MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString( 562 MUST_USE_RESULT static Object* StringReplaceGlobalRegExpWithEmptyString(
563 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, 563 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
564 Handle<JSObject> last_match_info) { 564 Handle<RegExpMatchInfo> last_match_info) {
565 DCHECK(subject->IsFlat()); 565 DCHECK(subject->IsFlat());
566 566
567 // Shortcut for simple non-regexp global replacements 567 // Shortcut for simple non-regexp global replacements
568 if (regexp->TypeTag() == JSRegExp::ATOM) { 568 if (regexp->TypeTag() == JSRegExp::ATOM) {
569 Handle<String> empty_string = isolate->factory()->empty_string(); 569 Handle<String> empty_string = isolate->factory()->empty_string();
570 if (subject->IsOneByteRepresentation()) { 570 if (subject->IsOneByteRepresentation()) {
571 return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>( 571 return StringReplaceGlobalAtomRegExpWithString<SeqOneByteString>(
572 isolate, subject, regexp, empty_string, last_match_info); 572 isolate, subject, regexp, empty_string, last_match_info);
573 } else { 573 } else {
574 return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>( 574 return StringReplaceGlobalAtomRegExpWithString<SeqTwoByteString>(
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
653 heap->CreateFillerObjectAt(end_of_string, delta, ClearRecordedSlots::kNo); 653 heap->CreateFillerObjectAt(end_of_string, delta, ClearRecordedSlots::kNo);
654 } 654 }
655 heap->AdjustLiveBytes(*answer, -delta, Heap::CONCURRENT_TO_SWEEPER); 655 heap->AdjustLiveBytes(*answer, -delta, Heap::CONCURRENT_TO_SWEEPER);
656 return *answer; 656 return *answer;
657 } 657 }
658 658
659 namespace { 659 namespace {
660 660
661 Object* StringReplaceGlobalRegExpWithStringHelper( 661 Object* StringReplaceGlobalRegExpWithStringHelper(
662 Isolate* isolate, Handle<JSRegExp> regexp, Handle<String> subject, 662 Isolate* isolate, Handle<JSRegExp> regexp, Handle<String> subject,
663 Handle<String> replacement, Handle<JSObject> last_match_info) { 663 Handle<String> replacement, Handle<RegExpMatchInfo> last_match_info) {
664 CHECK(regexp->GetFlags() & JSRegExp::kGlobal); 664 CHECK(regexp->GetFlags() & JSRegExp::kGlobal);
665 CHECK(last_match_info->HasFastObjectElements());
666 665
667 subject = String::Flatten(subject); 666 subject = String::Flatten(subject);
668 667
669 if (replacement->length() == 0) { 668 if (replacement->length() == 0) {
670 if (subject->HasOnlyOneByteChars()) { 669 if (subject->HasOnlyOneByteChars()) {
671 return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>( 670 return StringReplaceGlobalRegExpWithEmptyString<SeqOneByteString>(
672 isolate, subject, regexp, last_match_info); 671 isolate, subject, regexp, last_match_info);
673 } else { 672 } else {
674 return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>( 673 return StringReplaceGlobalRegExpWithEmptyString<SeqTwoByteString>(
675 isolate, subject, regexp, last_match_info); 674 isolate, subject, regexp, last_match_info);
676 } 675 }
677 } 676 }
678 677
679 replacement = String::Flatten(replacement); 678 replacement = String::Flatten(replacement);
680 679
681 return StringReplaceGlobalRegExpWithString(isolate, subject, regexp, 680 return StringReplaceGlobalRegExpWithString(isolate, subject, regexp,
682 replacement, last_match_info); 681 replacement, last_match_info);
683 } 682 }
684 683
685 } // namespace 684 } // namespace
686 685
687 RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) { 686 RUNTIME_FUNCTION(Runtime_StringReplaceGlobalRegExpWithString) {
688 HandleScope scope(isolate); 687 HandleScope scope(isolate);
689 DCHECK(args.length() == 4); 688 DCHECK(args.length() == 4);
690 689
691 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); 690 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
692 CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2); 691 CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
693 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); 692 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
694 CONVERT_ARG_HANDLE_CHECKED(JSObject, last_match_info, 3); 693 CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 3);
695 694
696 return StringReplaceGlobalRegExpWithStringHelper( 695 return StringReplaceGlobalRegExpWithStringHelper(
697 isolate, regexp, subject, replacement, last_match_info); 696 isolate, regexp, subject, replacement, last_match_info);
698 } 697 }
699 698
700 RUNTIME_FUNCTION(Runtime_StringSplit) { 699 RUNTIME_FUNCTION(Runtime_StringSplit) {
701 HandleScope handle_scope(isolate); 700 HandleScope handle_scope(isolate);
702 DCHECK(args.length() == 3); 701 DCHECK(args.length() == 3);
703 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); 702 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
704 CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1); 703 CONVERT_ARG_HANDLE_CHECKED(String, pattern, 1);
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 803
805 return *regexp; 804 return *regexp;
806 } 805 }
807 806
808 RUNTIME_FUNCTION(Runtime_RegExpExec) { 807 RUNTIME_FUNCTION(Runtime_RegExpExec) {
809 HandleScope scope(isolate); 808 HandleScope scope(isolate);
810 DCHECK(args.length() == 4); 809 DCHECK(args.length() == 4);
811 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); 810 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
812 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); 811 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
813 CONVERT_INT32_ARG_CHECKED(index, 2); 812 CONVERT_INT32_ARG_CHECKED(index, 2);
814 CONVERT_ARG_HANDLE_CHECKED(JSObject, last_match_info, 3); 813 CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 3);
815 // Due to the way the JS calls are constructed this must be less than the 814 // Due to the way the JS calls are constructed this must be less than the
816 // length of a string, i.e. it is always a Smi. We check anyway for security. 815 // length of a string, i.e. it is always a Smi. We check anyway for security.
817 CHECK(index >= 0); 816 CHECK(index >= 0);
818 CHECK(index <= subject->length()); 817 CHECK(index <= subject->length());
819 isolate->counters()->regexp_entry_runtime()->Increment(); 818 isolate->counters()->regexp_entry_runtime()->Increment();
820 RETURN_RESULT_OR_FAILURE( 819 RETURN_RESULT_OR_FAILURE(
821 isolate, RegExpImpl::Exec(regexp, subject, index, last_match_info)); 820 isolate, RegExpImpl::Exec(regexp, subject, index, last_match_info));
822 } 821 }
823 822
824 823
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
870 return *regexp; 869 return *regexp;
871 } 870 }
872 871
873 RUNTIME_FUNCTION(Runtime_RegExpInternalReplace) { 872 RUNTIME_FUNCTION(Runtime_RegExpInternalReplace) {
874 HandleScope scope(isolate); 873 HandleScope scope(isolate);
875 DCHECK(args.length() == 3); 874 DCHECK(args.length() == 3);
876 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0); 875 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 0);
877 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1); 876 CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
878 CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2); 877 CONVERT_ARG_HANDLE_CHECKED(String, replacement, 2);
879 878
880 static const int kInitialMatchSlots = 2; 879 Handle<RegExpMatchInfo> internal_match_info =
881 Handle<JSArray> internal_match_info = isolate->factory()->NewJSArray( 880 isolate->regexp_internal_match_info();
882 FAST_ELEMENTS, 0, RegExpImpl::kLastMatchOverhead + kInitialMatchSlots,
883 INITIALIZE_ARRAY_ELEMENTS_WITH_HOLE);
884 881
885 return StringReplaceGlobalRegExpWithStringHelper( 882 return StringReplaceGlobalRegExpWithStringHelper(
886 isolate, regexp, subject, replacement, internal_match_info); 883 isolate, regexp, subject, replacement, internal_match_info);
887 } 884 }
888 885
889 namespace { 886 namespace {
890 887
891 class MatchInfoBackedMatch : public String::Match { 888 class MatchInfoBackedMatch : public String::Match {
892 public: 889 public:
893 MatchInfoBackedMatch(Isolate* isolate, Handle<String> subject, 890 MatchInfoBackedMatch(Isolate* isolate, Handle<String> subject,
894 Handle<JSObject> match_info) 891 Handle<RegExpMatchInfo> match_info)
895 : isolate_(isolate), match_info_(match_info) { 892 : isolate_(isolate), match_info_(match_info) {
896 subject_ = String::Flatten(subject); 893 subject_ = String::Flatten(subject);
897 } 894 }
898 895
899 Handle<String> GetMatch() override { 896 Handle<String> GetMatch() override {
900 return RegExpUtils::GenericCaptureGetter(isolate_, match_info_, 0, nullptr); 897 return RegExpUtils::GenericCaptureGetter(isolate_, match_info_, 0, nullptr);
901 } 898 }
902 899
903 MaybeHandle<String> GetCapture(int i, bool* capture_exists) override { 900 MaybeHandle<String> GetCapture(int i, bool* capture_exists) override {
904 Handle<Object> capture_obj = 901 Handle<Object> capture_obj =
905 RegExpUtils::GenericCaptureGetter(isolate_, match_info_, i); 902 RegExpUtils::GenericCaptureGetter(isolate_, match_info_, i);
906 if (capture_obj->IsUndefined(isolate_)) { 903 if (capture_obj->IsUndefined(isolate_)) {
907 *capture_exists = false; 904 *capture_exists = false;
908 return isolate_->factory()->empty_string(); 905 return isolate_->factory()->empty_string();
909 } 906 }
910 *capture_exists = true; 907 *capture_exists = true;
911 return Object::ToString(isolate_, capture_obj); 908 return Object::ToString(isolate_, capture_obj);
912 } 909 }
913 910
914 Handle<String> GetPrefix() override { 911 Handle<String> GetPrefix() override {
915 const int match_start = 912 const int match_start = match_info_->Capture(0);
916 RegExpUtils::GetLastMatchCapture(isolate_, match_info_, 0);
917 return isolate_->factory()->NewSubString(subject_, 0, match_start); 913 return isolate_->factory()->NewSubString(subject_, 0, match_start);
918 } 914 }
919 915
920 Handle<String> GetSuffix() override { 916 Handle<String> GetSuffix() override {
921 const int match_end = 917 const int match_end = match_info_->Capture(1);
922 RegExpUtils::GetLastMatchCapture(isolate_, match_info_, 1);
923 return isolate_->factory()->NewSubString(subject_, match_end, 918 return isolate_->factory()->NewSubString(subject_, match_end,
924 subject_->length()); 919 subject_->length());
925 } 920 }
926 921
927 int CaptureCount() override { 922 int CaptureCount() override {
928 return RegExpUtils::GetLastMatchNumberOfCaptures(isolate_, match_info_) / 2; 923 return match_info_->NumberOfCaptureRegisters() / 2;
929 } 924 }
930 925
931 virtual ~MatchInfoBackedMatch() {} 926 virtual ~MatchInfoBackedMatch() {}
932 927
933 private: 928 private:
934 Isolate* isolate_; 929 Isolate* isolate_;
935 Handle<String> subject_; 930 Handle<String> subject_;
936 Handle<JSObject> match_info_; 931 Handle<RegExpMatchInfo> match_info_;
937 }; 932 };
938 933
939 class VectorBackedMatch : public String::Match { 934 class VectorBackedMatch : public String::Match {
940 public: 935 public:
941 VectorBackedMatch(Isolate* isolate, Handle<String> subject, 936 VectorBackedMatch(Isolate* isolate, Handle<String> subject,
942 Handle<String> match, int match_position, 937 Handle<String> match, int match_position,
943 ZoneVector<Handle<Object>>* captures) 938 ZoneVector<Handle<Object>>* captures)
944 : isolate_(isolate), 939 : isolate_(isolate),
945 match_(match), 940 match_(match),
946 match_position_(match_position), 941 match_position_(match_position),
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
978 Isolate* isolate_; 973 Isolate* isolate_;
979 Handle<String> subject_; 974 Handle<String> subject_;
980 Handle<String> match_; 975 Handle<String> match_;
981 const int match_position_; 976 const int match_position_;
982 ZoneVector<Handle<Object>>* captures_; 977 ZoneVector<Handle<Object>>* captures_;
983 }; 978 };
984 979
985 // Only called from RegExpExecMultiple so it doesn't need to maintain 980 // Only called from RegExpExecMultiple so it doesn't need to maintain
986 // separate last match info. See comment on that function. 981 // separate last match info. See comment on that function.
987 template <bool has_capture> 982 template <bool has_capture>
988 MaybeHandle<Object> SearchRegExpMultiple(Isolate* isolate, 983 MaybeHandle<Object> SearchRegExpMultiple(
989 Handle<String> subject, 984 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
990 Handle<JSRegExp> regexp, 985 Handle<RegExpMatchInfo> last_match_array,
991 Handle<JSObject> last_match_array, 986 Handle<FixedArray> result_elements) {
992 Handle<FixedArray> result_elements) {
993 DCHECK(subject->IsFlat()); 987 DCHECK(subject->IsFlat());
994 DCHECK_NE(has_capture, regexp->CaptureCount() == 0); 988 DCHECK_NE(has_capture, regexp->CaptureCount() == 0);
995 989
996 int capture_count = regexp->CaptureCount(); 990 int capture_count = regexp->CaptureCount();
997 int subject_length = subject->length(); 991 int subject_length = subject->length();
998 992
999 static const int kMinLengthToCache = 0x1000; 993 static const int kMinLengthToCache = 0x1000;
1000 994
1001 if (subject_length > kMinLengthToCache) { 995 if (subject_length > kMinLengthToCache) {
1002 FixedArray* last_match_cache; 996 FixedArray* last_match_cache;
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after
1126 return isolate->factory()->null_value(); // No matches at all. 1120 return isolate->factory()->null_value(); // No matches at all.
1127 } 1121 }
1128 } 1122 }
1129 1123
1130 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets 1124 // This is only called for StringReplaceGlobalRegExpWithFunction. This sets
1131 // lastMatchInfoOverride to maintain the last match info, so we don't need to 1125 // lastMatchInfoOverride to maintain the last match info, so we don't need to
1132 // set any other last match array info. 1126 // set any other last match array info.
1133 MaybeHandle<Object> RegExpExecMultiple(Isolate* isolate, 1127 MaybeHandle<Object> RegExpExecMultiple(Isolate* isolate,
1134 Handle<JSRegExp> regexp, 1128 Handle<JSRegExp> regexp,
1135 Handle<String> subject, 1129 Handle<String> subject,
1136 Handle<JSObject> last_match_info, 1130 Handle<RegExpMatchInfo> last_match_info,
1137 Handle<FixedArray> result_array) { 1131 Handle<FixedArray> result_array) {
1138 CHECK(last_match_info->HasFastObjectElements());
1139
1140 subject = String::Flatten(subject); 1132 subject = String::Flatten(subject);
1141 CHECK(regexp->GetFlags() & JSRegExp::kGlobal); 1133 CHECK(regexp->GetFlags() & JSRegExp::kGlobal);
1142 1134
1143 if (regexp->CaptureCount() == 0) { 1135 if (regexp->CaptureCount() == 0) {
1144 return SearchRegExpMultiple<false>(isolate, subject, regexp, 1136 return SearchRegExpMultiple<false>(isolate, subject, regexp,
1145 last_match_info, result_array); 1137 last_match_info, result_array);
1146 } else { 1138 } else {
1147 return SearchRegExpMultiple<true>(isolate, subject, regexp, last_match_info, 1139 return SearchRegExpMultiple<true>(isolate, subject, regexp, last_match_info,
1148 result_array); 1140 result_array);
1149 } 1141 }
1150 } 1142 }
1151 1143
1152 // Helper function for replacing regular expressions with the result of a 1144 // Helper function for replacing regular expressions with the result of a
1153 // function application in String.prototype.replace. 1145 // function application in String.prototype.replace.
1154 MaybeHandle<String> StringReplaceGlobalRegExpWithFunction( 1146 MaybeHandle<String> StringReplaceGlobalRegExpWithFunction(
1155 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, 1147 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
1156 Handle<Object> replace_obj) { 1148 Handle<Object> replace_obj) {
1157 Factory* factory = isolate->factory(); 1149 Factory* factory = isolate->factory();
1158 1150
1159 // TODO(jgruber): Convert result_array into a List<Handle<Object>> (or 1151 // TODO(jgruber): Convert result_array into a List<Handle<Object>> (or
1160 // similar) and adapt / remove FixedArrayBuilder. 1152 // similar) and adapt / remove FixedArrayBuilder.
1161 Handle<JSObject> last_match_info = isolate->regexp_last_match_info(); 1153 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1162 Handle<FixedArray> result_array = factory->NewFixedArrayWithHoles(16); 1154 Handle<FixedArray> result_array = factory->NewFixedArrayWithHoles(16);
1163 1155
1164 Handle<Object> res; 1156 Handle<Object> res;
1165 ASSIGN_RETURN_ON_EXCEPTION(isolate, res, 1157 ASSIGN_RETURN_ON_EXCEPTION(isolate, res,
1166 RegExpExecMultiple(isolate, regexp, subject, 1158 RegExpExecMultiple(isolate, regexp, subject,
1167 last_match_info, result_array), 1159 last_match_info, result_array),
1168 String); 1160 String);
1169 1161
1170 // Reload the last match info since it might have changed in the meantime. 1162 // Reload the last match info since it might have changed in the meantime.
1171 last_match_info = isolate->regexp_last_match_info(); 1163 last_match_info = isolate->regexp_last_match_info();
1172 1164
1173 if (res->IsNull(isolate)) return subject; // No matches at all. 1165 if (res->IsNull(isolate)) return subject; // No matches at all.
1174 1166
1175 result_array = Handle<FixedArray>::cast(res); 1167 result_array = Handle<FixedArray>::cast(res);
1176 const int result_length = result_array->length(); 1168 const int result_length = result_array->length();
1177 1169
1178 const int num_captures = 1170 const int num_captures = last_match_info->NumberOfCaptureRegisters() / 2;
1179 RegExpUtils::GetLastMatchNumberOfCaptures(isolate, last_match_info) / 2;
1180 if (num_captures == 1) { 1171 if (num_captures == 1) {
1181 // If the number of captures is one then there are no explicit captures in 1172 // If the number of captures is one then there are no explicit captures in
1182 // the regexp, just the implicit capture that captures the whole match. In 1173 // the regexp, just the implicit capture that captures the whole match. In
1183 // this case we can simplify quite a bit and end up with something faster. 1174 // this case we can simplify quite a bit and end up with something faster.
1184 // The builder will consist of some integers that indicate slices of the 1175 // The builder will consist of some integers that indicate slices of the
1185 // input string and some replacements that were returned from the replace 1176 // input string and some replacements that were returned from the replace
1186 // function. 1177 // function.
1187 int match_start = 0; 1178 int match_start = 0;
1188 for (int i = 0; i < result_length; i++) { 1179 for (int i = 0; i < result_length; i++) {
1189 Handle<Object> elem = FixedArray::get(*result_array, i, isolate); 1180 Handle<Object> elem = FixedArray::get(*result_array, i, isolate);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1302 } 1293 }
1303 1294
1304 UNREACHABLE(); 1295 UNREACHABLE();
1305 return MaybeHandle<String>(); 1296 return MaybeHandle<String>();
1306 } 1297 }
1307 1298
1308 MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction( 1299 MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction(
1309 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, 1300 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
1310 Handle<Object> replace_obj) { 1301 Handle<Object> replace_obj) {
1311 Factory* factory = isolate->factory(); 1302 Factory* factory = isolate->factory();
1312 Handle<JSObject> last_match_info = isolate->regexp_last_match_info(); 1303 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1313 1304
1314 // TODO(jgruber): This is a pattern we could refactor. 1305 // TODO(jgruber): This is a pattern we could refactor.
1315 Handle<Object> match_indices_obj; 1306 Handle<Object> match_indices_obj;
1316 ASSIGN_RETURN_ON_EXCEPTION( 1307 ASSIGN_RETURN_ON_EXCEPTION(
1317 isolate, match_indices_obj, 1308 isolate, match_indices_obj,
1318 RegExpImpl::Exec(regexp, subject, 0, last_match_info), String); 1309 RegExpImpl::Exec(regexp, subject, 0, last_match_info), String);
1319 1310
1320 if (match_indices_obj->IsNull(isolate)) { 1311 if (match_indices_obj->IsNull(isolate)) {
1321 RETURN_ON_EXCEPTION(isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0), 1312 RETURN_ON_EXCEPTION(isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0),
1322 String); 1313 String);
1323 return subject; 1314 return subject;
1324 } 1315 }
1325 1316
1326 Handle<JSObject> match_indices = Handle<JSObject>::cast(match_indices_obj); 1317 Handle<RegExpMatchInfo> match_indices =
1318 Handle<RegExpMatchInfo>::cast(match_indices_obj);
1327 1319
1328 const int index = RegExpUtils::GetLastMatchCapture(isolate, match_indices, 0); 1320 const int index = match_indices->Capture(0);
1329 const int end_of_match = 1321 const int end_of_match = match_indices->Capture(1);
1330 RegExpUtils::GetLastMatchCapture(isolate, match_indices, 1);
1331 1322
1332 IncrementalStringBuilder builder(isolate); 1323 IncrementalStringBuilder builder(isolate);
1333 builder.AppendString(factory->NewSubString(subject, 0, index)); 1324 builder.AppendString(factory->NewSubString(subject, 0, index));
1334 1325
1335 // Compute the parameter list consisting of the match, captures, index, 1326 // Compute the parameter list consisting of the match, captures, index,
1336 // and subject for the replace function invocation. 1327 // and subject for the replace function invocation.
1337 // The number of captures plus one for the match. 1328 // The number of captures plus one for the match.
1338 const int m = 1329 const int m = match_indices->NumberOfCaptureRegisters() / 2;
1339 RegExpUtils::GetLastMatchNumberOfCaptures(isolate, match_indices) / 2;
1340 1330
1341 const int argc = m + 2; 1331 const int argc = m + 2;
1342 ScopedVector<Handle<Object>> argv(argc); 1332 ScopedVector<Handle<Object>> argv(argc);
1343 1333
1344 for (int j = 0; j < m; j++) { 1334 for (int j = 0; j < m; j++) {
1345 bool ok; 1335 bool ok;
1346 Handle<String> capture = 1336 Handle<String> capture =
1347 RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok); 1337 RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok);
1348 if (ok) { 1338 if (ok) {
1349 argv[j] = capture; 1339 argv[j] = capture;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
1385 const int flags = regexp->GetFlags(); 1375 const int flags = regexp->GetFlags();
1386 const bool global = (flags & JSRegExp::kGlobal) != 0; 1376 const bool global = (flags & JSRegExp::kGlobal) != 0;
1387 1377
1388 const bool functional_replace = replace_obj->IsCallable(); 1378 const bool functional_replace = replace_obj->IsCallable();
1389 if (!functional_replace) { 1379 if (!functional_replace) {
1390 Handle<String> replace; 1380 Handle<String> replace;
1391 ASSIGN_RETURN_ON_EXCEPTION(isolate, replace, 1381 ASSIGN_RETURN_ON_EXCEPTION(isolate, replace,
1392 Object::ToString(isolate, replace_obj), String); 1382 Object::ToString(isolate, replace_obj), String);
1393 replace = String::Flatten(replace); 1383 replace = String::Flatten(replace);
1394 1384
1395 Handle<JSObject> last_match_info = isolate->regexp_last_match_info(); 1385 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1396 1386
1397 if (!global) { 1387 if (!global) {
1398 // Non-global regexp search, string replace. 1388 // Non-global regexp search, string replace.
1399 1389
1400 Handle<Object> match_indices_obj; 1390 Handle<Object> match_indices_obj;
1401 ASSIGN_RETURN_ON_EXCEPTION( 1391 ASSIGN_RETURN_ON_EXCEPTION(
1402 isolate, match_indices_obj, 1392 isolate, match_indices_obj,
1403 RegExpImpl::Exec(regexp, string, 0, last_match_info), String); 1393 RegExpImpl::Exec(regexp, string, 0, last_match_info), String);
1404 1394
1405 if (match_indices_obj->IsNull(isolate)) { 1395 if (match_indices_obj->IsNull(isolate)) {
1406 RETURN_ON_EXCEPTION( 1396 RETURN_ON_EXCEPTION(
1407 isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0), String); 1397 isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0), String);
1408 return string; 1398 return string;
1409 } 1399 }
1410 1400
1411 auto match_indices = Handle<JSReceiver>::cast(match_indices_obj); 1401 auto match_indices = Handle<RegExpMatchInfo>::cast(match_indices_obj);
1412 1402
1413 Handle<Object> start_index_obj = 1403 const int start_index = match_indices->Capture(0);
1414 JSReceiver::GetElement(isolate, match_indices, 1404 const int end_index = match_indices->Capture(1);
1415 RegExpImpl::kFirstCapture)
1416 .ToHandleChecked();
1417 const int start_index = Handle<Smi>::cast(start_index_obj)->value();
1418
1419 Handle<Object> end_index_obj =
1420 JSReceiver::GetElement(isolate, match_indices,
1421 RegExpImpl::kFirstCapture + 1)
1422 .ToHandleChecked();
1423 const int end_index = Handle<Smi>::cast(end_index_obj)->value();
1424 1405
1425 IncrementalStringBuilder builder(isolate); 1406 IncrementalStringBuilder builder(isolate);
1426 builder.AppendString(factory->NewSubString(string, 0, start_index)); 1407 builder.AppendString(factory->NewSubString(string, 0, start_index));
1427 1408
1428 if (replace->length() > 0) { 1409 if (replace->length() > 0) {
1429 MatchInfoBackedMatch m(isolate, string, last_match_info); 1410 MatchInfoBackedMatch m(isolate, string, match_indices);
1430 Handle<String> replacement; 1411 Handle<String> replacement;
1431 ASSIGN_RETURN_ON_EXCEPTION( 1412 ASSIGN_RETURN_ON_EXCEPTION(
1432 isolate, replacement, String::GetSubstitution(isolate, &m, replace), 1413 isolate, replacement, String::GetSubstitution(isolate, &m, replace),
1433 String); 1414 String);
1434 builder.AppendString(replacement); 1415 builder.AppendString(replacement);
1435 } 1416 }
1436 1417
1437 builder.AppendString( 1418 builder.AppendString(
1438 factory->NewSubString(string, end_index, string->length())); 1419 factory->NewSubString(string, end_index, string->length()));
1439 return builder.Finish(); 1420 return builder.Finish();
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after
1675 1656
1676 RUNTIME_FUNCTION(Runtime_IsRegExp) { 1657 RUNTIME_FUNCTION(Runtime_IsRegExp) {
1677 SealHandleScope shs(isolate); 1658 SealHandleScope shs(isolate);
1678 DCHECK(args.length() == 1); 1659 DCHECK(args.length() == 1);
1679 CONVERT_ARG_CHECKED(Object, obj, 0); 1660 CONVERT_ARG_CHECKED(Object, obj, 0);
1680 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); 1661 return isolate->heap()->ToBoolean(obj->IsJSRegExp());
1681 } 1662 }
1682 1663
1683 } // namespace internal 1664 } // namespace internal
1684 } // namespace v8 1665 } // namespace v8
OLDNEW
« no previous file with comments | « src/runtime/runtime.h ('k') | src/runtime/runtime-strings.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698