Clean up instanceof codegen in compiler.

Change-Id: I0179a0746bc5aaef02129169b6a6b1bbbe30dc7e
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index d81c200..173aa64 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -683,6 +683,7 @@
         Get(mir->dalvikInsn.vC);
     int classReg = r2;   // Fixed usage
     loadCurrMethodDirect(cUnit, r1);  // r1 <= current Method*
+    loadValueDirectFixed(cUnit, rlSrc, r0);  /* Ref */
     loadWordDisp(cUnit, r1, Method::DexCacheResolvedTypesOffset().Int32Value(),
                  classReg);
     loadWordDisp(cUnit, classReg, Array::DataOffset().Int32Value() +
@@ -697,35 +698,34 @@
         loadConstant(cUnit, r0, mir->dalvikInsn.vC);
         callRuntimeHelper(cUnit, rLR);  // resolveTypeFromCode(idx, method)
         genRegCopy(cUnit, r2, r0); // Align usage with fast path
+        loadValueDirectFixed(cUnit, rlSrc, r0);  /* reload Ref */
         // Rejoin code paths
         ArmLIR* hopTarget = newLIR0(cUnit, kArmPseudoTargetLabel);
         hopTarget->defMask = ENCODE_ALL;
         hopBranch->generic.target = (LIR*)hopTarget;
     }
-    // At this point, r2 has class
-    loadValueDirectFixed(cUnit, rlSrc, r3);  /* Ref */
-    /* When taken r0 has NULL which can be used for store directly */
-    loadConstant(cUnit, r0, 0);                /* Assume false */
-    ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, r3, 0);
+    /* r0 is ref, r2 is class.  If ref==null, use directly as bool result */
+    ArmLIR* branch1 = genCmpImmBranch(cUnit, kArmCondEq, r0, 0);
     /* load object->clazz */
     DCHECK_EQ(Object::ClassOffset().Int32Value(), 0);
-    loadWordDisp(cUnit, r3,  Object::ClassOffset().Int32Value(), r1);
-    /* r1 now contains object->clazz */
+    loadWordDisp(cUnit, r0,  Object::ClassOffset().Int32Value(), r1);
+    /* r0 is ref, r1 is ref->clazz, r2 is class */
     loadWordDisp(cUnit, rSELF,
                  OFFSETOF_MEMBER(Thread, pInstanceofNonTrivialFromCode), rLR);
-    loadConstant(cUnit, r0, 1);                /* Assume true */
-    opRegReg(cUnit, kOpCmp, r1, r2);
-    ArmLIR* branch2 = opCondBranch(cUnit, kArmCondEq);
-    genRegCopy(cUnit, r0, r3);
-    genRegCopy(cUnit, r1, r2);
-    callRuntimeHelper(cUnit, rLR);
+    opRegReg(cUnit, kOpCmp, r1, r2);  // Same?
+    genBarrier(cUnit);
+    genIT(cUnit, kArmCondEq, "EE");   // if-convert the test
+    loadConstant(cUnit, r0, 1);       // .eq case - load true
+    genRegCopy(cUnit, r0, r2);        // .ne case - arg0 <= class
+    opReg(cUnit, kOpBlx, rLR);        // .ne case: helper(class, ref->class)
+    genBarrier(cUnit);
+    oatClobberCalleeSave(cUnit);
     /* branch target here */
     ArmLIR* target = newLIR0(cUnit, kArmPseudoTargetLabel);
     target->defMask = ENCODE_ALL;
     RegLocation rlResult = oatGetReturn(cUnit);
     storeValue(cUnit, rlDest, rlResult);
     branch1->generic.target = (LIR*)target;
-    branch2->generic.target = (LIR*)target;
 }
 
 STATIC void genCheckCast(CompilationUnit* cUnit, MIR* mir, RegLocation rlSrc)
diff --git a/src/object.h b/src/object.h
index 1eee2b8..51d7b84 100644
--- a/src/object.h
+++ b/src/object.h
@@ -191,11 +191,6 @@
 // C++ mirror of java.lang.Object
 class MANAGED Object {
  public:
-  static uint32_t InstanceOfFromCode(const Object* object, const Class* klass) {
-    DCHECK(object != NULL);
-    return object->InstanceOf(klass) ? 1 : 0;
-  }
-
   static MemberOffset ClassOffset() {
     return OFFSET_OF_OBJECT_MEMBER(Object, klass_);
   }
@@ -1551,6 +1546,14 @@
     }
   }
 
+  // Assignable test for code, won't throw.  Null and equality tests already performed
+  static uint32_t IsAssignableFromCode(const Class* klass, const Class* ref_class)
+  {
+    DCHECK(klass != NULL);
+    DCHECK(ref_class != NULL);
+    return klass->IsAssignableFrom(ref_class) ? 1 : 0;
+  }
+
   Class* GetSuperClass() const {
     // Can only get super class for loaded classes (hack for when runtime is
     // initializing)
diff --git a/src/object_test.cc b/src/object_test.cc
index 79688a3..1451929 100644
--- a/src/object_test.cc
+++ b/src/object_test.cc
@@ -333,10 +333,10 @@
   ASSERT_TRUE(x != NULL);
   ASSERT_TRUE(y != NULL);
 
-  EXPECT_EQ(1U, Object::InstanceOfFromCode(x, X));
-  EXPECT_EQ(0U, Object::InstanceOfFromCode(x, Y));
-  EXPECT_EQ(1U, Object::InstanceOfFromCode(y, X));
-  EXPECT_EQ(1U, Object::InstanceOfFromCode(y, Y));
+  EXPECT_EQ(1U, Class::IsAssignableFromCode(X, x->GetClass()));
+  EXPECT_EQ(0U, Class::IsAssignableFromCode(Y, x->GetClass()));
+  EXPECT_EQ(1U, Class::IsAssignableFromCode(X, y->GetClass()));
+  EXPECT_EQ(1U, Class::IsAssignableFromCode(Y, y->GetClass()));
 
   EXPECT_TRUE(x->InstanceOf(X));
   EXPECT_FALSE(x->InstanceOf(Y));
diff --git a/src/thread.cc b/src/thread.cc
index 1bbe81c..0df4929 100644
--- a/src/thread.cc
+++ b/src/thread.cc
@@ -118,7 +118,7 @@
   pSetObjStatic = Field::SetObjStaticFromCode;
   pInitializeTypeFromCode = InitializeTypeFromCode;
   pResolveMethodFromCode = ResolveMethodFromCode;
-  pInstanceofNonTrivialFromCode = Object::InstanceOfFromCode;
+  pInstanceofNonTrivialFromCode = Class::IsAssignableFromCode;
   pLockObjectFromCode = LockObjectFromCode;
   pFindInstanceFieldFromCode = Field::FindInstanceFieldFromCode;
   pCheckSuspendFromCode = artCheckSuspendFromCode;
diff --git a/src/thread.h b/src/thread.h
index 3a8abba..e9491dd 100644
--- a/src/thread.h
+++ b/src/thread.h
@@ -212,7 +212,7 @@
   Object* (*pGetObjStatic)(uint32_t, const Method*);
   void (*pSetObjStatic)(uint32_t, const Method*, Object*);
   void (*pCanPutArrayElementFromCode)(void*, void*);
-  uint32_t (*pInstanceofNonTrivialFromCode) (const Object*, const Class*);
+  uint32_t (*pInstanceofNonTrivialFromCode) (const Class*, const Class*);
   void (*pCheckCastFromCode) (void*, void*);
   Method* (*pFindInterfaceMethodInCache)(Class*, uint32_t, const Method*, struct DvmDex*);
   void (*pUnlockObjectFromCode)(void*, void*);