Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(32)

Side by Side Diff: src/builtins/builtins-regexp-gen.cc

Issue 2811063003: [regexp] Address various minor nits (Closed)
Patch Set: Rebase Created 3 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/builtins/builtins-regexp-gen.h ('k') | src/code-stub-assembler.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
93 93
94 StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER); 94 StoreFixedArrayElement(result_elements, 0, first, SKIP_WRITE_BARRIER);
95 95
96 // If no captures exist we can skip named capture handling as well. 96 // If no captures exist we can skip named capture handling as well.
97 GotoIf(SmiEqual(num_results, SmiConstant(1)), &out); 97 GotoIf(SmiEqual(num_results, SmiConstant(1)), &out);
98 98
99 // Store all remaining captures. 99 // Store all remaining captures.
100 Node* const limit = IntPtrAdd( 100 Node* const limit = IntPtrAdd(
101 IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices); 101 IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex), num_indices);
102 102
103 Variable var_from_cursor( 103 VARIABLE(var_from_cursor, MachineType::PointerRepresentation(),
104 this, MachineType::PointerRepresentation(), 104 IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2));
105 IntPtrConstant(RegExpMatchInfo::kFirstCaptureIndex + 2));
106 VARIABLE(var_to_cursor, MachineType::PointerRepresentation(), 105 VARIABLE(var_to_cursor, MachineType::PointerRepresentation(),
107 IntPtrConstant(1)); 106 IntPtrConstant(1));
108 107
109 Variable* vars[] = {&var_from_cursor, &var_to_cursor}; 108 Variable* vars[] = {&var_from_cursor, &var_to_cursor};
110 Label loop(this, 2, vars); 109 Label loop(this, 2, vars);
111 110
112 Goto(&loop); 111 Goto(&loop);
113 BIND(&loop); 112 BIND(&loop);
114 { 113 {
115 Node* const from_cursor = var_from_cursor.value(); 114 Node* const from_cursor = var_from_cursor.value();
(...skipping 363 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 // match) or a fixed array containing match indices as returned by 478 // match) or a fixed array containing match indices as returned by
480 // RegExpExecStub. 479 // RegExpExecStub.
481 Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult( 480 Node* RegExpBuiltinsAssembler::RegExpPrototypeExecBodyWithoutResult(
482 Node* const context, Node* const regexp, Node* const string, 481 Node* const context, Node* const regexp, Node* const string,
483 Label* if_didnotmatch, const bool is_fastpath) { 482 Label* if_didnotmatch, const bool is_fastpath) {
484 Node* const null = NullConstant(); 483 Node* const null = NullConstant();
485 Node* const int_zero = IntPtrConstant(0); 484 Node* const int_zero = IntPtrConstant(0);
486 Node* const smi_zero = SmiConstant(Smi::kZero); 485 Node* const smi_zero = SmiConstant(Smi::kZero);
487 486
488 if (is_fastpath) { 487 if (is_fastpath) {
489 CSA_ASSERT(this, IsFastRegExpNoPrototype(context, regexp, LoadMap(regexp))); 488 CSA_ASSERT(this, IsFastRegExpNoPrototype(context, regexp));
490 } else { 489 } else {
491 ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE, 490 ThrowIfNotInstanceType(context, regexp, JS_REGEXP_TYPE,
492 "RegExp.prototype.exec"); 491 "RegExp.prototype.exec");
493 } 492 }
494 493
495 CSA_ASSERT(this, IsString(string)); 494 CSA_ASSERT(this, IsString(string));
496 CSA_ASSERT(this, IsJSRegExp(regexp)); 495 CSA_ASSERT(this, IsJSRegExp(regexp));
497 496
498 VARIABLE(var_result, MachineRepresentation::kTagged); 497 VARIABLE(var_result, MachineRepresentation::kTagged);
499 Label out(this); 498 Label out(this);
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 // The smi check is required to omit ToLength(lastIndex) calls with possible 686 // The smi check is required to omit ToLength(lastIndex) calls with possible
688 // user-code execution on the fast path. 687 // user-code execution on the fast path.
689 Node* const last_index = FastLoadLastIndex(object); 688 Node* const last_index = FastLoadLastIndex(object);
690 var_result.Bind(TaggedIsPositiveSmi(last_index)); 689 var_result.Bind(TaggedIsPositiveSmi(last_index));
691 Goto(&out); 690 Goto(&out);
692 691
693 BIND(&out); 692 BIND(&out);
694 return var_result.value(); 693 return var_result.value();
695 } 694 }
696 695
696 Node* RegExpBuiltinsAssembler::IsFastRegExpNoPrototype(Node* const context,
697 Node* const object) {
698 CSA_ASSERT(this, TaggedIsNotSmi(object));
Camillo Bruni 2017/04/11 09:21:13 Probably even: IsJSReceiver(object)
jgruber 2017/04/11 09:57:24 All I want to assert here is that we can load a ma
699 return IsFastRegExpNoPrototype(context, object, LoadMap(object));
700 }
701
697 // RegExp fast path implementations rely on unmodified JSRegExp instances. 702 // RegExp fast path implementations rely on unmodified JSRegExp instances.
698 // We use a fairly coarse granularity for this and simply check whether both 703 // We use a fairly coarse granularity for this and simply check whether both
699 // the regexp itself is unmodified (i.e. its map has not changed), its 704 // the regexp itself is unmodified (i.e. its map has not changed), its
700 // prototype is unmodified, and lastIndex is a non-negative smi. 705 // prototype is unmodified, and lastIndex is a non-negative smi.
701 void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* const context, 706 void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* const context,
702 Node* const object, 707 Node* const object,
703 Node* const map, 708 Node* const map,
704 Label* const if_isunmodified, 709 Label* const if_isunmodified,
705 Label* const if_ismodified) { 710 Label* const if_ismodified) {
706 CSA_ASSERT(this, WordEqual(LoadMap(object), map)); 711 CSA_ASSERT(this, WordEqual(LoadMap(object), map));
(...skipping 17 matching lines...) Expand all
724 WordEqual(proto_map, initial_proto_initial_map); 729 WordEqual(proto_map, initial_proto_initial_map);
725 730
726 GotoIfNot(proto_has_initialmap, if_ismodified); 731 GotoIfNot(proto_has_initialmap, if_ismodified);
727 732
728 // The smi check is required to omit ToLength(lastIndex) calls with possible 733 // The smi check is required to omit ToLength(lastIndex) calls with possible
729 // user-code execution on the fast path. 734 // user-code execution on the fast path.
730 Node* const last_index = FastLoadLastIndex(object); 735 Node* const last_index = FastLoadLastIndex(object);
731 Branch(TaggedIsPositiveSmi(last_index), if_isunmodified, if_ismodified); 736 Branch(TaggedIsPositiveSmi(last_index), if_isunmodified, if_ismodified);
732 } 737 }
733 738
739 void RegExpBuiltinsAssembler::BranchIfFastRegExp(Node* const context,
740 Node* const object,
741 Label* const if_isunmodified,
742 Label* const if_ismodified) {
743 CSA_ASSERT(this, TaggedIsNotSmi(object));
Camillo Bruni 2017/04/11 09:21:13 same here
744 BranchIfFastRegExp(context, object, LoadMap(object), if_isunmodified,
745 if_ismodified);
746 }
747
734 Node* RegExpBuiltinsAssembler::IsFastRegExp(Node* const context, 748 Node* RegExpBuiltinsAssembler::IsFastRegExp(Node* const context,
735 Node* const object) { 749 Node* const object) {
736 Label yup(this), nope(this), out(this); 750 Label yup(this), nope(this), out(this);
737 VARIABLE(var_result, MachineRepresentation::kWord32); 751 VARIABLE(var_result, MachineRepresentation::kWord32);
738 752
739 BranchIfFastRegExp(context, object, LoadMap(object), &yup, &nope); 753 BranchIfFastRegExp(context, object, &yup, &nope);
740 754
741 BIND(&yup); 755 BIND(&yup);
742 var_result.Bind(Int32Constant(1)); 756 var_result.Bind(Int32Constant(1));
743 Goto(&out); 757 Goto(&out);
744 758
745 BIND(&nope); 759 BIND(&nope);
746 var_result.Bind(Int32Constant(0)); 760 var_result.Bind(Int32Constant(0));
747 Goto(&out); 761 Goto(&out);
748 762
749 BIND(&out); 763 BIND(&out);
750 return var_result.value(); 764 return var_result.value();
751 } 765 }
752 766
753 void RegExpBuiltinsAssembler::BranchIfFastRegExpResult(Node* context, Node* map, 767 void RegExpBuiltinsAssembler::BranchIfFastRegExpResult(Node* const context,
768 Node* const object,
754 Label* if_isunmodified, 769 Label* if_isunmodified,
755 Label* if_ismodified) { 770 Label* if_ismodified) {
771 // Could be a Smi.
772 Node* const map = LoadReceiverMap(object);
773
756 Node* const native_context = LoadNativeContext(context); 774 Node* const native_context = LoadNativeContext(context);
757 Node* const initial_regexp_result_map = 775 Node* const initial_regexp_result_map =
758 LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX); 776 LoadContextElement(native_context, Context::REGEXP_RESULT_MAP_INDEX);
759 777
760 Branch(WordEqual(map, initial_regexp_result_map), if_isunmodified, 778 Branch(WordEqual(map, initial_regexp_result_map), if_isunmodified,
761 if_ismodified); 779 if_ismodified);
762 } 780 }
763 781
764 // Slow path stub for RegExpPrototypeExec to decrease code size. 782 // Slow path stub for RegExpPrototypeExec to decrease code size.
765 TF_BUILTIN(RegExpPrototypeExecSlow, RegExpBuiltinsAssembler) { 783 TF_BUILTIN(RegExpPrototypeExecSlow, RegExpBuiltinsAssembler) {
(...skipping 13 matching lines...) Expand all
779 797
780 // Ensure {maybe_receiver} is a JSRegExp. 798 // Ensure {maybe_receiver} is a JSRegExp.
781 ThrowIfNotInstanceType(context, maybe_receiver, JS_REGEXP_TYPE, 799 ThrowIfNotInstanceType(context, maybe_receiver, JS_REGEXP_TYPE,
782 "RegExp.prototype.exec"); 800 "RegExp.prototype.exec");
783 Node* const receiver = maybe_receiver; 801 Node* const receiver = maybe_receiver;
784 802
785 // Convert {maybe_string} to a String. 803 // Convert {maybe_string} to a String.
786 Node* const string = ToString(context, maybe_string); 804 Node* const string = ToString(context, maybe_string);
787 805
788 Label if_isfastpath(this), if_isslowpath(this); 806 Label if_isfastpath(this), if_isslowpath(this);
789 Branch(IsFastRegExpNoPrototype(context, receiver, LoadMap(receiver)), 807 Branch(IsFastRegExpNoPrototype(context, receiver), &if_isfastpath,
790 &if_isfastpath, &if_isslowpath); 808 &if_isslowpath);
791 809
792 BIND(&if_isfastpath); 810 BIND(&if_isfastpath);
793 { 811 {
794 Node* const result = 812 Node* const result =
795 RegExpPrototypeExecBody(context, receiver, string, true); 813 RegExpPrototypeExecBody(context, receiver, string, true);
796 Return(result); 814 Return(result);
797 } 815 }
798 816
799 BIND(&if_isslowpath); 817 BIND(&if_isslowpath);
800 { 818 {
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
883 #undef CASE_FOR_FLAG 901 #undef CASE_FOR_FLAG
884 } 902 }
885 903
886 // Allocate a string of the required length and fill it with the corresponding 904 // Allocate a string of the required length and fill it with the corresponding
887 // char for each set flag. 905 // char for each set flag.
888 906
889 { 907 {
890 Node* const result = AllocateSeqOneByteString(context, var_length.value()); 908 Node* const result = AllocateSeqOneByteString(context, var_length.value());
891 Node* const flags_intptr = var_flags.value(); 909 Node* const flags_intptr = var_flags.value();
892 910
893 Variable var_offset( 911 VARIABLE(var_offset, MachineType::PointerRepresentation(),
894 this, MachineType::PointerRepresentation(), 912 IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
895 IntPtrConstant(SeqOneByteString::kHeaderSize - kHeapObjectTag));
896 913
897 #define CASE_FOR_FLAG(FLAG, CHAR) \ 914 #define CASE_FOR_FLAG(FLAG, CHAR) \
898 do { \ 915 do { \
899 Label next(this); \ 916 Label next(this); \
900 GotoIfNot(IsSetWord(flags_intptr, FLAG), &next); \ 917 GotoIfNot(IsSetWord(flags_intptr, FLAG), &next); \
901 Node* const value = Int32Constant(CHAR); \ 918 Node* const value = Int32Constant(CHAR); \
902 StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \ 919 StoreNoWriteBarrier(MachineRepresentation::kWord8, result, \
903 var_offset.value(), value); \ 920 var_offset.value(), value); \
904 var_offset.Bind(IntPtrAdd(var_offset.value(), int_one)); \ 921 var_offset.Bind(IntPtrAdd(var_offset.value(), int_one)); \
905 Goto(&next); \ 922 Goto(&next); \
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after
1494 // Ensure {maybe_receiver} is a JSReceiver. 1511 // Ensure {maybe_receiver} is a JSReceiver.
1495 ThrowIfNotJSReceiver(context, maybe_receiver, 1512 ThrowIfNotJSReceiver(context, maybe_receiver,
1496 MessageTemplate::kIncompatibleMethodReceiver, 1513 MessageTemplate::kIncompatibleMethodReceiver,
1497 "RegExp.prototype.test"); 1514 "RegExp.prototype.test");
1498 Node* const receiver = maybe_receiver; 1515 Node* const receiver = maybe_receiver;
1499 1516
1500 // Convert {maybe_string} to a String. 1517 // Convert {maybe_string} to a String.
1501 Node* const string = ToString(context, maybe_string); 1518 Node* const string = ToString(context, maybe_string);
1502 1519
1503 Label fast_path(this), slow_path(this); 1520 Label fast_path(this), slow_path(this);
1504 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &fast_path, 1521 BranchIfFastRegExp(context, receiver, &fast_path, &slow_path);
1505 &slow_path);
1506 1522
1507 BIND(&fast_path); 1523 BIND(&fast_path);
1508 { 1524 {
1509 Label if_didnotmatch(this); 1525 Label if_didnotmatch(this);
1510 RegExpPrototypeExecBodyWithoutResult(context, receiver, string, 1526 RegExpPrototypeExecBodyWithoutResult(context, receiver, string,
1511 &if_didnotmatch, true); 1527 &if_didnotmatch, true);
1512 Return(TrueConstant()); 1528 Return(TrueConstant());
1513 1529
1514 BIND(&if_didnotmatch); 1530 BIND(&if_didnotmatch);
1515 Return(FalseConstant()); 1531 Return(FalseConstant());
(...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after
1809 } else { 1825 } else {
1810 DCHECK(!is_fastpath); 1826 DCHECK(!is_fastpath);
1811 Node* const result = RegExpExec(context, regexp, string); 1827 Node* const result = RegExpExec(context, regexp, string);
1812 1828
1813 Label load_match(this); 1829 Label load_match(this);
1814 Branch(WordEqual(result, null), &if_didnotmatch, &load_match); 1830 Branch(WordEqual(result, null), &if_didnotmatch, &load_match);
1815 1831
1816 BIND(&load_match); 1832 BIND(&load_match);
1817 { 1833 {
1818 Label fast_result(this), slow_result(this); 1834 Label fast_result(this), slow_result(this);
1819 BranchIfFastRegExpResult(context, LoadMap(result), &fast_result, 1835 BranchIfFastRegExpResult(context, result, &fast_result, &slow_result);
1820 &slow_result);
1821 1836
1822 BIND(&fast_result); 1837 BIND(&fast_result);
1823 { 1838 {
1824 Node* const result_fixed_array = LoadElements(result); 1839 Node* const result_fixed_array = LoadElements(result);
1825 Node* const match = LoadFixedArrayElement(result_fixed_array, 0); 1840 Node* const match = LoadFixedArrayElement(result_fixed_array, 0);
1826 1841
1827 // The match is guaranteed to be a string on the fast path. 1842 // The match is guaranteed to be a string on the fast path.
1828 CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(match))); 1843 CSA_ASSERT(this, IsStringInstanceType(LoadInstanceType(match)));
1829 1844
1830 var_match.Bind(match); 1845 var_match.Bind(match);
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1905 // Ensure {maybe_receiver} is a JSReceiver. 1920 // Ensure {maybe_receiver} is a JSReceiver.
1906 ThrowIfNotJSReceiver(context, maybe_receiver, 1921 ThrowIfNotJSReceiver(context, maybe_receiver,
1907 MessageTemplate::kIncompatibleMethodReceiver, 1922 MessageTemplate::kIncompatibleMethodReceiver,
1908 "RegExp.prototype.@@match"); 1923 "RegExp.prototype.@@match");
1909 Node* const receiver = maybe_receiver; 1924 Node* const receiver = maybe_receiver;
1910 1925
1911 // Convert {maybe_string} to a String. 1926 // Convert {maybe_string} to a String.
1912 Node* const string = ToString(context, maybe_string); 1927 Node* const string = ToString(context, maybe_string);
1913 1928
1914 Label fast_path(this), slow_path(this); 1929 Label fast_path(this), slow_path(this);
1915 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &fast_path, 1930 BranchIfFastRegExp(context, receiver, &fast_path, &slow_path);
1916 &slow_path);
1917 1931
1918 BIND(&fast_path); 1932 BIND(&fast_path);
1919 RegExpPrototypeMatchBody(context, receiver, string, true); 1933 RegExpPrototypeMatchBody(context, receiver, string, true);
1920 1934
1921 BIND(&slow_path); 1935 BIND(&slow_path);
1922 RegExpPrototypeMatchBody(context, receiver, string, false); 1936 RegExpPrototypeMatchBody(context, receiver, string, false);
1923 } 1937 }
1924 1938
1925 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast( 1939 void RegExpBuiltinsAssembler::RegExpPrototypeSearchBodyFast(
1926 Node* const context, Node* const regexp, Node* const string) { 1940 Node* const context, Node* const regexp, Node* const string) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1999 { 2013 {
2000 Label next(this); 2014 Label next(this);
2001 GotoIfNot(WordEqual(exec_result, NullConstant()), &next); 2015 GotoIfNot(WordEqual(exec_result, NullConstant()), &next);
2002 Return(SmiConstant(-1)); 2016 Return(SmiConstant(-1));
2003 BIND(&next); 2017 BIND(&next);
2004 } 2018 }
2005 2019
2006 // Return the index of the match. 2020 // Return the index of the match.
2007 { 2021 {
2008 Label fast_result(this), slow_result(this, Label::kDeferred); 2022 Label fast_result(this), slow_result(this, Label::kDeferred);
2009 BranchIfFastRegExpResult(context, LoadMap(exec_result), &fast_result, 2023 BranchIfFastRegExpResult(context, exec_result, &fast_result, &slow_result);
2010 &slow_result);
2011 2024
2012 BIND(&fast_result); 2025 BIND(&fast_result);
2013 { 2026 {
2014 Node* const index = 2027 Node* const index =
2015 LoadObjectField(exec_result, JSRegExpResult::kIndexOffset); 2028 LoadObjectField(exec_result, JSRegExpResult::kIndexOffset);
2016 Return(index); 2029 Return(index);
2017 } 2030 }
2018 2031
2019 BIND(&slow_result); 2032 BIND(&slow_result);
2020 { 2033 {
(...skipping 13 matching lines...) Expand all
2034 // Ensure {maybe_receiver} is a JSReceiver. 2047 // Ensure {maybe_receiver} is a JSReceiver.
2035 ThrowIfNotJSReceiver(context, maybe_receiver, 2048 ThrowIfNotJSReceiver(context, maybe_receiver,
2036 MessageTemplate::kIncompatibleMethodReceiver, 2049 MessageTemplate::kIncompatibleMethodReceiver,
2037 "RegExp.prototype.@@search"); 2050 "RegExp.prototype.@@search");
2038 Node* const receiver = maybe_receiver; 2051 Node* const receiver = maybe_receiver;
2039 2052
2040 // Convert {maybe_string} to a String. 2053 // Convert {maybe_string} to a String.
2041 Node* const string = ToString(context, maybe_string); 2054 Node* const string = ToString(context, maybe_string);
2042 2055
2043 Label fast_path(this), slow_path(this); 2056 Label fast_path(this), slow_path(this);
2044 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &fast_path, 2057 BranchIfFastRegExp(context, receiver, &fast_path, &slow_path);
2045 &slow_path);
2046 2058
2047 BIND(&fast_path); 2059 BIND(&fast_path);
2048 RegExpPrototypeSearchBodyFast(context, receiver, string); 2060 RegExpPrototypeSearchBodyFast(context, receiver, string);
2049 2061
2050 BIND(&slow_path); 2062 BIND(&slow_path);
2051 RegExpPrototypeSearchBodySlow(context, receiver, string); 2063 RegExpPrototypeSearchBodySlow(context, receiver, string);
2052 } 2064 }
2053 2065
2054 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp, 2066 // Generates the fast path for @@split. {regexp} is an unmodified JSRegExp,
2055 // {string} is a String, and {limit} is a Smi. 2067 // {string} is a String, and {limit} is a Smi.
(...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after
2321 GotoIf(IsUndefined(maybe_limit), &if_limitissmimax); 2333 GotoIf(IsUndefined(maybe_limit), &if_limitissmimax);
2322 GotoIf(TaggedIsPositiveSmi(maybe_limit), &limit_done); 2334 GotoIf(TaggedIsPositiveSmi(maybe_limit), &limit_done);
2323 2335
2324 Node* const limit = ToUint32(context, maybe_limit); 2336 Node* const limit = ToUint32(context, maybe_limit);
2325 { 2337 {
2326 // ToUint32(limit) could potentially change the shape of the RegExp 2338 // ToUint32(limit) could potentially change the shape of the RegExp
2327 // object. Recheck that we are still on the fast path and bail to runtime 2339 // object. Recheck that we are still on the fast path and bail to runtime
2328 // otherwise. 2340 // otherwise.
2329 { 2341 {
2330 Label next(this); 2342 Label next(this);
2331 BranchIfFastRegExp(context, regexp, LoadMap(regexp), &next, &runtime); 2343 BranchIfFastRegExp(context, regexp, &next, &runtime);
2332 Bind(&next); 2344 BIND(&next);
2333 } 2345 }
2334 2346
2335 GotoIfNot(TaggedIsSmi(limit), &if_limitissmimax); 2347 GotoIfNot(TaggedIsSmi(limit), &if_limitissmimax);
2336 2348
2337 var_limit.Bind(limit); 2349 var_limit.Bind(limit);
2338 Goto(&limit_done); 2350 Goto(&limit_done);
2339 } 2351 }
2340 2352
2341 BIND(&if_limitissmimax); 2353 BIND(&if_limitissmimax);
2342 { 2354 {
2343 // TODO(jgruber): In this case, we can probably avoid generation of limit 2355 // TODO(jgruber): In this case, we can probably avoid generation of limit
2344 // checks in Generate_RegExpPrototypeSplitBody. 2356 // checks in Generate_RegExpPrototypeSplitBody.
2345 var_limit.Bind(SmiConstant(Smi::kMaxValue)); 2357 var_limit.Bind(SmiConstant(Smi::kMaxValue));
2346 Goto(&limit_done); 2358 Goto(&limit_done);
2347 } 2359 }
2348 2360
2349 BIND(&limit_done); 2361 BIND(&limit_done);
2350 { 2362 {
2351 Node* const limit = var_limit.value(); 2363 Node* const limit = var_limit.value();
2352 RegExpPrototypeSplitBody(context, regexp, string, limit); 2364 RegExpPrototypeSplitBody(context, regexp, string, limit);
2353 } 2365 }
2354 2366
2355 Bind(&runtime); 2367 BIND(&runtime);
2356 { 2368 {
2357 // The runtime call passes in limit to ensure the second ToUint32(limit) 2369 // The runtime call passes in limit to ensure the second ToUint32(limit)
2358 // call is not observable. 2370 // call is not observable.
2359 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(limit))); 2371 CSA_ASSERT(this, IsHeapNumberMap(LoadReceiverMap(limit)));
2360 Return(CallRuntime(Runtime::kRegExpSplit, context, regexp, string, limit)); 2372 Return(CallRuntime(Runtime::kRegExpSplit, context, regexp, string, limit));
2361 } 2373 }
2362 } 2374 }
2363 2375
2364 // ES#sec-regexp.prototype-@@split 2376 // ES#sec-regexp.prototype-@@split
2365 // RegExp.prototype [ @@split ] ( string, limit ) 2377 // RegExp.prototype [ @@split ] ( string, limit )
2366 TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) { 2378 TF_BUILTIN(RegExpPrototypeSplit, RegExpBuiltinsAssembler) {
2367 Node* const maybe_receiver = Parameter(Descriptor::kReceiver); 2379 Node* const maybe_receiver = Parameter(Descriptor::kReceiver);
2368 Node* const maybe_string = Parameter(Descriptor::kString); 2380 Node* const maybe_string = Parameter(Descriptor::kString);
2369 Node* const maybe_limit = Parameter(Descriptor::kLimit); 2381 Node* const maybe_limit = Parameter(Descriptor::kLimit);
2370 Node* const context = Parameter(Descriptor::kContext); 2382 Node* const context = Parameter(Descriptor::kContext);
2371 2383
2372 // Ensure {maybe_receiver} is a JSReceiver. 2384 // Ensure {maybe_receiver} is a JSReceiver.
2373 ThrowIfNotJSReceiver(context, maybe_receiver, 2385 ThrowIfNotJSReceiver(context, maybe_receiver,
2374 MessageTemplate::kIncompatibleMethodReceiver, 2386 MessageTemplate::kIncompatibleMethodReceiver,
2375 "RegExp.prototype.@@split"); 2387 "RegExp.prototype.@@split");
2376 Node* const receiver = maybe_receiver; 2388 Node* const receiver = maybe_receiver;
2377 2389
2378 // Convert {maybe_string} to a String. 2390 // Convert {maybe_string} to a String.
2379 Node* const string = ToString(context, maybe_string); 2391 Node* const string = ToString(context, maybe_string);
2380 2392
2381 Label stub(this), runtime(this, Label::kDeferred); 2393 Label stub(this), runtime(this, Label::kDeferred);
2382 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &stub, &runtime); 2394 BranchIfFastRegExp(context, receiver, &stub, &runtime);
2383 2395
2384 BIND(&stub); 2396 BIND(&stub);
2385 Return(CallBuiltin(Builtins::kRegExpSplit, context, receiver, string, 2397 Return(CallBuiltin(Builtins::kRegExpSplit, context, receiver, string,
2386 maybe_limit)); 2398 maybe_limit));
2387 2399
2388 BIND(&runtime); 2400 BIND(&runtime);
2389 Return(CallRuntime(Runtime::kRegExpSplit, context, receiver, string, 2401 Return(CallRuntime(Runtime::kRegExpSplit, context, receiver, string,
2390 maybe_limit)); 2402 maybe_limit));
2391 } 2403 }
2392 2404
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
2728 BIND(&checkreplacestring); 2740 BIND(&checkreplacestring);
2729 { 2741 {
2730 Node* const replace_string = 2742 Node* const replace_string =
2731 CallBuiltin(Builtins::kToString, context, replace_value); 2743 CallBuiltin(Builtins::kToString, context, replace_value);
2732 2744
2733 // ToString(replaceValue) could potentially change the shape of the RegExp 2745 // ToString(replaceValue) could potentially change the shape of the RegExp
2734 // object. Recheck that we are still on the fast path and bail to runtime 2746 // object. Recheck that we are still on the fast path and bail to runtime
2735 // otherwise. 2747 // otherwise.
2736 { 2748 {
2737 Label next(this); 2749 Label next(this);
2738 BranchIfFastRegExp(context, regexp, LoadMap(regexp), &next, &runtime); 2750 BranchIfFastRegExp(context, regexp, &next, &runtime);
2739 Bind(&next); 2751 BIND(&next);
2740 } 2752 }
2741 2753
2742 Node* const dollar_string = HeapConstant( 2754 Node* const dollar_string = HeapConstant(
2743 isolate()->factory()->LookupSingleCharacterStringFromCode('$')); 2755 isolate()->factory()->LookupSingleCharacterStringFromCode('$'));
2744 Node* const dollar_ix = 2756 Node* const dollar_ix =
2745 CallBuiltin(Builtins::kStringIndexOf, context, replace_string, 2757 CallBuiltin(Builtins::kStringIndexOf, context, replace_string,
2746 dollar_string, SmiConstant(0)); 2758 dollar_string, SmiConstant(0));
2747 GotoIfNot(SmiEqual(dollar_ix, SmiConstant(-1)), &runtime); 2759 GotoIfNot(SmiEqual(dollar_ix, SmiConstant(-1)), &runtime);
2748 2760
2749 Return( 2761 Return(
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
2804 ThrowIfNotJSReceiver(context, maybe_receiver, 2816 ThrowIfNotJSReceiver(context, maybe_receiver,
2805 MessageTemplate::kIncompatibleMethodReceiver, 2817 MessageTemplate::kIncompatibleMethodReceiver,
2806 "RegExp.prototype.@@replace"); 2818 "RegExp.prototype.@@replace");
2807 Node* const receiver = maybe_receiver; 2819 Node* const receiver = maybe_receiver;
2808 2820
2809 // Convert {maybe_string} to a String. 2821 // Convert {maybe_string} to a String.
2810 Node* const string = CallBuiltin(Builtins::kToString, context, maybe_string); 2822 Node* const string = CallBuiltin(Builtins::kToString, context, maybe_string);
2811 2823
2812 // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance? 2824 // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance?
2813 Label stub(this), runtime(this, Label::kDeferred); 2825 Label stub(this), runtime(this, Label::kDeferred);
2814 BranchIfFastRegExp(context, receiver, LoadMap(receiver), &stub, &runtime); 2826 BranchIfFastRegExp(context, receiver, &stub, &runtime);
2815 2827
2816 BIND(&stub); 2828 BIND(&stub);
2817 Return(CallBuiltin(Builtins::kRegExpReplace, context, receiver, string, 2829 Return(CallBuiltin(Builtins::kRegExpReplace, context, receiver, string,
2818 replace_value)); 2830 replace_value));
2819 2831
2820 BIND(&runtime); 2832 BIND(&runtime);
2821 Return(CallRuntime(Runtime::kRegExpReplace, context, receiver, string, 2833 Return(CallRuntime(Runtime::kRegExpReplace, context, receiver, string,
2822 replace_value)); 2834 replace_value));
2823 } 2835 }
2824 2836
(...skipping 26 matching lines...) Expand all
2851 BIND(&if_matched); 2863 BIND(&if_matched);
2852 { 2864 {
2853 Node* result = 2865 Node* result =
2854 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); 2866 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string);
2855 Return(result); 2867 Return(result);
2856 } 2868 }
2857 } 2869 }
2858 2870
2859 } // namespace internal 2871 } // namespace internal
2860 } // namespace v8 2872 } // namespace v8
OLDNEW
« no previous file with comments | « src/builtins/builtins-regexp-gen.h ('k') | src/code-stub-assembler.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698