OLD | NEW |
1 // Copyright 2016 the V8 project authors. All rights reserved. | 1 // Copyright 2016 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-utils.h" | 5 #include "src/builtins/builtins-utils.h" |
6 #include "src/builtins/builtins.h" | 6 #include "src/builtins/builtins.h" |
7 | 7 |
8 #include "src/code-factory.h" | 8 #include "src/code-factory.h" |
9 #include "src/regexp/jsregexp.h" | 9 #include "src/regexp/jsregexp.h" |
10 #include "src/regexp/regexp-utils.h" | 10 #include "src/regexp/regexp-utils.h" |
(...skipping 951 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
962 | 962 |
963 BUILTIN(RegExpRightContextGetter) { | 963 BUILTIN(RegExpRightContextGetter) { |
964 HandleScope scope(isolate); | 964 HandleScope scope(isolate); |
965 Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info(); | 965 Handle<RegExpMatchInfo> match_info = isolate->regexp_last_match_info(); |
966 const int start_index = match_info->Capture(1); | 966 const int start_index = match_info->Capture(1); |
967 Handle<String> last_subject(match_info->LastSubject()); | 967 Handle<String> last_subject(match_info->LastSubject()); |
968 const int len = last_subject->length(); | 968 const int len = last_subject->length(); |
969 return *isolate->factory()->NewSubString(last_subject, start_index, len); | 969 return *isolate->factory()->NewSubString(last_subject, start_index, len); |
970 } | 970 } |
971 | 971 |
| 972 namespace { |
| 973 |
| 974 // ES#sec-regexpexec Runtime Semantics: RegExpExec ( R, S ) |
| 975 compiler::Node* RegExpExec(CodeStubAssembler* a, compiler::Node* context, |
| 976 compiler::Node* recv, compiler::Node* string) { |
| 977 typedef CodeStubAssembler::Variable Variable; |
| 978 typedef CodeStubAssembler::Label Label; |
| 979 typedef compiler::Node Node; |
| 980 |
| 981 Isolate* isolate = a->isolate(); |
| 982 |
| 983 Node* const null = a->NullConstant(); |
| 984 |
| 985 Variable var_result(a, MachineRepresentation::kTagged); |
| 986 Label out(a), call_builtin_exec(a), slow_path(a, Label::kDeferred); |
| 987 |
| 988 Node* const map = a->LoadMap(recv); |
| 989 BranchIfFastPath(a, context, map, &call_builtin_exec, &slow_path); |
| 990 |
| 991 a->Bind(&call_builtin_exec); |
| 992 { |
| 993 Node* const result = RegExpPrototypeExecInternal(a, context, recv, string); |
| 994 var_result.Bind(result); |
| 995 a->Goto(&out); |
| 996 } |
| 997 |
| 998 a->Bind(&slow_path); |
| 999 { |
| 1000 // Take the slow path of fetching the exec property, calling it, and |
| 1001 // verifying its return value. |
| 1002 |
| 1003 // Get the exec property. |
| 1004 Node* const name = a->HeapConstant(isolate->factory()->exec_string()); |
| 1005 Callable getproperty_callable = CodeFactory::GetProperty(a->isolate()); |
| 1006 Node* const exec = a->CallStub(getproperty_callable, context, recv, name); |
| 1007 |
| 1008 // Is {exec} callable? |
| 1009 Label if_iscallable(a), if_isnotcallable(a); |
| 1010 |
| 1011 a->GotoIf(a->TaggedIsSmi(exec), &if_isnotcallable); |
| 1012 |
| 1013 Node* const exec_map = a->LoadMap(exec); |
| 1014 a->Branch(a->IsCallableMap(exec_map), &if_iscallable, &if_isnotcallable); |
| 1015 |
| 1016 a->Bind(&if_iscallable); |
| 1017 { |
| 1018 Callable call_callable = CodeFactory::Call(isolate); |
| 1019 Node* const result = |
| 1020 a->CallJS(call_callable, context, exec, recv, string); |
| 1021 |
| 1022 var_result.Bind(result); |
| 1023 a->GotoIf(a->WordEqual(result, null), &out); |
| 1024 |
| 1025 ThrowIfNotJSReceiver(a, isolate, context, result, |
| 1026 MessageTemplate::kInvalidRegExpExecResult, "unused"); |
| 1027 |
| 1028 a->Goto(&out); |
| 1029 } |
| 1030 |
| 1031 a->Bind(&if_isnotcallable); |
| 1032 { |
| 1033 a->ThrowIfNotInstanceType(context, recv, JS_REGEXP_TYPE, |
| 1034 "RegExp.prototype.exec"); |
| 1035 a->Goto(&call_builtin_exec); |
| 1036 } |
| 1037 } |
| 1038 |
| 1039 a->Bind(&out); |
| 1040 return var_result.value(); |
| 1041 } |
| 1042 |
| 1043 } // namespace |
| 1044 |
972 // ES#sec-regexp.prototype.test | 1045 // ES#sec-regexp.prototype.test |
973 // RegExp.prototype.test ( S ) | 1046 // RegExp.prototype.test ( S ) |
974 BUILTIN(RegExpPrototypeTest) { | 1047 void Builtins::Generate_RegExpPrototypeTest(CodeStubAssembler* a) { |
975 HandleScope scope(isolate); | 1048 typedef compiler::Node Node; |
976 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.test"); | |
977 | 1049 |
978 Handle<Object> string_obj = args.atOrUndefined(isolate, 1); | 1050 Isolate* const isolate = a->isolate(); |
979 | 1051 |
980 Handle<String> string; | 1052 Node* const maybe_receiver = a->Parameter(0); |
981 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(isolate, string, | 1053 Node* const maybe_string = a->Parameter(1); |
982 Object::ToString(isolate, string_obj)); | 1054 Node* const context = a->Parameter(4); |
983 | 1055 |
984 Handle<Object> result; | 1056 // Ensure {maybe_receiver} is a JSReceiver. |
985 ASSIGN_RETURN_FAILURE_ON_EXCEPTION( | 1057 ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver, |
986 isolate, result, | 1058 MessageTemplate::kIncompatibleMethodReceiver, |
987 RegExpUtils::RegExpExec(isolate, recv, string, | 1059 "RegExp.prototype.test"); |
988 isolate->factory()->undefined_value())); | 1060 Node* const receiver = maybe_receiver; |
989 | 1061 |
990 return isolate->heap()->ToBoolean(!result->IsNull(isolate)); | 1062 // Convert {maybe_string} to a String. |
| 1063 Node* const string = a->ToString(context, maybe_string); |
| 1064 |
| 1065 // Call exec. |
| 1066 Node* const match_indices = RegExpExec(a, context, receiver, string); |
| 1067 |
| 1068 // Return true iff exec matched successfully. |
| 1069 Node* const result = a->Select(a->WordEqual(match_indices, a->NullConstant()), |
| 1070 a->FalseConstant(), a->TrueConstant()); |
| 1071 a->Return(result); |
991 } | 1072 } |
992 | 1073 |
993 // ES#sec-regexp.prototype-@@match | 1074 // ES#sec-regexp.prototype-@@match |
994 // RegExp.prototype [ @@match ] ( string ) | 1075 // RegExp.prototype [ @@match ] ( string ) |
995 BUILTIN(RegExpPrototypeMatch) { | 1076 BUILTIN(RegExpPrototypeMatch) { |
996 HandleScope scope(isolate); | 1077 HandleScope scope(isolate); |
997 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.@@match"); | 1078 CHECK_RECEIVER(JSReceiver, recv, "RegExp.prototype.@@match"); |
998 | 1079 |
999 Handle<Object> string_obj = args.atOrUndefined(isolate, 1); | 1080 Handle<Object> string_obj = args.atOrUndefined(isolate, 1); |
1000 | 1081 |
(...skipping 812 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1813 | 1894 |
1814 Isolate* const isolate = a->isolate(); | 1895 Isolate* const isolate = a->isolate(); |
1815 | 1896 |
1816 Node* const maybe_receiver = a->Parameter(0); | 1897 Node* const maybe_receiver = a->Parameter(0); |
1817 Node* const maybe_string = a->Parameter(1); | 1898 Node* const maybe_string = a->Parameter(1); |
1818 Node* const replace_value = a->Parameter(2); | 1899 Node* const replace_value = a->Parameter(2); |
1819 Node* const context = a->Parameter(5); | 1900 Node* const context = a->Parameter(5); |
1820 | 1901 |
1821 Node* const int_zero = a->IntPtrConstant(0); | 1902 Node* const int_zero = a->IntPtrConstant(0); |
1822 | 1903 |
1823 // Ensure {receiver} is a JSReceiver. | 1904 // Ensure {maybe_receiver} is a JSReceiver. |
1824 Node* const map = | 1905 Node* const map = |
1825 ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver, | 1906 ThrowIfNotJSReceiver(a, isolate, context, maybe_receiver, |
1826 MessageTemplate::kIncompatibleMethodReceiver, | 1907 MessageTemplate::kIncompatibleMethodReceiver, |
1827 "RegExp.prototype.@@replace"); | 1908 "RegExp.prototype.@@replace"); |
1828 Node* const receiver = maybe_receiver; | 1909 Node* const receiver = maybe_receiver; |
1829 | 1910 |
1830 // Convert {maybe_string} to a String. | 1911 // Convert {maybe_string} to a String. |
1831 Callable tostring_callable = CodeFactory::ToString(isolate); | 1912 Callable tostring_callable = CodeFactory::ToString(isolate); |
1832 Node* const string = a->CallStub(tostring_callable, context, maybe_string); | 1913 Node* const string = a->CallStub(tostring_callable, context, maybe_string); |
1833 | 1914 |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1929 a->Bind(&if_matched); | 2010 a->Bind(&if_matched); |
1930 { | 2011 { |
1931 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, | 2012 Node* result = ConstructNewResultFromMatchInfo(isolate, a, context, |
1932 match_indices, string); | 2013 match_indices, string); |
1933 a->Return(result); | 2014 a->Return(result); |
1934 } | 2015 } |
1935 } | 2016 } |
1936 | 2017 |
1937 } // namespace internal | 2018 } // namespace internal |
1938 } // namespace v8 | 2019 } // namespace v8 |
OLD | NEW |