< prev index next >

src/share/vm/opto/type.cpp

Print this page
rev 9165 : 8141551: C2 can not handle returns with inccompatible interface arrays

@@ -706,18 +706,26 @@
 
   const Type *mt = this_t->xmeet(t);
   if (isa_narrowoop() || t->isa_narrowoop()) return mt;
   if (isa_narrowklass() || t->isa_narrowklass()) return mt;
 #ifdef ASSERT
-  assert(mt == t->xmeet(this_t), "meet not commutative");
+  if (mt != t->xmeet(this_t)) {
+    // Array of Interface meet Array of Oop is Not Commutative.
+    if (!(this_t->make_ptr() && this_t->make_ptr()->isa_aryptr() &&
+        t->make_ptr() && t->make_ptr()->isa_aryptr() &&
+        interface_vs_oop(t))) {
+      fatal("meet not commutative");
+    }
+  }
   const Type* dual_join = mt->_dual;
   const Type *t2t    = dual_join->xmeet(t->_dual);
   const Type *t2this = dual_join->xmeet(this_t->_dual);
 
   // Interface meet Oop is Not Symmetric:
   // Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull
   // Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull
+  // Array of Interface meet Array of Oop is also Not Symmetric.
 
   if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != this_t->_dual) ) {
     tty->print_cr("=== Meet Not Symmetric ===");
     tty->print("t   =                   ");              t->dump(); tty->cr();
     tty->print("this=                   ");         this_t->dump(); tty->cr();

@@ -2027,11 +2035,15 @@
 //----------------------interface_vs_oop---------------------------------------
 #ifdef ASSERT
 bool TypeAry::interface_vs_oop(const Type *t) const {
   const TypeAry* t_ary = t->is_ary();
   if (t_ary) {
-    return _elem->interface_vs_oop(t_ary->_elem);
+    const TypePtr* this_ptr = _elem->make_ptr(); // In case it is narrow_oop
+    const TypePtr*    t_ptr = t_ary->_elem->make_ptr();
+    if(this_ptr != NULL && t_ptr != NULL) {
+      return this_ptr->interface_vs_oop(t_ptr);
+    }
   }
   return false;
 }
 #endif
 

@@ -3132,12 +3144,32 @@
     // both implement interface I, but their meet is at 'j/l/O' which
     // doesn't implement I, we have no way to tell if the result should
     // be 'I' or 'j/l/O'.  Thus we'll pick 'j/l/O'.  If this then flows
     // into a Phi which "knows" it's an Interface type we'll have to
     // uplift the type.
-    if (!empty() && ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface())
+    if (!empty()) {
+      if (ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface()) {
       return kills;             // Uplift to interface
+      }
+      const TypeAryPtr* ftap = ft->isa_aryptr();
+      const TypeAryPtr* ktap = kills->isa_aryptr();
+      if (ftap != NULL && ktap != NULL) {
+        // Handle multidimensional arrays
+        const TypePtr* ftp = ftap->elem()->make_ptr();
+        const TypePtr* ktp = ktap->elem()->make_ptr();
+        while (ftp && ftp->isa_aryptr() && ktp && ktp->isa_aryptr()) {
+          ftap = ftp->is_aryptr();
+          ktap = ktp->is_aryptr();
+          ftp = ftap->elem()->make_ptr();
+          ktp = ktap->elem()->make_ptr();
+        }
+        ktip = ktp ? ktp->isa_instptr() : NULL;
+        if (ktip != NULL && ktip->is_loaded() && ktip->klass()->is_interface()) {
+          return kills;         // Uplift to array of interface
+        }
+      }
+    }
 
     return Type::TOP;           // Canonical empty value
   }
 
   // If we have an interface-typed Phi or cast and we narrow to a class type,

@@ -4140,13 +4172,28 @@
           ((tap->_klass_is_exact && this->_klass_is_exact) ||
            // 'tap'  is exact and super or unrelated:
            (tap->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) ||
            // 'this' is exact and super or unrelated:
            (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
+
+        const TypeAry* tta = tap->_ary;
+        const TypeAry* mta = tary;
+        // Handle multidimensional arrays
+        const TypePtr* ftp = mta->_elem->make_ptr();
+        const TypePtr* ktp = tta->_elem->make_ptr();
+        while (ftp && ftp->isa_aryptr() && ktp && ktp->isa_aryptr()) {
+          mta = ftp->is_aryptr()->_ary;
+          tta = ktp->is_aryptr()->_ary;
+          ftp = mta->_elem->make_ptr();
+          ktp = tta->_elem->make_ptr();
+        }
+        const TypeInstPtr* ktip = ktp ? ktp->isa_instptr() : NULL;
+        if (ktip == NULL || !ktip->is_loaded() || !ktip->klass()->is_interface()) {
       if (above_centerline(ptr)) {
         tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
       }
+        }
       return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot, speculative, depth);
     }
 
     bool xk = false;
     switch (tap->ptr()) {
< prev index next >