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

Side by Side Diff: src/builtins/builtins-regexp-gen.cc

Issue 2799663003: [regexp] Add additional asserts to RegExp builtins (Closed)
Patch Set: Rebase Created 3 years, 8 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-regexp-gen.h ('k') | src/code-stub-assembler.h » ('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 2017 the V8 project authors. All rights reserved. 1 // Copyright 2017 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-regexp-gen.h" 5 #include "src/builtins/builtins-regexp-gen.h"
6 6
7 #include "src/builtins/builtins-constructor-gen.h" 7 #include "src/builtins/builtins-constructor-gen.h"
8 #include "src/builtins/builtins-utils-gen.h" 8 #include "src/builtins/builtins-utils-gen.h"
9 #include "src/builtins/builtins.h" 9 #include "src/builtins/builtins.h"
10 #include "src/code-factory.h" 10 #include "src/code-factory.h"
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 if (is_fastpath) { 62 if (is_fastpath) {
63 FastStoreLastIndex(regexp, value); 63 FastStoreLastIndex(regexp, value);
64 } else { 64 } else {
65 SlowStoreLastIndex(context, regexp, value); 65 SlowStoreLastIndex(context, regexp, value);
66 } 66 }
67 } 67 }
68 68
69 Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo( 69 Node* RegExpBuiltinsAssembler::ConstructNewResultFromMatchInfo(
70 Node* const context, Node* const regexp, Node* const match_info, 70 Node* const context, Node* const regexp, Node* const match_info,
71 Node* const string) { 71 Node* const string) {
72 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(match_info)));
73 CSA_ASSERT(this, IsJSRegExp(regexp));
74 CSA_ASSERT(this, IsString(string));
75
72 Label named_captures(this), out(this); 76 Label named_captures(this), out(this);
73 77
74 Node* const num_indices = SmiUntag(LoadFixedArrayElement( 78 Node* const num_indices = SmiUntag(LoadFixedArrayElement(
75 match_info, RegExpMatchInfo::kNumberOfCapturesIndex)); 79 match_info, RegExpMatchInfo::kNumberOfCapturesIndex));
76 Node* const num_results = SmiTag(WordShr(num_indices, 1)); 80 Node* const num_results = SmiTag(WordShr(num_indices, 1));
77 Node* const start = 81 Node* const start =
78 LoadFixedArrayElement(match_info, RegExpMatchInfo::kFirstCaptureIndex); 82 LoadFixedArrayElement(match_info, RegExpMatchInfo::kFirstCaptureIndex);
79 Node* const end = LoadFixedArrayElement( 83 Node* const end = LoadFixedArrayElement(
80 match_info, RegExpMatchInfo::kFirstCaptureIndex + 1); 84 match_info, RegExpMatchInfo::kFirstCaptureIndex + 1);
81 85
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
127 var_to_cursor.Bind(IntPtrAdd(to_cursor, IntPtrConstant(1))); 131 var_to_cursor.Bind(IntPtrAdd(to_cursor, IntPtrConstant(1)));
128 Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop, 132 Branch(UintPtrLessThan(var_from_cursor.value(), limit), &loop,
129 &named_captures); 133 &named_captures);
130 } 134 }
131 135
132 BIND(&named_captures); 136 BIND(&named_captures);
133 { 137 {
134 // We reach this point only if captures exist, implying that this is an 138 // We reach this point only if captures exist, implying that this is an
135 // IRREGEXP JSRegExp. 139 // IRREGEXP JSRegExp.
136 140
137 CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); 141 CSA_ASSERT(this, IsJSRegExp(regexp));
138 CSA_ASSERT(this, SmiGreaterThan(num_results, SmiConstant(1))); 142 CSA_ASSERT(this, SmiGreaterThan(num_results, SmiConstant(1)));
139 143
140 // Preparations for named capture properties. Exit early if the result does 144 // Preparations for named capture properties. Exit early if the result does
141 // not have any named captures to minimize performance impact. 145 // not have any named captures to minimize performance impact.
142 146
143 Node* const data = LoadObjectField(regexp, JSRegExp::kDataOffset); 147 Node* const data = LoadObjectField(regexp, JSRegExp::kDataOffset);
144 CSA_ASSERT(this, SmiEqual(LoadFixedArrayElement(data, JSRegExp::kTagIndex), 148 CSA_ASSERT(this, SmiEqual(LoadFixedArrayElement(data, JSRegExp::kTagIndex),
145 SmiConstant(JSRegExp::IRREGEXP))); 149 SmiConstant(JSRegExp::IRREGEXP)));
146 150
147 // The names fixed array associates names at even indices with a capture 151 // The names fixed array associates names at even indices with a capture
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 Node* const last_index, 238 Node* const last_index,
235 Node* const match_info) { 239 Node* const match_info) {
236 // Just jump directly to runtime if native RegExp is not selected at compile 240 // Just jump directly to runtime if native RegExp is not selected at compile
237 // time or if regexp entry in generated code is turned off runtime switch or 241 // time or if regexp entry in generated code is turned off runtime switch or
238 // at compilation. 242 // at compilation.
239 #ifdef V8_INTERPRETED_REGEXP 243 #ifdef V8_INTERPRETED_REGEXP
240 return CallRuntime(Runtime::kRegExpExec, context, regexp, string, last_index, 244 return CallRuntime(Runtime::kRegExpExec, context, regexp, string, last_index,
241 match_info); 245 match_info);
242 #else // V8_INTERPRETED_REGEXP 246 #else // V8_INTERPRETED_REGEXP
243 CSA_ASSERT(this, TaggedIsNotSmi(regexp)); 247 CSA_ASSERT(this, TaggedIsNotSmi(regexp));
244 CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); 248 CSA_ASSERT(this, IsJSRegExp(regexp));
245 249
246 CSA_ASSERT(this, TaggedIsNotSmi(string)); 250 CSA_ASSERT(this, TaggedIsNotSmi(string));
247 CSA_ASSERT(this, IsString(string)); 251 CSA_ASSERT(this, IsString(string));
248 252
249 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(last_index))); 253 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(last_index)));
250 CSA_ASSERT(this, IsFixedArrayMap(LoadReceiverMap(match_info))); 254 CSA_ASSERT(this, IsFixedArrayMap(LoadReceiverMap(match_info)));
251 255
252 Node* const int_zero = IntPtrConstant(0); 256 Node* const int_zero = IntPtrConstant(0);
253 257
254 ToDirectStringAssembler to_direct(state(), string); 258 ToDirectStringAssembler to_direct(state(), string);
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after
482 Node* const int_zero = IntPtrConstant(0); 486 Node* const int_zero = IntPtrConstant(0);
483 Node* const smi_zero = SmiConstant(Smi::kZero); 487 Node* const smi_zero = SmiConstant(Smi::kZero);
484 488
485 if (is_fastpath) { 489 if (is_fastpath) {
486 CSA_ASSERT(this, IsFastRegExpNoPrototype(context, regexp, LoadMap(regexp))); 490 CSA_ASSERT(this, IsFastRegExpNoPrototype(context, regexp, LoadMap(regexp)));
487 } else { 491 } else {
488 ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE, 492 ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE,
489 "RegExp.prototype.exec"); 493 "RegExp.prototype.exec");
490 } 494 }
491 495
492 CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(string))); 496 CSA_ASSERT(this, IsString(string));
493 CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); 497 CSA_ASSERT(this, IsJSRegExp(regexp));
494 498
495 Variable var_result(this, MachineRepresentation::kTagged); 499 Variable var_result(this, MachineRepresentation::kTagged);
496 Label out(this); 500 Label out(this);
497 501
498 // Load lastIndex. 502 // Load lastIndex.
499 Variable var_lastindex(this, MachineRepresentation::kTagged); 503 Variable var_lastindex(this, MachineRepresentation::kTagged);
500 { 504 {
501 Node* const regexp_lastindex = LoadLastIndex(context, regexp, is_fastpath); 505 Node* const regexp_lastindex = LoadLastIndex(context, regexp, is_fastpath);
502 var_lastindex.Bind(regexp_lastindex); 506 var_lastindex.Bind(regexp_lastindex);
503 507
(...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after
722 726
723 GotoIfNot(proto_has_initialmap, if_ismodified); 727 GotoIfNot(proto_has_initialmap, if_ismodified);
724 728
725 // The smi check is required to omit ToLength(lastIndex) calls with possible 729 // The smi check is required to omit ToLength(lastIndex) calls with possible
726 // user-code execution on the fast path. 730 // user-code execution on the fast path.
727 Node* const last_index = FastLoadLastIndex(object); 731 Node* const last_index = FastLoadLastIndex(object);
728 Branch(TaggedIsPositiveSmi(last_index), if_isunmodified, if_ismodified); 732 Branch(TaggedIsPositiveSmi(last_index), if_isunmodified, if_ismodified);
729 } 733 }
730 734
731 Node* RegExpBuiltinsAssembler::IsFastRegExp(Node* const context, 735 Node* RegExpBuiltinsAssembler::IsFastRegExp(Node* const context,
736 Node* const object) {
737 return IsFastRegExp(context, object, LoadMap(object));
738 }
739
740 Node* RegExpBuiltinsAssembler::IsFastRegExp(Node* const context,
732 Node* const object, 741 Node* const object,
733 Node* const map) { 742 Node* const map) {
734 Label yup(this), nope(this), out(this); 743 Label yup(this), nope(this), out(this);
735 Variable var_result(this, MachineRepresentation::kWord32); 744 Variable var_result(this, MachineRepresentation::kWord32);
736 745
737 BranchIfFastRegExp(context, object, map, &yup, &nope); 746 BranchIfFastRegExp(context, object, map, &yup, &nope);
738 747
739 BIND(&yup); 748 BIND(&yup);
740 var_result.Bind(Int32Constant(1)); 749 var_result.Bind(Int32Constant(1));
741 Goto(&out); 750 Goto(&out);
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
812 Variable var_length(this, MachineType::PointerRepresentation(), int_zero); 821 Variable var_length(this, MachineType::PointerRepresentation(), int_zero);
813 Variable var_flags(this, MachineType::PointerRepresentation()); 822 Variable var_flags(this, MachineType::PointerRepresentation());
814 823
815 Node* const is_dotall_enabled = IsDotAllEnabled(isolate); 824 Node* const is_dotall_enabled = IsDotAllEnabled(isolate);
816 825
817 // First, count the number of characters we will need and check which flags 826 // First, count the number of characters we will need and check which flags
818 // are set. 827 // are set.
819 828
820 if (is_fastpath) { 829 if (is_fastpath) {
821 // Refer to JSRegExp's flag property on the fast-path. 830 // Refer to JSRegExp's flag property on the fast-path.
831 CSA_ASSERT(this, IsJSRegExp(regexp));
822 Node* const flags_smi = LoadObjectField(regexp, JSRegExp::kFlagsOffset); 832 Node* const flags_smi = LoadObjectField(regexp, JSRegExp::kFlagsOffset);
823 Node* const flags_intptr = SmiUntag(flags_smi); 833 Node* const flags_intptr = SmiUntag(flags_smi);
824 var_flags.Bind(flags_intptr); 834 var_flags.Bind(flags_intptr);
825 835
826 #define CASE_FOR_FLAG(FLAG) \ 836 #define CASE_FOR_FLAG(FLAG) \
827 do { \ 837 do { \
828 Label next(this); \ 838 Label next(this); \
829 GotoIfNot(IsSetWord(flags_intptr, FLAG), &next); \ 839 GotoIfNot(IsSetWord(flags_intptr, FLAG), &next); \
830 var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \ 840 var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \
831 Goto(&next); \ 841 Goto(&next); \
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
935 945
936 // Check @@match. 946 // Check @@match.
937 { 947 {
938 Node* const value = 948 Node* const value =
939 GetProperty(context, receiver, isolate()->factory()->match_symbol()); 949 GetProperty(context, receiver, isolate()->factory()->match_symbol());
940 950
941 Label match_isundefined(this), match_isnotundefined(this); 951 Label match_isundefined(this), match_isnotundefined(this);
942 Branch(IsUndefined(value), &match_isundefined, &match_isnotundefined); 952 Branch(IsUndefined(value), &match_isundefined, &match_isnotundefined);
943 953
944 BIND(&match_isundefined); 954 BIND(&match_isundefined);
945 Branch(HasInstanceType(receiver, JS_REGEXP_TYPE), &if_isregexp, &out); 955 Branch(IsJSRegExp(receiver), &if_isregexp, &out);
946 956
947 BIND(&match_isnotundefined); 957 BIND(&match_isnotundefined);
948 BranchIfToBooleanIsTrue(value, &if_isregexp, &out); 958 BranchIfToBooleanIsTrue(value, &if_isregexp, &out);
949 } 959 }
950 960
951 BIND(&if_isregexp); 961 BIND(&if_isregexp);
952 var_result.Bind(Int32Constant(1)); 962 var_result.Bind(Int32Constant(1));
953 Goto(&out); 963 Goto(&out);
954 964
955 BIND(&out); 965 BIND(&out);
956 return var_result.value(); 966 return var_result.value();
957 } 967 }
958 968
959 // ES#sec-regexpinitialize 969 // ES#sec-regexpinitialize
960 // Runtime Semantics: RegExpInitialize ( obj, pattern, flags ) 970 // Runtime Semantics: RegExpInitialize ( obj, pattern, flags )
961 Node* RegExpBuiltinsAssembler::RegExpInitialize(Node* const context, 971 Node* RegExpBuiltinsAssembler::RegExpInitialize(Node* const context,
962 Node* const regexp, 972 Node* const regexp,
963 Node* const maybe_pattern, 973 Node* const maybe_pattern,
964 Node* const maybe_flags) { 974 Node* const maybe_flags) {
975 CSA_ASSERT(this, IsJSRegExp(regexp));
976
965 // Normalize pattern. 977 // Normalize pattern.
966 Node* const pattern = 978 Node* const pattern =
967 Select(IsUndefined(maybe_pattern), [=] { return EmptyStringConstant(); }, 979 Select(IsUndefined(maybe_pattern), [=] { return EmptyStringConstant(); },
968 [=] { return ToString(context, maybe_pattern); }, 980 [=] { return ToString(context, maybe_pattern); },
969 MachineRepresentation::kTagged); 981 MachineRepresentation::kTagged);
970 982
971 // Normalize flags. 983 // Normalize flags.
972 Node* const flags = 984 Node* const flags =
973 Select(IsUndefined(maybe_flags), [=] { return EmptyStringConstant(); }, 985 Select(IsUndefined(maybe_flags), [=] { return EmptyStringConstant(); },
974 [=] { return ToString(context, maybe_flags); }, 986 [=] { return ToString(context, maybe_flags); },
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1037 Return(pattern); 1049 Return(pattern);
1038 1050
1039 BIND(&next); 1051 BIND(&next);
1040 } 1052 }
1041 1053
1042 { 1054 {
1043 Label next(this), if_patternisfastregexp(this), 1055 Label next(this), if_patternisfastregexp(this),
1044 if_patternisslowregexp(this); 1056 if_patternisslowregexp(this);
1045 GotoIf(TaggedIsSmi(pattern), &next); 1057 GotoIf(TaggedIsSmi(pattern), &next);
1046 1058
1047 GotoIf(HasInstanceType(pattern, JS_REGEXP_TYPE), &if_patternisfastregexp); 1059 GotoIf(IsJSRegExp(pattern), &if_patternisfastregexp);
1048 1060
1049 Branch(pattern_is_regexp, &if_patternisslowregexp, &next); 1061 Branch(pattern_is_regexp, &if_patternisslowregexp, &next);
1050 1062
1051 BIND(&if_patternisfastregexp); 1063 BIND(&if_patternisfastregexp);
1052 { 1064 {
1053 Node* const source = LoadObjectField(pattern, JSRegExp::kSourceOffset); 1065 Node* const source = LoadObjectField(pattern, JSRegExp::kSourceOffset);
1054 var_pattern.Bind(source); 1066 var_pattern.Bind(source);
1055 1067
1056 { 1068 {
1057 Label inner_next(this); 1069 Label inner_next(this);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 Node* const receiver = maybe_receiver; 1153 Node* const receiver = maybe_receiver;
1142 1154
1143 Variable var_flags(this, MachineRepresentation::kTagged, maybe_flags); 1155 Variable var_flags(this, MachineRepresentation::kTagged, maybe_flags);
1144 Variable var_pattern(this, MachineRepresentation::kTagged, maybe_pattern); 1156 Variable var_pattern(this, MachineRepresentation::kTagged, maybe_pattern);
1145 1157
1146 // Handle a JSRegExp pattern. 1158 // Handle a JSRegExp pattern.
1147 { 1159 {
1148 Label next(this); 1160 Label next(this);
1149 1161
1150 GotoIf(TaggedIsSmi(maybe_pattern), &next); 1162 GotoIf(TaggedIsSmi(maybe_pattern), &next);
1151 GotoIfNot(HasInstanceType(maybe_pattern, JS_REGEXP_TYPE), &next); 1163 GotoIfNot(IsJSRegExp(maybe_pattern), &next);
1152 1164
1153 Node* const pattern = maybe_pattern; 1165 Node* const pattern = maybe_pattern;
1154 1166
1155 // {maybe_flags} must be undefined in this case, otherwise throw. 1167 // {maybe_flags} must be undefined in this case, otherwise throw.
1156 { 1168 {
1157 Label next(this); 1169 Label next(this);
1158 GotoIf(IsUndefined(maybe_flags), &next); 1170 GotoIf(IsUndefined(maybe_flags), &next);
1159 1171
1160 Node* const message_id = SmiConstant(MessageTemplate::kRegExpFlags); 1172 Node* const message_id = SmiConstant(MessageTemplate::kRegExpFlags);
1161 TailCallRuntime(Runtime::kThrowTypeError, context, message_id); 1173 TailCallRuntime(Runtime::kThrowTypeError, context, message_id);
(...skipping 19 matching lines...) Expand all
1181 // ES6 21.2.5.10. 1193 // ES6 21.2.5.10.
1182 // ES #sec-get-regexp.prototype.source 1194 // ES #sec-get-regexp.prototype.source
1183 TF_BUILTIN(RegExpPrototypeSourceGetter, RegExpBuiltinsAssembler) { 1195 TF_BUILTIN(RegExpPrototypeSourceGetter, RegExpBuiltinsAssembler) {
1184 Node* const receiver = Parameter(Descriptor::kReceiver); 1196 Node* const receiver = Parameter(Descriptor::kReceiver);
1185 Node* const context = Parameter(Descriptor::kContext); 1197 Node* const context = Parameter(Descriptor::kContext);
1186 1198
1187 // Check whether we have an unmodified regexp instance. 1199 // Check whether we have an unmodified regexp instance.
1188 Label if_isjsregexp(this), if_isnotjsregexp(this, Label::kDeferred); 1200 Label if_isjsregexp(this), if_isnotjsregexp(this, Label::kDeferred);
1189 1201
1190 GotoIf(TaggedIsSmi(receiver), &if_isnotjsregexp); 1202 GotoIf(TaggedIsSmi(receiver), &if_isnotjsregexp);
1191 Branch(HasInstanceType(receiver, JS_REGEXP_TYPE), &if_isjsregexp, 1203 Branch(IsJSRegExp(receiver), &if_isjsregexp, &if_isnotjsregexp);
1192 &if_isnotjsregexp);
1193 1204
1194 BIND(&if_isjsregexp); 1205 BIND(&if_isjsregexp);
1195 { 1206 {
1196 Node* const source = LoadObjectField(receiver, JSRegExp::kSourceOffset); 1207 Node* const source = LoadObjectField(receiver, JSRegExp::kSourceOffset);
1197 Return(source); 1208 Return(source);
1198 } 1209 }
1199 1210
1200 BIND(&if_isnotjsregexp); 1211 BIND(&if_isnotjsregexp);
1201 { 1212 {
1202 Isolate* isolate = this->isolate(); 1213 Isolate* isolate = this->isolate();
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
1311 void RegExpBuiltinsAssembler::FlagGetter(Node* context, Node* receiver, 1322 void RegExpBuiltinsAssembler::FlagGetter(Node* context, Node* receiver,
1312 JSRegExp::Flag flag, int counter, 1323 JSRegExp::Flag flag, int counter,
1313 const char* method_name) { 1324 const char* method_name) {
1314 Isolate* isolate = this->isolate(); 1325 Isolate* isolate = this->isolate();
1315 1326
1316 // Check whether we have an unmodified regexp instance. 1327 // Check whether we have an unmodified regexp instance.
1317 Label if_isunmodifiedjsregexp(this), 1328 Label if_isunmodifiedjsregexp(this),
1318 if_isnotunmodifiedjsregexp(this, Label::kDeferred); 1329 if_isnotunmodifiedjsregexp(this, Label::kDeferred);
1319 1330
1320 GotoIf(TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp); 1331 GotoIf(TaggedIsSmi(receiver), &if_isnotunmodifiedjsregexp);
1321 1332 Branch(IsJSRegExp(receiver), &if_isunmodifiedjsregexp,
1322 Node* const receiver_map = LoadMap(receiver); 1333 &if_isnotunmodifiedjsregexp);
1323 Node* const instance_type = LoadMapInstanceType(receiver_map);
1324
1325 Branch(Word32Equal(instance_type, Int32Constant(JS_REGEXP_TYPE)),
1326 &if_isunmodifiedjsregexp, &if_isnotunmodifiedjsregexp);
1327 1334
1328 BIND(&if_isunmodifiedjsregexp); 1335 BIND(&if_isunmodifiedjsregexp);
1329 { 1336 {
1330 // Refer to JSRegExp's flag property on the fast-path. 1337 // Refer to JSRegExp's flag property on the fast-path.
1331 Node* const is_flag_set = FastFlagGetter(receiver, flag); 1338 Node* const is_flag_set = FastFlagGetter(receiver, flag);
1332 Return(SelectBooleanConstant(is_flag_set)); 1339 Return(SelectBooleanConstant(is_flag_set));
1333 } 1340 }
1334 1341
1335 BIND(&if_isnotunmodifiedjsregexp); 1342 BIND(&if_isnotunmodifiedjsregexp);
1336 { 1343 {
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
1522 // Return true iff exec matched successfully. 1529 // Return true iff exec matched successfully.
1523 Node* const result = 1530 Node* const result =
1524 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant())); 1531 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant()));
1525 Return(result); 1532 Return(result);
1526 } 1533 }
1527 } 1534 }
1528 1535
1529 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, 1536 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string,
1530 Node* const index, 1537 Node* const index,
1531 Node* const is_unicode) { 1538 Node* const is_unicode) {
1539 CSA_ASSERT(this, IsString(string));
1540 // TODO(jgruber): Handle HeapNumber index.
1541
1532 // Default to last_index + 1. 1542 // Default to last_index + 1.
1533 Node* const index_plus_one = SmiAdd(index, SmiConstant(1)); 1543 Node* const index_plus_one = SmiAdd(index, SmiConstant(1));
1534 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one); 1544 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one);
1535 1545
1536 Label if_isunicode(this), out(this); 1546 Label if_isunicode(this), out(this);
1537 Branch(is_unicode, &if_isunicode, &out); 1547 Branch(is_unicode, &if_isunicode, &out);
1538 1548
1539 BIND(&if_isunicode); 1549 BIND(&if_isunicode);
1540 { 1550 {
1541 Node* const string_length = LoadStringLength(string); 1551 Node* const string_length = LoadStringLength(string);
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
1711 Variable var_length_; 1721 Variable var_length_;
1712 Variable var_capacity_; 1722 Variable var_capacity_;
1713 }; 1723 };
1714 1724
1715 } // namespace 1725 } // namespace
1716 1726
1717 void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, 1727 void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context,
1718 Node* const regexp, 1728 Node* const regexp,
1719 Node* const string, 1729 Node* const string,
1720 const bool is_fastpath) { 1730 const bool is_fastpath) {
1731 CSA_ASSERT(this, IsString(string));
1732 if (is_fastpath) CSA_ASSERT(this, IsFastRegExp(context, regexp));
1733
1721 Node* const null = NullConstant(); 1734 Node* const null = NullConstant();
1722 Node* const int_zero = IntPtrConstant(0); 1735 Node* const int_zero = IntPtrConstant(0);
1723 Node* const smi_zero = SmiConstant(Smi::kZero); 1736 Node* const smi_zero = SmiConstant(Smi::kZero);
1724 1737
1725 Node* const is_global = 1738 Node* const is_global =
1726 FlagGetter(context, regexp, JSRegExp::kGlobal, is_fastpath); 1739 FlagGetter(context, regexp, JSRegExp::kGlobal, is_fastpath);
1727 1740
1728 Label if_isglobal(this), if_isnotglobal(this); 1741 Label if_isglobal(this), if_isnotglobal(this);
1729 Branch(is_global, &if_isglobal, &if_isnotglobal); 1742 Branch(is_global, &if_isglobal, &if_isnotglobal);
1730 1743
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
1885 1898
1886 BIND(&fast_path); 1899 BIND(&fast_path);
1887 RegExpPrototypeMatchBody(context, receiver, string, true); 1900 RegExpPrototypeMatchBody(context, receiver, string, true);
1888 1901
1889 BIND(&slow_path); 1902 BIND(&slow_path);
1890 RegExpPrototypeMatchBody(context, receiver, string, false); 1903 RegExpPrototypeMatchBody(context, receiver, string, false);
1891 } 1904 }
1892 1905
1893 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( 1906 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast(
1894 Node* const context, Node* const regexp, Node* const string) { 1907 Node* const context, Node* const regexp, Node* const string) {
1908 CSA_ASSERT(this, IsFastRegExp(context, regexp));
1909 CSA_ASSERT(this, IsString(string));
1910
1895 // Grab the initial value of last index. 1911 // Grab the initial value of last index.
1896 Node* const previous_last_index = FastLoadLastIndex(regexp); 1912 Node* const previous_last_index = FastLoadLastIndex(regexp);
1897 1913
1898 // Ensure last index is 0. 1914 // Ensure last index is 0.
1899 FastStoreLastIndex(regexp, SmiConstant(Smi::kZero)); 1915 FastStoreLastIndex(regexp, SmiConstant(Smi::kZero));
1900 1916
1901 // Call exec. 1917 // Call exec.
1902 Label if_didnotmatch(this); 1918 Label if_didnotmatch(this);
1903 Node* const match_indices = RegExpPrototypeExecBodyWithoutResult( 1919 Node* const match_indices = RegExpPrototypeExecBodyWithoutResult(
1904 context, regexp, string, &if_didnotmatch, true); 1920 context, regexp, string, &if_didnotmatch, true);
(...skipping 12 matching lines...) Expand all
1917 BIND(&if_didnotmatch); 1933 BIND(&if_didnotmatch);
1918 { 1934 {
1919 // Reset last index and return -1. 1935 // Reset last index and return -1.
1920 FastStoreLastIndex(regexp, previous_last_index); 1936 FastStoreLastIndex(regexp, previous_last_index);
1921 Return(SmiConstant(-1)); 1937 Return(SmiConstant(-1));
1922 } 1938 }
1923 } 1939 }
1924 1940
1925 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodySlow( 1941 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodySlow(
1926 Node* const context, Node* const regexp, Node* const string) { 1942 Node* const context, Node* const regexp, Node* const string) {
1943 CSA_ASSERT(this, IsJSReceiver(regexp));
1944 CSA_ASSERT(this, IsString(string));
1945
1927 Isolate* const isolate = this->isolate(); 1946 Isolate* const isolate = this->isolate();
1928 1947
1929 Node* const smi_zero = SmiConstant(Smi::kZero); 1948 Node* const smi_zero = SmiConstant(Smi::kZero);
1930 1949
1931 // Grab the initial value of last index. 1950 // Grab the initial value of last index.
1932 Node* const previous_last_index = SlowLoadLastIndex(context, regexp); 1951 Node* const previous_last_index = SlowLoadLastIndex(context, regexp);
1933 1952
1934 // Ensure last index is 0. 1953 // Ensure last index is 0.
1935 { 1954 {
1936 Label next(this); 1955 Label next(this);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 BIND(&slow_path); 2030 BIND(&slow_path);
2012 RegExpPrototypeSearchBodySlow(context, receiver, string); 2031 RegExpPrototypeSearchBodySlow(context, receiver, string);
2013 } 2032 }
2014 2033
2015 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp, 2034 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp,
2016 // {string} is a String, and {limit} is a Smi. 2035 // {string} is a String, and {limit} is a Smi.
2017 void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, 2036 void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context,
2018 Node* const regexp, 2037 Node* const regexp,
2019 Node* const string, 2038 Node* const string,
2020 Node* const limit) { 2039 Node* const limit) {
2040 CSA_ASSERT(this, IsFastRegExp(context, regexp));
2041 CSA_ASSERT(this, TaggedIsSmi(limit));
2042 CSA_ASSERT(this, IsString(string));
2043
2021 Node* const null = NullConstant(); 2044 Node* const null = NullConstant();
2022 Node* const smi_zero = SmiConstant(0); 2045 Node* const smi_zero = SmiConstant(0);
2023 Node* const int_zero = IntPtrConstant(0); 2046 Node* const int_zero = IntPtrConstant(0);
2024 Node* const int_limit = SmiUntag(limit); 2047 Node* const int_limit = SmiUntag(limit);
2025 2048
2026 const ElementsKind kind = FAST_ELEMENTS; 2049 const ElementsKind kind = FAST_ELEMENTS;
2027 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; 2050 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS;
2028 2051
2029 Node* const allocation_site = nullptr; 2052 Node* const allocation_site = nullptr;
2030 Node* const native_context = LoadNativeContext(context); 2053 Node* const native_context = LoadNativeContext(context);
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
2091 &var_next_search_from}; 2114 &var_next_search_from};
2092 const int vars_count = sizeof(vars) / sizeof(vars[0]); 2115 const int vars_count = sizeof(vars) / sizeof(vars[0]);
2093 Label loop(this, vars_count, vars), push_suffix_and_out(this), out(this); 2116 Label loop(this, vars_count, vars), push_suffix_and_out(this), out(this);
2094 Goto(&loop); 2117 Goto(&loop);
2095 2118
2096 BIND(&loop); 2119 BIND(&loop);
2097 { 2120 {
2098 Node* const next_search_from = var_next_search_from.value(); 2121 Node* const next_search_from = var_next_search_from.value();
2099 Node* const last_matched_until = var_last_matched_until.value(); 2122 Node* const last_matched_until = var_last_matched_until.value();
2100 2123
2124 CSA_ASSERT(this, TaggedIsSmi(next_search_from));
2125 CSA_ASSERT(this, TaggedIsSmi(last_matched_until));
2126
2101 // We're done if we've reached the end of the string. 2127 // We're done if we've reached the end of the string.
2102 { 2128 {
2103 Label next(this); 2129 Label next(this);
2104 Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out, 2130 Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out,
2105 &next); 2131 &next);
2106 BIND(&next); 2132 BIND(&next);
2107 } 2133 }
2108 2134
2109 // Search for the given {regexp}. 2135 // Search for the given {regexp}.
2110 2136
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after
2254 } 2280 }
2255 } 2281 }
2256 2282
2257 // Helper that skips a few initial checks. 2283 // Helper that skips a few initial checks.
2258 TF_BUILTIN(RegExpSplit, RegExpBuiltinsAssembler) { 2284 TF_BUILTIN(RegExpSplit, RegExpBuiltinsAssembler) {
2259 Node* const regexp = Parameter(Descriptor::kReceiver); 2285 Node* const regexp = Parameter(Descriptor::kReceiver);
2260 Node* const string = Parameter(Descriptor::kString); 2286 Node* const string = Parameter(Descriptor::kString);
2261 Node* const maybe_limit = Parameter(Descriptor::kLimit); 2287 Node* const maybe_limit = Parameter(Descriptor::kLimit);
2262 Node* const context = Parameter(Descriptor::kContext); 2288 Node* const context = Parameter(Descriptor::kContext);
2263 2289
2264 CSA_ASSERT(this, IsFastRegExp(context, regexp, LoadMap(regexp))); 2290 CSA_ASSERT(this, IsFastRegExp(context, regexp));
2265 CSA_ASSERT(this, IsString(string)); 2291 CSA_ASSERT(this, IsString(string));
2266 2292
2267 // TODO(jgruber): Even if map checks send us to the fast path, we still need 2293 // TODO(jgruber): Even if map checks send us to the fast path, we still need
2268 // to verify the constructor property and jump to the slow path if it has 2294 // to verify the constructor property and jump to the slow path if it has
2269 // been changed. 2295 // been changed.
2270 2296
2271 // Convert {maybe_limit} to a uint32, capping at the maximal smi value. 2297 // Convert {maybe_limit} to a uint32, capping at the maximal smi value.
2272 Variable var_limit(this, MachineRepresentation::kTagged); 2298 Variable var_limit(this, MachineRepresentation::kTagged);
2273 Label if_limitissmimax(this), limit_done(this); 2299 Label if_limitissmimax(this), limit_done(this);
2274 2300
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
2324 BIND(&runtime); 2350 BIND(&runtime);
2325 Return(CallRuntime(Runtime::kRegExpSplit, context, receiver, string, 2351 Return(CallRuntime(Runtime::kRegExpSplit, context, receiver, string,
2326 maybe_limit)); 2352 maybe_limit));
2327 } 2353 }
2328 2354
2329 Node* RegExpBuiltinsAssembler::ReplaceGlobalCallableFastPath( 2355 Node* RegExpBuiltinsAssembler::ReplaceGlobalCallableFastPath(
2330 Node* context, Node* regexp, Node* string, Node* replace_callable) { 2356 Node* context, Node* regexp, Node* string, Node* replace_callable) {
2331 // The fast path is reached only if {receiver} is a global unmodified 2357 // The fast path is reached only if {receiver} is a global unmodified
2332 // JSRegExp instance and {replace_callable} is callable. 2358 // JSRegExp instance and {replace_callable} is callable.
2333 2359
2360 CSA_ASSERT(this, IsFastRegExp(context, regexp));
2361 CSA_ASSERT(this, IsCallable(replace_callable));
2362 CSA_ASSERT(this, IsString(string));
2363
2334 Isolate* const isolate = this->isolate(); 2364 Isolate* const isolate = this->isolate();
2335 2365
2336 Node* const null = NullConstant(); 2366 Node* const null = NullConstant();
2337 Node* const undefined = UndefinedConstant(); 2367 Node* const undefined = UndefinedConstant();
2338 Node* const int_zero = IntPtrConstant(0); 2368 Node* const int_zero = IntPtrConstant(0);
2339 Node* const int_one = IntPtrConstant(1); 2369 Node* const int_one = IntPtrConstant(1);
2340 Node* const smi_zero = SmiConstant(Smi::kZero); 2370 Node* const smi_zero = SmiConstant(Smi::kZero);
2341 2371
2342 Node* const native_context = LoadNativeContext(context); 2372 Node* const native_context = LoadNativeContext(context);
2343 2373
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after
2538 Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( 2568 Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath(
2539 Node* context, Node* regexp, Node* string, Node* replace_string) { 2569 Node* context, Node* regexp, Node* string, Node* replace_string) {
2540 // The fast path is reached only if {receiver} is an unmodified 2570 // The fast path is reached only if {receiver} is an unmodified
2541 // JSRegExp instance, {replace_value} is non-callable, and 2571 // JSRegExp instance, {replace_value} is non-callable, and
2542 // ToString({replace_value}) does not contain '$', i.e. we're doing a simple 2572 // ToString({replace_value}) does not contain '$', i.e. we're doing a simple
2543 // string replacement. 2573 // string replacement.
2544 2574
2545 Node* const int_zero = IntPtrConstant(0); 2575 Node* const int_zero = IntPtrConstant(0);
2546 Node* const smi_zero = SmiConstant(Smi::kZero); 2576 Node* const smi_zero = SmiConstant(Smi::kZero);
2547 2577
2578 CSA_ASSERT(this, IsFastRegExp(context, regexp));
2579 CSA_ASSERT(this, IsString(replace_string));
2580 CSA_ASSERT(this, IsString(string));
2581
2548 Label out(this); 2582 Label out(this);
2549 Variable var_result(this, MachineRepresentation::kTagged); 2583 Variable var_result(this, MachineRepresentation::kTagged);
2550 2584
2551 // Load the last match info. 2585 // Load the last match info.
2552 Node* const native_context = LoadNativeContext(context); 2586 Node* const native_context = LoadNativeContext(context);
2553 Node* const last_match_info = 2587 Node* const last_match_info =
2554 LoadContextElement(native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); 2588 LoadContextElement(native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
2555 2589
2556 // Is {regexp} global? 2590 // Is {regexp} global?
2557 Label if_isglobal(this), if_isnonglobal(this); 2591 Label if_isglobal(this), if_isnonglobal(this);
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
2634 return var_result.value(); 2668 return var_result.value();
2635 } 2669 }
2636 2670
2637 // Helper that skips a few initial checks. 2671 // Helper that skips a few initial checks.
2638 TF_BUILTIN(RegExpReplace, RegExpBuiltinsAssembler) { 2672 TF_BUILTIN(RegExpReplace, RegExpBuiltinsAssembler) {
2639 Node* const regexp = Parameter(Descriptor::kReceiver); 2673 Node* const regexp = Parameter(Descriptor::kReceiver);
2640 Node* const string = Parameter(Descriptor::kString); 2674 Node* const string = Parameter(Descriptor::kString);
2641 Node* const replace_value = Parameter(Descriptor::kReplaceValue); 2675 Node* const replace_value = Parameter(Descriptor::kReplaceValue);
2642 Node* const context = Parameter(Descriptor::kContext); 2676 Node* const context = Parameter(Descriptor::kContext);
2643 2677
2644 CSA_ASSERT(this, IsFastRegExp(context, regexp, LoadMap(regexp))); 2678 CSA_ASSERT(this, IsFastRegExp(context, regexp));
2645 CSA_ASSERT(this, IsString(string)); 2679 CSA_ASSERT(this, IsString(string));
2646 2680
2647 Label checkreplacestring(this), if_iscallable(this), 2681 Label checkreplacestring(this), if_iscallable(this),
2648 runtime(this, Label::kDeferred); 2682 runtime(this, Label::kDeferred);
2649 2683
2650 // 2. Is {replace_value} callable? 2684 // 2. Is {replace_value} callable?
2651 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); 2685 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring);
2652 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, 2686 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable,
2653 &checkreplacestring); 2687 &checkreplacestring);
2654 2688
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
2742 } 2776 }
2743 2777
2744 // Simple string matching functionality for internal use which does not modify 2778 // Simple string matching functionality for internal use which does not modify
2745 // the last match info. 2779 // the last match info.
2746 TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) { 2780 TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) {
2747 Node* const regexp = Parameter(Descriptor::kRegExp); 2781 Node* const regexp = Parameter(Descriptor::kRegExp);
2748 Node* const string = Parameter(Descriptor::kString); 2782 Node* const string = Parameter(Descriptor::kString);
2749 Node* const context = Parameter(Descriptor::kContext); 2783 Node* const context = Parameter(Descriptor::kContext);
2750 2784
2751 Node* const null = NullConstant(); 2785 Node* const null = NullConstant();
2752 Node* const smi_zero = SmiConstant(Smi::FromInt(0)); 2786 Node* const smi_zero = SmiConstant(0);
2787
2788 CSA_ASSERT(this, IsJSRegExp(regexp));
2789 CSA_ASSERT(this, IsString(string));
2753 2790
2754 Node* const native_context = LoadNativeContext(context); 2791 Node* const native_context = LoadNativeContext(context);
2755 Node* const internal_match_info = LoadContextElement( 2792 Node* const internal_match_info = LoadContextElement(
2756 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); 2793 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX);
2757 2794
2758 Node* const match_indices = 2795 Node* const match_indices =
2759 IrregexpExec(context, regexp, string, smi_zero, internal_match_info); 2796 IrregexpExec(context, regexp, string, smi_zero, internal_match_info);
2760 2797
2761 Label if_matched(this), if_didnotmatch(this); 2798 Label if_matched(this), if_didnotmatch(this);
2762 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched); 2799 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
2763 2800
2764 BIND(&if_didnotmatch); 2801 BIND(&if_didnotmatch);
2765 Return(null); 2802 Return(null);
2766 2803
2767 BIND(&if_matched); 2804 BIND(&if_matched);
2768 { 2805 {
2769 Node* result = 2806 Node* result =
2770 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2807 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
2771 Return(result); 2808 Return(result);
2772 } 2809 }
2773 } 2810 }
2774 2811
2775 } // namespace internal 2812 } // namespace internal
2776 } // namespace v8 2813 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-regexp-gen.h ('k') | src/code-stub-assembler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698