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 559 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
570 if (is_fastpath) { | 570 if (is_fastpath) { |
571 // ToLength on a positive smi is a nop and can be skipped. | 571 // ToLength on a positive smi is a nop and can be skipped. |
572 CSA_ASSERT(this, TaggedIsPositiveSmi(regexp_lastindex)); | 572 CSA_ASSERT(this, TaggedIsPositiveSmi(regexp_lastindex)); |
573 } else { | 573 } else { |
574 // Omit ToLength if lastindex is a non-negative smi. | 574 // Omit ToLength if lastindex is a non-negative smi. |
575 Label call_tolength(this, Label::kDeferred), next(this); | 575 Label call_tolength(this, Label::kDeferred), next(this); |
576 Branch(TaggedIsPositiveSmi(regexp_lastindex), &next, &call_tolength); | 576 Branch(TaggedIsPositiveSmi(regexp_lastindex), &next, &call_tolength); |
577 | 577 |
578 BIND(&call_tolength); | 578 BIND(&call_tolength); |
579 { | 579 { |
580 var_lastindex.Bind( | 580 var_lastindex.Bind(ToLength_Inline(context, regexp_lastindex)); |
581 CallBuiltin(Builtins::kToLength, context, regexp_lastindex)); | |
582 Goto(&next); | 581 Goto(&next); |
583 } | 582 } |
584 | 583 |
585 BIND(&next); | 584 BIND(&next); |
586 } | 585 } |
587 } | 586 } |
588 | 587 |
589 // Check whether the regexp is global or sticky, which determines whether we | 588 // Check whether the regexp is global or sticky, which determines whether we |
590 // update last index later on. | 589 // update last index later on. |
591 Node* const flags = LoadObjectField(regexp, JSRegExp::kFlagsOffset); | 590 Node* const flags = LoadObjectField(regexp, JSRegExp::kFlagsOffset); |
(...skipping 1342 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1934 | 1933 |
1935 // Advance last index if the match is the empty string. | 1934 // Advance last index if the match is the empty string. |
1936 | 1935 |
1937 Node* const match_length = LoadStringLength(match); | 1936 Node* const match_length = LoadStringLength(match); |
1938 GotoIfNot(SmiEqual(match_length, smi_zero), &loop); | 1937 GotoIfNot(SmiEqual(match_length, smi_zero), &loop); |
1939 | 1938 |
1940 Node* last_index = LoadLastIndex(context, regexp, is_fastpath); | 1939 Node* last_index = LoadLastIndex(context, regexp, is_fastpath); |
1941 if (is_fastpath) { | 1940 if (is_fastpath) { |
1942 CSA_ASSERT(this, TaggedIsPositiveSmi(last_index)); | 1941 CSA_ASSERT(this, TaggedIsPositiveSmi(last_index)); |
1943 } else { | 1942 } else { |
1944 last_index = CallBuiltin(Builtins::kToLength, context, last_index); | 1943 last_index = ToLength_Inline(context, last_index); |
1945 } | 1944 } |
1946 | 1945 |
1947 Node* const new_last_index = | 1946 Node* const new_last_index = |
1948 AdvanceStringIndex(string, last_index, is_unicode, is_fastpath); | 1947 AdvanceStringIndex(string, last_index, is_unicode, is_fastpath); |
1949 | 1948 |
1950 if (is_fastpath) { | 1949 if (is_fastpath) { |
1951 // On the fast path, we can be certain that lastIndex can never be | 1950 // On the fast path, we can be certain that lastIndex can never be |
1952 // incremented to overflow the Smi range since the maximal string | 1951 // incremented to overflow the Smi range since the maximal string |
1953 // length is less than the maximal Smi value. | 1952 // length is less than the maximal Smi value. |
1954 STATIC_ASSERT(String::kMaxLength < Smi::kMaxValue); | 1953 STATIC_ASSERT(String::kMaxLength < Smi::kMaxValue); |
(...skipping 847 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2802 runtime(this, Label::kDeferred); | 2801 runtime(this, Label::kDeferred); |
2803 | 2802 |
2804 // 2. Is {replace_value} callable? | 2803 // 2. Is {replace_value} callable? |
2805 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); | 2804 GotoIf(TaggedIsSmi(replace_value), &checkreplacestring); |
2806 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, | 2805 Branch(IsCallableMap(LoadMap(replace_value)), &if_iscallable, |
2807 &checkreplacestring); | 2806 &checkreplacestring); |
2808 | 2807 |
2809 // 3. Does ToString({replace_value}) contain '$'? | 2808 // 3. Does ToString({replace_value}) contain '$'? |
2810 BIND(&checkreplacestring); | 2809 BIND(&checkreplacestring); |
2811 { | 2810 { |
2812 Node* const replace_string = | 2811 Node* const replace_string = ToString_Inline(context, replace_value); |
2813 CallBuiltin(Builtins::kToString, context, replace_value); | |
2814 | 2812 |
2815 // ToString(replaceValue) could potentially change the shape of the RegExp | 2813 // ToString(replaceValue) could potentially change the shape of the RegExp |
2816 // object. Recheck that we are still on the fast path and bail to runtime | 2814 // object. Recheck that we are still on the fast path and bail to runtime |
2817 // otherwise. | 2815 // otherwise. |
2818 { | 2816 { |
2819 Label next(this); | 2817 Label next(this); |
2820 BranchIfFastRegExp(context, regexp, &next, &runtime); | 2818 BranchIfFastRegExp(context, regexp, &next, &runtime); |
2821 BIND(&next); | 2819 BIND(&next); |
2822 } | 2820 } |
2823 | 2821 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2891 // } | 2889 // } |
2892 // } | 2890 // } |
2893 | 2891 |
2894 // Ensure {maybe_receiver} is a JSReceiver. | 2892 // Ensure {maybe_receiver} is a JSReceiver. |
2895 ThrowIfNotJSReceiver(context, maybe_receiver, | 2893 ThrowIfNotJSReceiver(context, maybe_receiver, |
2896 MessageTemplate::kIncompatibleMethodReceiver, | 2894 MessageTemplate::kIncompatibleMethodReceiver, |
2897 "RegExp.prototype.@@replace"); | 2895 "RegExp.prototype.@@replace"); |
2898 Node* const receiver = maybe_receiver; | 2896 Node* const receiver = maybe_receiver; |
2899 | 2897 |
2900 // Convert {maybe_string} to a String. | 2898 // Convert {maybe_string} to a String. |
2901 Node* const string = CallBuiltin(Builtins::kToString, context, maybe_string); | 2899 Node* const string = ToString_Inline(context, maybe_string); |
2902 | 2900 |
2903 // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance? | 2901 // Fast-path checks: 1. Is the {receiver} an unmodified JSRegExp instance? |
2904 Label stub(this), runtime(this, Label::kDeferred); | 2902 Label stub(this), runtime(this, Label::kDeferred); |
2905 BranchIfFastRegExp(context, receiver, &stub, &runtime); | 2903 BranchIfFastRegExp(context, receiver, &stub, &runtime); |
2906 | 2904 |
2907 BIND(&stub); | 2905 BIND(&stub); |
2908 args.PopAndReturn(CallBuiltin(Builtins::kRegExpReplace, context, receiver, | 2906 args.PopAndReturn(CallBuiltin(Builtins::kRegExpReplace, context, receiver, |
2909 string, replace_value)); | 2907 string, replace_value)); |
2910 | 2908 |
2911 BIND(&runtime); | 2909 BIND(&runtime); |
(...skipping 30 matching lines...) Expand all Loading... |
2942 BIND(&if_matched); | 2940 BIND(&if_matched); |
2943 { | 2941 { |
2944 Node* result = | 2942 Node* result = |
2945 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); | 2943 ConstructNewResultFromMatchInfo(context, regexp, match_indices, string); |
2946 Return(result); | 2944 Return(result); |
2947 } | 2945 } |
2948 } | 2946 } |
2949 | 2947 |
2950 } // namespace internal | 2948 } // namespace internal |
2951 } // namespace v8 | 2949 } // namespace v8 |
OLD | NEW |