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, HasInstanceType(regexp, JS_REGEXP_TYPE)); | |
Camillo Bruni
2017/04/06 10:59:27
nit: could you use/add IsJSRegexp?
jgruber
2017/04/06 14:54:23
Done and updated all use sites.
| |
73 CSA_ASSERT(this, IsFixedArrayMap(LoadMap(match_info))); | |
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 400 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, HasInstanceType(regexp, JS_REGEXP_TYPE)); |
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); |
(...skipping 219 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, HasInstanceType(regexp, JS_REGEXP_TYPE)); | |
Camillo Bruni
2017/04/06 10:59:27
ditto
jgruber
2017/04/06 14:54:23
Done.
| |
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 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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, HasInstanceType(regexp, JS_REGEXP_TYPE)); | |
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 547 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1522 // Return true iff exec matched successfully. | 1534 // Return true iff exec matched successfully. |
1523 Node* const result = | 1535 Node* const result = |
1524 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant())); | 1536 SelectBooleanConstant(WordNotEqual(match_indices, NullConstant())); |
1525 Return(result); | 1537 Return(result); |
1526 } | 1538 } |
1527 } | 1539 } |
1528 | 1540 |
1529 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, | 1541 Node* RegExpBuiltinsAssembler::AdvanceStringIndex(Node* const string, |
1530 Node* const index, | 1542 Node* const index, |
1531 Node* const is_unicode) { | 1543 Node* const is_unicode) { |
1544 CSA_ASSERT(this, IsString(string)); | |
1545 // TODO(jgruber): Handle HeapNumber index. | |
1546 | |
1532 // Default to last_index + 1. | 1547 // Default to last_index + 1. |
1533 Node* const index_plus_one = SmiAdd(index, SmiConstant(1)); | 1548 Node* const index_plus_one = SmiAdd(index, SmiConstant(1)); |
1534 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one); | 1549 Variable var_result(this, MachineRepresentation::kTagged, index_plus_one); |
1535 | 1550 |
1536 Label if_isunicode(this), out(this); | 1551 Label if_isunicode(this), out(this); |
1537 Branch(is_unicode, &if_isunicode, &out); | 1552 Branch(is_unicode, &if_isunicode, &out); |
1538 | 1553 |
1539 Bind(&if_isunicode); | 1554 Bind(&if_isunicode); |
1540 { | 1555 { |
1541 Node* const string_length = LoadStringLength(string); | 1556 Node* const string_length = LoadStringLength(string); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1711 Variable var_length_; | 1726 Variable var_length_; |
1712 Variable var_capacity_; | 1727 Variable var_capacity_; |
1713 }; | 1728 }; |
1714 | 1729 |
1715 } // namespace | 1730 } // namespace |
1716 | 1731 |
1717 void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, | 1732 void RegExpBuiltinsAssembler::RegExpPrototypeMatchBody(Node* const context, |
1718 Node* const regexp, | 1733 Node* const regexp, |
1719 Node* const string, | 1734 Node* const string, |
1720 const bool is_fastpath) { | 1735 const bool is_fastpath) { |
1736 CSA_ASSERT(this, IsString(string)); | |
1737 if (is_fastpath) { | |
1738 CSA_ASSERT(this, IsFastRegExp(context, regexp)); | |
Camillo Bruni
2017/04/06 10:59:27
nit: oneline statement would be fine here.
if (...
jgruber
2017/04/06 14:54:23
Done.
| |
1739 } | |
1740 | |
1721 Node* const null = NullConstant(); | 1741 Node* const null = NullConstant(); |
1722 Node* const int_zero = IntPtrConstant(0); | 1742 Node* const int_zero = IntPtrConstant(0); |
1723 Node* const smi_zero = SmiConstant(Smi::kZero); | 1743 Node* const smi_zero = SmiConstant(Smi::kZero); |
1724 | 1744 |
1725 Node* const is_global = | 1745 Node* const is_global = |
1726 FlagGetter(context, regexp, JSRegExp::kGlobal, is_fastpath); | 1746 FlagGetter(context, regexp, JSRegExp::kGlobal, is_fastpath); |
1727 | 1747 |
1728 Label if_isglobal(this), if_isnotglobal(this); | 1748 Label if_isglobal(this), if_isnotglobal(this); |
1729 Branch(is_global, &if_isglobal, &if_isnotglobal); | 1749 Branch(is_global, &if_isglobal, &if_isnotglobal); |
1730 | 1750 |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1885 | 1905 |
1886 Bind(&fast_path); | 1906 Bind(&fast_path); |
1887 RegExpPrototypeMatchBody(context, receiver, string, true); | 1907 RegExpPrototypeMatchBody(context, receiver, string, true); |
1888 | 1908 |
1889 Bind(&slow_path); | 1909 Bind(&slow_path); |
1890 RegExpPrototypeMatchBody(context, receiver, string, false); | 1910 RegExpPrototypeMatchBody(context, receiver, string, false); |
1891 } | 1911 } |
1892 | 1912 |
1893 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( | 1913 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( |
1894 Node* const context, Node* const regexp, Node* const string) { | 1914 Node* const context, Node* const regexp, Node* const string) { |
1915 CSA_ASSERT(this, IsFastRegExp(context, regexp)); | |
1916 CSA_ASSERT(this, IsString(string)); | |
1917 | |
1895 // Grab the initial value of last index. | 1918 // Grab the initial value of last index. |
1896 Node* const previous_last_index = FastLoadLastIndex(regexp); | 1919 Node* const previous_last_index = FastLoadLastIndex(regexp); |
1897 | 1920 |
1898 // Ensure last index is 0. | 1921 // Ensure last index is 0. |
1899 FastStoreLastIndex(regexp, SmiConstant(Smi::kZero)); | 1922 FastStoreLastIndex(regexp, SmiConstant(Smi::kZero)); |
1900 | 1923 |
1901 // Call exec. | 1924 // Call exec. |
1902 Label if_didnotmatch(this); | 1925 Label if_didnotmatch(this); |
1903 Node* const match_indices = RegExpPrototypeExecBodyWithoutResult( | 1926 Node* const match_indices = RegExpPrototypeExecBodyWithoutResult( |
1904 context, regexp, string, &if_didnotmatch, true); | 1927 context, regexp, string, &if_didnotmatch, true); |
(...skipping 12 matching lines...) Expand all Loading... | |
1917 Bind(&if_didnotmatch); | 1940 Bind(&if_didnotmatch); |
1918 { | 1941 { |
1919 // Reset last index and return -1. | 1942 // Reset last index and return -1. |
1920 FastStoreLastIndex(regexp, previous_last_index); | 1943 FastStoreLastIndex(regexp, previous_last_index); |
1921 Return(SmiConstant(-1)); | 1944 Return(SmiConstant(-1)); |
1922 } | 1945 } |
1923 } | 1946 } |
1924 | 1947 |
1925 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodySlow( | 1948 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodySlow( |
1926 Node* const context, Node* const regexp, Node* const string) { | 1949 Node* const context, Node* const regexp, Node* const string) { |
1950 CSA_ASSERT(this, IsJSReceiver(regexp)); | |
1951 CSA_ASSERT(this, IsString(string)); | |
1952 | |
1927 Isolate* const isolate = this->isolate(); | 1953 Isolate* const isolate = this->isolate(); |
1928 | 1954 |
1929 Node* const smi_zero = SmiConstant(Smi::kZero); | 1955 Node* const smi_zero = SmiConstant(Smi::kZero); |
1930 | 1956 |
1931 // Grab the initial value of last index. | 1957 // Grab the initial value of last index. |
1932 Node* const previous_last_index = SlowLoadLastIndex(context, regexp); | 1958 Node* const previous_last_index = SlowLoadLastIndex(context, regexp); |
1933 | 1959 |
1934 // Ensure last index is 0. | 1960 // Ensure last index is 0. |
1935 { | 1961 { |
1936 Label next(this); | 1962 Label next(this); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2011 Bind(&slow_path); | 2037 Bind(&slow_path); |
2012 RegExpPrototypeSearchBodySlow(context, receiver, string); | 2038 RegExpPrototypeSearchBodySlow(context, receiver, string); |
2013 } | 2039 } |
2014 | 2040 |
2015 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp, | 2041 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp, |
2016 // {string} is a String, and {limit} is a Smi. | 2042 // {string} is a String, and {limit} is a Smi. |
2017 void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, | 2043 void RegExpBuiltinsAssembler::RegExpPrototypeSplitBody(Node* const context, |
2018 Node* const regexp, | 2044 Node* const regexp, |
2019 Node* const string, | 2045 Node* const string, |
2020 Node* const limit) { | 2046 Node* const limit) { |
2047 CSA_ASSERT(this, IsFastRegExp(context, regexp)); | |
2048 CSA_ASSERT(this, TaggedIsSmi(limit)); | |
2049 CSA_ASSERT(this, IsString(string)); | |
2050 | |
2021 Node* const null = NullConstant(); | 2051 Node* const null = NullConstant(); |
2022 Node* const smi_zero = SmiConstant(0); | 2052 Node* const smi_zero = SmiConstant(0); |
2023 Node* const int_zero = IntPtrConstant(0); | 2053 Node* const int_zero = IntPtrConstant(0); |
2024 Node* const int_limit = SmiUntag(limit); | 2054 Node* const int_limit = SmiUntag(limit); |
2025 | 2055 |
2026 const ElementsKind kind = FAST_ELEMENTS; | 2056 const ElementsKind kind = FAST_ELEMENTS; |
2027 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; | 2057 const ParameterMode mode = CodeStubAssembler::INTPTR_PARAMETERS; |
2028 | 2058 |
2029 Node* const allocation_site = nullptr; | 2059 Node* const allocation_site = nullptr; |
2030 Node* const native_context = LoadNativeContext(context); | 2060 Node* const native_context = LoadNativeContext(context); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2091 &var_next_search_from}; | 2121 &var_next_search_from}; |
2092 const int vars_count = sizeof(vars) / sizeof(vars[0]); | 2122 const int vars_count = sizeof(vars) / sizeof(vars[0]); |
2093 Label loop(this, vars_count, vars), push_suffix_and_out(this), out(this); | 2123 Label loop(this, vars_count, vars), push_suffix_and_out(this), out(this); |
2094 Goto(&loop); | 2124 Goto(&loop); |
2095 | 2125 |
2096 Bind(&loop); | 2126 Bind(&loop); |
2097 { | 2127 { |
2098 Node* const next_search_from = var_next_search_from.value(); | 2128 Node* const next_search_from = var_next_search_from.value(); |
2099 Node* const last_matched_until = var_last_matched_until.value(); | 2129 Node* const last_matched_until = var_last_matched_until.value(); |
2100 | 2130 |
2131 CSA_ASSERT(this, TaggedIsSmi(next_search_from)); | |
2132 CSA_ASSERT(this, TaggedIsSmi(last_matched_until)); | |
2133 | |
2101 // We're done if we've reached the end of the string. | 2134 // We're done if we've reached the end of the string. |
2102 { | 2135 { |
2103 Label next(this); | 2136 Label next(this); |
2104 Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out, | 2137 Branch(SmiEqual(next_search_from, string_length), &push_suffix_and_out, |
2105 &next); | 2138 &next); |
2106 Bind(&next); | 2139 Bind(&next); |
2107 } | 2140 } |
2108 | 2141 |
2109 // Search for the given {regexp}. | 2142 // Search for the given {regexp}. |
2110 | 2143 |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2254 } | 2287 } |
2255 } | 2288 } |
2256 | 2289 |
2257 // Helper that skips a few initial checks. | 2290 // Helper that skips a few initial checks. |
2258 TF_BUILTIN(RegExpSplit, RegExpBuiltinsAssembler) { | 2291 TF_BUILTIN(RegExpSplit, RegExpBuiltinsAssembler) { |
2259 Node* const regexp = Parameter(Descriptor::kReceiver); | 2292 Node* const regexp = Parameter(Descriptor::kReceiver); |
2260 Node* const string = Parameter(Descriptor::kString); | 2293 Node* const string = Parameter(Descriptor::kString); |
2261 Node* const maybe_limit = Parameter(Descriptor::kLimit); | 2294 Node* const maybe_limit = Parameter(Descriptor::kLimit); |
2262 Node* const context = Parameter(Descriptor::kContext); | 2295 Node* const context = Parameter(Descriptor::kContext); |
2263 | 2296 |
2264 CSA_ASSERT(this, IsFastRegExp(context, regexp, LoadMap(regexp))); | 2297 CSA_ASSERT(this, IsFastRegExp(context, regexp)); |
2265 CSA_ASSERT(this, IsString(string)); | 2298 CSA_ASSERT(this, IsString(string)); |
2266 | 2299 |
2267 // TODO(jgruber): Even if map checks send us to the fast path, we still need | 2300 // 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 | 2301 // to verify the constructor property and jump to the slow path if it has |
2269 // been changed. | 2302 // been changed. |
2270 | 2303 |
2271 // Convert {maybe_limit} to a uint32, capping at the maximal smi value. | 2304 // Convert {maybe_limit} to a uint32, capping at the maximal smi value. |
2272 Variable var_limit(this, MachineRepresentation::kTagged); | 2305 Variable var_limit(this, MachineRepresentation::kTagged); |
2273 Label if_limitissmimax(this), limit_done(this); | 2306 Label if_limitissmimax(this), limit_done(this); |
2274 | 2307 |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2324 Bind(&runtime); | 2357 Bind(&runtime); |
2325 Return(CallRuntime(Runtime::kRegExpSplit, context, receiver, string, | 2358 Return(CallRuntime(Runtime::kRegExpSplit, context, receiver, string, |
2326 maybe_limit)); | 2359 maybe_limit)); |
2327 } | 2360 } |
2328 | 2361 |
2329 Node* RegExpBuiltinsAssembler::ReplaceGlobalCallableFastPath( | 2362 Node* RegExpBuiltinsAssembler::ReplaceGlobalCallableFastPath( |
2330 Node* context, Node* regexp, Node* string, Node* replace_callable) { | 2363 Node* context, Node* regexp, Node* string, Node* replace_callable) { |
2331 // The fast path is reached only if {receiver} is a global unmodified | 2364 // The fast path is reached only if {receiver} is a global unmodified |
2332 // JSRegExp instance and {replace_callable} is callable. | 2365 // JSRegExp instance and {replace_callable} is callable. |
2333 | 2366 |
2367 CSA_ASSERT(this, IsFastRegExp(context, regexp)); | |
2368 CSA_ASSERT(this, IsCallable(replace_callable)); | |
2369 CSA_ASSERT(this, IsString(string)); | |
2370 | |
2334 Isolate* const isolate = this->isolate(); | 2371 Isolate* const isolate = this->isolate(); |
2335 | 2372 |
2336 Node* const null = NullConstant(); | 2373 Node* const null = NullConstant(); |
2337 Node* const undefined = UndefinedConstant(); | 2374 Node* const undefined = UndefinedConstant(); |
2338 Node* const int_zero = IntPtrConstant(0); | 2375 Node* const int_zero = IntPtrConstant(0); |
2339 Node* const int_one = IntPtrConstant(1); | 2376 Node* const int_one = IntPtrConstant(1); |
2340 Node* const smi_zero = SmiConstant(Smi::kZero); | 2377 Node* const smi_zero = SmiConstant(Smi::kZero); |
2341 | 2378 |
2342 Node* const native_context = LoadNativeContext(context); | 2379 Node* const native_context = LoadNativeContext(context); |
2343 | 2380 |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2538 Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( | 2575 Node* RegExpBuiltinsAssembler::ReplaceSimpleStringFastPath( |
2539 Node* context, Node* regexp, Node* string, Node* replace_string) { | 2576 Node* context, Node* regexp, Node* string, Node* replace_string) { |
2540 // The fast path is reached only if {receiver} is an unmodified | 2577 // The fast path is reached only if {receiver} is an unmodified |
2541 // JSRegExp instance, {replace_value} is non-callable, and | 2578 // JSRegExp instance, {replace_value} is non-callable, and |
2542 // ToString({replace_value}) does not contain '$', i.e. we're doing a simple | 2579 // ToString({replace_value}) does not contain '$', i.e. we're doing a simple |
2543 // string replacement. | 2580 // string replacement. |
2544 | 2581 |
2545 Node* const int_zero = IntPtrConstant(0); | 2582 Node* const int_zero = IntPtrConstant(0); |
2546 Node* const smi_zero = SmiConstant(Smi::kZero); | 2583 Node* const smi_zero = SmiConstant(Smi::kZero); |
2547 | 2584 |
2585 CSA_ASSERT(this, IsFastRegExp(context, regexp)); | |
2586 CSA_ASSERT(this, IsString(replace_string)); | |
2587 CSA_ASSERT(this, IsString(string)); | |
2588 | |
2548 Label out(this); | 2589 Label out(this); |
2549 Variable var_result(this, MachineRepresentation::kTagged); | 2590 Variable var_result(this, MachineRepresentation::kTagged); |
2550 | 2591 |
2551 // Load the last match info. | 2592 // Load the last match info. |
2552 Node* const native_context = LoadNativeContext(context); | 2593 Node* const native_context = LoadNativeContext(context); |
2553 Node* const last_match_info = | 2594 Node* const last_match_info = |
2554 LoadContextElement(native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); | 2595 LoadContextElement(native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX); |
2555 | 2596 |
2556 // Is {regexp} global? | 2597 // Is {regexp} global? |
2557 Label if_isglobal(this), if_isnonglobal(this); | 2598 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(); | 2675 return var_result.value(); |
2635 } | 2676 } |
2636 | 2677 |
2637 // Helper that skips a few initial checks. | 2678 // Helper that skips a few initial checks. |
2638 TF_BUILTIN(RegExpReplace, RegExpBuiltinsAssembler) { | 2679 TF_BUILTIN(RegExpReplace, RegExpBuiltinsAssembler) { |
2639 Node* const regexp = Parameter(Descriptor::kReceiver); | 2680 Node* const regexp = Parameter(Descriptor::kReceiver); |
2640 Node* const string = Parameter(Descriptor::kString); | 2681 Node* const string = Parameter(Descriptor::kString); |
2641 Node* const replace_value = Parameter(Descriptor::kReplaceValue); | 2682 Node* const replace_value = Parameter(Descriptor::kReplaceValue); |
2642 Node* const context = Parameter(Descriptor::kContext); | 2683 Node* const context = Parameter(Descriptor::kContext); |
2643 | 2684 |
2644 CSA_ASSERT(this, IsFastRegExp(context, regexp, LoadMap(regexp))); | 2685 CSA_ASSERT(this, IsFastRegExp(context, regexp)); |
2645 CSA_ASSERT(this, IsString(string)); | 2686 CSA_ASSERT(this, IsString(string)); |
2646 | 2687 |
2647 Label checkreplacestring(this), if_iscallable(this), | 2688 Label checkreplacestring(this), if_iscallable(this), |
2648 runtime(this, Label::kDeferred); | 2689 runtime(this, Label::kDeferred); |
2649 | 2690 |
2650 // 2. Is {replace_value} callable? | 2691 // 2. Is {replace_value} callable? |
2651 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); | 2692 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); |
2652 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, | 2693 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, |
2653 &checkreplacestring); | 2694 &checkreplacestring); |
2654 | 2695 |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2742 } | 2783 } |
2743 | 2784 |
2744 // Simple string matching functionality for internal use which does not modify | 2785 // Simple string matching functionality for internal use which does not modify |
2745 // the last match info. | 2786 // the last match info. |
2746 TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) { | 2787 TF_BUILTIN(RegExpInternalMatch, RegExpBuiltinsAssembler) { |
2747 Node* const regexp = Parameter(Descriptor::kRegExp); | 2788 Node* const regexp = Parameter(Descriptor::kRegExp); |
2748 Node* const string = Parameter(Descriptor::kString); | 2789 Node* const string = Parameter(Descriptor::kString); |
2749 Node* const context = Parameter(Descriptor::kContext); | 2790 Node* const context = Parameter(Descriptor::kContext); |
2750 | 2791 |
2751 Node* const null = NullConstant(); | 2792 Node* const null = NullConstant(); |
2752 Node* const smi_zero = SmiConstant(Smi::FromInt(0)); | 2793 Node* const smi_zero = SmiConstant(0); |
2794 | |
2795 CSA_ASSERT(this, HasInstanceType(regexp, JS_REGEXP_TYPE)); | |
2796 CSA_ASSERT(this, IsString(string)); | |
2753 | 2797 |
2754 Node* const native_context = LoadNativeContext(context); | 2798 Node* const native_context = LoadNativeContext(context); |
2755 Node* const internal_match_info = LoadContextElement( | 2799 Node* const internal_match_info = LoadContextElement( |
2756 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); | 2800 native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX); |
2757 | 2801 |
2758 Node* const match_indices = | 2802 Node* const match_indices = |
2759 IrregexpExec(context, regexp, string, smi_zero, internal_match_info); | 2803 IrregexpExec(context, regexp, string, smi_zero, internal_match_info); |
2760 | 2804 |
2761 Label if_matched(this), if_didnotmatch(this); | 2805 Label if_matched(this), if_didnotmatch(this); |
2762 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched); | 2806 Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched); |
2763 | 2807 |
2764 Bind(&if_didnotmatch); | 2808 Bind(&if_didnotmatch); |
2765 Return(null); | 2809 Return(null); |
2766 | 2810 |
2767 Bind(&if_matched); | 2811 Bind(&if_matched); |
2768 { | 2812 { |
2769 Node* result = | 2813 Node* result = |
2770 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2814 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
2771 Return(result); | 2815 Return(result); |
2772 } | 2816 } |
2773 } | 2817 } |
2774 | 2818 |
2775 } // namespace internal | 2819 } // namespace internal |
2776 } // namespace v8 | 2820 } // namespace v8 |
OLD | NEW |