[VM interpreter] Fix InterpretCall stub.
The stub was marking the thread as executing VM code too early, since the slow
path of AllocateArray (called via PushArrayOfArguments) calls into the runtime.
With this fix, DeltaBlueClosures can run in fully interpreted mode.

Change-Id: I16f8e93fe0c1ee02dd284a19971eee4915f47c28
Reviewed-on: https://dart-review.googlesource.com/63500
Reviewed-by: Alexander Markov <alexmarkov@google.com>
Commit-Queue: Régis Crelier <regis@google.com>
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/stub_code_arm64.cc
index 12f4302..fceea40 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/stub_code_arm64.cc
@@ -1966,10 +1966,6 @@
   __ SetPrologueOffset();
   __ EnterStubFrame();
 
-  // Save exit frame information to enable stack walking as we are about
-  // to transition to Dart VM C++ code.
-  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
-
 #if defined(DEBUG)
   {
     Label ok;
@@ -1982,9 +1978,6 @@
   }
 #endif
 
-  // Mark that the thread is executing VM code.
-  __ StoreToOffset(R5, THR, Thread::vm_tag_offset());
-
   // Setup space on stack for result of the interpreted function call.
   __ Push(ZR);
 
@@ -2004,7 +1997,7 @@
 
   // Push 4th Dart argument of the interpreted function call.
   // R2: Smi-tagged arguments array length.
-  PushArrayOfArguments(assembler);
+  PushArrayOfArguments(assembler);  // May call into the runtime.
   const intptr_t kNumArgs = 4;
 
   // Reserve space for arguments and align frame before entering C++ world.
@@ -2033,13 +2026,20 @@
   __ StoreToOffset(R3, SP, retval_offset);
   __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
 
+  // Save exit frame information to enable stack walking as we are about
+  // to transition to Dart VM C++ code.
+  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
+
+  // Mark that the thread is executing VM code.
+  __ LoadImmediate(R5, kInterpretCallRuntimeEntry.GetEntryPoint());
+  __ StoreToOffset(R5, THR, Thread::vm_tag_offset());
+
   // We are entering runtime code, so the C stack pointer must be restored from
   // the stack limit to the top of the stack. We cache the stack limit address
   // in a callee-saved register.
   __ mov(R25, CSP);
   __ mov(CSP, SP);
 
-  __ LoadImmediate(R5, kInterpretCallRuntimeEntry.GetEntryPoint());
   __ blr(R5);
 
   // Restore SP and CSP.
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/stub_code_x64.cc
index f6b0b26..a16794a 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/stub_code_x64.cc
@@ -1906,10 +1906,6 @@
 
   __ EnterStubFrame();
 
-  // Save exit frame information to enable stack walking as we are about
-  // to transition to Dart VM C++ code.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
-
 #if defined(DEBUG)
   {
     Label ok;
@@ -1922,10 +1918,6 @@
   }
 #endif
 
-  // Mark that the thread is executing VM code.
-  __ movq(RCX, Immediate(kInterpretCallRuntimeEntry.GetEntryPoint()));
-  __ movq(Assembler::VMTagAddress(), RCX);
-
   // Push result and first 3 arguments of the interpreted function call.
   __ pushq(Immediate(0));  // Setup space on stack for result.
   __ pushq(RAX);           // Function.
@@ -1944,7 +1936,7 @@
 
   // Push 4th Dart argument of the interpreted function call.
   // R10: Smi-tagged arguments array length.
-  PushArrayOfArguments(assembler);
+  PushArrayOfArguments(assembler);  // May call into the runtime.
   const intptr_t kNumArgs = 4;
 
   // Set callee-saved RBX to point to first one of the 4 Dart arguments.
@@ -1967,7 +1959,14 @@
   ASSERT(sizeof(NativeArguments) > CallingConventions::kRegisterTransferLimit);
   __ movq(CallingConventions::kArg1Reg, RSP);
 #endif
+  // Save exit frame information to enable stack walking as we are about
+  // to transition to Dart VM C++ code.
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
+
+  // Mark that the thread is executing VM code.
   __ movq(RCX, Immediate(kInterpretCallRuntimeEntry.GetEntryPoint()));
+  __ movq(Assembler::VMTagAddress(), RCX);
+
   __ CallCFunction(RCX);
 
   // Mark that the thread is executing Dart code.