6837094: False positive for "meet not symmetric" failure
Have the meet not symmetric check recursively do the interface-vs-oop check on array subtypes. Reviewed-by: jrose
This commit is contained in:
parent
0f4f530213
commit
2c5f52b511
@ -487,6 +487,23 @@ bool Type::is_nan() const {
|
|||||||
return false;
|
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-------------------------------------------
|
//------------------------------meet-------------------------------------------
|
||||||
// Compute the MEET of two types. NOT virtual. It enforces that meet is
|
// Compute the MEET of two types. NOT virtual. It enforces that meet is
|
||||||
// commutative and the lattice is symmetric.
|
// commutative and the lattice is symmetric.
|
||||||
@ -507,16 +524,8 @@ const Type *Type::meet( const Type *t ) const {
|
|||||||
// Interface meet Oop is Not Symmetric:
|
// Interface meet Oop is Not Symmetric:
|
||||||
// Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull
|
// Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull
|
||||||
// Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull
|
// 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_cr("=== Meet Not Symmetric ===");
|
||||||
tty->print("t = "); t->dump(); tty->cr();
|
tty->print("t = "); t->dump(); tty->cr();
|
||||||
tty->print("this= "); dump(); tty->cr();
|
tty->print("this= "); dump(); tty->cr();
|
||||||
@ -1800,6 +1809,17 @@ int TypeAry::hash(void) const {
|
|||||||
return (intptr_t)_elem + (intptr_t)_size;
|
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------------------------------------------
|
//------------------------------dump2------------------------------------------
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void TypeAry::dump2( Dict &d, uint depth, outputStream *st ) const {
|
void TypeAry::dump2( Dict &d, uint depth, outputStream *st ) const {
|
||||||
@ -3389,6 +3409,17 @@ const Type *TypeAryPtr::xdual() const {
|
|||||||
return new TypeAryPtr( dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id() );
|
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------------------------------------------
|
//------------------------------dump2------------------------------------------
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
|
void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const {
|
||||||
|
@ -190,6 +190,11 @@ public:
|
|||||||
// Currently, it also works around limitations involving interface types.
|
// Currently, it also works around limitations involving interface types.
|
||||||
virtual const Type *filter( const Type *kills ) const;
|
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
|
// Returns true if this pointer points at memory which contains a
|
||||||
// compressed oop references.
|
// compressed oop references.
|
||||||
bool is_ptr_to_narrowoop() const;
|
bool is_ptr_to_narrowoop() const;
|
||||||
@ -546,6 +551,10 @@ public:
|
|||||||
virtual const Type *xmeet( const Type *t ) const;
|
virtual const Type *xmeet( const Type *t ) const;
|
||||||
virtual const Type *xdual() const; // Compute dual right now.
|
virtual const Type *xdual() const; // Compute dual right now.
|
||||||
bool ary_must_be_exact() const; // true if arrays of such are never generic
|
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
|
#ifndef PRODUCT
|
||||||
virtual void dump2( Dict &d, uint, outputStream *st ) const; // Specialized per-Type dumping
|
virtual void dump2( Dict &d, uint, outputStream *st ) const; // Specialized per-Type dumping
|
||||||
#endif
|
#endif
|
||||||
@ -867,6 +876,10 @@ public:
|
|||||||
}
|
}
|
||||||
static const TypeAryPtr *_array_body_type[T_CONFLICT+1];
|
static const TypeAryPtr *_array_body_type[T_CONFLICT+1];
|
||||||
// sharpen the type of an int which is used as an array size
|
// 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
|
#ifndef PRODUCT
|
||||||
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
|
virtual void dump2( Dict &d, uint depth, outputStream *st ) const; // Specialized per-Type dumping
|
||||||
#endif
|
#endif
|
||||||
|
94
hotspot/test/compiler/6837094/Test.java
Normal file
94
hotspot/test/compiler/6837094/Test.java
Normal file
@ -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 {
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user