Cherry-pick "Refactor Regexp.prototype"

Original change: https://chromium-review.googlesource.com/c/v8/v8/+/1547660

Bug: 147664838
Test: pacrunner32 test.pac
Test: gts-tradefed run gts-dev --module GtsGmscoreHostTestCases --test com.google.android.gts.devicepolicy.DeviceOwnerTest#testProxyPacProxyTest

Change-Id: Iac9370d48ca0ed84d5903ab0469c0ae01d62a621
Merged-In: Iac9370d48ca0ed84d5903ab0469c0ae01d62a621
(cherry picked from commit 15a4f1bc94195a20eae4ce121ae20e5cca5063f2)
diff --git a/src/regexp/regexp-utils.cc b/src/regexp/regexp-utils.cc
index 62daf3f..af451e3 100644
--- a/src/regexp/regexp-utils.cc
+++ b/src/regexp/regexp-utils.cc
@@ -35,7 +35,7 @@
 
 namespace {
 
-V8_INLINE bool HasInitialRegExpMap(Isolate* isolate, Handle<JSReceiver> recv) {
+V8_INLINE bool HasInitialRegExpMap(Isolate* isolate, JSReceiver* recv) {
   return recv->map() == isolate->regexp_function()->initial_map();
 }
 
@@ -44,7 +44,7 @@
 MaybeHandle<Object> RegExpUtils::SetLastIndex(Isolate* isolate,
                                               Handle<JSReceiver> recv,
                                               int value) {
-  if (HasInitialRegExpMap(isolate, recv)) {
+  if (HasInitialRegExpMap(isolate, *recv)) {
     JSRegExp::cast(*recv)->SetLastIndex(value);
     return recv;
   } else {
@@ -55,7 +55,7 @@
 
 MaybeHandle<Object> RegExpUtils::GetLastIndex(Isolate* isolate,
                                               Handle<JSReceiver> recv) {
-  if (HasInitialRegExpMap(isolate, recv)) {
+  if (HasInitialRegExpMap(isolate, *recv)) {
     return handle(JSRegExp::cast(*recv)->LastIndex(), isolate);
   } else {
     return Object::GetProperty(recv, isolate->factory()->lastIndex_string());
@@ -142,9 +142,7 @@
 
   JSReceiver* recv = JSReceiver::cast(*obj);
 
-  // Check the receiver's map.
-  Handle<JSFunction> regexp_function = isolate->regexp_function();
-  if (recv->map() != regexp_function->initial_map()) return false;
+  if (!HasInitialRegExpMap(isolate, recv)) return false;
 
   // Check the receiver's prototype's map.
   Object* proto = recv->map()->prototype();
diff --git a/src/runtime/runtime-regexp.cc b/src/runtime/runtime-regexp.cc
index d572eed..7f7428f 100644
--- a/src/runtime/runtime-regexp.cc
+++ b/src/runtime/runtime-regexp.cc
@@ -1147,7 +1147,7 @@
 MUST_USE_RESULT MaybeHandle<String> RegExpReplace(Isolate* isolate,
                                                   Handle<JSRegExp> regexp,
                                                   Handle<String> string,
-                                                  Handle<Object> replace_obj) {
+                                                  Handle<String> replace) {
   Factory* factory = isolate->factory();
 
   // TODO(jgruber): We need the even stricter guarantee of an unmodified
@@ -1155,12 +1155,6 @@
   const int flags = regexp->GetFlags();
   const bool global = (flags & JSRegExp::kGlobal) != 0;
 
-  // Functional fast-paths are dispatched directly by replace builtin.
-  DCHECK(!replace_obj->IsCallable());
-
-  Handle<String> replace;
-  ASSIGN_RETURN_ON_EXCEPTION(isolate, replace,
-                             Object::ToString(isolate, replace_obj), String);
   replace = String::Flatten(replace);
 
   Handle<RegExpMatchInfo> last_match_info = isolate->regexp_last_match_info();
@@ -1243,18 +1237,23 @@
   CONVERT_ARG_HANDLE_CHECKED(String, subject, 1);
   CONVERT_ARG_HANDLE_CHECKED(RegExpMatchInfo, last_match_info, 2);
   CONVERT_ARG_HANDLE_CHECKED(JSArray, result_array, 3);
+
+  DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
   CHECK(result_array->HasFastObjectElements());
 
   subject = String::Flatten(subject);
   CHECK(regexp->GetFlags() & JSRegExp::kGlobal);
 
+  Object* result;
   if (regexp->CaptureCount() == 0) {
-    return SearchRegExpMultiple<false>(isolate, subject, regexp,
-                                       last_match_info, result_array);
+    result = SearchRegExpMultiple<false>(isolate, subject, regexp,
+                                         last_match_info, result_array);
   } else {
-    return SearchRegExpMultiple<true>(isolate, subject, regexp, last_match_info,
-                                      result_array);
+    result = SearchRegExpMultiple<true>(isolate, subject, regexp,
+                                        last_match_info, result_array);
   }
+  DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, regexp));
+  return result;
 }
 
 RUNTIME_FUNCTION(Runtime_StringReplaceNonGlobalRegExpWithFunction) {
@@ -1284,14 +1283,6 @@
 
   string = String::Flatten(string);
 
-  // Fast-path for unmodified JSRegExps.
-  if (RegExpUtils::IsUnmodifiedRegExp(isolate, recv)) {
-    RETURN_RESULT_OR_FAILURE(
-        isolate, RegExpReplace(isolate, Handle<JSRegExp>::cast(recv), string,
-                               replace_obj));
-  }
-
-  const int length = string->length();
   const bool functional_replace = replace_obj->IsCallable();
 
   Handle<String> replace;
@@ -1300,6 +1291,21 @@
                                        Object::ToString(isolate, replace_obj));
   }
 
+  // Fast-path for unmodified JSRegExps (and non-functional replace).
+  if (RegExpUtils::IsUnmodifiedRegExp(isolate, recv)) {
+    // We should never get here with functional replace because unmodified
+    // regexp and functional replace should be fully handled in CSA code.
+    CHECK(!functional_replace);
+    Handle<Object> result;
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+        isolate, result,
+        RegExpReplace(isolate, Handle<JSRegExp>::cast(recv), string, replace));
+    DCHECK(RegExpUtils::IsUnmodifiedRegExp(isolate, recv));
+    return *result;
+  }
+
+  const uint32_t length = string->length();
+
   Handle<Object> global_obj;
   ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
       isolate, global_obj,
@@ -1382,7 +1388,7 @@
     ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
         isolate, position_obj, Object::ToInteger(isolate, position_obj));
     const int position =
-        std::max(std::min(Handle<Smi>::cast(position_obj)->value(), length), 0);
+        std::max(std::min(Handle<Smi>::cast(position_obj)->value(), (int)length), 0);
 
     ZoneVector<Handle<Object>> captures(&zone);
     for (int n = 0; n < captures_length; n++) {