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