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

Side by Side Diff: src/runtime/runtime-regexp.cc

Issue 2685183003: [regexp] Sticky handling in fast slow path (Closed)
Patch Set: Revert "Remove custom ToUint32" Created 3 years, 10 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
OLDNEW
1 // Copyright 2014 the V8 project authors. All rights reserved. 1 // Copyright 2014 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/runtime/runtime-utils.h" 5 #include "src/runtime/runtime-utils.h"
6 6
7 #include "src/arguments.h" 7 #include "src/arguments.h"
8 #include "src/conversions-inl.h" 8 #include "src/conversions-inl.h"
9 #include "src/isolate-inl.h" 9 #include "src/isolate-inl.h"
10 #include "src/messages.h" 10 #include "src/messages.h"
(...skipping 1066 matching lines...) Expand 10 before | Expand all | Expand 10 after
1077 return isolate->heap()->null_value(); // No matches at all. 1077 return isolate->heap()->null_value(); // No matches at all.
1078 } 1078 }
1079 } 1079 }
1080 1080
1081 MUST_USE_RESULT MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction( 1081 MUST_USE_RESULT MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction(
1082 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp, 1082 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
1083 Handle<Object> replace_obj) { 1083 Handle<Object> replace_obj) {
1084 Factory* factory = isolate->factory(); 1084 Factory* factory = isolate->factory();
1085 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info(); 1085 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1086 1086
1087 // TODO(jgruber): This is a pattern we could refactor. 1087 const int flags = regexp->GetFlags();
1088
1089 DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
1090 DCHECK_EQ(flags & JSRegExp::kGlobal, 0);
1091
1092 // TODO(jgruber): This should be an easy port to CSA with massive payback.
1093
1094 const bool sticky = (flags & JSRegExp::kSticky) != 0;
1095 uint32_t last_index = 0;
1096 if (sticky) {
1097 Handle<Object> last_index_obj(regexp->LastIndex(), isolate);
1098 ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
1099 Object::ToLength(isolate, last_index_obj),
1100 String);
1101 last_index = PositiveNumberToUint32(*last_index_obj);
1102
1103 if (static_cast<int>(last_index) > subject->length()) last_index = 0;
1104 }
1105
1088 Handle<Object> match_indices_obj; 1106 Handle<Object> match_indices_obj;
1089 ASSIGN_RETURN_ON_EXCEPTION( 1107 ASSIGN_RETURN_ON_EXCEPTION(
1090 isolate, match_indices_obj, 1108 isolate, match_indices_obj,
1091 RegExpImpl::Exec(regexp, subject, 0, last_match_info), String); 1109 RegExpImpl::Exec(regexp, subject, last_index, last_match_info), String);
1092 1110
1093 if (match_indices_obj->IsNull(isolate)) { 1111 if (match_indices_obj->IsNull(isolate)) {
1094 RETURN_ON_EXCEPTION(isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0), 1112 if (sticky) regexp->SetLastIndex(0);
1095 String);
1096 return subject; 1113 return subject;
1097 } 1114 }
1098 1115
1099 Handle<RegExpMatchInfo> match_indices = 1116 Handle<RegExpMatchInfo> match_indices =
1100 Handle<RegExpMatchInfo>::cast(match_indices_obj); 1117 Handle<RegExpMatchInfo>::cast(match_indices_obj);
1101 1118
1102 const int index = match_indices->Capture(0); 1119 const int index = match_indices->Capture(0);
1103 const int end_of_match = match_indices->Capture(1); 1120 const int end_of_match = match_indices->Capture(1);
1104 1121
1122 if (sticky) regexp->SetLastIndex(end_of_match);
1123
1105 IncrementalStringBuilder builder(isolate); 1124 IncrementalStringBuilder builder(isolate);
1106 builder.AppendString(factory->NewSubString(subject, 0, index)); 1125 builder.AppendString(factory->NewSubString(subject, 0, index));
1107 1126
1108 // Compute the parameter list consisting of the match, captures, index, 1127 // Compute the parameter list consisting of the match, captures, index,
1109 // and subject for the replace function invocation. 1128 // and subject for the replace function invocation.
1110 // The number of captures plus one for the match. 1129 // The number of captures plus one for the match.
1111 const int m = match_indices->NumberOfCaptureRegisters() / 2; 1130 const int m = match_indices->NumberOfCaptureRegisters() / 2;
1112 1131
1113 const int argc = m + 2; 1132 const int argc = m + 2;
1114 ScopedVector<Handle<Object>> argv(argc); 1133 ScopedVector<Handle<Object>> argv(argc);
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1146 } 1165 }
1147 1166
1148 // Legacy implementation of RegExp.prototype[Symbol.replace] which 1167 // Legacy implementation of RegExp.prototype[Symbol.replace] which
1149 // doesn't properly call the underlying exec method. 1168 // doesn't properly call the underlying exec method.
1150 MUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate, 1169 MUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate,
1151 Handle<JSRegExp> regexp, 1170 Handle<JSRegExp> regexp,
1152 Handle<String> string, 1171 Handle<String> string,
1153 Handle<Object> replace_obj) { 1172 Handle<Object> replace_obj) {
1154 Factory* factory = isolate->factory(); 1173 Factory* factory = isolate->factory();
1155 1174
1156 // TODO(jgruber): We need the even stricter guarantee of an unmodified
1157 // JSRegExp map here for access to GetFlags to be legal.
1158 const int flags = regexp->GetFlags(); 1175 const int flags = regexp->GetFlags();
1159 const bool global = (flags & JSRegExp::kGlobal) != 0; 1176 const bool global = (flags & JSRegExp::kGlobal) != 0;
1177 const bool sticky = (flags & JSRegExp::kSticky) != 0;
1160 1178
1161 // Functional fast-paths are dispatched directly by replace builtin. 1179 // Functional fast-paths are dispatched directly by replace builtin.
1162 DCHECK(!replace_obj->IsCallable()); 1180 DCHECK(!replace_obj->IsCallable());
1163 1181
1164 Handle<String> replace; 1182 Handle<String> replace;
1165 ASSIGN_RETURN_ON_EXCEPTION(isolate, replace, 1183 ASSIGN_RETURN_ON_EXCEPTION(isolate, replace,
1166 Object::ToString(isolate, replace_obj), String); 1184 Object::ToString(isolate, replace_obj), String);
1167 replace = String::Flatten(replace); 1185 replace = String::Flatten(replace);
1168 1186
1169 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info(); 1187 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1170 1188
1171 if (!global) { 1189 if (!global) {
1172 // Non-global regexp search, string replace. 1190 // Non-global regexp search, string replace.
1173 1191
1192 uint32_t last_index = 0;
1193 if (sticky) {
1194 Handle<Object> last_index_obj(regexp->LastIndex(), isolate);
1195 ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
1196 Object::ToLength(isolate, last_index_obj),
1197 String);
1198 last_index = PositiveNumberToUint32(*last_index_obj);
1199
1200 if (static_cast<int>(last_index) > string->length()) last_index = 0;
1201 }
1202
1174 Handle<Object> match_indices_obj; 1203 Handle<Object> match_indices_obj;
1175 ASSIGN_RETURN_ON_EXCEPTION( 1204 ASSIGN_RETURN_ON_EXCEPTION(
1176 isolate, match_indices_obj, 1205 isolate, match_indices_obj,
1177 RegExpImpl::Exec(regexp, string, 0, last_match_info), String); 1206 RegExpImpl::Exec(regexp, string, last_index, last_match_info), String);
1178 1207
1179 if (match_indices_obj->IsNull(isolate)) { 1208 if (match_indices_obj->IsNull(isolate)) {
1180 RETURN_ON_EXCEPTION( 1209 if (sticky) regexp->SetLastIndex(0);
1181 isolate, RegExpUtils::SetLastIndex(isolate, regexp, 0), String);
1182 return string; 1210 return string;
1183 } 1211 }
1184 1212
1185 auto match_indices = Handle<RegExpMatchInfo>::cast(match_indices_obj); 1213 auto match_indices = Handle<RegExpMatchInfo>::cast(match_indices_obj);
1186 1214
1187 const int start_index = match_indices->Capture(0); 1215 const int start_index = match_indices->Capture(0);
1188 const int end_index = match_indices->Capture(1); 1216 const int end_index = match_indices->Capture(1);
1189 1217
1218 if (sticky) regexp->SetLastIndex(end_index);
1219
1190 IncrementalStringBuilder builder(isolate); 1220 IncrementalStringBuilder builder(isolate);
1191 builder.AppendString(factory->NewSubString(string, 0, start_index)); 1221 builder.AppendString(factory->NewSubString(string, 0, start_index));
1192 1222
1193 if (replace->length() > 0) { 1223 if (replace->length() > 0) {
1194 MatchInfoBackedMatch m(isolate, string, match_indices); 1224 MatchInfoBackedMatch m(isolate, string, match_indices);
1195 Handle<String> replacement; 1225 Handle<String> replacement;
1196 ASSIGN_RETURN_ON_EXCEPTION(isolate, replacement, 1226 ASSIGN_RETURN_ON_EXCEPTION(isolate, replacement,
1197 String::GetSubstitution(isolate, &m, replace), 1227 String::GetSubstitution(isolate, &m, replace),
1198 String); 1228 String);
1199 builder.AppendString(replacement); 1229 builder.AppendString(replacement);
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
1261 } 1291 }
1262 1292
1263 RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) { 1293 RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) {
1264 HandleScope scope(isolate); 1294 HandleScope scope(isolate);
1265 DCHECK_EQ(3, args.length()); 1295 DCHECK_EQ(3, args.length());
1266 1296
1267 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); 1297 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
1268 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); 1298 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
1269 CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2); 1299 CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2);
1270 1300
1301 DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
1302
1271 RETURN_RESULT_OR_FAILURE(isolate, StringReplaceNonGlobalRegExpWithFunction( 1303 RETURN_RESULT_OR_FAILURE(isolate, StringReplaceNonGlobalRegExpWithFunction(
1272 isolate, subject, regexp, replace)); 1304 isolate, subject, regexp, replace));
1273 } 1305 }
1274 1306
1275 namespace { 1307 namespace {
1276 1308
1277 // ES##sec-speciesconstructor 1309 // ES##sec-speciesconstructor
1278 // SpeciesConstructor ( O, defaultConstructor ) 1310 // SpeciesConstructor ( O, defaultConstructor )
1279 MUST_USE_RESULT MaybeHandle<Object> SpeciesConstructor( 1311 MUST_USE_RESULT MaybeHandle<Object> SpeciesConstructor(
1280 Isolate* isolate, Handle<JSReceiver> recv, 1312 Isolate* isolate, Handle<JSReceiver> recv,
(...skipping 400 matching lines...) Expand 10 before | Expand all | Expand 10 after
1681 1713
1682 RUNTIME_FUNCTION(Runtime_IsRegExp) { 1714 RUNTIME_FUNCTION(Runtime_IsRegExp) {
1683 SealHandleScope shs(isolate); 1715 SealHandleScope shs(isolate);
1684 DCHECK_EQ(1, args.length()); 1716 DCHECK_EQ(1, args.length());
1685 CONVERT_ARG_CHECKED(Object, obj, 0); 1717 CONVERT_ARG_CHECKED(Object, obj, 0);
1686 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); 1718 return isolate->heap()->ToBoolean(obj->IsJSRegExp());
1687 } 1719 }
1688 1720
1689 } // namespace internal 1721 } // namespace internal
1690 } // namespace v8 1722 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698