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 715 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
726 GotoIfNot(proto_has_initialmap, if_ismodified); | 726 GotoIfNot(proto_has_initialmap, if_ismodified); |
727 | 727 |
728 // The smi check is required to omit ToLength(lastIndex) calls with possible | 728 // The smi check is required to omit ToLength(lastIndex) calls with possible |
729 // user-code execution on the fast path. | 729 // user-code execution on the fast path. |
730 Node* const last_index = FastLoadLastIndex(object); | 730 Node* const last_index = FastLoadLastIndex(object); |
731 Branch(TaggedIsPositiveSmi(last_index), if_isunmodified, if_ismodified); | 731 Branch(TaggedIsPositiveSmi(last_index), if_isunmodified, if_ismodified); |
732 } | 732 } |
733 | 733 |
734 Node* RegExpBuiltinsAssembler::IsFastRegExp(Node* const context, | 734 Node* RegExpBuiltinsAssembler::IsFastRegExp(Node* const context, |
735 Node* const object) { | 735 Node* const object) { |
736 return IsFastRegExp(context, object, LoadMap(object)); | |
737 } | |
738 | |
739 Node* RegExpBuiltinsAssembler::IsFastRegExp(Node* const context, | |
740 Node* const object, | |
741 Node* const map) { | |
742 Label yup(this), nope(this), out(this); | 736 Label yup(this), nope(this), out(this); |
743 VARIABLE(var_result, MachineRepresentation::kWord32); | 737 VARIABLE(var_result, MachineRepresentation::kWord32); |
744 | 738 |
745 BranchIfFastRegExp(context, object, map, &yup, &nope); | 739 BranchIfFastRegExp(context, object, LoadMap(object), &yup, &nope); |
746 | 740 |
747 BIND(&yup); | 741 BIND(&yup); |
748 var_result.Bind(Int32Constant(1)); | 742 var_result.Bind(Int32Constant(1)); |
749 Goto(&out); | 743 Goto(&out); |
750 | 744 |
751 BIND(&nope); | 745 BIND(&nope); |
752 var_result.Bind(Int32Constant(0)); | 746 var_result.Bind(Int32Constant(0)); |
753 Goto(&out); | 747 Goto(&out); |
754 | 748 |
755 BIND(&out); | 749 BIND(&out); |
(...skipping 21 matching lines...) Expand all Loading... |
777 } | 771 } |
778 | 772 |
779 // ES#sec-regexp.prototype.exec | 773 // ES#sec-regexp.prototype.exec |
780 // RegExp.prototype.exec ( string ) | 774 // RegExp.prototype.exec ( string ) |
781 TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) { | 775 TF_BUILTIN(RegExpPrototypeExec, RegExpBuiltinsAssembler) { |
782 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); | 776 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); |
783 Node* const maybe_string = Parameter(Descriptor::kString); | 777 Node* const maybe_string = Parameter(Descriptor::kString); |
784 Node* const context = Parameter(Descriptor::kContext); | 778 Node* const context = Parameter(Descriptor::kContext); |
785 | 779 |
786 // Ensure {maybe_receiver} is a JSRegExp. | 780 // Ensure {maybe_receiver} is a JSRegExp. |
787 Node* const regexp_map = ThrowIfNotInstanceType( | 781 ThrowIfNotInstanceType(context, maybe_receiver, JS_REGEXP_TYPE, |
788 context, maybe_receiver, JS_REGEXP_TYPE, "RegExp.prototype.exec"); | 782 "RegExp.prototype.exec"); |
789 Node* const receiver = maybe_receiver; | 783 Node* const receiver = maybe_receiver; |
790 | 784 |
791 // Convert {maybe_string} to a String. | 785 // Convert {maybe_string} to a String. |
792 Node* const string = ToString(context, maybe_string); | 786 Node* const string = ToString(context, maybe_string); |
793 | 787 |
794 Label if_isfastpath(this), if_isslowpath(this); | 788 Label if_isfastpath(this), if_isslowpath(this); |
795 Branch(IsFastRegExpNoPrototype(context, receiver, regexp_map), &if_isfastpath, | 789 Branch(IsFastRegExpNoPrototype(context, receiver, LoadMap(receiver)), |
796 &if_isslowpath); | 790 &if_isfastpath, &if_isslowpath); |
797 | 791 |
798 BIND(&if_isfastpath); | 792 BIND(&if_isfastpath); |
799 { | 793 { |
800 Node* const result = | 794 Node* const result = |
801 RegExpPrototypeExecBody(context, receiver, string, true); | 795 RegExpPrototypeExecBody(context, receiver, string, true); |
802 Return(result); | 796 Return(result); |
803 } | 797 } |
804 | 798 |
805 BIND(&if_isslowpath); | 799 BIND(&if_isslowpath); |
806 { | 800 { |
(...skipping 684 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1491 } | 1485 } |
1492 | 1486 |
1493 // ES#sec-regexp.prototype.test | 1487 // ES#sec-regexp.prototype.test |
1494 // RegExp.prototype.test ( S ) | 1488 // RegExp.prototype.test ( S ) |
1495 TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) { | 1489 TF_BUILTIN(RegExpPrototypeTest, RegExpBuiltinsAssembler) { |
1496 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); | 1490 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); |
1497 Node* const maybe_string = Parameter(Descriptor::kString); | 1491 Node* const maybe_string = Parameter(Descriptor::kString); |
1498 Node* const context = Parameter(Descriptor::kContext); | 1492 Node* const context = Parameter(Descriptor::kContext); |
1499 | 1493 |
1500 // Ensure {maybe_receiver} is a JSReceiver. | 1494 // Ensure {maybe_receiver} is a JSReceiver. |
1501 Node* const map = ThrowIfNotJSReceiver( | 1495 ThrowIfNotJSReceiver(context, maybe_receiver, |
1502 context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, | 1496 MessageTemplate::kIncompatibleMethodReceiver, |
1503 "RegExp.prototype.test"); | 1497 "RegExp.prototype.test"); |
1504 Node* const receiver = maybe_receiver; | 1498 Node* const receiver = maybe_receiver; |
1505 | 1499 |
1506 // Convert {maybe_string} to a String. | 1500 // Convert {maybe_string} to a String. |
1507 Node* const string = ToString(context, maybe_string); | 1501 Node* const string = ToString(context, maybe_string); |
1508 | 1502 |
1509 Label fast_path(this), slow_path(this); | 1503 Label fast_path(this), slow_path(this); |
1510 BranchIfFastRegExp(context, receiver, map, &fast_path, &slow_path); | 1504 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &fast_path, |
| 1505 &slow_path); |
1511 | 1506 |
1512 BIND(&fast_path); | 1507 BIND(&fast_path); |
1513 { | 1508 { |
1514 Label if_didnotmatch(this); | 1509 Label if_didnotmatch(this); |
1515 RegExpPrototypeExecBodyWithoutResult(context, receiver, string, | 1510 RegExpPrototypeExecBodyWithoutResult(context, receiver, string, |
1516 &if_didnotmatch, true); | 1511 &if_didnotmatch, true); |
1517 Return(TrueConstant()); | 1512 Return(TrueConstant()); |
1518 | 1513 |
1519 BIND(&if_didnotmatch); | 1514 BIND(&if_didnotmatch); |
1520 Return(FalseConstant()); | 1515 Return(FalseConstant()); |
(...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1901 } | 1896 } |
1902 | 1897 |
1903 // ES#sec-regexp.prototype-@@match | 1898 // ES#sec-regexp.prototype-@@match |
1904 // RegExp.prototype [ @@match ] ( string ) | 1899 // RegExp.prototype [ @@match ] ( string ) |
1905 TF_BUILTIN(RegExpPrototypeMatch, RegExpBuiltinsAssembler) { | 1900 TF_BUILTIN(RegExpPrototypeMatch, RegExpBuiltinsAssembler) { |
1906 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); | 1901 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); |
1907 Node* const maybe_string = Parameter(Descriptor::kString); | 1902 Node* const maybe_string = Parameter(Descriptor::kString); |
1908 Node* const context = Parameter(Descriptor::kContext); | 1903 Node* const context = Parameter(Descriptor::kContext); |
1909 | 1904 |
1910 // Ensure {maybe_receiver} is a JSReceiver. | 1905 // Ensure {maybe_receiver} is a JSReceiver. |
1911 Node* const map = ThrowIfNotJSReceiver( | 1906 ThrowIfNotJSReceiver(context, maybe_receiver, |
1912 context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, | 1907 MessageTemplate::kIncompatibleMethodReceiver, |
1913 "RegExp.prototype.@@match"); | 1908 "RegExp.prototype.@@match"); |
1914 Node* const receiver = maybe_receiver; | 1909 Node* const receiver = maybe_receiver; |
1915 | 1910 |
1916 // Convert {maybe_string} to a String. | 1911 // Convert {maybe_string} to a String. |
1917 Node* const string = ToString(context, maybe_string); | 1912 Node* const string = ToString(context, maybe_string); |
1918 | 1913 |
1919 Label fast_path(this), slow_path(this); | 1914 Label fast_path(this), slow_path(this); |
1920 BranchIfFastRegExp(context, receiver, map, &fast_path, &slow_path); | 1915 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &fast_path, |
| 1916 &slow_path); |
1921 | 1917 |
1922 BIND(&fast_path); | 1918 BIND(&fast_path); |
1923 RegExpPrototypeMatchBody(context, receiver, string, true); | 1919 RegExpPrototypeMatchBody(context, receiver, string, true); |
1924 | 1920 |
1925 BIND(&slow_path); | 1921 BIND(&slow_path); |
1926 RegExpPrototypeMatchBody(context, receiver, string, false); | 1922 RegExpPrototypeMatchBody(context, receiver, string, false); |
1927 } | 1923 } |
1928 | 1924 |
1929 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( | 1925 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( |
1930 Node* const context, Node* const regexp, Node* const string) { | 1926 Node* const context, Node* const regexp, Node* const string) { |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2029 } | 2025 } |
2030 | 2026 |
2031 // ES#sec-regexp.prototype-@@search | 2027 // ES#sec-regexp.prototype-@@search |
2032 // RegExp.prototype [ @@search ] ( string ) | 2028 // RegExp.prototype [ @@search ] ( string ) |
2033 TF_BUILTIN(RegExpPrototypeSearch, RegExpBuiltinsAssembler) { | 2029 TF_BUILTIN(RegExpPrototypeSearch, RegExpBuiltinsAssembler) { |
2034 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); | 2030 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); |
2035 Node* const maybe_string = Parameter(Descriptor::kString); | 2031 Node* const maybe_string = Parameter(Descriptor::kString); |
2036 Node* const context = Parameter(Descriptor::kContext); | 2032 Node* const context = Parameter(Descriptor::kContext); |
2037 | 2033 |
2038 // Ensure {maybe_receiver} is a JSReceiver. | 2034 // Ensure {maybe_receiver} is a JSReceiver. |
2039 Node* const map = ThrowIfNotJSReceiver( | 2035 ThrowIfNotJSReceiver(context, maybe_receiver, |
2040 context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, | 2036 MessageTemplate::kIncompatibleMethodReceiver, |
2041 "RegExp.prototype.@@search"); | 2037 "RegExp.prototype.@@search"); |
2042 Node* const receiver = maybe_receiver; | 2038 Node* const receiver = maybe_receiver; |
2043 | 2039 |
2044 // Convert {maybe_string} to a String. | 2040 // Convert {maybe_string} to a String. |
2045 Node* const string = ToString(context, maybe_string); | 2041 Node* const string = ToString(context, maybe_string); |
2046 | 2042 |
2047 Label fast_path(this), slow_path(this); | 2043 Label fast_path(this), slow_path(this); |
2048 BranchIfFastRegExp(context, receiver, map, &fast_path, &slow_path); | 2044 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &fast_path, |
| 2045 &slow_path); |
2049 | 2046 |
2050 BIND(&fast_path); | 2047 BIND(&fast_path); |
2051 RegExpPrototypeSearchBodyFast(context, receiver, string); | 2048 RegExpPrototypeSearchBodyFast(context, receiver, string); |
2052 | 2049 |
2053 BIND(&slow_path); | 2050 BIND(&slow_path); |
2054 RegExpPrototypeSearchBodySlow(context, receiver, string); | 2051 RegExpPrototypeSearchBodySlow(context, receiver, string); |
2055 } | 2052 } |
2056 | 2053 |
2057 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp, | 2054 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp, |
2058 // {string} is a String, and {limit} is a Smi. | 2055 // {string} is a String, and {limit} is a Smi. |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2366 | 2363 |
2367 // ES#sec-regexp.prototype-@@split | 2364 // ES#sec-regexp.prototype-@@split |
2368 // RegExp.prototype [ @@split ] ( string, limit ) | 2365 // RegExp.prototype [ @@split ] ( string, limit ) |
2369 TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { | 2366 TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { |
2370 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); | 2367 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); |
2371 Node* const maybe_string = Parameter(Descriptor::kString); | 2368 Node* const maybe_string = Parameter(Descriptor::kString); |
2372 Node* const maybe_limit = Parameter(Descriptor::kLimit); | 2369 Node* const maybe_limit = Parameter(Descriptor::kLimit); |
2373 Node* const context = Parameter(Descriptor::kContext); | 2370 Node* const context = Parameter(Descriptor::kContext); |
2374 | 2371 |
2375 // Ensure {maybe_receiver} is a JSReceiver. | 2372 // Ensure {maybe_receiver} is a JSReceiver. |
2376 Node* const map = ThrowIfNotJSReceiver( | 2373 ThrowIfNotJSReceiver(context, maybe_receiver, |
2377 context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, | 2374 MessageTemplate::kIncompatibleMethodReceiver, |
2378 "RegExp.prototype.@@split"); | 2375 "RegExp.prototype.@@split"); |
2379 Node* const receiver = maybe_receiver; | 2376 Node* const receiver = maybe_receiver; |
2380 | 2377 |
2381 // Convert {maybe_string} to a String. | 2378 // Convert {maybe_string} to a String. |
2382 Node* const string = ToString(context, maybe_string); | 2379 Node* const string = ToString(context, maybe_string); |
2383 | 2380 |
2384 Label stub(this), runtime(this, Label::kDeferred); | 2381 Label stub(this), runtime(this, Label::kDeferred); |
2385 BranchIfFastRegExp(context, receiver, map, &stub, &runtime); | 2382 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &stub, &runtime); |
2386 | 2383 |
2387 BIND(&stub); | 2384 BIND(&stub); |
2388 Return(CallBuiltin(Builtins::kRegExpSplit, context, receiver, string, | 2385 Return(CallBuiltin(Builtins::kRegExpSplit, context, receiver, string, |
2389 maybe_limit)); | 2386 maybe_limit)); |
2390 | 2387 |
2391 BIND(&runtime); | 2388 BIND(&runtime); |
2392 Return(CallRuntime(Runtime::kRegExpSplit, context, receiver, string, | 2389 Return(CallRuntime(Runtime::kRegExpSplit, context, receiver, string, |
2393 maybe_limit)); | 2390 maybe_limit)); |
2394 } | 2391 } |
2395 | 2392 |
(...skipping 401 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2797 // } | 2794 // } |
2798 // } else { | 2795 // } else { |
2799 // if (replace.contains("$")) { | 2796 // if (replace.contains("$")) { |
2800 // CallRuntime(RegExpReplace) | 2797 // CallRuntime(RegExpReplace) |
2801 // } else { | 2798 // } else { |
2802 // ReplaceSimpleStringFastPath() // Bails to runtime for global regexps. | 2799 // ReplaceSimpleStringFastPath() // Bails to runtime for global regexps. |
2803 // } | 2800 // } |
2804 // } | 2801 // } |
2805 | 2802 |
2806 // Ensure {maybe_receiver} is a JSReceiver. | 2803 // Ensure {maybe_receiver} is a JSReceiver. |
2807 Node* const map = ThrowIfNotJSReceiver( | 2804 ThrowIfNotJSReceiver(context, maybe_receiver, |
2808 context, maybe_receiver, MessageTemplate::kIncompatibleMethodReceiver, | 2805 MessageTemplate::kIncompatibleMethodReceiver, |
2809 "RegExp.prototype.@@replace"); | 2806 "RegExp.prototype.@@replace"); |
2810 Node* const receiver = maybe_receiver; | 2807 Node* const receiver = maybe_receiver; |
2811 | 2808 |
2812 // Convert {maybe_string} to a String. | 2809 // Convert {maybe_string} to a String. |
2813 Node* const string = CallBuiltin(Builtins::kToString, context, maybe_string); | 2810 Node* const string = CallBuiltin(Builtins::kToString, context, maybe_string); |
2814 | 2811 |
2815 // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance? | 2812 // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance? |
2816 Label stub(this), runtime(this, Label::kDeferred); | 2813 Label stub(this), runtime(this, Label::kDeferred); |
2817 BranchIfFastRegExp(context, receiver, map, &stub, &runtime); | 2814 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &stub, &runtime); |
2818 | 2815 |
2819 BIND(&stub); | 2816 BIND(&stub); |
2820 Return(CallBuiltin(Builtins::kRegExpReplace, context, receiver, string, | 2817 Return(CallBuiltin(Builtins::kRegExpReplace, context, receiver, string, |
2821 replace_value)); | 2818 replace_value)); |
2822 | 2819 |
2823 BIND(&runtime); | 2820 BIND(&runtime); |
2824 Return(CallRuntime(Runtime::kRegExpReplace, context, receiver, string, | 2821 Return(CallRuntime(Runtime::kRegExpReplace, context, receiver, string, |
2825 replace_value)); | 2822 replace_value)); |
2826 } | 2823 } |
2827 | 2824 |
(...skipping 26 matching lines...) Expand all Loading... |
2854 BIND(&if_matched); | 2851 BIND(&if_matched); |
2855 { | 2852 { |
2856 Node* result = | 2853 Node* result = |
2857 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2854 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
2858 Return(result); | 2855 Return(result); |
2859 } | 2856 } |
2860 } | 2857 } |
2861 | 2858 |
2862 } // namespace internal | 2859 } // namespace internal |
2863 } // namespace v8 | 2860 } // namespace v8 |
OLD | NEW |