src/hotspot/share/c1/c1_GraphBuilder.cpp
changeset 53595 8462b295c08b
parent 53208 40187283e6eb
child 53634 f57b943a1a22
--- a/src/hotspot/share/c1/c1_GraphBuilder.cpp	Thu Jan 31 17:48:25 2019 -0800
+++ b/src/hotspot/share/c1/c1_GraphBuilder.cpp	Thu Jan 31 17:48:29 2019 -0800
@@ -1942,7 +1942,8 @@
       // Use CHA on the receiver to select a more precise method.
       cha_monomorphic_target = target->find_monomorphic_target(calling_klass, callee_holder, actual_recv);
     } else if (code == Bytecodes::_invokeinterface && callee_holder->is_loaded() && receiver != NULL) {
-      // if there is only one implementor of this interface then we
+      assert(callee_holder->is_interface(), "invokeinterface to non interface?");
+      // If there is only one implementor of this interface then we
       // may be able bind this invoke directly to the implementing
       // klass but we need both a dependence on the single interface
       // and on the method we bind to.  Additionally since all we know
@@ -1950,53 +1951,44 @@
       // interface we have to insert a check that it's the class we
       // expect.  Interface types are not checked by the verifier so
       // they are roughly equivalent to Object.
+      // The number of implementors for declared_interface is less or
+      // equal to the number of implementors for target->holder() so
+      // if number of implementors of target->holder() == 1 then
+      // number of implementors for decl_interface is 0 or 1. If
+      // it's 0 then no class implements decl_interface and there's
+      // no point in inlining.
       ciInstanceKlass* singleton = NULL;
-      if (target->holder()->nof_implementors() == 1) {
-        singleton = target->holder()->implementor();
-        assert(singleton != NULL && singleton != target->holder(),
-               "just checking");
-
-        assert(holder->is_interface(), "invokeinterface to non interface?");
-        ciInstanceKlass* decl_interface = (ciInstanceKlass*)holder;
-        // the number of implementors for decl_interface is less or
-        // equal to the number of implementors for target->holder() so
-        // if number of implementors of target->holder() == 1 then
-        // number of implementors for decl_interface is 0 or 1. If
-        // it's 0 then no class implements decl_interface and there's
-        // no point in inlining.
-        if (!holder->is_loaded() || decl_interface->nof_implementors() != 1 || decl_interface->has_nonstatic_concrete_methods()) {
-          singleton = NULL;
-        }
-      }
-      if (singleton) {
-        cha_monomorphic_target = target->find_monomorphic_target(calling_klass, target->holder(), singleton);
+      ciInstanceKlass* declared_interface = callee_holder;
+      if (declared_interface->nof_implementors() == 1 &&
+          (!target->is_default_method() || target->is_overpass()) /* CHA doesn't support default methods yet. */) {
+        singleton = declared_interface->implementor();
+        assert(singleton != NULL && singleton != declared_interface, "");
+        cha_monomorphic_target = target->find_monomorphic_target(calling_klass, declared_interface, singleton);
         if (cha_monomorphic_target != NULL) {
-          // If CHA is able to bind this invoke then update the class
-          // to match that class, otherwise klass will refer to the
-          // interface.
-          klass = cha_monomorphic_target->holder();
-          actual_recv = target->holder();
-
-          // insert a check it's really the expected class.
-          CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception());
-          c->set_incompatible_class_change_check();
-          c->set_direct_compare(klass->is_final());
-          // pass the result of the checkcast so that the compiler has
-          // more accurate type info in the inlinee
-          better_receiver = append_split(c);
+          if (cha_monomorphic_target->holder() != compilation()->env()->Object_klass()) {
+            // If CHA is able to bind this invoke then update the class
+            // to match that class, otherwise klass will refer to the
+            // interface.
+            klass = cha_monomorphic_target->holder();
+            actual_recv = declared_interface;
+
+            // insert a check it's really the expected class.
+            CheckCast* c = new CheckCast(klass, receiver, copy_state_for_exception());
+            c->set_incompatible_class_change_check();
+            c->set_direct_compare(klass->is_final());
+            // pass the result of the checkcast so that the compiler has
+            // more accurate type info in the inlinee
+            better_receiver = append_split(c);
+          } else {
+            cha_monomorphic_target = NULL; // subtype check against Object is useless
+          }
         }
       }
     }
   }
 
   if (cha_monomorphic_target != NULL) {
-    if (cha_monomorphic_target->is_abstract()) {
-      // Do not optimize for abstract methods
-      cha_monomorphic_target = NULL;
-    }
-  }
-
-  if (cha_monomorphic_target != NULL) {
+    assert(!cha_monomorphic_target->is_abstract(), "");
     if (!(target->is_final_method())) {
       // If we inlined because CHA revealed only a single target method,
       // then we are dependent on that target method not getting overridden