hotspot/src/share/vm/opto/parse1.cpp
changeset 34202 5d19ca9c25a8
parent 34186 69c8391e72e1
child 35071 a0910b1d3e0d
--- a/hotspot/src/share/vm/opto/parse1.cpp	Mon Oct 05 23:50:43 2015 +0200
+++ b/hotspot/src/share/vm/opto/parse1.cpp	Mon Nov 16 14:19:10 2015 +0100
@@ -988,13 +988,18 @@
       // In case of concurrent class loading, the type we set for the
       // ret_phi in build_exits() may have been too optimistic and the
       // ret_phi may be top now.
-#ifdef ASSERT
+      // Otherwise, we've encountered an error and have to mark the method as
+      // not compilable. Just using an assertion instead would be dangerous
+      // as this could lead to an infinite compile loop in non-debug builds.
       {
         MutexLockerEx ml(Compile_lock, Mutex::_no_safepoint_check_flag);
-        assert(ret_type->isa_ptr() && C->env()->system_dictionary_modification_counter_changed(), "return value must be well defined");
+        if (C->env()->system_dictionary_modification_counter_changed()) {
+          C->record_failure(C2Compiler::retry_class_loading_during_parsing());
+        } else {
+          C->record_method_not_compilable("Can't determine return type.");
+        }
       }
-#endif
-      C->record_failure(C2Compiler::retry_class_loading_during_parsing());
+      return;
     }
     _exits.push_node(ret_type->basic_type(), ret_phi);
   }
@@ -2144,15 +2149,24 @@
     // here.
     Node* phi = _exits.argument(0);
     const TypeInstPtr *tr = phi->bottom_type()->isa_instptr();
-    if( tr && tr->klass()->is_loaded() &&
-        tr->klass()->is_interface() ) {
+    if (tr && tr->klass()->is_loaded() &&
+        tr->klass()->is_interface()) {
       const TypeInstPtr *tp = value->bottom_type()->isa_instptr();
       if (tp && tp->klass()->is_loaded() &&
           !tp->klass()->is_interface()) {
         // sharpen the type eagerly; this eases certain assert checking
         if (tp->higher_equal(TypeInstPtr::NOTNULL))
           tr = tr->join_speculative(TypeInstPtr::NOTNULL)->is_instptr();
-        value = _gvn.transform(new CheckCastPPNode(0,value,tr));
+        value = _gvn.transform(new CheckCastPPNode(0, value, tr));
+      }
+    } else {
+      // Also handle returns of oop-arrays to an arrays-of-interface return
+      const TypeInstPtr* phi_tip;
+      const TypeInstPtr* val_tip;
+      Type::get_arrays_base_elements(phi->bottom_type(), value->bottom_type(), &phi_tip, &val_tip);
+      if (phi_tip != NULL && phi_tip->is_loaded() && phi_tip->klass()->is_interface() &&
+          val_tip != NULL && val_tip->is_loaded() && !val_tip->klass()->is_interface()) {
+        value = _gvn.transform(new CheckCastPPNode(0, value, phi->bottom_type()));
       }
     }
     phi->add_req(value);