X86: Fix bug in GenerateVarHandleAccessModeCheck

The condition of taking the slow path for VarHandle access mode check
was reversed.

Solving this bug revealed another problem: in the case of an instance
field, the object might be null. The null check is now done for the
object.

Test: art/test.py --host --32 -r -t 712-varhandle-invocations
Bug: 65872996
Change-Id: I8d047cc0ecba3d05178ea67945afe762c545c27e
diff --git a/compiler/optimizing/intrinsics_x86.cc b/compiler/optimizing/intrinsics_x86.cc
index b988eb0..53cf350 100644
--- a/compiler/optimizing/intrinsics_x86.cc
+++ b/compiler/optimizing/intrinsics_x86.cc
@@ -3093,7 +3093,7 @@
 
   // If the access mode is not supported, bail to runtime implementation to handle
   __ testl(Address(varhandle_object, access_modes_bitmask_offset), Immediate(access_mode_bit));
-  __ j(kNotEqual, slow_path->GetEntryLabel());
+  __ j(kZero, slow_path->GetEntryLabel());
 }
 
 static void GenerateVarHandleStaticFieldCheck(Register varhandle_object,
@@ -3111,11 +3111,18 @@
                                        Register temp,
                                        Address type_address,
                                        SlowPathCode* slow_path,
-                                       X86Assembler* assembler) {
+                                       X86Assembler* assembler,
+                                       bool object_can_be_null = true) {
   const uint32_t class_offset = mirror::Object::ClassOffset().Uint32Value();
   const uint32_t super_class_offset = mirror::Class::SuperClassOffset().Uint32Value();
   NearLabel check_type_compatibility, type_matched;
 
+  // If the object is null, there is no need to check the type
+  if (object_can_be_null) {
+    __ testl(object, object);
+    __ j(kZero, &type_matched);
+  }
+
   // Do not unpoison for in-memory comparison.
   // We deliberately avoid the read barrier, letting the slow path handle the false negatives.
   __ movl(temp, Address(object, class_offset));
@@ -3147,12 +3154,17 @@
   __ cmpl(Address(varhandle_object, coordtype1_offset), Immediate(0));
   __ j(kNotEqual, slow_path->GetEntryLabel());
 
+  // Check if the object is null
+  __ testl(object, object);
+  __ j(kZero, slow_path->GetEntryLabel());
+
   // Check the object's class against coordinateType0.
   GenerateSubTypeObjectCheck(object,
                              temp,
                              Address(varhandle_object, coordtype0_offset),
                              slow_path,
-                             assembler);
+                             assembler,
+                             /* object_can_be_null= */ false);
 }
 
 static void GenerateVarHandleCommonChecks(HInvoke *invoke,
@@ -3233,8 +3245,9 @@
     return temp;
   }
 
-  // For instance fields, return the register containing the object
+  // For instance fields, return the register containing the object.
   DCHECK_EQ(expected_coordinates_count, 1u);
+
   return locations->InAt(1).AsRegister<Register>();
 }
 
@@ -3441,6 +3454,7 @@
 
   // Check the varType.primitiveType against the type of the value we're trying to set.
   GenerateVarTypePrimitiveTypeCheck(varhandle_object, temp, value_type, slow_path, assembler);
+
   if (value_type == DataType::Type::kReference) {
     Register value_reg = value.AsRegister<Register>();
     const uint32_t var_type_offset = mirror::VarHandle::VarTypeOffset().Uint32Value();