| Index: src/runtime/runtime-regexp.cc
|
| diff --git a/src/runtime/runtime-regexp.cc b/src/runtime/runtime-regexp.cc
|
| index c2271fd0ced27dd60539c3cdd2f5b93dd24dae32..b10ee3230b1671d11422f3569963c79105663181 100644
|
| --- a/src/runtime/runtime-regexp.cc
|
| +++ b/src/runtime/runtime-regexp.cc
|
| @@ -1078,92 +1078,6 @@ static Object* SearchRegExpMultiple(Isolate* isolate, Handle<String> subject,
|
| }
|
| }
|
|
|
| -MUST_USE_RESULT MaybeHandle<String> StringReplaceNonGlobalRegExpWithFunction(
|
| - Isolate* isolate, Handle<String> subject, Handle<JSRegExp> regexp,
|
| - Handle<Object> replace_obj) {
|
| - Factory* factory = isolate->factory();
|
| - Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
|
| -
|
| - const int flags = regexp->GetFlags();
|
| -
|
| - DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
|
| - DCHECK_EQ(flags & JSRegExp::kGlobal, 0);
|
| -
|
| - // TODO(jgruber): This should be an easy port to CSA with massive payback.
|
| -
|
| - const bool sticky = (flags & JSRegExp::kSticky) != 0;
|
| - uint32_t last_index = 0;
|
| - if (sticky) {
|
| - Handle<Object> last_index_obj(regexp->LastIndex(), isolate);
|
| - ASSIGN_RETURN_ON_EXCEPTION(isolate, last_index_obj,
|
| - Object::ToLength(isolate, last_index_obj),
|
| - String);
|
| - last_index = PositiveNumberToUint32(*last_index_obj);
|
| -
|
| - if (static_cast<int>(last_index) > subject->length()) last_index = 0;
|
| - }
|
| -
|
| - Handle<Object> match_indices_obj;
|
| - ASSIGN_RETURN_ON_EXCEPTION(
|
| - isolate, match_indices_obj,
|
| - RegExpImpl::Exec(regexp, subject, last_index, last_match_info), String);
|
| -
|
| - if (match_indices_obj->IsNull(isolate)) {
|
| - if (sticky) regexp->SetLastIndex(0);
|
| - return subject;
|
| - }
|
| -
|
| - Handle<RegExpMatchInfo> match_indices =
|
| - Handle<RegExpMatchInfo>::cast(match_indices_obj);
|
| -
|
| - const int index = match_indices->Capture(0);
|
| - const int end_of_match = match_indices->Capture(1);
|
| -
|
| - if (sticky) regexp->SetLastIndex(end_of_match);
|
| -
|
| - IncrementalStringBuilder builder(isolate);
|
| - builder.AppendString(factory->NewSubString(subject, 0, index));
|
| -
|
| - // Compute the parameter list consisting of the match, captures, index,
|
| - // and subject for the replace function invocation.
|
| - // The number of captures plus one for the match.
|
| - const int m = match_indices->NumberOfCaptureRegisters() / 2;
|
| -
|
| - const int argc = m + 2;
|
| - ScopedVector<Handle<Object>> argv(argc);
|
| -
|
| - for (int j = 0; j < m; j++) {
|
| - bool ok;
|
| - Handle<String> capture =
|
| - RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok);
|
| - if (ok) {
|
| - argv[j] = capture;
|
| - } else {
|
| - argv[j] = factory->undefined_value();
|
| - }
|
| - }
|
| -
|
| - argv[argc - 2] = handle(Smi::FromInt(index), isolate);
|
| - argv[argc - 1] = subject;
|
| -
|
| - Handle<Object> replacement_obj;
|
| - ASSIGN_RETURN_ON_EXCEPTION(
|
| - isolate, replacement_obj,
|
| - Execution::Call(isolate, replace_obj, factory->undefined_value(), argc,
|
| - argv.start()),
|
| - String);
|
| -
|
| - Handle<String> replacement;
|
| - ASSIGN_RETURN_ON_EXCEPTION(
|
| - isolate, replacement, Object::ToString(isolate, replacement_obj), String);
|
| -
|
| - builder.AppendString(replacement);
|
| - builder.AppendString(
|
| - factory->NewSubString(subject, end_of_match, subject->length()));
|
| -
|
| - return builder.Finish();
|
| -}
|
| -
|
| // Legacy implementation of RegExp.prototype[Symbol.replace] which
|
| // doesn't properly call the underlying exec method.
|
| MUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate,
|
| @@ -1293,15 +1207,89 @@ RUNTIME_FUNCTION(Runtime_RegExpExecMultiple) {
|
| RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) {
|
| HandleScope scope(isolate);
|
| DCHECK_EQ(3, args.length());
|
| -
|
| CONVERT_ARG_HANDLE_CHECKED(String, subject, 0);
|
| CONVERT_ARG_HANDLE_CHECKED(JSRegExp, regexp, 1);
|
| - CONVERT_ARG_HANDLE_CHECKED(JSObject, replace, 2);
|
| + CONVERT_ARG_HANDLE_CHECKED(JSObject, replace_obj, 2);
|
|
|
| DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
|
|
|
| - RETURN_RESULT_OR_FAILURE(isolate, StringReplaceNonGlobalRegExpWithFunction(
|
| - isolate, subject, regexp, replace));
|
| + Factory* factory = isolate->factory();
|
| + Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
|
| +
|
| + const int flags = regexp->GetFlags();
|
| + DCHECK_EQ(flags & JSRegExp::kGlobal, 0);
|
| +
|
| + // TODO(jgruber): This should be an easy port to CSA with massive payback.
|
| +
|
| + const bool sticky = (flags & JSRegExp::kSticky) != 0;
|
| + uint32_t last_index = 0;
|
| + if (sticky) {
|
| + Handle<Object> last_index_obj(regexp->LastIndex(), isolate);
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, last_index_obj, Object::ToLength(isolate, last_index_obj));
|
| + last_index = PositiveNumberToUint32(*last_index_obj);
|
| +
|
| + if (static_cast<int>(last_index) > subject->length()) last_index = 0;
|
| + }
|
| +
|
| + Handle<Object> match_indices_obj;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, match_indices_obj,
|
| + RegExpImpl::Exec(regexp, subject, last_index, last_match_info));
|
| +
|
| + if (match_indices_obj->IsNull(isolate)) {
|
| + if (sticky) regexp->SetLastIndex(0);
|
| + return *subject;
|
| + }
|
| +
|
| + Handle<RegExpMatchInfo> match_indices =
|
| + Handle<RegExpMatchInfo>::cast(match_indices_obj);
|
| +
|
| + const int index = match_indices->Capture(0);
|
| + const int end_of_match = match_indices->Capture(1);
|
| +
|
| + if (sticky) regexp->SetLastIndex(end_of_match);
|
| +
|
| + IncrementalStringBuilder builder(isolate);
|
| + builder.AppendString(factory->NewSubString(subject, 0, index));
|
| +
|
| + // Compute the parameter list consisting of the match, captures, index,
|
| + // and subject for the replace function invocation.
|
| + // The number of captures plus one for the match.
|
| + const int m = match_indices->NumberOfCaptureRegisters() / 2;
|
| +
|
| + const int argc = m + 2;
|
| + ScopedVector<Handle<Object>> argv(argc);
|
| +
|
| + for (int j = 0; j < m; j++) {
|
| + bool ok;
|
| + Handle<String> capture =
|
| + RegExpUtils::GenericCaptureGetter(isolate, match_indices, j, &ok);
|
| + if (ok) {
|
| + argv[j] = capture;
|
| + } else {
|
| + argv[j] = factory->undefined_value();
|
| + }
|
| + }
|
| +
|
| + argv[argc - 2] = handle(Smi::FromInt(index), isolate);
|
| + argv[argc - 1] = subject;
|
| +
|
| + Handle<Object> replacement_obj;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, replacement_obj,
|
| + Execution::Call(isolate, replace_obj, factory->undefined_value(), argc,
|
| + argv.start()));
|
| +
|
| + Handle<String> replacement;
|
| + ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
|
| + isolate, replacement, Object::ToString(isolate, replacement_obj));
|
| +
|
| + builder.AppendString(replacement);
|
| + builder.AppendString(
|
| + factory->NewSubString(subject, end_of_match, subject->length()));
|
| +
|
| + RETURN_RESULT_OR_FAILURE(isolate, builder.Finish());
|
| }
|
|
|
| namespace {
|
|
|