[regexp] Remove remainder of native RegExpExecStub

If we avoid throwing a stack overflow exception from Irregexp code during
direct calls, there is no need to construct exit frames before the Irregexp
call anymore. As that was the last remaining blocker, we can now implement the
entire stub in CSA.

BUG=v8:5339

Review-Url: https://codereview.chromium.org/2752143003
Cr-Original-Commit-Position: refs/heads/master@{#44770}
Committed: https://chromium.googlesource.com/v8/v8/+/74f2497eae068f85da26904d8c451376c77957bf
Review-Url: https://codereview.chromium.org/2752143003
Cr-Commit-Position: refs/heads/master@{#44775}
diff --git a/src/arm/code-stubs-arm.cc b/src/arm/code-stubs-arm.cc
index 9bdc485..2459f98 100644
--- a/src/arm/code-stubs-arm.cc
+++ b/src/arm/code-stubs-arm.cc
@@ -1145,75 +1145,6 @@
   __ ldm(ia_w, sp, kCalleeSaved | pc.bit());
 }
 
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
-  // This case is handled prior to the RegExpExecStub call.
-  __ Abort(kUnexpectedRegExpExecCall);
-#else  // V8_INTERPRETED_REGEXP
-  // Isolates: note we add an additional parameter here (isolate pointer).
-  const int kRegExpExecuteArguments = 9;
-  const int kParameterRegisters = 4;
-  __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
-
-  // Stack pointer now points to cell where return address is to be written.
-  // Arguments are before that on the stack or in registers.
-
-  // Argument 9 (sp[20]): Pass current isolate address.
-  __ mov(r5, Operand(ExternalReference::isolate_address(isolate())));
-  __ str(r5, MemOperand(sp, 5 * kPointerSize));
-
-  // Argument 8 (sp[16]): Indicate that this is a direct call from JavaScript.
-  __ mov(r5, Operand(1));
-  __ str(r5, MemOperand(sp, 4 * kPointerSize));
-
-  // Argument 7 (sp[12]): Start (high end) of backtracking stack memory area.
-  ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address(isolate());
-  ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size(isolate());
-  __ mov(r5, Operand(address_of_regexp_stack_memory_address));
-  __ ldr(r5, MemOperand(r5, 0));
-  __ mov(r6, Operand(address_of_regexp_stack_memory_size));
-  __ ldr(r6, MemOperand(r6, 0));
-  __ add(r5, r5, Operand(r6));
-  __ str(r5, MemOperand(sp, 3 * kPointerSize));
-
-  // Argument 6: Set the number of capture registers to zero to force global
-  // regexps to behave as non-global.  This does not affect non-global regexps.
-  __ mov(r5, Operand::Zero());
-  __ str(r5, MemOperand(sp, 2 * kPointerSize));
-
-  // Argument 5 (sp[4]): static offsets vector buffer.
-  __ mov(
-      r5,
-      Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
-  __ str(r5, MemOperand(sp, 1 * kPointerSize));
-
-  // Argument 4: End of string data
-  // Argument 3: Start of string data
-  CHECK(r3.is(RegExpExecDescriptor::StringEndRegister()));
-  CHECK(r2.is(RegExpExecDescriptor::StringStartRegister()));
-
-  // Argument 2 (r1): Previous index.
-  CHECK(r1.is(RegExpExecDescriptor::LastIndexRegister()));
-
-  // Argument 1 (r0): Subject string.
-  CHECK(r0.is(RegExpExecDescriptor::StringRegister()));
-
-  // Locate the code entry and call it.
-  Register code_reg = RegExpExecDescriptor::CodeRegister();
-  __ add(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
-
-  DirectCEntryStub stub(isolate());
-  stub.GenerateCall(masm, code_reg);
-
-  __ LeaveExitFrame(false, no_reg, true);
-
-  __ SmiTag(r0);
-  __ Ret();
-#endif  // V8_INTERPRETED_REGEXP
-}
-
 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
   // r0 : number of arguments to the construct function
   // r1 : the function to call
diff --git a/src/arm/interface-descriptors-arm.cc b/src/arm/interface-descriptors-arm.cc
index 7e56698..f4303b9 100644
--- a/src/arm/interface-descriptors-arm.cc
+++ b/src/arm/interface-descriptors-arm.cc
@@ -58,11 +58,6 @@
   return MathPowTaggedDescriptor::exponent();
 }
 
-const Register RegExpExecDescriptor::StringRegister() { return r0; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return r1; }
-const Register RegExpExecDescriptor::StringStartRegister() { return r2; }
-const Register RegExpExecDescriptor::StringEndRegister() { return r3; }
-const Register RegExpExecDescriptor::CodeRegister() { return r4; }
 
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return r0; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return r3; }
diff --git a/src/arm/simulator-arm.h b/src/arm/simulator-arm.h
index f5ebf21..9c92c96 100644
--- a/src/arm/simulator-arm.h
+++ b/src/arm/simulator-arm.h
@@ -27,18 +27,14 @@
 #define CALL_GENERATED_CODE(isolate, entry, p0, p1, p2, p3, p4) \
   (entry(p0, p1, p2, p3, p4))
 
-typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*,
-                                  void*, int*, int, Address, int, Isolate*);
-
+typedef int (*arm_regexp_matcher)(String*, int, const byte*, const byte*, int*,
+                                  int, Address, int, Isolate*);
 
 // Call the generated regexp code directly. The code at the entry address
 // should act as a function matching the type arm_regexp_matcher.
-// The fifth argument is a dummy that reserves the space used for
-// the return address added by the ExitFrame in native calls.
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
-  (FUNCTION_CAST<arm_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6,  \
-                                            p7, p8))
+  (FUNCTION_CAST<arm_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, p8))
 
 // The stack limit beyond which we will throw stack overflow errors in
 // generated code. Because generated code on arm uses the C stack, we
@@ -549,9 +545,8 @@
 
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
-  Simulator::current(isolate)                                                  \
-      ->Call(entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
-
+  Simulator::current(isolate)->Call(entry, 9, p0, p1, p2, p3, p4, p5, p6, p7,  \
+                                    p8)
 
 // The simulator has its own stack. Thus it has a different stack limit from
 // the C-based native code.  The JS-based limit normally points near the end of
diff --git a/src/arm64/code-stubs-arm64.cc b/src/arm64/code-stubs-arm64.cc
index ec00581..b327773 100644
--- a/src/arm64/code-stubs-arm64.cc
+++ b/src/arm64/code-stubs-arm64.cc
@@ -1267,73 +1267,6 @@
   __ Ret();
 }
 
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
-  // This case is handled prior to the RegExpExecStub call.
-  __ Abort(kUnexpectedRegExpExecCall);
-#else  // V8_INTERPRETED_REGEXP
-  // Isolates: note we add an additional parameter here (isolate pointer).
-  __ EnterExitFrame(false, x10, 1);
-  DCHECK(csp.Is(__ StackPointer()));
-
-  // We have 9 arguments to pass to the regexp code, therefore we have to pass
-  // one on the stack and the rest as registers.
-
-  // Note that the placement of the argument on the stack isn't standard
-  // AAPCS64:
-  // csp[0]: Space for the return address placed by DirectCEntryStub.
-  // csp[8]: Argument 9, the current isolate address.
-
-  __ Mov(x10, ExternalReference::isolate_address(isolate()));
-  __ Poke(x10, kPointerSize);
-
-  // Argument 1 (x0): Subject string.
-  CHECK(x0.is(RegExpExecDescriptor::StringRegister()));
-
-  // Argument 2 (x1): Previous index, already there.
-  CHECK(x1.is(RegExpExecDescriptor::LastIndexRegister()));
-
-  // Argument 3 (x2): Input start.
-  // Argument 4 (x3): Input end.
-  CHECK(x2.is(RegExpExecDescriptor::StringStartRegister()));
-  CHECK(x3.is(RegExpExecDescriptor::StringEndRegister()));
-
-  // Argument 5 (x4): static offsets vector buffer.
-  __ Mov(x4, ExternalReference::address_of_static_offsets_vector(isolate()));
-
-  // Argument 6 (x5): Set the number of capture registers to zero to force
-  // global regexps to behave as non-global. This stub is not used for global
-  // regexps.
-  __ Mov(x5, 0);
-
-  // Argument 7 (x6): Start (high end) of backtracking stack memory area.
-  ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address(isolate());
-  ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size(isolate());
-  __ Mov(x10, address_of_regexp_stack_memory_address);
-  __ Ldr(x10, MemOperand(x10));
-  __ Mov(x11, address_of_regexp_stack_memory_size);
-  __ Ldr(x11, MemOperand(x11));
-  __ Add(x6, x10, x11);
-
-  // Argument 8 (x7): Indicate that this is a direct call from JavaScript.
-  __ Mov(x7, 1);
-
-  // Locate the code entry and call it.
-  Register code_object = RegExpExecDescriptor::CodeRegister();
-  __ Add(code_object, code_object, Code::kHeaderSize - kHeapObjectTag);
-  DirectCEntryStub stub(isolate());
-  stub.GenerateCall(masm, code_object);
-
-  __ LeaveExitFrame(false, x10, true);
-
-  // Return the smi-tagged result.
-  __ SmiTag(x0);
-  __ Ret();
-#endif
-}
-
 
 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub,
                                        Register argc, Register function,
diff --git a/src/arm64/interface-descriptors-arm64.cc b/src/arm64/interface-descriptors-arm64.cc
index c73d371..0555a00 100644
--- a/src/arm64/interface-descriptors-arm64.cc
+++ b/src/arm64/interface-descriptors-arm64.cc
@@ -57,11 +57,6 @@
 
 const Register MathPowIntegerDescriptor::exponent() { return x12; }
 
-const Register RegExpExecDescriptor::StringRegister() { return x0; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return x1; }
-const Register RegExpExecDescriptor::StringStartRegister() { return x2; }
-const Register RegExpExecDescriptor::StringEndRegister() { return x3; }
-const Register RegExpExecDescriptor::CodeRegister() { return x8; }
 
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return x0; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return x3; }
diff --git a/src/arm64/simulator-arm64.cc b/src/arm64/simulator-arm64.cc
index b536fd5..c8a26e4 100644
--- a/src/arm64/simulator-arm64.cc
+++ b/src/arm64/simulator-arm64.cc
@@ -208,7 +208,6 @@
                               int64_t output_size,
                               Address stack_base,
                               int64_t direct_call,
-                              void* return_address,
                               Isolate* isolate) {
   CallArgument args[] = {
     CallArgument(input),
@@ -219,7 +218,6 @@
     CallArgument(output_size),
     CallArgument(stack_base),
     CallArgument(direct_call),
-    CallArgument(return_address),
     CallArgument(isolate),
     CallArgument::End()
   };
diff --git a/src/arm64/simulator-arm64.h b/src/arm64/simulator-arm64.h
index 3016e61..e700b4c 100644
--- a/src/arm64/simulator-arm64.h
+++ b/src/arm64/simulator-arm64.h
@@ -41,12 +41,10 @@
 
 // Call the generated regexp code directly. The code at the entry address
 // should act as a function matching the type arm64_regexp_matcher.
-// The ninth argument is a dummy that reserves the space used for
-// the return address added by the ExitFrame in native calls.
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
   (FUNCTION_CAST<arm64_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7,  \
-                                              NULL, p8))
+                                              p8))
 
 // Running without a simulator there is nothing to do.
 class SimulatorStack : public v8::internal::AllStatic {
@@ -201,7 +199,6 @@
                      int64_t output_size,
                      Address stack_base,
                      int64_t direct_call,
-                     void* return_address,
                      Isolate* isolate);
 
   // A wrapper class that stores an argument for one of the above Call
@@ -973,8 +970,7 @@
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
   static_cast<int>(Simulator::current(isolate)->CallRegExp(                    \
-      entry, p0, p1, p2, p3, p4, p5, p6, p7, NULL, p8))
-
+      entry, p0, p1, p2, p3, p4, p5, p6, p7, p8))
 
 // The simulator has its own stack. Thus it has a different stack limit from
 // the C-based native code.  The JS-based limit normally points near the end of
diff --git a/src/bailout-reason.h b/src/bailout-reason.h
index 1ae7df5..2797851 100644
--- a/src/bailout-reason.h
+++ b/src/bailout-reason.h
@@ -234,7 +234,6 @@
   V(kUnexpectedStringType, "Unexpected string type")                           \
   V(kUnexpectedTestTypeofLiteralFlag,                                          \
     "Unexpected literal flag for TestTypeof bytecode")                         \
-  V(kUnexpectedRegExpExecCall, "Unexpected call to the RegExpExecStub")        \
   V(kUnexpectedValue, "Unexpected value")                                      \
   V(kUnsupportedDoubleImmediate, "Unsupported double immediate")               \
   V(kUnsupportedLetCompoundAssignment, "Unsupported let compound assignment")  \
diff --git a/src/builtins/builtins-regexp-gen.cc b/src/builtins/builtins-regexp-gen.cc
index f1169c0..d1fb9e8 100644
--- a/src/builtins/builtins-regexp-gen.cc
+++ b/src/builtins/builtins-regexp-gen.cc
@@ -231,11 +231,11 @@
   var_string_end->Bind(IntPtrAdd(string_data, to_offset));
 }
 
-Node* RegExpBuiltinsAssembler::IrregexpExec(Node* const context,
-                                            Node* const regexp,
-                                            Node* const string,
-                                            Node* const last_index,
-                                            Node* const match_info) {
+Node* RegExpBuiltinsAssembler::RegExpExecInternal(Node* const context,
+                                                  Node* const regexp,
+                                                  Node* const string,
+                                                  Node* const last_index,
+                                                  Node* const match_info) {
 // Just jump directly to runtime if native RegExp is not selected at compile
 // time or if regexp entry in generated code is turned off runtime switch or
 // at compilation.
@@ -260,12 +260,14 @@
   Label out(this), runtime(this, Label::kDeferred);
 
   // External constants.
+  Node* const isolate_address =
+      ExternalConstant(ExternalReference::isolate_address(isolate()));
+  Node* const regexp_stack_memory_address_address = ExternalConstant(
+      ExternalReference::address_of_regexp_stack_memory_address(isolate()));
   Node* const regexp_stack_memory_size_address = ExternalConstant(
       ExternalReference::address_of_regexp_stack_memory_size(isolate()));
   Node* const static_offsets_vector_address = ExternalConstant(
       ExternalReference::address_of_static_offsets_vector(isolate()));
-  Node* const pending_exception_address = ExternalConstant(
-      ExternalReference(Isolate::kPendingExceptionAddress, isolate()));
 
   // Ensure that a RegExp stack is allocated.
   {
@@ -361,22 +363,85 @@
   {
     IncrementCounter(isolate()->counters()->regexp_entry_native(), 1);
 
-    Callable exec_callable = CodeFactory::RegExpExec(isolate());
-    Node* const result = CallStub(
-        exec_callable, context, string, TruncateWordToWord32(int_last_index),
-        var_string_start.value(), var_string_end.value(), code);
+    // Set up args for the final call into generated Irregexp code.
+
+    MachineType type_int32 = MachineType::Int32();
+    MachineType type_tagged = MachineType::AnyTagged();
+    MachineType type_ptr = MachineType::Pointer();
+
+    // Result: A NativeRegExpMacroAssembler::Result return code.
+    MachineType retval_type = type_int32;
+
+    // Argument 0: Original subject string.
+    MachineType arg0_type = type_tagged;
+    Node* const arg0 = string;
+
+    // Argument 1: Previous index.
+    MachineType arg1_type = type_int32;
+    Node* const arg1 = TruncateWordToWord32(int_last_index);
+
+    // Argument 2: Start of string data.
+    MachineType arg2_type = type_ptr;
+    Node* const arg2 = var_string_start.value();
+
+    // Argument 3: End of string data.
+    MachineType arg3_type = type_ptr;
+    Node* const arg3 = var_string_end.value();
+
+    // Argument 4: static offsets vector buffer.
+    MachineType arg4_type = type_ptr;
+    Node* const arg4 = static_offsets_vector_address;
+
+    // Argument 5: Set the number of capture registers to zero to force global
+    // regexps to behave as non-global.  This does not affect non-global
+    // regexps.
+    MachineType arg5_type = type_int32;
+    Node* const arg5 = Int32Constant(0);
+
+    // Argument 6: Start (high end) of backtracking stack memory area.
+    Node* const stack_start =
+        Load(MachineType::Pointer(), regexp_stack_memory_address_address);
+    Node* const stack_size =
+        Load(MachineType::IntPtr(), regexp_stack_memory_size_address);
+    Node* const stack_end = IntPtrAdd(stack_start, stack_size);
+
+    MachineType arg6_type = type_ptr;
+    Node* const arg6 = stack_end;
+
+    // Argument 7: Indicate that this is a direct call from JavaScript.
+    MachineType arg7_type = type_int32;
+    Node* const arg7 = Int32Constant(1);
+
+    // Argument 8: Pass current isolate address.
+    MachineType arg8_type = type_ptr;
+    Node* const arg8 = isolate_address;
+
+    Node* const code_entry =
+        IntPtrAdd(BitcastTaggedToWord(code),
+                  IntPtrConstant(Code::kHeaderSize - kHeapObjectTag));
+
+    Node* const result = CallCFunction9(
+        retval_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
+        arg5_type, arg6_type, arg7_type, arg8_type, code_entry, arg0, arg1,
+        arg2, arg3, arg4, arg5, arg6, arg7, arg8);
 
     // Check the result.
-    // We expect exactly one result since the stub forces the called regexp to
-    // behave as non-global.
-    GotoIf(SmiEqual(result, SmiConstant(1)), &if_success);
-    GotoIf(SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::FAILURE)),
+    // We expect exactly one result since we force the called regexp to behave
+    // as non-global.
+    Node* const int_result = ChangeInt32ToIntPtr(result);
+    GotoIf(IntPtrEqual(int_result,
+                       IntPtrConstant(NativeRegExpMacroAssembler::SUCCESS)),
+           &if_success);
+    GotoIf(IntPtrEqual(int_result,
+                       IntPtrConstant(NativeRegExpMacroAssembler::FAILURE)),
            &if_failure);
-    GotoIf(SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::EXCEPTION)),
+    GotoIf(IntPtrEqual(int_result,
+                       IntPtrConstant(NativeRegExpMacroAssembler::EXCEPTION)),
            &if_exception);
 
-    CSA_ASSERT(
-        this, SmiEqual(result, SmiConstant(NativeRegExpMacroAssembler::RETRY)));
+    CSA_ASSERT(this,
+               IntPtrEqual(int_result,
+                           IntPtrConstant(NativeRegExpMacroAssembler::RETRY)));
     Goto(&runtime);
   }
 
@@ -440,22 +505,15 @@
 
   BIND(&if_exception);
   {
-    Node* const pending_exception =
-        Load(MachineType::AnyTagged(), pending_exception_address);
-
-    // If there is no pending exception, a
-    // stack overflow (on the backtrack stack) was detected in RegExp code.
-
-    Label stack_overflow(this), rethrow(this);
-    Branch(IsTheHole(pending_exception), &stack_overflow, &rethrow);
-
-    BIND(&stack_overflow);
+// A stack overflow was detected in RegExp code.
+#ifdef DEBUG
+    Node* const pending_exception_address = ExternalConstant(
+        ExternalReference(Isolate::kPendingExceptionAddress, isolate()));
+    CSA_ASSERT(this, IsTheHole(Load(MachineType::AnyTagged(),
+                                    pending_exception_address)));
+#endif  // DEBUG
     CallRuntime(Runtime::kThrowStackOverflow, context);
     Unreachable();
-
-    BIND(&rethrow);
-    CallRuntime(Runtime::kRegExpExecReThrow, context);
-    Unreachable();
   }
 
   BIND(&runtime);
@@ -571,8 +629,8 @@
         native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
 
     // Call the exec stub.
-    match_indices = IrregexpExec(context, regexp, string, var_lastindex.value(),
-                                 last_match_info);
+    match_indices = RegExpExecInternal(context, regexp, string,
+                                       var_lastindex.value(), last_match_info);
     var_result.Bind(match_indices);
 
     // {match_indices} is either null or the RegExpMatchInfo array.
@@ -2104,8 +2162,8 @@
       Node* const last_match_info = LoadContextElement(
           native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
 
-      Node* const match_indices =
-          IrregexpExec(context, regexp, string, smi_zero, last_match_info);
+      Node* const match_indices = RegExpExecInternal(context, regexp, string,
+                                                     smi_zero, last_match_info);
 
       Label return_singleton_array(this);
       Branch(WordEqual(match_indices, null), &return_singleton_array,
@@ -2166,8 +2224,8 @@
     Node* const last_match_info = LoadContextElement(
         native_context, Context::REGEXP_LAST_MATCH_INFO_INDEX);
 
-    Node* const match_indices = IrregexpExec(context, regexp, string,
-                                             next_search_from, last_match_info);
+    Node* const match_indices = RegExpExecInternal(
+        context, regexp, string, next_search_from, last_match_info);
 
     // We're done if no match was found.
     {
@@ -2848,8 +2906,8 @@
   Node* const internal_match_info = LoadContextElement(
       native_context, Context::REGEXP_INTERNAL_MATCH_INFO_INDEX);
 
-  Node* const match_indices =
-      IrregexpExec(context, regexp, string, smi_zero, internal_match_info);
+  Node* const match_indices = RegExpExecInternal(context, regexp, string,
+                                                 smi_zero, internal_match_info);
 
   Label if_matched(this), if_didnotmatch(this);
   Branch(WordEqual(match_indices, null), &if_didnotmatch, &if_matched);
diff --git a/src/builtins/builtins-regexp-gen.h b/src/builtins/builtins-regexp-gen.h
index 0f66ebf..3db92f1 100644
--- a/src/builtins/builtins-regexp-gen.h
+++ b/src/builtins/builtins-regexp-gen.h
@@ -36,10 +36,10 @@
                          String::Encoding encoding, Variable* var_string_start,
                          Variable* var_string_end);
 
-  // Low level logic around the actual call into generated Irregexp code.
-  Node* IrregexpExec(Node* const context, Node* const regexp,
-                     Node* const string, Node* const last_index,
-                     Node* const match_info);
+  // Low level logic around the actual call into pattern matching code.
+  Node* RegExpExecInternal(Node* const context, Node* const regexp,
+                           Node* const string, Node* const last_index,
+                           Node* const match_info);
 
   Node* ConstructNewResultFromMatchInfo(Node* const context, Node* const regexp,
                                         Node* const match_info,
diff --git a/src/code-factory.cc b/src/code-factory.cc
index 71fbb1d..49dd7c7 100644
--- a/src/code-factory.cc
+++ b/src/code-factory.cc
@@ -232,12 +232,6 @@
 }
 
 // static
-Callable CodeFactory::RegExpExec(Isolate* isolate) {
-  RegExpExecStub stub(isolate);
-  return Callable(stub.GetCode(), stub.GetCallInterfaceDescriptor());
-}
-
-// static
 Callable CodeFactory::StringFromCharCode(Isolate* isolate) {
   Handle<Code> code(isolate->builtins()->StringFromCharCode());
   return Callable(code, BuiltinDescriptor(isolate));
diff --git a/src/code-factory.h b/src/code-factory.h
index 669f379..e5653b8 100644
--- a/src/code-factory.h
+++ b/src/code-factory.h
@@ -91,8 +91,6 @@
                                       OrdinaryToPrimitiveHint hint);
   static Callable NumberToString(Isolate* isolate);
 
-  static Callable RegExpExec(Isolate* isolate);
-
   static Callable Add(Isolate* isolate);
   static Callable Subtract(Isolate* isolate);
   static Callable Multiply(Isolate* isolate);
diff --git a/src/code-stubs.h b/src/code-stubs.h
index b3269ea..bfacf6c 100644
--- a/src/code-stubs.h
+++ b/src/code-stubs.h
@@ -45,7 +45,6 @@
   V(MathPow)                                  \
   V(ProfileEntryHook)                         \
   V(RecordWrite)                              \
-  V(RegExpExec)                               \
   V(StoreBufferOverflow)                      \
   V(StoreSlowElement)                         \
   V(SubString)                                \
@@ -1136,15 +1135,6 @@
   DEFINE_PLATFORM_CODE_STUB(JSEntry, PlatformCodeStub);
 };
 
-
-class RegExpExecStub: public PlatformCodeStub {
- public:
-  explicit RegExpExecStub(Isolate* isolate) : PlatformCodeStub(isolate) { }
-
-  DEFINE_CALL_INTERFACE_DESCRIPTOR(RegExpExec);
-  DEFINE_PLATFORM_CODE_STUB(RegExpExec, PlatformCodeStub);
-};
-
 // TODO(bmeurer/mvstanton): Turn CallConstructStub into ConstructICStub.
 class CallConstructStub final : public PlatformCodeStub {
  public:
diff --git a/src/compiler/code-assembler.cc b/src/compiler/code-assembler.cc
index cc1ef80..9e528dd 100644
--- a/src/compiler/code-assembler.cc
+++ b/src/compiler/code-assembler.cc
@@ -743,6 +743,18 @@
       arg5_type, function, arg0, arg1, arg2, arg3, arg4, arg5);
 }
 
+Node* CodeAssembler::CallCFunction9(
+    MachineType return_type, MachineType arg0_type, MachineType arg1_type,
+    MachineType arg2_type, MachineType arg3_type, MachineType arg4_type,
+    MachineType arg5_type, MachineType arg6_type, MachineType arg7_type,
+    MachineType arg8_type, Node* function, Node* arg0, Node* arg1, Node* arg2,
+    Node* arg3, Node* arg4, Node* arg5, Node* arg6, Node* arg7, Node* arg8) {
+  return raw_assembler()->CallCFunction9(
+      return_type, arg0_type, arg1_type, arg2_type, arg3_type, arg4_type,
+      arg5_type, arg6_type, arg7_type, arg8_type, function, arg0, arg1, arg2,
+      arg3, arg4, arg5, arg6, arg7, arg8);
+}
+
 void CodeAssembler::Goto(Label* label) {
   label->MergeVariables();
   raw_assembler()->Goto(label->label_);
diff --git a/src/compiler/code-assembler.h b/src/compiler/code-assembler.h
index c79780c..1f2e4d8 100644
--- a/src/compiler/code-assembler.h
+++ b/src/compiler/code-assembler.h
@@ -429,6 +429,16 @@
                        Node* arg1, Node* arg2, Node* arg3, Node* arg4,
                        Node* arg5);
 
+  // Call to a C function with nine arguments.
+  Node* CallCFunction9(MachineType return_type, MachineType arg0_type,
+                       MachineType arg1_type, MachineType arg2_type,
+                       MachineType arg3_type, MachineType arg4_type,
+                       MachineType arg5_type, MachineType arg6_type,
+                       MachineType arg7_type, MachineType arg8_type,
+                       Node* function, Node* arg0, Node* arg1, Node* arg2,
+                       Node* arg3, Node* arg4, Node* arg5, Node* arg6,
+                       Node* arg7, Node* arg8);
+
   // Exception handling support.
   void GotoIfException(Node* node, Label* if_exception,
                        Variable* exception_var = nullptr);
diff --git a/src/ia32/code-stubs-ia32.cc b/src/ia32/code-stubs-ia32.cc
index 56ce2c5..0afefc3 100644
--- a/src/ia32/code-stubs-ia32.cc
+++ b/src/ia32/code-stubs-ia32.cc
@@ -462,69 +462,6 @@
   __ ret(0);
 }
 
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
-  // This case is handled prior to the RegExpExecStub call.
-  __ Abort(kUnexpectedRegExpExecCall);
-#else  // V8_INTERPRETED_REGEXP
-  // Isolates: note we add an additional parameter here (isolate pointer).
-  static const int kRegExpExecuteArguments = 9;
-  __ EnterApiExitFrame(kRegExpExecuteArguments);
-
-  // Argument 9: Pass current isolate address.
-  __ mov(Operand(esp, 8 * kPointerSize),
-      Immediate(ExternalReference::isolate_address(isolate())));
-
-  // Argument 8: Indicate that this is a direct call from JavaScript.
-  __ mov(Operand(esp, 7 * kPointerSize), Immediate(1));
-
-  // Argument 7: Start (high end) of backtracking stack memory area.
-  ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address(isolate());
-  ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size(isolate());
-  __ mov(esi, Operand::StaticVariable(address_of_regexp_stack_memory_address));
-  __ add(esi, Operand::StaticVariable(address_of_regexp_stack_memory_size));
-  __ mov(Operand(esp, 6 * kPointerSize), esi);
-
-  // Argument 6: Set the number of capture registers to zero to force global
-  // regexps to behave as non-global.  This does not affect non-global regexps.
-  __ mov(Operand(esp, 5 * kPointerSize), Immediate(0));
-
-  // Argument 5: static offsets vector buffer.
-  __ mov(Operand(esp, 4 * kPointerSize),
-         Immediate(ExternalReference::address_of_static_offsets_vector(
-             isolate())));
-
-  // Argument 4: End of string data
-  // Argument 3: Start of string data
-  __ mov(Operand(esp, 3 * kPointerSize),
-         RegExpExecDescriptor::StringEndRegister());
-  __ mov(Operand(esp, 2 * kPointerSize),
-         RegExpExecDescriptor::StringStartRegister());
-
-  // Argument 2: Previous index.
-  __ mov(Operand(esp, 1 * kPointerSize),
-         RegExpExecDescriptor::LastIndexRegister());
-
-  // Argument 1: Original subject string.
-  __ mov(Operand(esp, 0 * kPointerSize),
-         RegExpExecDescriptor::StringRegister());
-
-  // Locate the code entry and call it.
-  __ add(RegExpExecDescriptor::CodeRegister(),
-         Immediate(Code::kHeaderSize - kHeapObjectTag));
-  __ call(RegExpExecDescriptor::CodeRegister());
-
-  // Drop arguments and come back to JS mode.
-  __ LeaveApiExitFrame(true);
-
-  // TODO(jgruber): Don't tag return value once this is supported by stubs.
-  __ SmiTag(eax);
-  __ ret(0 * kPointerSize);
-#endif  // V8_INTERPRETED_REGEXP
-}
-
 
 static int NegativeComparisonResult(Condition cc) {
   DCHECK(cc != equal);
diff --git a/src/ia32/interface-descriptors-ia32.cc b/src/ia32/interface-descriptors-ia32.cc
index 304191b..c49a6fd 100644
--- a/src/ia32/interface-descriptors-ia32.cc
+++ b/src/ia32/interface-descriptors-ia32.cc
@@ -56,11 +56,6 @@
   return MathPowTaggedDescriptor::exponent();
 }
 
-const Register RegExpExecDescriptor::StringRegister() { return eax; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return ecx; }
-const Register RegExpExecDescriptor::StringStartRegister() { return edx; }
-const Register RegExpExecDescriptor::StringEndRegister() { return ebx; }
-const Register RegExpExecDescriptor::CodeRegister() { return edi; }
 
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return eax; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return ebx; }
diff --git a/src/interface-descriptors.cc b/src/interface-descriptors.cc
index a5dccc3..619af3f 100644
--- a/src/interface-descriptors.cc
+++ b/src/interface-descriptors.cc
@@ -492,24 +492,6 @@
                                       machine_types);
 }
 
-void RegExpExecDescriptor::InitializePlatformIndependent(
-    CallInterfaceDescriptorData* data) {
-  // kString, kLastIndex, kStringStart, kStringEnd, kEntryPoint
-  MachineType machine_types[] = {MachineType::AnyTagged(), MachineType::Int32(),
-                                 MachineType::Pointer(), MachineType::Pointer(),
-                                 MachineType::AnyTagged()};
-  data->InitializePlatformIndependent(arraysize(machine_types), 0,
-                                      machine_types);
-}
-
-void RegExpExecDescriptor::InitializePlatformSpecific(
-    CallInterfaceDescriptorData* data) {
-  Register registers[] = {StringRegister(), LastIndexRegister(),
-                          StringStartRegister(), StringEndRegister(),
-                          CodeRegister()};
-  data->InitializePlatformSpecific(arraysize(registers), registers);
-}
-
 void BuiltinDescriptor::InitializePlatformIndependent(
     CallInterfaceDescriptorData* data) {
   // kTarget, kNewTarget, kArgumentsCount
diff --git a/src/interface-descriptors.h b/src/interface-descriptors.h
index b97c45c..4a42862 100644
--- a/src/interface-descriptors.h
+++ b/src/interface-descriptors.h
@@ -49,7 +49,6 @@
   V(CallTrampoline)                        \
   V(ConstructStub)                         \
   V(ConstructTrampoline)                   \
-  V(RegExpExec)                            \
   V(TransitionElementsKind)                \
   V(AllocateHeapNumber)                    \
   V(Builtin)                               \
@@ -613,19 +612,6 @@
   DECLARE_DESCRIPTOR(CallConstructDescriptor, CallInterfaceDescriptor)
 };
 
-class RegExpExecDescriptor : public CallInterfaceDescriptor {
- public:
-  DEFINE_PARAMETERS(kString, kLastIndex, kStringStart, kStringEnd, kCode)
-  DECLARE_DESCRIPTOR_WITH_CUSTOM_FUNCTION_TYPE(RegExpExecDescriptor,
-                                               CallInterfaceDescriptor)
-
-  static const Register StringRegister();
-  static const Register LastIndexRegister();
-  static const Register StringStartRegister();
-  static const Register StringEndRegister();
-  static const Register CodeRegister();
-};
-
 class TransitionElementsKindDescriptor : public CallInterfaceDescriptor {
  public:
   DEFINE_PARAMETERS(kObject, kMap)
diff --git a/src/mips/code-stubs-mips.cc b/src/mips/code-stubs-mips.cc
index 2f5fa2c..8dbf184 100644
--- a/src/mips/code-stubs-mips.cc
+++ b/src/mips/code-stubs-mips.cc
@@ -1271,87 +1271,6 @@
   __ Jump(ra);
 }
 
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
-  // This case is handled prior to the RegExpExecStub call.
-  __ Abort(kUnexpectedRegExpExecCall);
-#else  // V8_INTERPRETED_REGEXP
-  // Isolates: note we add an additional parameter here (isolate pointer).
-  const int kRegExpExecuteArguments = 9;
-  const int kParameterRegisters = 4;
-  __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
-
-  // Stack pointer now points to cell where return address is to be written.
-  // Arguments are before that on the stack or in registers, meaning we
-  // treat the return address as argument 5. Thus every argument after that
-  // needs to be shifted back by 1. Since DirectCEntryStub will handle
-  // allocating space for the c argument slots, we don't need to calculate
-  // that into the argument positions on the stack. This is how the stack will
-  // look (sp meaning the value of sp at this moment):
-  // [sp + 5] - Argument 9
-  // [sp + 4] - Argument 8
-  // [sp + 3] - Argument 7
-  // [sp + 2] - Argument 6
-  // [sp + 1] - Argument 5
-  // [sp + 0] - saved ra
-
-  // Argument 9: Pass current isolate address.
-  // CFunctionArgumentOperand handles MIPS stack argument slots.
-  __ li(t1, Operand(ExternalReference::isolate_address(isolate())));
-  __ sw(t1, MemOperand(sp, 5 * kPointerSize));
-
-  // Argument 8: Indicate that this is a direct call from JavaScript.
-  __ li(t1, Operand(1));
-  __ sw(t1, MemOperand(sp, 4 * kPointerSize));
-
-  // Argument 7: Start (high end) of backtracking stack memory area.
-  ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address(isolate());
-  ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size(isolate());
-  __ li(t1, Operand(address_of_regexp_stack_memory_address));
-  __ lw(t1, MemOperand(t1, 0));
-  __ li(t2, Operand(address_of_regexp_stack_memory_size));
-  __ lw(t2, MemOperand(t2, 0));
-  __ addu(t1, t1, t2);
-  __ sw(t1, MemOperand(sp, 3 * kPointerSize));
-
-  // Argument 6: Set the number of capture registers to zero to force global
-  // regexps to behave as non-global.  This does not affect non-global regexps.
-  __ mov(t1, zero_reg);
-  __ sw(t1, MemOperand(sp, 2 * kPointerSize));
-
-  // Argument 5: static offsets vector buffer.
-  __ li(
-      t1,
-      Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
-  __ sw(t1, MemOperand(sp, 1 * kPointerSize));
-
-  // Argument 4, a3: End of string data
-  // Argument 3, a2: Start of string data
-  CHECK(a3.is(RegExpExecDescriptor::StringEndRegister()));
-  CHECK(a2.is(RegExpExecDescriptor::StringStartRegister()));
-
-  // Argument 2 (a1): Previous index.
-  CHECK(a1.is(RegExpExecDescriptor::LastIndexRegister()));
-
-  // Argument 1 (a0): Subject string.
-  CHECK(a0.is(RegExpExecDescriptor::StringRegister()));
-
-  // Locate the code entry and call it.
-  Register code_reg = RegExpExecDescriptor::CodeRegister();
-  __ Addu(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
-  DirectCEntryStub stub(isolate());
-  stub.GenerateCall(masm, code_reg);
-
-  __ LeaveExitFrame(false, no_reg, true);
-
-  // Return the smi-tagged result.
-  __ SmiTag(v0);
-  __ Ret();
-#endif  // V8_INTERPRETED_REGEXP
-}
-
 
 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
   // a0 : number of arguments to the construct function
diff --git a/src/mips/interface-descriptors-mips.cc b/src/mips/interface-descriptors-mips.cc
index 6e77ee8..2fea9a8 100644
--- a/src/mips/interface-descriptors-mips.cc
+++ b/src/mips/interface-descriptors-mips.cc
@@ -56,11 +56,6 @@
   return MathPowTaggedDescriptor::exponent();
 }
 
-const Register RegExpExecDescriptor::StringRegister() { return a0; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return a1; }
-const Register RegExpExecDescriptor::StringStartRegister() { return a2; }
-const Register RegExpExecDescriptor::StringEndRegister() { return a3; }
-const Register RegExpExecDescriptor::CodeRegister() { return t0; }
 
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return a0; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return a3; }
diff --git a/src/mips/simulator-mips.h b/src/mips/simulator-mips.h
index 2785f91..53c0f23 100644
--- a/src/mips/simulator-mips.h
+++ b/src/mips/simulator-mips.h
@@ -32,12 +32,10 @@
 
 // Call the generated regexp code directly. The code at the entry address
 // should act as a function matching the type arm_regexp_matcher.
-// The fifth argument is a dummy that reserves the space used for
-// the return address added by the ExitFrame in native calls.
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
-  (FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, NULL, p4, p5, p6, \
-                                             p7, p8))
+  (FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7,   \
+                                             p8))
 
 // The stack limit beyond which we will throw stack overflow errors in
 // generated code. Because generated code on mips uses the C stack, we
@@ -530,9 +528,8 @@
 
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
-  Simulator::current(isolate)                                                  \
-      ->Call(entry, 10, p0, p1, p2, p3, NULL, p4, p5, p6, p7, p8)
-
+  Simulator::current(isolate)->Call(entry, 9, p0, p1, p2, p3, p4, p5, p6, p7,  \
+                                    p8)
 
 // The simulator has its own stack. Thus it has a different stack limit from
 // the C-based native code.  The JS-based limit normally points near the end of
diff --git a/src/mips64/code-stubs-mips64.cc b/src/mips64/code-stubs-mips64.cc
index 7ea89d2..4a0e51a 100644
--- a/src/mips64/code-stubs-mips64.cc
+++ b/src/mips64/code-stubs-mips64.cc
@@ -1266,86 +1266,6 @@
   __ Jump(ra);
 }
 
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
-  // This case is handled prior to the RegExpExecStub call.
-  __ Abort(kUnexpectedRegExpExecCall);
-#else  // V8_INTERPRETED_REGEXP
-  // Isolates: note we add an additional parameter here (isolate pointer).
-  const int kRegExpExecuteArguments = 9;
-  const int kParameterRegisters = 8;
-  __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
-
-  // Stack pointer now points to cell where return address is to be written.
-  // Arguments are before that on the stack or in registers, meaning we
-  // treat the return address as argument 5. Thus every argument after that
-  // needs to be shifted back by 1. Since DirectCEntryStub will handle
-  // allocating space for the c argument slots, we don't need to calculate
-  // that into the argument positions on the stack. This is how the stack will
-  // look (sp meaning the value of sp at this moment):
-  // Abi n64:
-  //   [sp + 1] - Argument 9
-  //   [sp + 0] - saved ra
-  // Abi O32:
-  //   [sp + 5] - Argument 9
-  //   [sp + 4] - Argument 8
-  //   [sp + 3] - Argument 7
-  //   [sp + 2] - Argument 6
-  //   [sp + 1] - Argument 5
-  //   [sp + 0] - saved ra
-
-  // Argument 9: Pass current isolate address.
-  __ li(t1, Operand(ExternalReference::isolate_address(isolate())));
-  __ Sd(t1, MemOperand(sp, 1 * kPointerSize));
-
-  // Argument 8: Indicate that this is a direct call from JavaScript.
-  __ li(a7, Operand(1));
-
-  // Argument 7: Start (high end) of backtracking stack memory area.
-  ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address(isolate());
-  ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size(isolate());
-  __ li(t1, Operand(address_of_regexp_stack_memory_address));
-  __ Ld(t1, MemOperand(t1, 0));
-  __ li(t2, Operand(address_of_regexp_stack_memory_size));
-  __ Ld(t2, MemOperand(t2, 0));
-  __ daddu(a6, t1, t2);
-
-  // Argument 6: Set the number of capture registers to zero to force global
-  // regexps to behave as non-global. This does not affect non-global regexps.
-  __ mov(a5, zero_reg);
-
-  // Argument 5: static offsets vector buffer.
-  __ li(
-      a4,
-      Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
-
-  // Argument 4, a3: End of string data
-  // Argument 3, a2: Start of string data
-  CHECK(a3.is(RegExpExecDescriptor::StringEndRegister()));
-  CHECK(a2.is(RegExpExecDescriptor::StringStartRegister()));
-
-  // Argument 2 (a1): Previous index.
-  CHECK(a1.is(RegExpExecDescriptor::LastIndexRegister()));
-
-  // Argument 1 (a0): Subject string.
-  CHECK(a0.is(RegExpExecDescriptor::StringRegister()));
-
-  // Locate the code entry and call it.
-  Register code_reg = RegExpExecDescriptor::CodeRegister();
-  __ Daddu(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
-  DirectCEntryStub stub(isolate());
-  stub.GenerateCall(masm, code_reg);
-
-  __ LeaveExitFrame(false, no_reg, true);
-
-  // Return the smi-tagged result.
-  __ SmiTag(v0);
-  __ Ret();
-#endif  // V8_INTERPRETED_REGEXP
-}
-
 
 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
   // a0 : number of arguments to the construct function
diff --git a/src/mips64/interface-descriptors-mips64.cc b/src/mips64/interface-descriptors-mips64.cc
index 8deb518..9aabfdc 100644
--- a/src/mips64/interface-descriptors-mips64.cc
+++ b/src/mips64/interface-descriptors-mips64.cc
@@ -56,11 +56,6 @@
   return MathPowTaggedDescriptor::exponent();
 }
 
-const Register RegExpExecDescriptor::StringRegister() { return a0; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return a1; }
-const Register RegExpExecDescriptor::StringStartRegister() { return a2; }
-const Register RegExpExecDescriptor::StringEndRegister() { return a3; }
-const Register RegExpExecDescriptor::CodeRegister() { return t0; }
 
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return a0; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return a3; }
diff --git a/src/mips64/simulator-mips64.h b/src/mips64/simulator-mips64.h
index 6c41ae1..8cc5ac1 100644
--- a/src/mips64/simulator-mips64.h
+++ b/src/mips64/simulator-mips64.h
@@ -29,8 +29,6 @@
 
 // Call the generated regexp code directly. The code at the entry address
 // should act as a function matching the type arm_regexp_matcher.
-// The fifth (or ninth) argument is a dummy that reserves the space used for
-// the return address added by the ExitFrame in native calls.
 typedef int (*mips_regexp_matcher)(String* input,
                                    int64_t start_offset,
                                    const byte* input_start,
@@ -39,14 +37,12 @@
                                    int64_t output_size,
                                    Address stack_base,
                                    int64_t direct_call,
-                                   void* return_address,
                                    Isolate* isolate);
 
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
   (FUNCTION_CAST<mips_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7,   \
-                                             NULL, p8))
-
+                                             p8))
 
 // The stack limit beyond which we will throw stack overflow errors in
 // generated code. Because generated code on mips uses the C stack, we
@@ -560,13 +556,11 @@
       reinterpret_cast<int64_t*>(p1), reinterpret_cast<int64_t*>(p2), \
       reinterpret_cast<int64_t*>(p3), reinterpret_cast<int64_t*>(p4)))
 
-
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
   static_cast<int>(Simulator::current(isolate)->Call(                          \
-      entry, 10, p0, p1, p2, p3, p4, reinterpret_cast<int64_t*>(p5), p6, p7,   \
-      NULL, p8))
-
+      entry, 9, p0, p1, p2, p3, p4, reinterpret_cast<int64_t*>(p5), p6, p7,    \
+      p8))
 
 // The simulator has its own stack. Thus it has a different stack limit from
 // the C-based native code.  The JS-based limit normally points near the end of
diff --git a/src/ppc/code-stubs-ppc.cc b/src/ppc/code-stubs-ppc.cc
index 8c1ea46..6e6de33 100644
--- a/src/ppc/code-stubs-ppc.cc
+++ b/src/ppc/code-stubs-ppc.cc
@@ -1214,77 +1214,6 @@
   __ blr();
 }
 
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
-  // This case is handled prior to the RegExpExecStub call.
-  __ Abort(kUnexpectedRegExpExecCall);
-#else  // V8_INTERPRETED_REGEXP
-  // Isolates: note we add an additional parameter here (isolate pointer).
-  const int kRegExpExecuteArguments = 10;
-  const int kParameterRegisters = 8;
-  __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
-
-  // Stack pointer now points to cell where return address is to be written.
-  // Arguments are before that on the stack or in registers.
-
-  // Argument 10 (in stack parameter area): Pass current isolate address.
-  __ mov(r11, Operand(ExternalReference::isolate_address(isolate())));
-  __ StoreP(r11,
-            MemOperand(sp, (kStackFrameExtraParamSlot + 1) * kPointerSize));
-
-  // Argument 9 is a dummy that reserves the space used for
-  // the return address added by the ExitFrame in native calls.
-
-  // Argument 8 (r10): Indicate that this is a direct call from JavaScript.
-  __ li(r10, Operand(1));
-
-  // Argument 7 (r9): Start (high end) of backtracking stack memory area.
-  ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address(isolate());
-  ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size(isolate());
-  __ mov(r11, Operand(address_of_regexp_stack_memory_address));
-  __ LoadP(r11, MemOperand(r11, 0));
-  __ mov(ip, Operand(address_of_regexp_stack_memory_size));
-  __ LoadP(ip, MemOperand(ip, 0));
-  __ add(r9, r11, ip);
-
-  // Argument 6 (r8): Set the number of capture registers to zero to force
-  // global egexps to behave as non-global.  This does not affect non-global
-  // regexps.
-  __ li(r8, Operand::Zero());
-
-  // Argument 5 (r7): static offsets vector buffer.
-  __ mov(
-      r7,
-      Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
-
-  // Argument 4, r6: End of string data
-  // Argument 3, r5: Start of string data
-  CHECK(r6.is(RegExpExecDescriptor::StringEndRegister()));
-  CHECK(r5.is(RegExpExecDescriptor::StringStartRegister()));
-
-  // Argument 2 (r4): Previous index.
-  CHECK(r4.is(RegExpExecDescriptor::LastIndexRegister()));
-
-  // Argument 1 (r3): Subject string.
-  CHECK(r3.is(RegExpExecDescriptor::StringRegister()));
-
-  // Locate the code entry and call it.
-  Register code_reg = RegExpExecDescriptor::CodeRegister();
-  __ addi(code_reg, code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
-
-  DirectCEntryStub stub(isolate());
-  stub.GenerateCall(masm, code_reg);
-
-  __ LeaveExitFrame(false, no_reg, true);
-
-  // Return the smi-tagged result.
-  __ SmiTag(r3);
-  __ Ret();
-#endif  // V8_INTERPRETED_REGEXP
-}
-
 
 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
   // r3 : number of arguments to the construct function
diff --git a/src/ppc/interface-descriptors-ppc.cc b/src/ppc/interface-descriptors-ppc.cc
index 734ed4a..19cbce4 100644
--- a/src/ppc/interface-descriptors-ppc.cc
+++ b/src/ppc/interface-descriptors-ppc.cc
@@ -56,11 +56,6 @@
   return MathPowTaggedDescriptor::exponent();
 }
 
-const Register RegExpExecDescriptor::StringRegister() { return r3; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return r4; }
-const Register RegExpExecDescriptor::StringStartRegister() { return r5; }
-const Register RegExpExecDescriptor::StringEndRegister() { return r6; }
-const Register RegExpExecDescriptor::CodeRegister() { return r17; }
 
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return r3; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return r6; }
diff --git a/src/ppc/simulator-ppc.h b/src/ppc/simulator-ppc.h
index 0c23b04..c91304e 100644
--- a/src/ppc/simulator-ppc.h
+++ b/src/ppc/simulator-ppc.h
@@ -26,17 +26,13 @@
   (entry(p0, p1, p2, p3, p4))
 
 typedef int (*ppc_regexp_matcher)(String*, int, const byte*, const byte*, int*,
-                                  int, Address, int, void*, Isolate*);
-
+                                  int, Address, int, Isolate*);
 
 // Call the generated regexp code directly. The code at the entry address
 // should act as a function matching the type ppc_regexp_matcher.
-// The ninth argument is a dummy that reserves the space used for
-// the return address added by the ExitFrame in native calls.
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
-  (FUNCTION_CAST<ppc_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7,    \
-                                            NULL, p8))
+  (FUNCTION_CAST<ppc_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7, p8))
 
 // The stack limit beyond which we will throw stack overflow errors in
 // generated code. Because generated code on ppc uses the C stack, we
@@ -495,11 +491,9 @@
 
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
-  Simulator::current(isolate)->Call(entry, 10, (intptr_t)p0, (intptr_t)p1,     \
-                                    (intptr_t)p2, (intptr_t)p3, (intptr_t)p4,  \
-                                    (intptr_t)p5, (intptr_t)p6, (intptr_t)p7,  \
-                                    (intptr_t)NULL, (intptr_t)p8)
-
+  Simulator::current(isolate)->Call(                                           \
+      entry, 9, (intptr_t)p0, (intptr_t)p1, (intptr_t)p2, (intptr_t)p3,        \
+      (intptr_t)p4, (intptr_t)p5, (intptr_t)p6, (intptr_t)p7, (intptr_t)p8)
 
 // The simulator has its own stack. Thus it has a different stack limit from
 // the C-based native code.  The JS-based limit normally points near the end of
diff --git a/src/regexp/arm/regexp-macro-assembler-arm.cc b/src/regexp/arm/regexp-macro-assembler-arm.cc
index 579423f..5caaee3 100644
--- a/src/regexp/arm/regexp-macro-assembler-arm.cc
+++ b/src/regexp/arm/regexp-macro-assembler-arm.cc
@@ -41,14 +41,13 @@
  * Each call to a public method should retain this convention.
  *
  * The stack will have the following structure:
- *  - fp[56]  Isolate* isolate   (address of the current isolate)
- *  - fp[52]  direct_call        (if 1, direct call from JavaScript code,
+ *  - fp[52]  Isolate* isolate   (address of the current isolate)
+ *  - fp[48]  direct_call        (if 1, direct call from JavaScript code,
  *                                if 0, call through the runtime system).
- *  - fp[48]  stack_area_base    (high end of the memory area to use as
+ *  - fp[44]  stack_area_base    (high end of the memory area to use as
  *                                backtracking stack).
- *  - fp[44]  capture array size (may fit multiple sets of matches)
- *  - fp[40]  int* capture_array (int[num_saved_registers_], for output).
- *  - fp[36]  secondary link/return address used by native call.
+ *  - fp[40]  capture array size (may fit multiple sets of matches)
+ *  - fp[36]  int* capture_array (int[num_saved_registers_], for output).
  *  --- sp when called ---
  *  - fp[32]  return address     (lr).
  *  - fp[28]  old frame pointer  (r11).
@@ -81,17 +80,14 @@
  *              int start_index,
  *              Address start,
  *              Address end,
- *              Address secondary_return_address,  // Only used by native call.
  *              int* capture_output_array,
+ *              int num_capture_registers,
  *              byte* stack_area_base,
- *              bool direct_call = false)
+ *              bool direct_call = false,
+ *              Isolate* isolate);
  * The call is performed by NativeRegExpMacroAssembler::Execute()
  * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
  * in arm/simulator-arm.h.
- * When calling as a non-direct call (i.e., from C++ code), the return address
- * area is overwritten with the LR register by the RegExp code. When doing a
- * direct call from generated code, the return address is placed there by
- * the calling code, as in a normal exit frame.
  */
 
 #define __ ACCESS_MASM(masm_)
diff --git a/src/regexp/arm/regexp-macro-assembler-arm.h b/src/regexp/arm/regexp-macro-assembler-arm.h
index 6c91064..a522f53 100644
--- a/src/regexp/arm/regexp-macro-assembler-arm.h
+++ b/src/regexp/arm/regexp-macro-assembler-arm.h
@@ -103,9 +103,8 @@
   static const int kStoredRegisters = kFramePointer;
   // Return address (stored from link register, read into pc on return).
   static const int kReturnAddress = kStoredRegisters + 8 * kPointerSize;
-  static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
   // Stack parameters placed by caller.
-  static const int kRegisterOutput = kSecondaryReturnAddress + kPointerSize;
+  static const int kRegisterOutput = kReturnAddress + kPointerSize;
   static const int kNumOutputRegisters = kRegisterOutput + kPointerSize;
   static const int kStackHighEnd = kNumOutputRegisters + kPointerSize;
   static const int kDirectCall = kStackHighEnd + kPointerSize;
diff --git a/src/regexp/arm64/regexp-macro-assembler-arm64.cc b/src/regexp/arm64/regexp-macro-assembler-arm64.cc
index 7d015d0..d4b80a7 100644
--- a/src/regexp/arm64/regexp-macro-assembler-arm64.cc
+++ b/src/regexp/arm64/regexp-macro-assembler-arm64.cc
@@ -56,10 +56,7 @@
  *              (as referred to in
  *              the code)
  *
- *  - fp[104]   isolate            Address of the current isolate.
- *  - fp[96]    return_address     Secondary link/return address
- *                                 used by an exit frame if this is a
- *                                 native call.
+ *  - fp[96]   isolate            Address of the current isolate.
  *  ^^^ csp when called ^^^
  *  - fp[88]    lr                 Return from the RegExp code.
  *  - fp[80]    r29                Old frame pointer (CalleeSaved).
@@ -89,23 +86,18 @@
  * The data up to the return address must be placed there by the calling
  * code and the remaining arguments are passed in registers, e.g. by calling the
  * code entry as cast to a function with the signature:
- * int (*match)(String* input,
- *              int start_offset,
- *              Address input_start,
- *              Address input_end,
- *              int* output,
- *              int output_size,
- *              Address stack_base,
+ * int (*match)(String* input_string,
+ *              int start_index,
+ *              Address start,
+ *              Address end,
+ *              int* capture_output_array,
+ *              int num_capture_registers,
+ *              byte* stack_area_base,
  *              bool direct_call = false,
- *              Address secondary_return_address,  // Only used by native call.
- *              Isolate* isolate)
+ *              Isolate* isolate);
  * The call is performed by NativeRegExpMacroAssembler::Execute()
  * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
  * in arm64/simulator-arm64.h.
- * When calling as a non-direct call (i.e., from C++ code), the return address
- * area is overwritten with the LR register by the RegExp code. When doing a
- * direct call from generated code, the return address is placed there by
- * the calling code, as in a normal exit frame.
  */
 
 #define __ ACCESS_MASM(masm_)
diff --git a/src/regexp/arm64/regexp-macro-assembler-arm64.h b/src/regexp/arm64/regexp-macro-assembler-arm64.h
index 5db220e..614be62 100644
--- a/src/regexp/arm64/regexp-macro-assembler-arm64.h
+++ b/src/regexp/arm64/regexp-macro-assembler-arm64.h
@@ -109,9 +109,8 @@
   // Return address.
   // It is placed above the 11 callee-saved registers.
   static const int kReturnAddress = kCalleeSavedRegisters + 11 * kPointerSize;
-  static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
   // Stack parameter placed by caller.
-  static const int kIsolate = kSecondaryReturnAddress + kPointerSize;
+  static const int kIsolate = kReturnAddress + kPointerSize;
 
   // Below the frame pointer.
   // Register parameters stored by setup code.
diff --git a/src/regexp/ia32/regexp-macro-assembler-ia32.cc b/src/regexp/ia32/regexp-macro-assembler-ia32.cc
index 6b4ea24..ef4a3890 100644
--- a/src/regexp/ia32/regexp-macro-assembler-ia32.cc
+++ b/src/regexp/ia32/regexp-macro-assembler-ia32.cc
@@ -69,9 +69,10 @@
  *              Address start,
  *              Address end,
  *              int* capture_output_array,
- *              bool at_start,
+ *              int num_capture_registers,
  *              byte* stack_area_base,
- *              bool direct_call)
+ *              bool direct_call = false,
+ *              Isolate* isolate);
  */
 
 #define __ ACCESS_MASM(masm_)
diff --git a/src/regexp/mips/regexp-macro-assembler-mips.cc b/src/regexp/mips/regexp-macro-assembler-mips.cc
index 062d661..89bf40f 100644
--- a/src/regexp/mips/regexp-macro-assembler-mips.cc
+++ b/src/regexp/mips/regexp-macro-assembler-mips.cc
@@ -38,14 +38,13 @@
  *
  * The stack will have the following structure:
  *
- *  - fp[64]  Isolate* isolate   (address of the current isolate)
- *  - fp[60]  direct_call  (if 1, direct call from JavaScript code,
+ *  - fp[60]  Isolate* isolate   (address of the current isolate)
+ *  - fp[56]  direct_call  (if 1, direct call from JavaScript code,
  *                          if 0, call through the runtime system).
- *  - fp[56]  stack_area_base (High end of the memory area to use as
+ *  - fp[52]  stack_area_base (High end of the memory area to use as
  *                             backtracking stack).
- *  - fp[52]  capture array size (may fit multiple sets of matches)
- *  - fp[48]  int* capture_array (int[num_saved_registers_], for output).
- *  - fp[44]  secondary link/return address used by native call.
+ *  - fp[48]  capture array size (may fit multiple sets of matches)
+ *  - fp[44]  int* capture_array (int[num_saved_registers_], for output).
  *  --- sp when called ---
  *  - fp[40]  return address      (lr).
  *  - fp[36]  old frame pointer   (r11).
@@ -78,17 +77,14 @@
  *              int start_index,
  *              Address start,
  *              Address end,
- *              Address secondary_return_address,  // Only used by native call.
  *              int* capture_output_array,
+ *              int num_capture_registers,
  *              byte* stack_area_base,
- *              bool direct_call = false)
+ *              bool direct_call = false,
+ *              Isolate* isolate);
  * The call is performed by NativeRegExpMacroAssembler::Execute()
  * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
  * in mips/simulator-mips.h.
- * When calling as a non-direct call (i.e., from C++ code), the return address
- * area is overwritten with the ra register by the RegExp code. When doing a
- * direct call from generated code, the return address is placed there by
- * the calling code, as in a normal exit frame.
  */
 
 #define __ ACCESS_MASM(masm_)
diff --git a/src/regexp/mips/regexp-macro-assembler-mips.h b/src/regexp/mips/regexp-macro-assembler-mips.h
index 6dedb1e..6c1ba64 100644
--- a/src/regexp/mips/regexp-macro-assembler-mips.h
+++ b/src/regexp/mips/regexp-macro-assembler-mips.h
@@ -103,9 +103,8 @@
   static const int kStoredRegisters = kFramePointer;
   // Return address (stored from link register, read into pc on return).
   static const int kReturnAddress = kStoredRegisters + 9 * kPointerSize;
-  static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
   // Stack frame header.
-  static const int kStackFrameHeader = kReturnAddress + kPointerSize;
+  static const int kStackFrameHeader = kReturnAddress;
   // Stack parameters placed by caller.
   static const int kRegisterOutput = kStackFrameHeader + 20;
   static const int kNumOutputRegisters = kRegisterOutput + kPointerSize;
diff --git a/src/regexp/mips64/regexp-macro-assembler-mips64.cc b/src/regexp/mips64/regexp-macro-assembler-mips64.cc
index 60f1fda..5b83530 100644
--- a/src/regexp/mips64/regexp-macro-assembler-mips64.cc
+++ b/src/regexp/mips64/regexp-macro-assembler-mips64.cc
@@ -17,7 +17,9 @@
 namespace internal {
 
 #ifndef V8_INTERPRETED_REGEXP
-/*
+
+/* clang-format off
+ *
  * This assembler uses the following register assignment convention
  * - t3 : Temporarily stores the index of capture start after a matching pass
  *        for a global regexp.
@@ -41,15 +43,14 @@
  *
  * The O32 stack will have the following structure:
  *
- *  - fp[76]  Isolate* isolate   (address of the current isolate)
- *  - fp[72]  direct_call  (if 1, direct call from JavaScript code,
+ *  - fp[72]  Isolate* isolate   (address of the current isolate)
+ *  - fp[68]  direct_call  (if 1, direct call from JavaScript code,
  *                          if 0, call through the runtime system).
- *  - fp[68]  stack_area_base (High end of the memory area to use as
+ *  - fp[64]  stack_area_base (High end of the memory area to use as
  *                             backtracking stack).
- *  - fp[64]  capture array size (may fit multiple sets of matches)
- *  - fp[60]  int* capture_array (int[num_saved_registers_], for output).
+ *  - fp[60]  capture array size (may fit multiple sets of matches)
  *  - fp[44..59]  MIPS O32 four argument slots
- *  - fp[40]  secondary link/return address used by native call.
+ *  - fp[40]  int* capture_array (int[num_saved_registers_], for output).
  *  --- sp when called ---
  *  - fp[36]  return address      (lr).
  *  - fp[32]  old frame pointer   (r11).
@@ -74,9 +75,8 @@
  *
  * The N64 stack will have the following structure:
  *
- *  - fp[88]  Isolate* isolate   (address of the current isolate)               kIsolate
- *  - fp[80]  secondary link/return address used by exit frame on native call.  kSecondaryReturnAddress
-                                                                                kStackFrameHeader
+ *  - fp[80]  Isolate* isolate   (address of the current isolate)               kIsolate
+ *                                                                              kStackFrameHeader
  *  --- sp when called ---
  *  - fp[72]  ra                 Return from RegExp code (ra).                  kReturnAddress
  *  - fp[64]  s9, old-fp         Old fp, callee saved(s9).
@@ -112,19 +112,16 @@
  *              int start_index,
  *              Address start,
  *              Address end,
- *              Address secondary_return_address,  // Only used by native call.
  *              int* capture_output_array,
+ *              int num_capture_registers,
  *              byte* stack_area_base,
  *              bool direct_call = false,
- *              void* return_address,
  *              Isolate* isolate);
  * The call is performed by NativeRegExpMacroAssembler::Execute()
  * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
  * in mips/simulator-mips.h.
- * When calling as a non-direct call (i.e., from C++ code), the return address
- * area is overwritten with the ra register by the RegExp code. When doing a
- * direct call from generated code, the return address is placed there by
- * the calling code, as in a normal exit frame.
+ *
+ * clang-format on
  */
 
 #define __ ACCESS_MASM(masm_)
diff --git a/src/regexp/mips64/regexp-macro-assembler-mips64.h b/src/regexp/mips64/regexp-macro-assembler-mips64.h
index df2c6c5..722ca01 100644
--- a/src/regexp/mips64/regexp-macro-assembler-mips64.h
+++ b/src/regexp/mips64/regexp-macro-assembler-mips64.h
@@ -107,9 +107,8 @@
   // TODO(plind): This 9 - is 8 s-regs (s0..s7) plus fp.
 
   static const int kReturnAddress = kStoredRegisters + 9 * kPointerSize;
-  static const int kSecondaryReturnAddress = kReturnAddress + kPointerSize;
   // Stack frame header.
-  static const int kStackFrameHeader = kSecondaryReturnAddress;
+  static const int kStackFrameHeader = kReturnAddress;
   // Stack parameters placed by caller.
   static const int kIsolate = kStackFrameHeader + kPointerSize;
 
diff --git a/src/regexp/ppc/regexp-macro-assembler-ppc.cc b/src/regexp/ppc/regexp-macro-assembler-ppc.cc
index d6af025..5c3f8d5 100644
--- a/src/regexp/ppc/regexp-macro-assembler-ppc.cc
+++ b/src/regexp/ppc/regexp-macro-assembler-ppc.cc
@@ -38,8 +38,7 @@
  * Each call to a public method should retain this convention.
  *
  * The stack will have the following structure:
- *  - fp[44]  Isolate* isolate   (address of the current isolate)
- *  - fp[40]  secondary link/return address used by native call.
+ *  - fp[40]  Isolate* isolate   (address of the current isolate)
  *  - fp[36]  lr save area (currently unused)
  *  - fp[32]  backchain    (currently unused)
  *  --- sp when called ---
@@ -81,16 +80,13 @@
  *              Address start,
  *              Address end,
  *              int* capture_output_array,
+ *              int num_capture_registers,
  *              byte* stack_area_base,
- *              Address secondary_return_address,  // Only used by native call.
- *              bool direct_call = false)
+ *              bool direct_call = false,
+ *              Isolate* isolate);
  * The call is performed by NativeRegExpMacroAssembler::Execute()
  * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
  * in ppc/simulator-ppc.h.
- * When calling as a non-direct call (i.e., from C++ code), the return address
- * area is overwritten with the LR register by the RegExp code. When doing a
- * direct call from generated code, the return address is placed there by
- * the calling code, as in a normal exit frame.
  */
 
 #define __ ACCESS_MASM(masm_)
diff --git a/src/regexp/ppc/regexp-macro-assembler-ppc.h b/src/regexp/ppc/regexp-macro-assembler-ppc.h
index 9151bf7..bd6da42 100644
--- a/src/regexp/ppc/regexp-macro-assembler-ppc.h
+++ b/src/regexp/ppc/regexp-macro-assembler-ppc.h
@@ -96,9 +96,8 @@
   static const int kReturnAddress = kStoredRegisters + 7 * kPointerSize;
   static const int kCallerFrame = kReturnAddress + kPointerSize;
   // Stack parameters placed by caller.
-  static const int kSecondaryReturnAddress =
+  static const int kIsolate =
       kCallerFrame + kStackFrameExtraParamSlot * kPointerSize;
-  static const int kIsolate = kSecondaryReturnAddress + kPointerSize;
 
   // Below the frame pointer.
   // Register parameters stored by setup code.
diff --git a/src/regexp/regexp-macro-assembler.cc b/src/regexp/regexp-macro-assembler.cc
index 2e3a8a2..755b604 100644
--- a/src/regexp/regexp-macro-assembler.cc
+++ b/src/regexp/regexp-macro-assembler.cc
@@ -170,15 +170,18 @@
   bool is_one_byte = subject_handle->IsOneByteRepresentationUnderneath();
 
   StackLimitCheck check(isolate);
-  if (check.JsHasOverflowed()) {
+  bool js_has_overflowed = check.JsHasOverflowed();
+
+  if (is_direct_call) {
+    // Direct calls from JavaScript can be interrupted in two ways:
+    // 1. A real stack overflow, in which case we let the caller throw the
+    //    exception.
+    // 2. The stack guard was used to interrupt execution for another purpose,
+    //    forcing the call through the runtime system.
+    return_value = js_has_overflowed ? EXCEPTION : RETRY;
+  } else if (js_has_overflowed) {
     isolate->StackOverflow();
     return_value = EXCEPTION;
-  } else if (is_direct_call) {
-    // If not real stack overflow the stack guard was used to interrupt
-    // execution for another purpose.  If this is a direct call from JavaScript
-    // retry the RegExp forcing the call through the runtime system.
-    // Currently the direct call cannot handle a GC.
-    return_value = RETRY;
   } else {
     Object* result = isolate->stack_guard()->HandleInterrupts();
     if (result->IsException(isolate)) return_value = EXCEPTION;
diff --git a/src/regexp/s390/regexp-macro-assembler-s390.cc b/src/regexp/s390/regexp-macro-assembler-s390.cc
index d927a11..7b8ac8e 100644
--- a/src/regexp/s390/regexp-macro-assembler-s390.cc
+++ b/src/regexp/s390/regexp-macro-assembler-s390.cc
@@ -39,8 +39,7 @@
  * Each call to a public method should retain this convention.
  *
  * The stack will have the following structure:
- *  - fp[112] Isolate* isolate   (address of the current isolate)
- *  - fp[108] secondary link/return address used by native call.
+ *  - fp[108] Isolate* isolate   (address of the current isolate)
  *  - fp[104] direct_call        (if 1, direct call from JavaScript code,
  *                                if 0, call through the runtime system).
  *  - fp[100] stack_area_base    (high end of the memory area to use as
@@ -83,16 +82,13 @@
  *              Address start,
  *              Address end,
  *              int* capture_output_array,
+ *              int num_capture_registers,
  *              byte* stack_area_base,
- *              Address secondary_return_address,  // Only used by native call.
- *              bool direct_call = false)
+ *              bool direct_call = false,
+ *              Isolate* isolate);
  * The call is performed by NativeRegExpMacroAssembler::Execute()
  * (in regexp-macro-assembler.cc) via the CALL_GENERATED_REGEXP_CODE macro
  * in s390/simulator-s390.h.
- * When calling as a non-direct call (i.e., from C++ code), the return address
- * area is overwritten with the LR register by the RegExp code. When doing a
- * direct call from generated code, the return address is placed there by
- * the calling code, as in a normal exit frame.
  */
 
 #define __ ACCESS_MASM(masm_)
diff --git a/src/regexp/s390/regexp-macro-assembler-s390.h b/src/regexp/s390/regexp-macro-assembler-s390.h
index 755bc89..b8a3bed 100644
--- a/src/regexp/s390/regexp-macro-assembler-s390.h
+++ b/src/regexp/s390/regexp-macro-assembler-s390.h
@@ -97,8 +97,7 @@
   static const int kCaptureArraySize = kCallerFrame;
   static const int kStackAreaBase = kCallerFrame + kPointerSize;
   // kDirectCall again
-  static const int kSecondaryReturnAddress = kStackAreaBase + 2 * kPointerSize;
-  static const int kIsolate = kSecondaryReturnAddress + kPointerSize;
+  static const int kIsolate = kStackAreaBase + 2 * kPointerSize;
 
   // Below the frame pointer.
   // Register parameters stored by setup code.
diff --git a/src/regexp/x64/regexp-macro-assembler-x64.cc b/src/regexp/x64/regexp-macro-assembler-x64.cc
index 54dc341..fe65ea2 100644
--- a/src/regexp/x64/regexp-macro-assembler-x64.cc
+++ b/src/regexp/x64/regexp-macro-assembler-x64.cc
@@ -85,9 +85,10 @@
  *              Address start,
  *              Address end,
  *              int* capture_output_array,
- *              bool at_start,
+ *              int num_capture_registers,
  *              byte* stack_area_base,
- *              bool direct_call)
+ *              bool direct_call = false,
+ *              Isolate* isolate);
  */
 
 #define __ ACCESS_MASM((&masm_))
diff --git a/src/regexp/x87/regexp-macro-assembler-x87.cc b/src/regexp/x87/regexp-macro-assembler-x87.cc
index 4a1c3a8..8d08231 100644
--- a/src/regexp/x87/regexp-macro-assembler-x87.cc
+++ b/src/regexp/x87/regexp-macro-assembler-x87.cc
@@ -69,9 +69,10 @@
  *              Address start,
  *              Address end,
  *              int* capture_output_array,
- *              bool at_start,
+ *              int num_capture_registers,
  *              byte* stack_area_base,
- *              bool direct_call)
+ *              bool direct_call = false,
+ *              Isolate* isolate);
  */
 
 #define __ ACCESS_MASM(masm_)
diff --git a/src/s390/code-stubs-s390.cc b/src/s390/code-stubs-s390.cc
index 15d5475..b66d79b 100644
--- a/src/s390/code-stubs-s390.cc
+++ b/src/s390/code-stubs-s390.cc
@@ -1205,87 +1205,6 @@
   __ b(r14);
 }
 
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
-  // This case is handled prior to the RegExpExecStub call.
-  __ Abort(kUnexpectedRegExpExecCall);
-#else   // V8_INTERPRETED_REGEXP
-  __ CleanseP(r14);
-
-  // Isolates: note we add an additional parameter here (isolate pointer).
-  const int kRegExpExecuteArguments = 10;
-  const int kParameterRegisters = 5;
-  __ EnterExitFrame(false, kRegExpExecuteArguments - kParameterRegisters);
-
-  // Stack pointer now points to cell where return address is to be written.
-  // Arguments are before that on the stack or in registers.
-
-  // Argument 10 (in stack parameter area): Pass current isolate address.
-  __ mov(r6, Operand(ExternalReference::isolate_address(isolate())));
-  __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
-                                   4 * kPointerSize));
-
-  // Argument 9 is a dummy that reserves the space used for
-  // the return address added by the ExitFrame in native calls.
-  __ mov(r6, Operand::Zero());
-  __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
-                                   3 * kPointerSize));
-
-  // Argument 8: Indicate that this is a direct call from JavaScript.
-  __ mov(r6, Operand(1));
-  __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
-                                   2 * kPointerSize));
-
-  // Argument 7: Start (high end) of backtracking stack memory area.
-  ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address(isolate());
-  ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size(isolate());
-  __ mov(r6, Operand(address_of_regexp_stack_memory_address));
-  __ LoadP(r6, MemOperand(r6, 0));
-  __ mov(r1, Operand(address_of_regexp_stack_memory_size));
-  __ LoadP(r1, MemOperand(r1, 0));
-  __ AddP(r6, r1);
-  __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
-                                   1 * kPointerSize));
-
-  // Argument 6: Set the number of capture registers to zero to force
-  // global egexps to behave as non-global.  This does not affect non-global
-  // regexps.
-  __ mov(r6, Operand::Zero());
-  __ StoreP(r6, MemOperand(sp, kStackFrameExtraParamSlot * kPointerSize +
-                                   0 * kPointerSize));
-
-  // Argument 5 (r6): static offsets vector buffer.
-  __ mov(
-      r6,
-      Operand(ExternalReference::address_of_static_offsets_vector(isolate())));
-
-  // Argument 4, r5: End of string data
-  // Argument 3, r4: Start of string data
-  CHECK(r5.is(RegExpExecDescriptor::StringEndRegister()));
-  CHECK(r4.is(RegExpExecDescriptor::StringStartRegister()));
-
-  // Argument 2 (r3): Previous index.
-  CHECK(r3.is(RegExpExecDescriptor::LastIndexRegister()));
-
-  // Argument 1 (r2): Subject string.
-  CHECK(r2.is(RegExpExecDescriptor::StringRegister()));
-
-  // Locate the code entry and call it.
-  Register code_reg = RegExpExecDescriptor::CodeRegister();
-  __ AddP(code_reg, Operand(Code::kHeaderSize - kHeapObjectTag));
-
-  DirectCEntryStub stub(isolate());
-  stub.GenerateCall(masm, code_reg);
-
-  __ LeaveExitFrame(false, no_reg, true);
-
-  // Return the smi-tagged result.
-  __ SmiTag(r2);
-  __ Ret();
-#endif  // V8_INTERPRETED_REGEXP
-}
 
 static void CallStubInRecordCallTarget(MacroAssembler* masm, CodeStub* stub) {
   // r2 : number of arguments to the construct function
diff --git a/src/s390/interface-descriptors-s390.cc b/src/s390/interface-descriptors-s390.cc
index 091a645..031ccaf 100644
--- a/src/s390/interface-descriptors-s390.cc
+++ b/src/s390/interface-descriptors-s390.cc
@@ -56,12 +56,6 @@
   return MathPowTaggedDescriptor::exponent();
 }
 
-const Register RegExpExecDescriptor::StringRegister() { return r2; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return r3; }
-const Register RegExpExecDescriptor::StringStartRegister() { return r4; }
-const Register RegExpExecDescriptor::StringEndRegister() { return r5; }
-const Register RegExpExecDescriptor::CodeRegister() { return r9; }
-
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return r2; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return r5; }
 
diff --git a/src/s390/simulator-s390.h b/src/s390/simulator-s390.h
index 95a7d05..3d3fc44 100644
--- a/src/s390/simulator-s390.h
+++ b/src/s390/simulator-s390.h
@@ -25,16 +25,14 @@
   (entry(p0, p1, p2, p3, p4))
 
 typedef int (*s390_regexp_matcher)(String*, int, const byte*, const byte*, int*,
-                                   int, Address, int, void*, Isolate*);
+                                   int, Address, int, Isolate*);
 
 // Call the generated regexp code directly. The code at the entry address
 // should act as a function matching the type ppc_regexp_matcher.
-// The ninth argument is a dummy that reserves the space used for
-// the return address added by the ExitFrame in native calls.
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
   (FUNCTION_CAST<s390_regexp_matcher>(entry)(p0, p1, p2, p3, p4, p5, p6, p7,   \
-                                             NULL, p8))
+                                             p8))
 
 // The stack limit beyond which we will throw stack overflow errors in
 // generated code. Because generated code on s390 uses the C stack, we
@@ -1259,10 +1257,9 @@
 
 #define CALL_GENERATED_REGEXP_CODE(isolate, entry, p0, p1, p2, p3, p4, p5, p6, \
                                    p7, p8)                                     \
-  Simulator::current(isolate)->Call(entry, 10, (intptr_t)p0, (intptr_t)p1,     \
-                                    (intptr_t)p2, (intptr_t)p3, (intptr_t)p4,  \
-                                    (intptr_t)p5, (intptr_t)p6, (intptr_t)p7,  \
-                                    (intptr_t)NULL, (intptr_t)p8)
+  Simulator::current(isolate)->Call(                                           \
+      entry, 9, (intptr_t)p0, (intptr_t)p1, (intptr_t)p2, (intptr_t)p3,        \
+      (intptr_t)p4, (intptr_t)p5, (intptr_t)p6, (intptr_t)p7, (intptr_t)p8)
 
 // The simulator has its own stack. Thus it has a different stack limit from
 // the C-based native code.  The JS-based limit normally points near the end of
diff --git a/src/x64/code-stubs-x64.cc b/src/x64/code-stubs-x64.cc
index fc080f4..3a1edf4 100644
--- a/src/x64/code-stubs-x64.cc
+++ b/src/x64/code-stubs-x64.cc
@@ -350,85 +350,6 @@
   __ ret(0);
 }
 
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
-  // This case is handled prior to the RegExpExecStub call.
-  __ Abort(kUnexpectedRegExpExecCall);
-#else  // V8_INTERPRETED_REGEXP
-  // Isolates: note we add an additional parameter here (isolate pointer).
-  static const int kRegExpExecuteArguments = 9;
-  int argument_slots_on_stack =
-      masm->ArgumentStackSlotsForCFunctionCall(kRegExpExecuteArguments);
-  __ EnterApiExitFrame(argument_slots_on_stack);
-
-  // Argument 9: Pass current isolate address.
-  __ LoadAddress(kScratchRegister,
-                 ExternalReference::isolate_address(isolate()));
-  __ movq(Operand(rsp, (argument_slots_on_stack - 1) * kRegisterSize),
-          kScratchRegister);
-
-  // Argument 8: Indicate that this is a direct call from JavaScript.
-  __ movq(Operand(rsp, (argument_slots_on_stack - 2) * kRegisterSize),
-          Immediate(1));
-
-  // Argument 7: Start (high end) of backtracking stack memory area.
-  ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address(isolate());
-  ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size(isolate());
-  __ Move(kScratchRegister, address_of_regexp_stack_memory_address);
-  __ movp(r12, Operand(kScratchRegister, 0));
-  __ Move(kScratchRegister, address_of_regexp_stack_memory_size);
-  __ addp(r12, Operand(kScratchRegister, 0));
-  __ movq(Operand(rsp, (argument_slots_on_stack - 3) * kRegisterSize), r12);
-
-  // Argument 6: Set the number of capture registers to zero to force global
-  // regexps to behave as non-global.  This does not affect non-global regexps.
-  // Argument 6 is passed in r9 on Linux and on the stack on Windows.
-#ifdef _WIN64
-  __ movq(Operand(rsp, (argument_slots_on_stack - 4) * kRegisterSize),
-          Immediate(0));
-#else
-  __ Set(r9, 0);
-#endif
-
-  // Argument 5: static offsets vector buffer.
-  // Argument 5 passed in r8 on Linux and on the stack on Windows.
-#ifdef _WIN64
-  __ LoadAddress(
-      r12, ExternalReference::address_of_static_offsets_vector(isolate()));
-  __ movq(Operand(rsp, (argument_slots_on_stack - 5) * kRegisterSize), r12);
-#else  // _WIN64
-  __ LoadAddress(
-      r8, ExternalReference::address_of_static_offsets_vector(isolate()));
-#endif
-
-  // Argument 2: Previous index.
-  // TODO(jgruber): Ideally, LastIndexRegister would already equal arg_reg_2,
-  // but that makes register allocation fail.
-  __ movp(arg_reg_2, RegExpExecDescriptor::LastIndexRegister());
-
-  // Argument 4: End of string data
-  // Argument 3: Start of string data
-  CHECK(arg_reg_4.is(RegExpExecDescriptor::StringEndRegister()));
-  CHECK(arg_reg_3.is(RegExpExecDescriptor::StringStartRegister()));
-
-  // Argument 1: Original subject string.
-  CHECK(arg_reg_1.is(RegExpExecDescriptor::StringRegister()));
-
-  __ addp(RegExpExecDescriptor::CodeRegister(),
-          Immediate(Code::kHeaderSize - kHeapObjectTag));
-  __ call(RegExpExecDescriptor::CodeRegister());
-
-  __ LeaveApiExitFrame(true);
-
-  // TODO(jgruber): Don't tag return value once this is supported by stubs.
-  __ Integer32ToSmi(rax, rax);
-  __ ret(0 * kPointerSize);
-#endif  // V8_INTERPRETED_REGEXP
-}
-
-
 static int NegativeComparisonResult(Condition cc) {
   DCHECK(cc != equal);
   DCHECK((cc == less) || (cc == less_equal)
diff --git a/src/x64/interface-descriptors-x64.cc b/src/x64/interface-descriptors-x64.cc
index dd03f19..04ecff5 100644
--- a/src/x64/interface-descriptors-x64.cc
+++ b/src/x64/interface-descriptors-x64.cc
@@ -56,11 +56,6 @@
   return MathPowTaggedDescriptor::exponent();
 }
 
-const Register RegExpExecDescriptor::StringRegister() { return arg_reg_1; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return r11; }
-const Register RegExpExecDescriptor::StringStartRegister() { return arg_reg_3; }
-const Register RegExpExecDescriptor::StringEndRegister() { return arg_reg_4; }
-const Register RegExpExecDescriptor::CodeRegister() { return rax; }
 
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return rax; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return rbx; }
diff --git a/src/x87/code-stubs-x87.cc b/src/x87/code-stubs-x87.cc
index 4ec7a45..8b6fbad 100644
--- a/src/x87/code-stubs-x87.cc
+++ b/src/x87/code-stubs-x87.cc
@@ -281,69 +281,6 @@
   __ ret(0);
 }
 
-void RegExpExecStub::Generate(MacroAssembler* masm) {
-#ifdef V8_INTERPRETED_REGEXP
-  // This case is handled prior to the RegExpExecStub call.
-  __ Abort(kUnexpectedRegExpExecCall);
-#else  // V8_INTERPRETED_REGEXP
-  // Isolates: note we add an additional parameter here (isolate pointer).
-  static const int kRegExpExecuteArguments = 9;
-  __ EnterApiExitFrame(kRegExpExecuteArguments);
-
-  // Argument 9: Pass current isolate address.
-  __ mov(Operand(esp, 8 * kPointerSize),
-      Immediate(ExternalReference::isolate_address(isolate())));
-
-  // Argument 8: Indicate that this is a direct call from JavaScript.
-  __ mov(Operand(esp, 7 * kPointerSize), Immediate(1));
-
-  // Argument 7: Start (high end) of backtracking stack memory area.
-  ExternalReference address_of_regexp_stack_memory_address =
-      ExternalReference::address_of_regexp_stack_memory_address(isolate());
-  ExternalReference address_of_regexp_stack_memory_size =
-      ExternalReference::address_of_regexp_stack_memory_size(isolate());
-  __ mov(esi, Operand::StaticVariable(address_of_regexp_stack_memory_address));
-  __ add(esi, Operand::StaticVariable(address_of_regexp_stack_memory_size));
-  __ mov(Operand(esp, 6 * kPointerSize), esi);
-
-  // Argument 6: Set the number of capture registers to zero to force global
-  // regexps to behave as non-global.  This does not affect non-global regexps.
-  __ mov(Operand(esp, 5 * kPointerSize), Immediate(0));
-
-  // Argument 5: static offsets vector buffer.
-  __ mov(Operand(esp, 4 * kPointerSize),
-         Immediate(ExternalReference::address_of_static_offsets_vector(
-             isolate())));
-
-  // Argument 4: End of string data
-  // Argument 3: Start of string data
-  __ mov(Operand(esp, 3 * kPointerSize),
-         RegExpExecDescriptor::StringEndRegister());
-  __ mov(Operand(esp, 2 * kPointerSize),
-         RegExpExecDescriptor::StringStartRegister());
-
-  // Argument 2: Previous index.
-  __ mov(Operand(esp, 1 * kPointerSize),
-         RegExpExecDescriptor::LastIndexRegister());
-
-  // Argument 1: Original subject string.
-  __ mov(Operand(esp, 0 * kPointerSize),
-         RegExpExecDescriptor::StringRegister());
-
-  // Locate the code entry and call it.
-  __ add(RegExpExecDescriptor::CodeRegister(),
-         Immediate(Code::kHeaderSize - kHeapObjectTag));
-  __ call(RegExpExecDescriptor::CodeRegister());
-
-  // Drop arguments and come back to JS mode.
-  __ LeaveApiExitFrame(true);
-
-  // TODO(jgruber): Don't tag return value once this is supported by stubs.
-  __ SmiTag(eax);
-  __ ret(0 * kPointerSize);
-#endif  // V8_INTERPRETED_REGEXP
-}
-
 
 static int NegativeComparisonResult(Condition cc) {
   DCHECK(cc != equal);
diff --git a/src/x87/interface-descriptors-x87.cc b/src/x87/interface-descriptors-x87.cc
index 4601e98..25707a3 100644
--- a/src/x87/interface-descriptors-x87.cc
+++ b/src/x87/interface-descriptors-x87.cc
@@ -56,11 +56,6 @@
   return MathPowTaggedDescriptor::exponent();
 }
 
-const Register RegExpExecDescriptor::StringRegister() { return eax; }
-const Register RegExpExecDescriptor::LastIndexRegister() { return ecx; }
-const Register RegExpExecDescriptor::StringStartRegister() { return edx; }
-const Register RegExpExecDescriptor::StringEndRegister() { return ebx; }
-const Register RegExpExecDescriptor::CodeRegister() { return edi; }
 
 const Register GrowArrayElementsDescriptor::ObjectRegister() { return eax; }
 const Register GrowArrayElementsDescriptor::KeyRegister() { return ebx; }