| OLD | NEW |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |