x86: Fix CriticalNative argument spilling in JNI stubs.

Do not move incoming stack arguments before we have spilled
the scratch register ECX.

Fix JniCompilerTest to initialize classes early so that we
really test what we were supposed to. This exposed the x86
bug fixed here.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 172332525
Change-Id: I7c06c8ccf18f5f66772c70f6a9a9a314668ce70d
diff --git a/compiler/utils/x86/jni_macro_assembler_x86.cc b/compiler/utils/x86/jni_macro_assembler_x86.cc
index 67ec93d..2c7902b 100644
--- a/compiler/utils/x86/jni_macro_assembler_x86.cc
+++ b/compiler/utils/x86/jni_macro_assembler_x86.cc
@@ -308,18 +308,28 @@
     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());
+    if (src.IsRegister()) {
+      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;
+        DCHECK(
+            !dest.GetRegister().Equals(X86ManagedRegister::FromCpuRegister(GetScratchRegister())));
+        Move(dest.GetRegister(), src.GetRegister(), dest.GetSize());
       } else {
-        Copy(dest.GetFrameOffset(), src.GetFrameOffset(), dest.GetSize());
+        Store(dest.GetFrameOffset(), src.GetRegister(), dest.GetSize());
       }
+    } else {
+      // Delay copying until we have spilled all registers, including the scratch register ECX.
+    }
+  }
+  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 (!src.IsRegister()) {
+      DCHECK(!dest.IsRegister());
+      Copy(dest.GetFrameOffset(), src.GetFrameOffset(), dest.GetSize());
     }
   }
 }