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

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

Issue 2766423004: [regexp] Inline StringReplaceNonGlobalRegExpWithFunction (Closed)
Patch Set: Created 3 years, 9 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 | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1060 matching lines...) Expand 10 before | Expand all | Expand 10 after
1071 RegExpResultsCache::Enter( 1071 RegExpResultsCache::Enter(
1072 isolate, subject, handle(regexp->data(), isolate), copied_fixed_array, 1072 isolate, subject, handle(regexp->data(), isolate), copied_fixed_array,
1073 last_match_cache, RegExpResultsCache::REGEXP_MULTIPLE_INDICES); 1073 last_match_cache, RegExpResultsCache::REGEXP_MULTIPLE_INDICES);
1074 } 1074 }
1075 return *builder.ToJSArray(result_array); 1075 return *builder.ToJSArray(result_array);
1076 } else { 1076 } else {
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(
1082 Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
1083 Handle<Object> replace_obj) {
1084 Factory* factory = isolate->factory();
1085 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1086
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
1106 Handle<Object> match_indices_obj;
1107 ASSIGN_RETURN_ON_EXCEPTION(
1108 isolate, match_indices_obj,
1109 RegExpImpl::Exec(regexp, subject, last_index, last_match_info), String);
1110
1111 if (match_indices_obj->IsNull(isolate)) {
1112 if (sticky) regexp->SetLastIndex(0);
1113 return subject;
1114 }
1115
1116 Handle<RegExpMatchInfo> match_indices =
1117 Handle<RegExpMatchInfo>::cast(match_indices_obj);
1118
1119 const int index = match_indices->Capture(0);
1120 const int end_of_match = match_indices->Capture(1);
1121
1122 if (sticky) regexp->SetLastIndex(end_of_match);
1123
1124 IncrementalStringBuilder builder(isolate);
1125 builder.AppendString(factory->NewSubString(subject, 0, index));
1126
1127 // Compute the parameter list consisting of the match, captures, index,
1128 // and subject for the replace function invocation.
1129 // The number of captures plus one for the match.
1130 const int m = match_indices->NumberOfCaptureRegisters() / 2;
1131
1132 const int argc = m + 2;
1133 ScopedVector<Handle<Object>> argv(argc);
1134
1135 for (int j = 0; j < m; j++) {
1136 bool ok;
1137 Handle<String> capture =
1138 RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok);
1139 if (ok) {
1140 argv[j] = capture;
1141 } else {
1142 argv[j] = factory->undefined_value();
1143 }
1144 }
1145
1146 argv[argc - 2] = handle(Smi::FromInt(index), isolate);
1147 argv[argc - 1] = subject;
1148
1149 Handle<Object> replacement_obj;
1150 ASSIGN_RETURN_ON_EXCEPTION(
1151 isolate, replacement_obj,
1152 Execution::Call(isolate, replace_obj, factory->undefined_value(), argc,
1153 argv.start()),
1154 String);
1155
1156 Handle<String> replacement;
1157 ASSIGN_RETURN_ON_EXCEPTION(
1158 isolate, replacement, Object::ToString(isolate, replacement_obj), String);
1159
1160 builder.AppendString(replacement);
1161 builder.AppendString(
1162 factory->NewSubString(subject, end_of_match, subject->length()));
1163
1164 return builder.Finish();
1165 }
1166
1167 // Legacy implementation of RegExp.prototype[Symbol.replace] which 1081 // Legacy implementation of RegExp.prototype[Symbol.replace] which
1168 // doesn't properly call the underlying exec method. 1082 // doesn't properly call the underlying exec method.
1169 MUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate, 1083 MUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate,
1170 Handle<JSRegExp> regexp, 1084 Handle<JSRegExp> regexp,
1171 Handle<String> string, 1085 Handle<String> string,
1172 Handle<Object> replace_obj) { 1086 Handle<Object> replace_obj) {
1173 Factory* factory = isolate->factory(); 1087 Factory* factory = isolate->factory();
1174 1088
1175 const int flags = regexp->GetFlags(); 1089 const int flags = regexp->GetFlags();
1176 const bool global = (flags & JSRegExp::kGlobal) != 0; 1090 const bool global = (flags & JSRegExp::kGlobal) != 0;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
1286 last_match_info, result_array); 1200 last_match_info, result_array);
1287 } else { 1201 } else {
1288 return SearchRegExpMultiple<true>(isolate, subject, regexp, last_match_info, 1202 return SearchRegExpMultiple<true>(isolate, subject, regexp, last_match_info,
1289 result_array); 1203 result_array);
1290 } 1204 }
1291 } 1205 }
1292 1206
1293 RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) { 1207 RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) {
1294 HandleScope scope(isolate); 1208 HandleScope scope(isolate);
1295 DCHECK_EQ(3, args.length()); 1209 DCHECK_EQ(3, args.length());
1296
1297 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0); 1210 CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
1298 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1); 1211 CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
1299 CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2); 1212 CONVERT_ARG_HANDLE_CHECKED(JSObject, replace_obj, 2);
1300 1213
1301 DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp)); 1214 DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
1302 1215
1303 RETURN_RESULT_OR_FAILURE(isolate, StringReplaceNonGlobalRegExpWithFunction( 1216 Factory* factory = isolate->factory();
1304 isolate, subject, regexp, replace)); 1217 Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
1218
1219 const int flags = regexp->GetFlags();
1220 DCHECK_EQ(flags & JSRegExp::kGlobal, 0);
1221
1222 // TODO(jgruber): This should be an easy port to CSA with massive payback.
1223
1224 const bool sticky = (flags & JSRegExp::kSticky) != 0;
1225 uint32_t last_index = 0;
1226 if (sticky) {
1227 Handle<Object> last_index_obj(regexp->LastIndex(), isolate);
1228 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1229 isolate, last_index_obj, Object::ToLength(isolate, last_index_obj));
1230 last_index = PositiveNumberToUint32(*last_index_obj);
1231
1232 if (static_cast<int>(last_index) > subject->length()) last_index = 0;
1233 }
1234
1235 Handle<Object> match_indices_obj;
1236 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1237 isolate, match_indices_obj,
1238 RegExpImpl::Exec(regexp, subject, last_index, last_match_info));
1239
1240 if (match_indices_obj->IsNull(isolate)) {
1241 if (sticky) regexp->SetLastIndex(0);
1242 return *subject;
1243 }
1244
1245 Handle<RegExpMatchInfo> match_indices =
1246 Handle<RegExpMatchInfo>::cast(match_indices_obj);
1247
1248 const int index = match_indices->Capture(0);
1249 const int end_of_match = match_indices->Capture(1);
1250
1251 if (sticky) regexp->SetLastIndex(end_of_match);
1252
1253 IncrementalStringBuilder builder(isolate);
1254 builder.AppendString(factory->NewSubString(subject, 0, index));
1255
1256 // Compute the parameter list consisting of the match, captures, index,
1257 // and subject for the replace function invocation.
1258 // The number of captures plus one for the match.
1259 const int m = match_indices->NumberOfCaptureRegisters() / 2;
1260
1261 const int argc = m + 2;
1262 ScopedVector<Handle<Object>> argv(argc);
1263
1264 for (int j = 0; j < m; j++) {
1265 bool ok;
1266 Handle<String> capture =
1267 RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok);
1268 if (ok) {
1269 argv[j] = capture;
1270 } else {
1271 argv[j] = factory->undefined_value();
1272 }
1273 }
1274
1275 argv[argc - 2] = handle(Smi::FromInt(index), isolate);
1276 argv[argc - 1] = subject;
1277
1278 Handle<Object> replacement_obj;
1279 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1280 isolate, replacement_obj,
1281 Execution::Call(isolate, replace_obj, factory->undefined_value(), argc,
1282 argv.start()));
1283
1284 Handle<String> replacement;
1285 ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
1286 isolate, replacement, Object::ToString(isolate, replacement_obj));
1287
1288 builder.AppendString(replacement);
1289 builder.AppendString(
1290 factory->NewSubString(subject, end_of_match, subject->length()));
1291
1292 RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
1305 } 1293 }
1306 1294
1307 namespace { 1295 namespace {
1308 1296
1309 MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate, 1297 MUST_USE_RESULT MaybeHandle<Object> ToUint32(Isolate* isolate,
1310 Handle<Object> object, 1298 Handle<Object> object,
1311 uint32_t* out) { 1299 uint32_t* out) {
1312 if (object->IsUndefined(isolate)) { 1300 if (object->IsUndefined(isolate)) {
1313 *out = kMaxUInt32; 1301 *out = kMaxUInt32;
1314 return object; 1302 return object;
(...skipping 361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1676 1664
1677 RUNTIME_FUNCTION(Runtime_IsRegExp) { 1665 RUNTIME_FUNCTION(Runtime_IsRegExp) {
1678 SealHandleScope shs(isolate); 1666 SealHandleScope shs(isolate);
1679 DCHECK_EQ(1, args.length()); 1667 DCHECK_EQ(1, args.length());
1680 CONVERT_ARG_CHECKED(Object, obj, 0); 1668 CONVERT_ARG_CHECKED(Object, obj, 0);
1681 return isolate->heap()->ToBoolean(obj->IsJSRegExp()); 1669 return isolate->heap()->ToBoolean(obj->IsJSRegExp());
1682 } 1670 }
1683 1671
1684 } // namespace internal 1672 } // namespace internal
1685 } // namespace v8 1673 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698