jni: Add read barrier fast path to jni compiler

Static method dispatch via JNI requires a read barrier
for the ArtMethod::GetDeclaringClass() load before adding it to the
JNI StackHandleScope.

We used to call ReadBarrierJni unconditionally but add a branch
to skip calling it if the GC is not currently in the marking phase.

Test: ART_USE_READ_BARRIER=true make test-art-host test-art-target
Bug: 30437917
Change-Id: I4f505ebde17c0a67209c7bb51b3f39e37a06373a
diff --git a/compiler/utils/x86/jni_macro_assembler_x86.cc b/compiler/utils/x86/jni_macro_assembler_x86.cc
index 77af885..cfdf80b 100644
--- a/compiler/utils/x86/jni_macro_assembler_x86.cc
+++ b/compiler/utils/x86/jni_macro_assembler_x86.cc
@@ -215,8 +215,12 @@
   if (dest.IsNoRegister()) {
     CHECK_EQ(0u, size);
   } else if (dest.IsCpuRegister()) {
-    CHECK_EQ(4u, size);
-    __ fs()->movl(dest.AsCpuRegister(), Address::Absolute(src));
+    if (size == 1u) {
+      __ fs()->movzxb(dest.AsCpuRegister(), Address::Absolute(src));
+    } else {
+      CHECK_EQ(4u, size);
+      __ fs()->movl(dest.AsCpuRegister(), Address::Absolute(src));
+    }
   } else if (dest.IsRegisterPair()) {
     CHECK_EQ(8u, size);
     __ fs()->movl(dest.AsRegisterPairLow(), Address::Absolute(src));
@@ -519,6 +523,48 @@
   __ j(kNotEqual, slow->Entry());
 }
 
+std::unique_ptr<JNIMacroLabel> X86JNIMacroAssembler::CreateLabel() {
+  return std::unique_ptr<JNIMacroLabel>(new X86JNIMacroLabel());
+}
+
+void X86JNIMacroAssembler::Jump(JNIMacroLabel* label) {
+  CHECK(label != nullptr);
+  __ jmp(X86JNIMacroLabel::Cast(label)->AsX86());
+}
+
+void X86JNIMacroAssembler::Jump(JNIMacroLabel* label,
+                                JNIMacroUnaryCondition condition,
+                                ManagedRegister test) {
+  CHECK(label != nullptr);
+
+  art::x86::Condition x86_cond;
+  switch (condition) {
+    case JNIMacroUnaryCondition::kZero:
+      x86_cond = art::x86::kZero;
+      break;
+    case JNIMacroUnaryCondition::kNotZero:
+      x86_cond = art::x86::kNotZero;
+      break;
+    default:
+      LOG(FATAL) << "Not implemented condition: " << static_cast<int>(condition);
+      UNREACHABLE();
+  }
+
+  // TEST reg, reg
+  // Jcc <Offset>
+  __ testl(test.AsX86().AsCpuRegister(), test.AsX86().AsCpuRegister());
+  __ j(x86_cond, X86JNIMacroLabel::Cast(label)->AsX86());
+
+
+  // X86 also has JCZX, JECZX, however it's not worth it to implement
+  // because we aren't likely to codegen with ECX+kZero check.
+}
+
+void X86JNIMacroAssembler::Bind(JNIMacroLabel* label) {
+  CHECK(label != nullptr);
+  __ Bind(X86JNIMacroLabel::Cast(label)->AsX86());
+}
+
 #undef __
 
 void X86ExceptionSlowPath::Emit(Assembler *sasm) {