Clean up InstanceOf/CheckCast.

Avoid read barriers for boot image class InstanceOf. Boot
image classes are non-moveable, so comparing them against
from-space and to-space reference yields the same result.

Change the notion of a "fatal" type check slow path to mean
that the runtime call shall not return by normal path, i.e.
"fatal" now includes certainly throwing in a try-block. This
avoids unnecessary code to restore registers and jump back.
For boot image classes the CheckCast comparisons do not need
read barriers (for the same reason as for InstanceOf), so we
shall not have any false negatives and can treat the check's
slow paths as final in the same cases as in non-CC configs.

Boot image size for aosp_taimen-userdebug in AOSP master:
  - before:
    arm boot*.oat: 37075460
    arm64 boot*.oat: 43431768
  - after:
    arm boot*.oat: 36894292 (-177KiB, -0.5%)
    arm64 boot*.oat: 43201256 (-225KiB, -0.5%)

Also remove some obsolete helpers from CodeGenerator.

Test: Additional test in 603-checker-instanceof.
Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Test: Pixel 2 XL boots.
Test: testrunner.py --target --optimizing
Bug: 12687968
Change-Id: Ib1381084e46a10e70320dcc618f0502ad725f0b8
diff --git a/compiler/optimizing/code_generator.h b/compiler/optimizing/code_generator.h
index 08e4462..3c5a37f 100644
--- a/compiler/optimizing/code_generator.h
+++ b/compiler/optimizing/code_generator.h
@@ -388,13 +388,6 @@
   bool IsBlockedCoreRegister(size_t i) { return blocked_core_registers_[i]; }
   bool IsBlockedFloatingPointRegister(size_t i) { return blocked_fpu_registers_[i]; }
 
-  // Helper that returns the pointer offset of an index in an object array.
-  // Note: this method assumes we always have the same pointer size, regardless
-  // of the architecture.
-  static size_t GetCacheOffset(uint32_t index);
-  // Pointer variant for ArtMethod and ArtField arrays.
-  size_t GetCachePointerOffset(uint32_t index);
-
   // Helper that returns the offset of the array's length field.
   // Note: Besides the normal arrays, we also use the HArrayLength for
   // accessing the String's `count` field in String intrinsics.
@@ -412,6 +405,50 @@
                          Location to2,
                          DataType::Type type2);
 
+  static bool InstanceOfNeedsReadBarrier(HInstanceOf* instance_of) {
+    // Used only for kExactCheck, kAbstractClassCheck, kClassHierarchyCheck and kArrayObjectCheck.
+    DCHECK(instance_of->GetTypeCheckKind() == TypeCheckKind::kExactCheck ||
+           instance_of->GetTypeCheckKind() == TypeCheckKind::kAbstractClassCheck ||
+           instance_of->GetTypeCheckKind() == TypeCheckKind::kClassHierarchyCheck ||
+           instance_of->GetTypeCheckKind() == TypeCheckKind::kArrayObjectCheck)
+        << instance_of->GetTypeCheckKind();
+    // If the target class is in the boot image, it's non-moveable and it doesn't matter
+    // if we compare it with a from-space or to-space reference, the result is the same.
+    // It's OK to traverse a class hierarchy jumping between from-space and to-space.
+    return kEmitCompilerReadBarrier && !instance_of->GetTargetClass()->IsInBootImage();
+  }
+
+  static ReadBarrierOption ReadBarrierOptionForInstanceOf(HInstanceOf* instance_of) {
+    return InstanceOfNeedsReadBarrier(instance_of) ? kWithReadBarrier : kWithoutReadBarrier;
+  }
+
+  static bool IsTypeCheckSlowPathFatal(HCheckCast* check_cast) {
+    switch (check_cast->GetTypeCheckKind()) {
+      case TypeCheckKind::kExactCheck:
+      case TypeCheckKind::kAbstractClassCheck:
+      case TypeCheckKind::kClassHierarchyCheck:
+      case TypeCheckKind::kArrayObjectCheck:
+      case TypeCheckKind::kInterfaceCheck: {
+        bool needs_read_barrier =
+            kEmitCompilerReadBarrier && !check_cast->GetTargetClass()->IsInBootImage();
+        // We do not emit read barriers for HCheckCast, so we can get false negatives
+        // and the slow path shall re-check and simply return if the cast is actually OK.
+        return !needs_read_barrier;
+      }
+      case TypeCheckKind::kArrayCheck:
+      case TypeCheckKind::kUnresolvedCheck:
+        return false;
+    }
+    LOG(FATAL) << "Unreachable";
+    UNREACHABLE();
+  }
+
+  static LocationSummary::CallKind GetCheckCastCallKind(HCheckCast* check_cast) {
+    return (IsTypeCheckSlowPathFatal(check_cast) && !check_cast->CanThrowIntoCatchBlock())
+        ? LocationSummary::kNoCall  // In fact, call on a fatal (non-returning) slow path.
+        : LocationSummary::kCallOnSlowPath;
+  }
+
   static bool StoreNeedsWriteBarrier(DataType::Type type, HInstruction* value) {
     // Check that null value is not represented as an integer constant.
     DCHECK(type != DataType::Type::kReference || !value->IsIntConstant());