6837094: False positive for "meet not symmetric" failure
Summary: Have the meet not symmetric check recursively do the interface-vs-oop check on array subtypes.
Reviewed-by: jrose
Contributed-by: rasbold@google.com
--- a/hotspot/src/share/vm/opto/type.cpp Wed Jun 10 12:19:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/type.cpp Tue Jun 23 17:52:29 2009 -0700
@@ -487,6 +487,23 @@
return false;
}
+//----------------------interface_vs_oop---------------------------------------
+#ifdef ASSERT
+bool Type::interface_vs_oop(const Type *t) const {
+ bool result = false;
+
+ const TypeInstPtr* this_inst = this->isa_instptr();
+ const TypeInstPtr* t_inst = t->isa_instptr();
+ if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) {
+ bool this_interface = this_inst->klass()->is_interface();
+ bool t_interface = t_inst->klass()->is_interface();
+ result = this_interface ^ t_interface;
+ }
+
+ return result;
+}
+#endif
+
//------------------------------meet-------------------------------------------
// Compute the MEET of two types. NOT virtual. It enforces that meet is
// commutative and the lattice is symmetric.
@@ -507,16 +524,8 @@
// Interface meet Oop is Not Symmetric:
// Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull
// Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull
- const TypeInstPtr* this_inst = this->isa_instptr();
- const TypeInstPtr* t_inst = t->isa_instptr();
- bool interface_vs_oop = false;
- if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) {
- bool this_interface = this_inst->klass()->is_interface();
- bool t_interface = t_inst->klass()->is_interface();
- interface_vs_oop = this_interface ^ t_interface;
- }
-
- if( !interface_vs_oop && (t2t != t->_dual || t2this != _dual) ) {
+
+ if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != _dual) ) {
tty->print_cr("=== Meet Not Symmetric ===");
tty->print("t = "); t->dump(); tty->cr();
tty->print("this= "); dump(); tty->cr();
@@ -1800,6 +1809,17 @@
return (intptr_t)_elem + (intptr_t)_size;
}
+//----------------------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);
+ }
+ return false;
+}
+#endif
+
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
void TypeAry::dump2( Dict &d, uint depth, outputStream *st ) const {
@@ -3389,6 +3409,17 @@
return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id() );
}
+//----------------------interface_vs_oop---------------------------------------
+#ifdef ASSERT
+bool TypeAryPtr::interface_vs_oop(const Type *t) const {
+ const TypeAryPtr* t_aryptr = t->isa_aryptr();
+ if (t_aryptr) {
+ return _ary->interface_vs_oop(t_aryptr->_ary);
+ }
+ return false;
+}
+#endif
+
//------------------------------dump2------------------------------------------
#ifndef PRODUCT
void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
--- a/hotspot/src/share/vm/opto/type.hpp Wed Jun 10 12:19:48 2009 -0700
+++ b/hotspot/src/share/vm/opto/type.hpp Tue Jun 23 17:52:29 2009 -0700
@@ -190,6 +190,11 @@
// Currently, it also works around limitations involving interface types.
virtual const Type *filter( const Type *kills ) const;
+#ifdef ASSERT
+ // One type is interface, the other is oop
+ virtual bool interface_vs_oop(const Type *t) const;
+#endif
+
// Returns true if this pointer points at memory which contains a
// compressed oop references.
bool is_ptr_to_narrowoop() const;
@@ -546,6 +551,10 @@
virtual const Type *xmeet( const Type *t ) const;
virtual const Type *xdual() const; // Compute dual right now.
bool ary_must_be_exact() const; // true if arrays of such are never generic
+#ifdef ASSERT
+ // One type is interface, the other is oop
+ virtual bool interface_vs_oop(const Type *t) const;
+#endif
#ifndef PRODUCT
virtual void dump2( Dict &d, uint, outputStream *st ) const; // Specialized per-Type dumping
#endif
@@ -867,6 +876,10 @@
}
static const TypeAryPtr *_array_body_type[T_CONFLICT+1];
// sharpen the type of an int which is used as an array size
+#ifdef ASSERT
+ // One type is interface, the other is oop
+ virtual bool interface_vs_oop(const Type *t) const;
+#endif
#ifndef PRODUCT
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/compiler/6837094/Test.java Tue Jun 23 17:52:29 2009 -0700
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ *
+ */
+
+/**
+ * @test
+ * @bug 6837094
+ * @summary False positive for "meet not symmetric" failure
+ *
+ * @run main/othervm -Xbatch -XX:CompileOnly=Test.collectIs,Test$Factory$1.getArray,Test$Factory$2.getArray Test
+ */
+
+import java.util.Set;
+import java.util.HashSet;
+
+public class Test {
+
+ private interface Factory<M extends Interface> {
+ Factory<Child0> Zero = new Factory<Child0>() {
+ public Child0[] getArray() { return new Child0[1]; }
+ };
+
+ Factory<Child1> One = new Factory<Child1>() {
+ public Child1[] getArray() { return new Child1[1]; }
+ };
+
+ M[] getArray();
+ }
+
+ /**
+ * C2 asserts when compiling this method. Bimorphic inlining happens at
+ * getArray call site. A Phi in the catch block tries to join the meet type
+ * from he inline site (Parent[]) with the type expected by CI (Interface[]).
+ *
+ * C2 throws an assert when it doesn't need to.
+ */
+ private static <I extends Interface> void collectIs(
+ Factory<I> factory, Set<Interface> s) {
+ for (I i : factory.getArray()) {
+ try {
+ s.add(i);
+ } catch (Exception e) {
+ }
+ }
+ }
+
+ static public void main(String argv[]) {
+ Set<Interface> s = new HashSet();
+
+ for (int i = 0; i < 25000; i++) {
+ collectIs(Factory.Zero, s);
+ collectIs(Factory.One, s);
+ }
+ }
+}
+
+/**
+ * Establish necessary class hierarchy
+ */
+
+interface Interface {
+}
+
+class Parent {
+}
+
+class Child0 extends Parent implements Interface {
+}
+
+class Child1 extends Parent implements Interface {
+}
+
+class Child2 extends Parent implements Interface {
+}