8202465: [C1] casts should not be eliminated for interface types
authorvlivanov
Fri, 04 May 2018 16:49:22 -0700
changeset 50016 947f79c91b35
parent 50015 d0a350777bd1
child 50017 88cc95780b6e
8202465: [C1] casts should not be eliminated for interface types Reviewed-by: jrose, thartmann
src/hotspot/share/c1/c1_Canonicalizer.cpp
test/jdk/java/lang/invoke/I4Special.jcod
test/jdk/java/lang/invoke/SpecialInterfaceCall.java
test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm
--- a/src/hotspot/share/c1/c1_Canonicalizer.cpp	Fri May 04 17:52:10 2018 -0400
+++ b/src/hotspot/share/c1/c1_Canonicalizer.cpp	Fri May 04 16:49:22 2018 -0700
@@ -648,13 +648,21 @@
 void Canonicalizer::do_NewObjectArray (NewObjectArray*  x) {}
 void Canonicalizer::do_NewMultiArray  (NewMultiArray*   x) {}
 void Canonicalizer::do_CheckCast      (CheckCast*       x) {
-  if (x->klass()->is_loaded() && !x->is_invokespecial_receiver_check()) {
+  if (x->klass()->is_loaded()) {
     Value obj = x->obj();
     ciType* klass = obj->exact_type();
-    if (klass == NULL) klass = obj->declared_type();
-    if (klass != NULL && klass->is_loaded() && klass->is_subtype_of(x->klass())) {
-      set_canonical(obj);
-      return;
+    if (klass == NULL) {
+      klass = obj->declared_type();
+    }
+    if (klass != NULL && klass->is_loaded()) {
+      bool is_interface = klass->is_instance_klass() &&
+                          klass->as_instance_klass()->is_interface();
+      // Interface casts can't be statically optimized away since verifier doesn't
+      // enforce interface types in bytecode.
+      if (!is_interface && klass->is_subtype_of(x->klass())) {
+        set_canonical(obj);
+        return;
+      }
     }
     // checkcast of null returns null
     if (obj->as_Constant() && obj->type()->as_ObjectType()->constant_value()->is_null_object()) {
--- a/test/jdk/java/lang/invoke/I4Special.jcod	Fri May 04 17:52:10 2018 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,106 +0,0 @@
-/*
- * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-// invokeDirect is modified to use invokespecial instead of invokevirtual
-
-class SpecialInterfaceCall$I4 {
-  0xCAFEBABE;
-  0; // minor version
-  55; // version
-  [] { // Constant Pool
-    ; // first element is empty
-    Method #3 #13; // #1
-    class #15; // #2
-    class #16; // #3
-    class #17; // #4
-    Utf8 "invokeDirect"; // #5
-    Utf8 "I4"; // #6
-    Utf8 "InnerClasses"; // #7
-    Utf8 "(LSpecialInterfaceCall$I4;)V"; // #8
-    Utf8 "Code"; // #9
-    Utf8 "LineNumberTable"; // #10
-    Utf8 "SourceFile"; // #11
-    Utf8 "SpecialInterfaceCall.java"; // #12
-    NameAndType #19 #20; // #13
-    class #21; // #14
-    Utf8 "SpecialInterfaceCall$I4"; // #15
-    Utf8 "java/lang/Object"; // #16
-    Utf8 "SpecialInterfaceCall$I1"; // #17
-    Utf8 "I1"; // #18
-    Utf8 "toString"; // #19
-    Utf8 "()Ljava/lang/String;"; // #20
-    Utf8 "SpecialInterfaceCall"; // #21
-  } // Constant Pool
-
-  0x0600; // access
-  #2;// this_cpx
-  #3;// super_cpx
-
-  [] { // Interfaces
-    #4;
-  } // Interfaces
-
-  [] { // fields
-  } // fields
-
-  [] { // methods
-    { // Member
-      0x0009; // access
-      #5; // name_cpx
-      #8; // sig_cpx
-      [] { // Attributes
-        Attr(#9) { // Code
-          1; // max_stack
-          2; // max_locals
-          Bytes[]{
-//            0x2AB600014CB1;
-            0x2AB700014CB1;  // invokespecial
-          };
-          [] { // Traps
-          } // end Traps
-          [] { // Attributes
-            Attr(#10) { // LineNumberTable
-              [] { // LineNumberTable
-                0  77;
-                5  78;
-              }
-            } // end LineNumberTable
-          } // Attributes
-        } // end Code
-      } // Attributes
-    } // Member
-  } // methods
-
-  [] { // Attributes
-    Attr(#11) { // SourceFile
-      #12;
-    } // end SourceFile
-    ;
-    Attr(#7) { // InnerClasses
-      [] { // InnerClasses
-        #2 #14 #6 1544;
-        #4 #14 #18 1544;
-      }
-    } // end InnerClasses
-  } // Attributes
-} // end class SpecialInterfaceCall$I4
--- a/test/jdk/java/lang/invoke/SpecialInterfaceCall.java	Fri May 04 17:52:10 2018 -0400
+++ b/test/jdk/java/lang/invoke/SpecialInterfaceCall.java	Fri May 04 16:49:22 2018 -0700
@@ -26,11 +26,9 @@
  * @bug 8200167
  * @summary Test direct and MethodHandle access to interface methods using invokespecial semantics
  * @compile SpecialInterfaceCall.java
- * @compile I4Special.jcod
+ * @compile SpecialInterfaceCallI4.jasm
  * @run main/othervm -Xint SpecialInterfaceCall
  * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=1 SpecialInterfaceCall
- * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=2 SpecialInterfaceCall
- * @run main/othervm -Xbatch -XX:+TieredCompilation -XX:TieredStopAtLevel=3 SpecialInterfaceCall
  * @run main/othervm -Xbatch -XX:-TieredCompilation SpecialInterfaceCall
  */
 
@@ -74,9 +72,10 @@
     }
     // This interface acts like I2 but we define a directInvoke method
     // that we will rewrite the bytecode of to use invokespecial
+    // (see SpecialInterfaceCallI4.jasm).
     interface I4 extends I1 {
         static void invokeDirect(I4 i) {
-            String s = i.toString();
+            throw new Error("Class file for I4 is not overwritten");
         }
     }
 
@@ -250,5 +249,4 @@
             throw new Error(e);
         }
     }
-
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/jdk/java/lang/invoke/SpecialInterfaceCallI4.jasm	Fri May 04 16:49:22 2018 -0700
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+// invokeDirect is modified to use invokespecial instead of invokevirtual
+
+interface SpecialInterfaceCall$I4 implements SpecialInterfaceCall$I1
+  version 55:0
+{
+    public static Method invokeDirect:"(LSpecialInterfaceCall$I4;)V"
+      stack 1 locals 2
+    {
+        aload_0;
+        invokespecial Method java/lang/Object.toString:"()Ljava/lang/String;";
+        astore_1;
+        return;
+    }
+
+    static abstract interface InnerClass I4=class SpecialInterfaceCall$I4 of class SpecialInterfaceCall;
+    static abstract interface InnerClass I1=class SpecialInterfaceCall$I1 of class SpecialInterfaceCall;
+
+} // end Class SpecialInterfaceCall$I4