6837094: False positive for "meet not symmetric" failure

Tue, 23 Jun 2009 17:52:29 -0700

author
kvn
date
Tue, 23 Jun 2009 17:52:29 -0700
changeset 1255
915cc9c5ebc6
parent 1254
c6386080541b
child 1257
e306d7c7222c

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

src/share/vm/opto/type.cpp file | annotate | diff | comparison | revisions
src/share/vm/opto/type.hpp file | annotate | diff | comparison | revisions
test/compiler/6837094/Test.java file | annotate | diff | comparison | revisions
     1.1 --- a/src/share/vm/opto/type.cpp	Wed Jun 10 12:19:48 2009 -0700
     1.2 +++ b/src/share/vm/opto/type.cpp	Tue Jun 23 17:52:29 2009 -0700
     1.3 @@ -487,6 +487,23 @@
     1.4    return false;
     1.5  }
     1.6  
     1.7 +//----------------------interface_vs_oop---------------------------------------
     1.8 +#ifdef ASSERT
     1.9 +bool Type::interface_vs_oop(const Type *t) const {
    1.10 +  bool result = false;
    1.11 +
    1.12 +  const TypeInstPtr* this_inst = this->isa_instptr();
    1.13 +  const TypeInstPtr*    t_inst =    t->isa_instptr();
    1.14 +  if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) {
    1.15 +    bool this_interface = this_inst->klass()->is_interface();
    1.16 +    bool    t_interface =    t_inst->klass()->is_interface();
    1.17 +    result = this_interface ^ t_interface;
    1.18 +  }
    1.19 +
    1.20 +  return result;
    1.21 +}
    1.22 +#endif
    1.23 +
    1.24  //------------------------------meet-------------------------------------------
    1.25  // Compute the MEET of two types.  NOT virtual.  It enforces that meet is
    1.26  // commutative and the lattice is symmetric.
    1.27 @@ -507,16 +524,8 @@
    1.28    // Interface meet Oop is Not Symmetric:
    1.29    // Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull
    1.30    // Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull
    1.31 -  const TypeInstPtr* this_inst = this->isa_instptr();
    1.32 -  const TypeInstPtr*    t_inst =    t->isa_instptr();
    1.33 -  bool interface_vs_oop = false;
    1.34 -  if( this_inst && this_inst->is_loaded() && t_inst && t_inst->is_loaded() ) {
    1.35 -    bool this_interface = this_inst->klass()->is_interface();
    1.36 -    bool    t_interface =    t_inst->klass()->is_interface();
    1.37 -    interface_vs_oop = this_interface ^ t_interface;
    1.38 -  }
    1.39 -
    1.40 -  if( !interface_vs_oop && (t2t != t->_dual || t2this != _dual) ) {
    1.41 +
    1.42 +  if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != _dual) ) {
    1.43      tty->print_cr("=== Meet Not Symmetric ===");
    1.44      tty->print("t   =                   ");         t->dump(); tty->cr();
    1.45      tty->print("this=                   ");            dump(); tty->cr();
    1.46 @@ -1800,6 +1809,17 @@
    1.47    return (intptr_t)_elem + (intptr_t)_size;
    1.48  }
    1.49  
    1.50 +//----------------------interface_vs_oop---------------------------------------
    1.51 +#ifdef ASSERT
    1.52 +bool TypeAry::interface_vs_oop(const Type *t) const {
    1.53 +  const TypeAry* t_ary = t->is_ary();
    1.54 +  if (t_ary) {
    1.55 +    return _elem->interface_vs_oop(t_ary->_elem);
    1.56 +  }
    1.57 +  return false;
    1.58 +}
    1.59 +#endif
    1.60 +
    1.61  //------------------------------dump2------------------------------------------
    1.62  #ifndef PRODUCT
    1.63  void TypeAry::dump2( Dict &d, uint depth, outputStream *st ) const {
    1.64 @@ -3389,6 +3409,17 @@
    1.65    return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id() );
    1.66  }
    1.67  
    1.68 +//----------------------interface_vs_oop---------------------------------------
    1.69 +#ifdef ASSERT
    1.70 +bool TypeAryPtr::interface_vs_oop(const Type *t) const {
    1.71 +  const TypeAryPtr* t_aryptr = t->isa_aryptr();
    1.72 +  if (t_aryptr) {
    1.73 +    return _ary->interface_vs_oop(t_aryptr->_ary);
    1.74 +  }
    1.75 +  return false;
    1.76 +}
    1.77 +#endif
    1.78 +
    1.79  //------------------------------dump2------------------------------------------
    1.80  #ifndef PRODUCT
    1.81  void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
     2.1 --- a/src/share/vm/opto/type.hpp	Wed Jun 10 12:19:48 2009 -0700
     2.2 +++ b/src/share/vm/opto/type.hpp	Tue Jun 23 17:52:29 2009 -0700
     2.3 @@ -190,6 +190,11 @@
     2.4    // Currently, it also works around limitations involving interface types.
     2.5    virtual const Type *filter( const Type *kills ) const;
     2.6  
     2.7 +#ifdef ASSERT
     2.8 +  // One type is interface, the other is oop
     2.9 +  virtual bool interface_vs_oop(const Type *t) const;
    2.10 +#endif
    2.11 +
    2.12    // Returns true if this pointer points at memory which contains a
    2.13    // compressed oop references.
    2.14    bool is_ptr_to_narrowoop() const;
    2.15 @@ -546,6 +551,10 @@
    2.16    virtual const Type *xmeet( const Type *t ) const;
    2.17    virtual const Type *xdual() const;    // Compute dual right now.
    2.18    bool ary_must_be_exact() const;  // true if arrays of such are never generic
    2.19 +#ifdef ASSERT
    2.20 +  // One type is interface, the other is oop
    2.21 +  virtual bool interface_vs_oop(const Type *t) const;
    2.22 +#endif
    2.23  #ifndef PRODUCT
    2.24    virtual void dump2( Dict &d, uint, outputStream *st  ) const; // Specialized per-Type dumping
    2.25  #endif
    2.26 @@ -867,6 +876,10 @@
    2.27    }
    2.28    static const TypeAryPtr *_array_body_type[T_CONFLICT+1];
    2.29    // sharpen the type of an int which is used as an array size
    2.30 +#ifdef ASSERT
    2.31 +  // One type is interface, the other is oop
    2.32 +  virtual bool interface_vs_oop(const Type *t) const;
    2.33 +#endif
    2.34  #ifndef PRODUCT
    2.35    virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
    2.36  #endif
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/compiler/6837094/Test.java	Tue Jun 23 17:52:29 2009 -0700
     3.3 @@ -0,0 +1,94 @@
     3.4 +/*
     3.5 + * Copyright 2009 Sun Microsystems, Inc.  All Rights Reserved.
     3.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3.7 + *
     3.8 + * This code is free software; you can redistribute it and/or modify it
     3.9 + * under the terms of the GNU General Public License version 2 only, as
    3.10 + * published by the Free Software Foundation.
    3.11 + *
    3.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
    3.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    3.14 + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    3.15 + * version 2 for more details (a copy is included in the LICENSE file that
    3.16 + * accompanied this code).
    3.17 + *
    3.18 + * You should have received a copy of the GNU General Public License version
    3.19 + * 2 along with this work; if not, write to the Free Software Foundation,
    3.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    3.21 + *
    3.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    3.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
    3.24 + * have any questions.
    3.25 + *
    3.26 + */
    3.27 +
    3.28 +/**
    3.29 + * @test
    3.30 + * @bug 6837094
    3.31 + * @summary False positive for "meet not symmetric" failure
    3.32 + *
    3.33 + * @run main/othervm -Xbatch -XX:CompileOnly=Test.collectIs,Test$Factory$1.getArray,Test$Factory$2.getArray Test
    3.34 + */
    3.35 +
    3.36 +import java.util.Set;
    3.37 +import java.util.HashSet;
    3.38 +
    3.39 +public class Test {
    3.40 +
    3.41 +  private interface Factory<M extends Interface> {
    3.42 +    Factory<Child0> Zero = new Factory<Child0>() {
    3.43 +      public Child0[] getArray() { return new Child0[1]; }
    3.44 +    };
    3.45 +
    3.46 +    Factory<Child1> One = new Factory<Child1>() {
    3.47 +      public Child1[] getArray() { return new Child1[1]; }
    3.48 +    };
    3.49 +
    3.50 +    M[] getArray();
    3.51 +  }
    3.52 +
    3.53 +  /**
    3.54 +   * C2 asserts when compiling this method. Bimorphic inlining happens at
    3.55 +   * getArray call site. A Phi in the catch block tries to join the meet type
    3.56 +   * from he inline site (Parent[]) with the type expected by CI (Interface[]).
    3.57 +   *
    3.58 +   * C2 throws an assert when it doesn't need to.
    3.59 +   */
    3.60 +  private static <I extends Interface> void collectIs(
    3.61 +      Factory<I> factory, Set<Interface> s) {
    3.62 +    for (I i : factory.getArray()) {
    3.63 +      try {
    3.64 +        s.add(i);
    3.65 +      } catch (Exception e) {
    3.66 +      }
    3.67 +    }
    3.68 +  }
    3.69 +
    3.70 +  static public void main(String argv[]) {
    3.71 +    Set<Interface> s = new HashSet();
    3.72 +
    3.73 +    for (int i = 0; i < 25000; i++) {
    3.74 +      collectIs(Factory.Zero, s);
    3.75 +      collectIs(Factory.One, s);
    3.76 +    }
    3.77 +  }
    3.78 +}
    3.79 +
    3.80 +/**
    3.81 + * Establish necessary class hierarchy
    3.82 + */
    3.83 +
    3.84 +interface Interface {
    3.85 +}
    3.86 +
    3.87 +class Parent {
    3.88 +}
    3.89 +
    3.90 +class Child0 extends Parent implements Interface {
    3.91 +}
    3.92 +
    3.93 +class Child1 extends Parent implements Interface {
    3.94 +}
    3.95 +
    3.96 +class Child2 extends Parent implements Interface {
    3.97 +}

mercurial