| OLD | NEW |
| 1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/builtins/builtins-regexp.h" | 5 #include "src/builtins/builtins-regexp.h" |
| 6 | 6 |
| 7 #include "src/builtins/builtins-constructor.h" | 7 #include "src/builtins/builtins-constructor.h" |
| 8 #include "src/builtins/builtins-utils.h" | 8 #include "src/builtins/builtins-utils.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 16 matching lines...) Expand all Loading... |
| 27 | 27 |
| 28 Node* RegExpBuiltinsAssembler::FastLoadLastIndex(Node* regexp) { | 28 Node* RegExpBuiltinsAssembler::FastLoadLastIndex(Node* regexp) { |
| 29 // Load the in-object field. | 29 // Load the in-object field. |
| 30 static const int field_offset = | 30 static const int field_offset = |
| 31 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; | 31 JSRegExp::kSize + JSRegExp::kLastIndexFieldIndex * kPointerSize; |
| 32 return LoadObjectField(regexp, field_offset); | 32 return LoadObjectField(regexp, field_offset); |
| 33 } | 33 } |
| 34 | 34 |
| 35 Node* RegExpBuiltinsAssembler::SlowLoadLastIndex(Node* context, Node* regexp) { | 35 Node* RegExpBuiltinsAssembler::SlowLoadLastIndex(Node* context, Node* regexp) { |
| 36 // Load through the GetProperty stub. | 36 // Load through the GetProperty stub. |
| 37 Node* const name = HeapConstant(isolate()->factory()->lastIndex_string()); | 37 return GetProperty(context, regexp, isolate()->factory()->lastIndex_string()); |
| 38 Callable getproperty_callable = CodeFactory::GetProperty(isolate()); | |
| 39 return CallStub(getproperty_callable, context, regexp, name); | |
| 40 } | 38 } |
| 41 | 39 |
| 42 Node* RegExpBuiltinsAssembler::LoadLastIndex(Node* context, Node* regexp, | 40 Node* RegExpBuiltinsAssembler::LoadLastIndex(Node* context, Node* regexp, |
| 43 bool is_fastpath) { | 41 bool is_fastpath) { |
| 44 return is_fastpath ? FastLoadLastIndex(regexp) | 42 return is_fastpath ? FastLoadLastIndex(regexp) |
| 45 : SlowLoadLastIndex(context, regexp); | 43 : SlowLoadLastIndex(context, regexp); |
| 46 } | 44 } |
| 47 | 45 |
| 48 // The fast-path of StoreLastIndex when regexp is guaranteed to be an unmodified | 46 // The fast-path of StoreLastIndex when regexp is guaranteed to be an unmodified |
| 49 // JSRegExp instance. | 47 // JSRegExp instance. |
| (...skipping 773 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 823 CASE_FOR_FLAG(JSRegExp::kMultiline); | 821 CASE_FOR_FLAG(JSRegExp::kMultiline); |
| 824 CASE_FOR_FLAG(JSRegExp::kUnicode); | 822 CASE_FOR_FLAG(JSRegExp::kUnicode); |
| 825 CASE_FOR_FLAG(JSRegExp::kSticky); | 823 CASE_FOR_FLAG(JSRegExp::kSticky); |
| 826 #undef CASE_FOR_FLAG | 824 #undef CASE_FOR_FLAG |
| 827 } else { | 825 } else { |
| 828 DCHECK(!is_fastpath); | 826 DCHECK(!is_fastpath); |
| 829 | 827 |
| 830 // Fall back to GetProperty stub on the slow-path. | 828 // Fall back to GetProperty stub on the slow-path. |
| 831 var_flags.Bind(int_zero); | 829 var_flags.Bind(int_zero); |
| 832 | 830 |
| 833 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 831 #define CASE_FOR_FLAG(NAME, FLAG) \ |
| 834 | 832 do { \ |
| 835 #define CASE_FOR_FLAG(NAME, FLAG) \ | 833 Label next(this); \ |
| 836 do { \ | 834 Node* const flag = GetProperty( \ |
| 837 Label next(this); \ | 835 context, regexp, isolate->factory()->InternalizeUtf8String(NAME)); \ |
| 838 Node* const name = \ | 836 Label if_isflagset(this); \ |
| 839 HeapConstant(isolate->factory()->InternalizeUtf8String(NAME)); \ | 837 BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \ |
| 840 Node* const flag = CallStub(getproperty_callable, context, regexp, name); \ | 838 Bind(&if_isflagset); \ |
| 841 Label if_isflagset(this); \ | 839 var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \ |
| 842 BranchIfToBooleanIsTrue(flag, &if_isflagset, &next); \ | 840 var_flags.Bind(WordOr(var_flags.value(), IntPtrConstant(FLAG))); \ |
| 843 Bind(&if_isflagset); \ | 841 Goto(&next); \ |
| 844 var_length.Bind(IntPtrAdd(var_length.value(), int_one)); \ | 842 Bind(&next); \ |
| 845 var_flags.Bind(WordOr(var_flags.value(), IntPtrConstant(FLAG))); \ | |
| 846 Goto(&next); \ | |
| 847 Bind(&next); \ | |
| 848 } while (false) | 843 } while (false) |
| 849 | 844 |
| 850 CASE_FOR_FLAG("global", JSRegExp::kGlobal); | 845 CASE_FOR_FLAG("global", JSRegExp::kGlobal); |
| 851 CASE_FOR_FLAG("ignoreCase", JSRegExp::kIgnoreCase); | 846 CASE_FOR_FLAG("ignoreCase", JSRegExp::kIgnoreCase); |
| 852 CASE_FOR_FLAG("multiline", JSRegExp::kMultiline); | 847 CASE_FOR_FLAG("multiline", JSRegExp::kMultiline); |
| 853 CASE_FOR_FLAG("unicode", JSRegExp::kUnicode); | 848 CASE_FOR_FLAG("unicode", JSRegExp::kUnicode); |
| 854 CASE_FOR_FLAG("sticky", JSRegExp::kSticky); | 849 CASE_FOR_FLAG("sticky", JSRegExp::kSticky); |
| 855 #undef CASE_FOR_FLAG | 850 #undef CASE_FOR_FLAG |
| 856 } | 851 } |
| 857 | 852 |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 896 | 891 |
| 897 Variable var_result(this, MachineRepresentation::kWord32, Int32Constant(0)); | 892 Variable var_result(this, MachineRepresentation::kWord32, Int32Constant(0)); |
| 898 | 893 |
| 899 GotoIf(TaggedIsSmi(maybe_receiver), &out); | 894 GotoIf(TaggedIsSmi(maybe_receiver), &out); |
| 900 GotoIfNot(IsJSReceiver(maybe_receiver), &out); | 895 GotoIfNot(IsJSReceiver(maybe_receiver), &out); |
| 901 | 896 |
| 902 Node* const receiver = maybe_receiver; | 897 Node* const receiver = maybe_receiver; |
| 903 | 898 |
| 904 // Check @@match. | 899 // Check @@match. |
| 905 { | 900 { |
| 906 Callable getproperty_callable = CodeFactory::GetProperty(isolate()); | 901 Node* const value = |
| 907 Node* const name = HeapConstant(isolate()->factory()->match_symbol()); | 902 GetProperty(context, receiver, isolate()->factory()->match_symbol()); |
| 908 Node* const value = CallStub(getproperty_callable, context, receiver, name); | |
| 909 | 903 |
| 910 Label match_isundefined(this), match_isnotundefined(this); | 904 Label match_isundefined(this), match_isnotundefined(this); |
| 911 Branch(IsUndefined(value), &match_isundefined, &match_isnotundefined); | 905 Branch(IsUndefined(value), &match_isundefined, &match_isnotundefined); |
| 912 | 906 |
| 913 Bind(&match_isundefined); | 907 Bind(&match_isundefined); |
| 914 Branch(HasInstanceType(receiver, JS_REGEXP_TYPE), &if_isregexp, &out); | 908 Branch(HasInstanceType(receiver, JS_REGEXP_TYPE), &if_isregexp, &out); |
| 915 | 909 |
| 916 Bind(&match_isnotundefined); | 910 Bind(&match_isnotundefined); |
| 917 BranchIfToBooleanIsTrue(value, &if_isregexp, &out); | 911 BranchIfToBooleanIsTrue(value, &if_isregexp, &out); |
| 918 } | 912 } |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 990 | 984 |
| 991 { | 985 { |
| 992 Label next(this); | 986 Label next(this); |
| 993 | 987 |
| 994 GotoIfNot(IsUndefined(new_target), &next); | 988 GotoIfNot(IsUndefined(new_target), &next); |
| 995 var_new_target.Bind(regexp_function); | 989 var_new_target.Bind(regexp_function); |
| 996 | 990 |
| 997 GotoIfNot(pattern_is_regexp, &next); | 991 GotoIfNot(pattern_is_regexp, &next); |
| 998 GotoIfNot(IsUndefined(flags), &next); | 992 GotoIfNot(IsUndefined(flags), &next); |
| 999 | 993 |
| 1000 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 994 Node* const value = |
| 1001 Node* const name = HeapConstant(isolate->factory()->constructor_string()); | 995 GetProperty(context, pattern, isolate->factory()->constructor_string()); |
| 1002 Node* const value = CallStub(getproperty_callable, context, pattern, name); | |
| 1003 | 996 |
| 1004 GotoIfNot(WordEqual(value, regexp_function), &next); | 997 GotoIfNot(WordEqual(value, regexp_function), &next); |
| 1005 Return(pattern); | 998 Return(pattern); |
| 1006 | 999 |
| 1007 Bind(&next); | 1000 Bind(&next); |
| 1008 } | 1001 } |
| 1009 | 1002 |
| 1010 { | 1003 { |
| 1011 Label next(this), if_patternisfastregexp(this), | 1004 Label next(this), if_patternisfastregexp(this), |
| 1012 if_patternisslowregexp(this); | 1005 if_patternisslowregexp(this); |
| (...skipping 17 matching lines...) Expand all Loading... |
| 1030 Goto(&inner_next); | 1023 Goto(&inner_next); |
| 1031 | 1024 |
| 1032 Bind(&inner_next); | 1025 Bind(&inner_next); |
| 1033 } | 1026 } |
| 1034 | 1027 |
| 1035 Goto(&next); | 1028 Goto(&next); |
| 1036 } | 1029 } |
| 1037 | 1030 |
| 1038 Bind(&if_patternisslowregexp); | 1031 Bind(&if_patternisslowregexp); |
| 1039 { | 1032 { |
| 1040 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | |
| 1041 | |
| 1042 { | 1033 { |
| 1043 Node* const name = HeapConstant(isolate->factory()->source_string()); | |
| 1044 Node* const value = | 1034 Node* const value = |
| 1045 CallStub(getproperty_callable, context, pattern, name); | 1035 GetProperty(context, pattern, isolate->factory()->source_string()); |
| 1046 var_pattern.Bind(value); | 1036 var_pattern.Bind(value); |
| 1047 } | 1037 } |
| 1048 | 1038 |
| 1049 { | 1039 { |
| 1050 Label inner_next(this); | 1040 Label inner_next(this); |
| 1051 GotoIfNot(IsUndefined(flags), &inner_next); | 1041 GotoIfNot(IsUndefined(flags), &inner_next); |
| 1052 | 1042 |
| 1053 Node* const name = HeapConstant(isolate->factory()->flags_string()); | |
| 1054 Node* const value = | 1043 Node* const value = |
| 1055 CallStub(getproperty_callable, context, pattern, name); | 1044 GetProperty(context, pattern, isolate->factory()->flags_string()); |
| 1056 var_flags.Bind(value); | 1045 var_flags.Bind(value); |
| 1057 Goto(&inner_next); | 1046 Goto(&inner_next); |
| 1058 | 1047 |
| 1059 Bind(&inner_next); | 1048 Bind(&inner_next); |
| 1060 } | 1049 } |
| 1061 | 1050 |
| 1062 Goto(&next); | 1051 Goto(&next); |
| 1063 } | 1052 } |
| 1064 | 1053 |
| 1065 Bind(&next); | 1054 Bind(&next); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1256 | 1245 |
| 1257 // Load through the GetProperty stub. | 1246 // Load through the GetProperty stub. |
| 1258 Node* RegExpBuiltinsAssembler::SlowFlagGetter(Node* const context, | 1247 Node* RegExpBuiltinsAssembler::SlowFlagGetter(Node* const context, |
| 1259 Node* const regexp, | 1248 Node* const regexp, |
| 1260 JSRegExp::Flag flag) { | 1249 JSRegExp::Flag flag) { |
| 1261 Factory* factory = isolate()->factory(); | 1250 Factory* factory = isolate()->factory(); |
| 1262 | 1251 |
| 1263 Label out(this); | 1252 Label out(this); |
| 1264 Variable var_result(this, MachineRepresentation::kWord32); | 1253 Variable var_result(this, MachineRepresentation::kWord32); |
| 1265 | 1254 |
| 1266 Node* name; | 1255 Handle<String> name; |
| 1267 | |
| 1268 switch (flag) { | 1256 switch (flag) { |
| 1269 case JSRegExp::kGlobal: | 1257 case JSRegExp::kGlobal: |
| 1270 name = HeapConstant(factory->global_string()); | 1258 name = factory->global_string(); |
| 1271 break; | 1259 break; |
| 1272 case JSRegExp::kIgnoreCase: | 1260 case JSRegExp::kIgnoreCase: |
| 1273 name = HeapConstant(factory->ignoreCase_string()); | 1261 name = factory->ignoreCase_string(); |
| 1274 break; | 1262 break; |
| 1275 case JSRegExp::kMultiline: | 1263 case JSRegExp::kMultiline: |
| 1276 name = HeapConstant(factory->multiline_string()); | 1264 name = factory->multiline_string(); |
| 1277 break; | 1265 break; |
| 1278 case JSRegExp::kSticky: | 1266 case JSRegExp::kSticky: |
| 1279 name = HeapConstant(factory->sticky_string()); | 1267 name = factory->sticky_string(); |
| 1280 break; | 1268 break; |
| 1281 case JSRegExp::kUnicode: | 1269 case JSRegExp::kUnicode: |
| 1282 name = HeapConstant(factory->unicode_string()); | 1270 name = factory->unicode_string(); |
| 1283 break; | 1271 break; |
| 1284 default: | 1272 default: |
| 1285 UNREACHABLE(); | 1273 UNREACHABLE(); |
| 1286 } | 1274 } |
| 1287 | 1275 |
| 1288 Callable getproperty_callable = CodeFactory::GetProperty(isolate()); | 1276 Node* const value = GetProperty(context, regexp, name); |
| 1289 Node* const value = CallStub(getproperty_callable, context, regexp, name); | |
| 1290 | 1277 |
| 1291 Label if_true(this), if_false(this); | 1278 Label if_true(this), if_false(this); |
| 1292 BranchIfToBooleanIsTrue(value, &if_true, &if_false); | 1279 BranchIfToBooleanIsTrue(value, &if_true, &if_false); |
| 1293 | 1280 |
| 1294 Bind(&if_true); | 1281 Bind(&if_true); |
| 1295 { | 1282 { |
| 1296 var_result.Bind(Int32Constant(1)); | 1283 var_result.Bind(Int32Constant(1)); |
| 1297 Goto(&out); | 1284 Goto(&out); |
| 1298 } | 1285 } |
| 1299 | 1286 |
| (...skipping 207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1507 var_result.Bind(result); | 1494 var_result.Bind(result); |
| 1508 Goto(&out); | 1495 Goto(&out); |
| 1509 } | 1496 } |
| 1510 | 1497 |
| 1511 Bind(&if_isslowpath); | 1498 Bind(&if_isslowpath); |
| 1512 { | 1499 { |
| 1513 // Take the slow path of fetching the exec property, calling it, and | 1500 // Take the slow path of fetching the exec property, calling it, and |
| 1514 // verifying its return value. | 1501 // verifying its return value. |
| 1515 | 1502 |
| 1516 // Get the exec property. | 1503 // Get the exec property. |
| 1517 Node* const name = HeapConstant(isolate->factory()->exec_string()); | 1504 Node* const exec = |
| 1518 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 1505 GetProperty(context, regexp, isolate->factory()->exec_string()); |
| 1519 Node* const exec = CallStub(getproperty_callable, context, regexp, name); | |
| 1520 | 1506 |
| 1521 // Is {exec} callable? | 1507 // Is {exec} callable? |
| 1522 Label if_iscallable(this), if_isnotcallable(this); | 1508 Label if_iscallable(this), if_isnotcallable(this); |
| 1523 | 1509 |
| 1524 GotoIf(TaggedIsSmi(exec), &if_isnotcallable); | 1510 GotoIf(TaggedIsSmi(exec), &if_isnotcallable); |
| 1525 | 1511 |
| 1526 Node* const exec_map = LoadMap(exec); | 1512 Node* const exec_map = LoadMap(exec); |
| 1527 Branch(IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable); | 1513 Branch(IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable); |
| 1528 | 1514 |
| 1529 Bind(&if_iscallable); | 1515 Bind(&if_iscallable); |
| (...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1869 // The match is guaranteed to be a string on the fast path. | 1855 // The match is guaranteed to be a string on the fast path. |
| 1870 CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(match))); | 1856 CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(match))); |
| 1871 | 1857 |
| 1872 var_match.Bind(match); | 1858 var_match.Bind(match); |
| 1873 Goto(&if_didmatch); | 1859 Goto(&if_didmatch); |
| 1874 } | 1860 } |
| 1875 | 1861 |
| 1876 Bind(&slow_result); | 1862 Bind(&slow_result); |
| 1877 { | 1863 { |
| 1878 // TODO(ishell): Use GetElement stub once it's available. | 1864 // TODO(ishell): Use GetElement stub once it's available. |
| 1879 Node* const name = smi_zero; | 1865 Node* const match = GetProperty(context, result, smi_zero); |
| 1880 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | |
| 1881 Node* const match = | |
| 1882 CallStub(getproperty_callable, context, result, name); | |
| 1883 | |
| 1884 var_match.Bind(ToString(context, match)); | 1866 var_match.Bind(ToString(context, match)); |
| 1885 Goto(&if_didmatch); | 1867 Goto(&if_didmatch); |
| 1886 } | 1868 } |
| 1887 } | 1869 } |
| 1888 } | 1870 } |
| 1889 | 1871 |
| 1890 Bind(&if_didnotmatch); | 1872 Bind(&if_didnotmatch); |
| 1891 { | 1873 { |
| 1892 // Return null if there were no matches, otherwise just exit the loop. | 1874 // Return null if there were no matches, otherwise just exit the loop. |
| 1893 GotoIfNot(IntPtrEqual(array.length(), int_zero), &out); | 1875 GotoIfNot(IntPtrEqual(array.length(), int_zero), &out); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2040 | 2022 |
| 2041 Bind(&fast_result); | 2023 Bind(&fast_result); |
| 2042 { | 2024 { |
| 2043 Node* const index = | 2025 Node* const index = |
| 2044 LoadObjectField(exec_result, JSRegExpResult::kIndexOffset); | 2026 LoadObjectField(exec_result, JSRegExpResult::kIndexOffset); |
| 2045 Return(index); | 2027 Return(index); |
| 2046 } | 2028 } |
| 2047 | 2029 |
| 2048 Bind(&slow_result); | 2030 Bind(&slow_result); |
| 2049 { | 2031 { |
| 2050 Node* const name = HeapConstant(isolate->factory()->index_string()); | 2032 Return(GetProperty(context, exec_result, |
| 2051 Callable getproperty_callable = CodeFactory::GetProperty(isolate); | 2033 isolate->factory()->index_string())); |
| 2052 Node* const index = | |
| 2053 CallStub(getproperty_callable, context, exec_result, name); | |
| 2054 Return(index); | |
| 2055 } | 2034 } |
| 2056 } | 2035 } |
| 2057 } | 2036 } |
| 2058 | 2037 |
| 2059 // ES#sec-regexp.prototype-@@search | 2038 // ES#sec-regexp.prototype-@@search |
| 2060 // RegExp.prototype [ @@search ] ( string ) | 2039 // RegExp.prototype [ @@search ] ( string ) |
| 2061 TF_BUILTIN(RegExpPrototypeSearch, RegExpBuiltinsAssembler) { | 2040 TF_BUILTIN(RegExpPrototypeSearch, RegExpBuiltinsAssembler) { |
| 2062 Node* const maybe_receiver = Parameter(0); | 2041 Node* const maybe_receiver = Parameter(0); |
| 2063 Node* const maybe_string = Parameter(1); | 2042 Node* const maybe_string = Parameter(1); |
| 2064 Node* const context = Parameter(4); | 2043 Node* const context = Parameter(4); |
| (...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2841 Bind(&if_matched); | 2820 Bind(&if_matched); |
| 2842 { | 2821 { |
| 2843 Node* result = | 2822 Node* result = |
| 2844 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2823 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
| 2845 Return(result); | 2824 Return(result); |
| 2846 } | 2825 } |
| 2847 } | 2826 } |
| 2848 | 2827 |
| 2849 } // namespace internal | 2828 } // namespace internal |
| 2850 } // namespace v8 | 2829 } // namespace v8 |
| OLD | NEW |