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 |