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

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

Issue 2807153002: [regexp] Avoid side effects between map load and fast path check (Closed)
Patch Set: 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') | test/mjsunit/regress/regress-709029.js » ('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 715 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « src/builtins/builtins-regexp-gen.h ('k') | test/mjsunit/regress/regress-709029.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698