jni: Add @CriticalNative optimization to speed up JNI transitions

Change-Id: I963059ac3a72dd8e6a867596c356d7062deb6da7
diff --git a/compiler/utils/arm/jni_macro_assembler_arm.cc b/compiler/utils/arm/jni_macro_assembler_arm.cc
index e0bfa12..cf7a4d1 100644
--- a/compiler/utils/arm/jni_macro_assembler_arm.cc
+++ b/compiler/utils/arm/jni_macro_assembler_arm.cc
@@ -367,11 +367,21 @@
       CHECK(src.IsCoreRegister()) << src;
       __ mov(dst.AsCoreRegister(), ShifterOperand(src.AsCoreRegister()));
     } else if (dst.IsDRegister()) {
-      CHECK(src.IsDRegister()) << src;
-      __ vmovd(dst.AsDRegister(), src.AsDRegister());
+      if (src.IsDRegister()) {
+        __ vmovd(dst.AsDRegister(), src.AsDRegister());
+      } else {
+        // VMOV Dn, Rlo, Rhi (Dn = {Rlo, Rhi})
+        CHECK(src.IsRegisterPair()) << src;
+        __ vmovdrr(dst.AsDRegister(), src.AsRegisterPairLow(), src.AsRegisterPairHigh());
+      }
     } else if (dst.IsSRegister()) {
-      CHECK(src.IsSRegister()) << src;
-      __ vmovs(dst.AsSRegister(), src.AsSRegister());
+      if (src.IsSRegister()) {
+        __ vmovs(dst.AsSRegister(), src.AsSRegister());
+      } else {
+        // VMOV Sn, Rn  (Sn = Rn)
+        CHECK(src.IsCoreRegister()) << src;
+        __ vmovsr(dst.AsSRegister(), src.AsCoreRegister());
+      }
     } else {
       CHECK(dst.IsRegisterPair()) << dst;
       CHECK(src.IsRegisterPair()) << src;
diff --git a/compiler/utils/assembler_thumb_test.cc b/compiler/utils/assembler_thumb_test.cc
index 367ed97..3b05173 100644
--- a/compiler/utils/assembler_thumb_test.cc
+++ b/compiler/utils/assembler_thumb_test.cc
@@ -1661,13 +1661,19 @@
 TEST_F(ArmVIXLAssemblerTest, VixlJniHelpers) {
   const bool is_static = true;
   const bool is_synchronized = false;
+  const bool is_critical_native = false;
   const char* shorty = "IIFII";
 
   ArenaPool pool;
   ArenaAllocator arena(&pool);
 
   std::unique_ptr<JniCallingConvention> jni_conv(
-      JniCallingConvention::Create(&arena, is_static, is_synchronized, shorty, kThumb2));
+      JniCallingConvention::Create(&arena,
+                                   is_static,
+                                   is_synchronized,
+                                   is_critical_native,
+                                   shorty,
+                                   kThumb2));
   std::unique_ptr<ManagedRuntimeCallingConvention> mr_conv(
       ManagedRuntimeCallingConvention::Create(&arena, is_static, is_synchronized, shorty, kThumb2));
   const int frame_size(jni_conv->FrameSize());