Move @CriticalNative arguments in registers.

And spill stack arguments directly to the right location.
Do not spill to the reserved space in the caller's frame.

Preliminary Golem results for art-opt-cc:
                            x86 x86-64    arm  arm64
NativeDowncallCritical6:    n/a +14.3% +17.2% +26.1%
(x86 seems to be currently providing results that are worse
than interpreter, so something is not working.)

Test: Additional tests in 178-app-image-native-method test.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: aosp_taimen-userdebug boots.
Test: run-gtests.sh
Test: testrunner.py --target --optimizing
Bug: 112189621
Change-Id: I709c52ab2585a8f5f441f53ad2bf4a01d2b25dca
diff --git a/compiler/utils/x86/jni_macro_assembler_x86.cc b/compiler/utils/x86/jni_macro_assembler_x86.cc
index 1adcc20..67ec93d 100644
--- a/compiler/utils/x86/jni_macro_assembler_x86.cc
+++ b/compiler/utils/x86/jni_macro_assembler_x86.cc
@@ -300,6 +300,30 @@
   }
 }
 
+void X86JNIMacroAssembler::MoveArguments(ArrayRef<ArgumentLocation> dests,
+                                         ArrayRef<ArgumentLocation> srcs) {
+  DCHECK_EQ(dests.size(), srcs.size());
+  bool found_hidden_arg = false;
+  for (size_t i = 0, arg_count = srcs.size(); i != arg_count; ++i) {
+    const ArgumentLocation& src = srcs[i];
+    const ArgumentLocation& dest = dests[i];
+    DCHECK_EQ(src.GetSize(), dest.GetSize());
+    if (UNLIKELY(dest.IsRegister())) {
+      // Native ABI has only stack arguments but we may pass one "hidden arg" in register.
+      CHECK(!found_hidden_arg);
+      found_hidden_arg = true;
+      CHECK(src.IsRegister());
+      Move(dest.GetRegister(), src.GetRegister(), dest.GetSize());
+    } else {
+      if (src.IsRegister()) {
+        Store(dest.GetFrameOffset(), src.GetRegister(), dest.GetSize());
+      } else {
+        Copy(dest.GetFrameOffset(), src.GetFrameOffset(), dest.GetSize());
+      }
+    }
+  }
+}
+
 void X86JNIMacroAssembler::Move(ManagedRegister mdest, ManagedRegister msrc, size_t size) {
   DCHECK(!mdest.Equals(X86ManagedRegister::FromCpuRegister(GetScratchRegister())));
   X86ManagedRegister dest = mdest.AsX86();