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/jni_macro_assembler.h b/compiler/utils/jni_macro_assembler.h
index 48b3f01..3490959 100644
--- a/compiler/utils/jni_macro_assembler.h
+++ b/compiler/utils/jni_macro_assembler.h
@@ -43,6 +43,40 @@
   kNotZero
 };
 
+class ArgumentLocation {
+ public:
+  ArgumentLocation(ManagedRegister reg, size_t size)
+      : reg_(reg), frame_offset_(0u), size_(size) {
+    DCHECK(reg.IsRegister());
+  }
+
+  ArgumentLocation(FrameOffset frame_offset, size_t size)
+      : reg_(ManagedRegister::NoRegister()), frame_offset_(frame_offset), size_(size) {}
+
+  bool IsRegister() const {
+    return reg_.IsRegister();
+  }
+
+  ManagedRegister GetRegister() const {
+    DCHECK(IsRegister());
+    return reg_;
+  }
+
+  FrameOffset GetFrameOffset() const {
+    DCHECK(!IsRegister());
+    return frame_offset_;
+  }
+
+  size_t GetSize() const {
+    return size_;
+  }
+
+ private:
+  ManagedRegister reg_;
+  FrameOffset frame_offset_;
+  size_t size_;
+};
+
 template <PointerSize kPointerSize>
 class JNIMacroAssembler : public DeletableArenaObject<kArenaAllocAssembler> {
  public:
@@ -112,6 +146,8 @@
   virtual void LoadRawPtrFromThread(ManagedRegister dest, ThreadOffset<kPointerSize> offs) = 0;
 
   // Copying routines
+  virtual void MoveArguments(ArrayRef<ArgumentLocation> dests, ArrayRef<ArgumentLocation> srcs) = 0;
+
   virtual void Move(ManagedRegister dest, ManagedRegister src, size_t size) = 0;
 
   virtual void CopyRawPtrFromThread(FrameOffset fr_offs, ThreadOffset<kPointerSize> thr_offs) = 0;