Revert "Use the object class as top in reference type propagation"

This reverts commit 3fabec7a25d151b26ba7de13615bbead0dd615a6.

Change-Id: Id8614f6b6e3e0e4c9caeb9f771e4c145d9fec64f
diff --git a/compiler/optimizing/nodes.h b/compiler/optimizing/nodes.h
index 2c7bac5..57c7829 100644
--- a/compiler/optimizing/nodes.h
+++ b/compiler/optimizing/nodes.h
@@ -1353,63 +1353,79 @@
  public:
   typedef Handle<mirror::Class> TypeHandle;
 
-  static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact) {
-    // The constructor will check that the type_handle is valid.
-    return ReferenceTypeInfo(type_handle, is_exact);
+  static ReferenceTypeInfo Create(TypeHandle type_handle, bool is_exact)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    if (type_handle->IsObjectClass()) {
+      // Override the type handle to be consistent with the case when we get to
+      // Top but don't have the Object class available. It avoids having to guess
+      // what value the type_handle has when it's Top.
+      return ReferenceTypeInfo(TypeHandle(), is_exact, true);
+    } else {
+      return ReferenceTypeInfo(type_handle, is_exact, false);
+    }
   }
 
-  static ReferenceTypeInfo CreateInvalid() { return ReferenceTypeInfo(); }
-
-  static bool IsValidHandle(TypeHandle handle) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return handle.GetReference() != nullptr;
+  static ReferenceTypeInfo CreateTop(bool is_exact) {
+    return ReferenceTypeInfo(TypeHandle(), is_exact, true);
   }
 
-  bool IsValid() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    return IsValidHandle(type_handle_);
-  }
   bool IsExact() const { return is_exact_; }
-  bool IsObjectClass() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(IsValid());
-    return GetTypeHandle()->IsObjectClass();
-  }
+  bool IsTop() const { return is_top_; }
   bool IsInterface() const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(IsValid());
-    return GetTypeHandle()->IsInterface();
+    return !IsTop() && GetTypeHandle()->IsInterface();
   }
 
   Handle<mirror::Class> GetTypeHandle() const { return type_handle_; }
 
   bool IsSupertypeOf(ReferenceTypeInfo rti) const SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    DCHECK(IsValid());
-    DCHECK(rti.IsValid());
+    if (IsTop()) {
+      // Top (equivalent for java.lang.Object) is supertype of anything.
+      return true;
+    }
+    if (rti.IsTop()) {
+      // If we get here `this` is not Top() so it can't be a supertype.
+      return false;
+    }
     return GetTypeHandle()->IsAssignableFrom(rti.GetTypeHandle().Get());
   }
 
   // Returns true if the type information provide the same amount of details.
   // Note that it does not mean that the instructions have the same actual type
-  // (because the type can be the result of a merge).
+  // (e.g. tops are equal but they can be the result of a merge).
   bool IsEqual(ReferenceTypeInfo rti) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    if (!IsValid() && !rti.IsValid()) {
-      // Invalid types are equal.
-      return true;
-    }
-    if (!IsValid() || !rti.IsValid()) {
-      // One is valid, the other not.
+    if (IsExact() != rti.IsExact()) {
       return false;
     }
-    return IsExact() == rti.IsExact()
-        && GetTypeHandle().Get() == rti.GetTypeHandle().Get();
+    if (IsTop() && rti.IsTop()) {
+      // `Top` means java.lang.Object, so the types are equivalent.
+      return true;
+    }
+    if (IsTop() || rti.IsTop()) {
+      // If only one is top or object than they are not equivalent.
+      // NB: We need this extra check because the type_handle of `Top` is invalid
+      // and we cannot inspect its reference.
+      return false;
+    }
+
+    // Finally check the types.
+    return GetTypeHandle().Get() == rti.GetTypeHandle().Get();
   }
 
  private:
-  ReferenceTypeInfo();
-  ReferenceTypeInfo(TypeHandle type_handle, bool is_exact);
+  ReferenceTypeInfo() : ReferenceTypeInfo(TypeHandle(), false, true) {}
+  ReferenceTypeInfo(TypeHandle type_handle, bool is_exact, bool is_top)
+      : type_handle_(type_handle), is_exact_(is_exact), is_top_(is_top) {}
 
   // The class of the object.
   TypeHandle type_handle_;
   // Whether or not the type is exact or a superclass of the actual type.
   // Whether or not we have any information about this type.
   bool is_exact_;
+  // A true value here means that the object type should be java.lang.Object.
+  // We don't have access to the corresponding mirror object every time so this
+  // flag acts as a substitute. When true, the TypeHandle refers to a null
+  // pointer and should not be used.
+  bool is_top_;
 };
 
 std::ostream& operator<<(std::ostream& os, const ReferenceTypeInfo& rhs);
@@ -1427,7 +1443,7 @@
         live_interval_(nullptr),
         lifetime_position_(kNoLifetime),
         side_effects_(side_effects),
-        reference_type_info_(ReferenceTypeInfo::CreateInvalid()) {}
+        reference_type_info_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {}
 
   virtual ~HInstruction() {}
 
@@ -1483,7 +1499,10 @@
     return false;
   }
 
-  void SetReferenceTypeInfo(ReferenceTypeInfo rti);
+  void SetReferenceTypeInfo(ReferenceTypeInfo reference_type_info) {
+    DCHECK_EQ(GetType(), Primitive::kPrimNot);
+    reference_type_info_ = reference_type_info;
+  }
 
   ReferenceTypeInfo GetReferenceTypeInfo() const {
     DCHECK_EQ(GetType(), Primitive::kPrimNot);
@@ -3760,7 +3779,7 @@
         is_referrers_class_(is_referrers_class),
         dex_pc_(dex_pc),
         generate_clinit_check_(false),
-        loaded_class_rti_(ReferenceTypeInfo::CreateInvalid()) {
+        loaded_class_rti_(ReferenceTypeInfo::CreateTop(/* is_exact */ false)) {
     SetRawInputAt(0, current_method);
   }
 
@@ -3811,6 +3830,10 @@
     loaded_class_rti_ = rti;
   }
 
+  bool IsResolved() {
+    return loaded_class_rti_.IsExact();
+  }
+
   const DexFile& GetDexFile() { return dex_file_; }
 
   bool NeedsDexCache() const OVERRIDE { return !is_referrers_class_; }
@@ -4048,15 +4071,12 @@
 
 class HBoundType : public HExpression<1> {
  public:
-  // Constructs an HBoundType with the given upper_bound.
-  // Ensures that the upper_bound is valid.
   HBoundType(HInstruction* input, ReferenceTypeInfo upper_bound, bool upper_can_be_null)
       : HExpression(Primitive::kPrimNot, SideEffects::None()),
         upper_bound_(upper_bound),
         upper_can_be_null_(upper_can_be_null) {
     DCHECK_EQ(input->GetType(), Primitive::kPrimNot);
     SetRawInputAt(0, input);
-    SetReferenceTypeInfo(upper_bound_);
   }
 
   // GetUpper* should only be used in reference type propagation.