8240676: Meet not symmetric failure when running lucene on jdk8

Reviewed-by: kvn, thartmann
This commit is contained in:
Roland Westrelin 2020-03-24 11:06:26 +01:00
parent 7048684ca7
commit 5ff2d7baaa
5 changed files with 126 additions and 25 deletions

View file

@ -1009,6 +1009,9 @@ void Compile::Init(int aliaslevel) {
_range_check_casts = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); _range_check_casts = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
_opaque4_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); _opaque4_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL);
register_library_intrinsics(); register_library_intrinsics();
#ifdef ASSERT
_type_verify_symmetry = true;
#endif
} }
//---------------------------init_start---------------------------------------- //---------------------------init_start----------------------------------------

View file

@ -1179,6 +1179,9 @@ class Compile : public Phase {
bool select_24_bit_instr() const { return _select_24_bit_instr; } bool select_24_bit_instr() const { return _select_24_bit_instr; }
bool in_24_bit_fp_mode() const { return _in_24_bit_fp_mode; } bool in_24_bit_fp_mode() const { return _in_24_bit_fp_mode; }
#endif // IA32 #endif // IA32
#ifdef ASSERT
bool _type_verify_symmetry;
#endif
}; };
#endif // SHARE_OPTO_COMPILE_HPP #endif // SHARE_OPTO_COMPILE_HPP

View file

@ -810,6 +810,35 @@ bool Type::interface_vs_oop(const Type *t) const {
#endif #endif
void Type::check_symmetrical(const Type *t, const Type *mt) const {
#ifdef ASSERT
assert(mt == t->xmeet(this), "meet not commutative");
const Type* dual_join = mt->_dual;
const Type *t2t = dual_join->xmeet(t->_dual);
const Type *t2this = dual_join->xmeet(this->_dual);
// Interface meet Oop is Not Symmetric:
// Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull
// Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull
if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != this->_dual) ) {
tty->print_cr("=== Meet Not Symmetric ===");
tty->print("t = "); t->dump(); tty->cr();
tty->print("this= "); dump(); tty->cr();
tty->print("mt=(t meet this)= "); mt->dump(); tty->cr();
tty->print("t_dual= "); t->_dual->dump(); tty->cr();
tty->print("this_dual= "); _dual->dump(); tty->cr();
tty->print("mt_dual= "); mt->_dual->dump(); tty->cr();
tty->print("mt_dual meet t_dual= "); t2t ->dump(); tty->cr();
tty->print("mt_dual meet this_dual= "); t2this ->dump(); tty->cr();
fatal("meet not symmetric" );
}
#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.
@ -827,33 +856,28 @@ const Type *Type::meet_helper(const Type *t, bool include_speculative) const {
t = t->maybe_remove_speculative(include_speculative); t = t->maybe_remove_speculative(include_speculative);
const Type *mt = this_t->xmeet(t); const Type *mt = this_t->xmeet(t);
#ifdef ASSERT
if (isa_narrowoop() || t->isa_narrowoop()) return mt; if (isa_narrowoop() || t->isa_narrowoop()) return mt;
if (isa_narrowklass() || t->isa_narrowklass()) return mt; if (isa_narrowklass() || t->isa_narrowklass()) return mt;
#ifdef ASSERT Compile* C = Compile::current();
assert(mt == t->xmeet(this_t), "meet not commutative"); if (!C->_type_verify_symmetry) {
const Type* dual_join = mt->_dual; return mt;
const Type *t2t = dual_join->xmeet(t->_dual);
const Type *t2this = dual_join->xmeet(this_t->_dual);
// Interface meet Oop is Not Symmetric:
// Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull
// Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull
if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != this_t->_dual) ) {
tty->print_cr("=== Meet Not Symmetric ===");
tty->print("t = "); t->dump(); tty->cr();
tty->print("this= "); this_t->dump(); tty->cr();
tty->print("mt=(t meet this)= "); mt->dump(); tty->cr();
tty->print("t_dual= "); t->_dual->dump(); tty->cr();
tty->print("this_dual= "); this_t->_dual->dump(); tty->cr();
tty->print("mt_dual= "); mt->_dual->dump(); tty->cr();
tty->print("mt_dual meet t_dual= "); t2t ->dump(); tty->cr();
tty->print("mt_dual meet this_dual= "); t2this ->dump(); tty->cr();
fatal("meet not symmetric" );
} }
this_t->check_symmetrical(t, mt);
// In the case of an array, computing the meet above, caused the
// computation of the meet of the elements which at verification
// time caused the computation of the meet of the dual of the
// elements. Computing the meet of the dual of the arrays here
// causes the meet of the dual of the elements to be computed which
// would cause the meet of the dual of the dual of the elements,
// that is the meet of the elements already computed above to be
// computed. Avoid redundant computations by requesting no
// verification.
C->_type_verify_symmetry = false;
const Type *mt_dual = this_t->_dual->xmeet(t->_dual);
this_t->_dual->check_symmetrical(t->_dual, mt_dual);
assert(!C->_type_verify_symmetry, "shouldn't have changed");
C->_type_verify_symmetry = true;
#endif #endif
return mt; return mt;
} }
@ -4315,7 +4339,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const {
(tap->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) || (tap->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) ||
// 'this' is exact and super or unrelated: // 'this' is exact and super or unrelated:
(this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) { (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) {
if (above_centerline(ptr)) { if (above_centerline(ptr) || (tary->_elem->make_ptr() && above_centerline(tary->_elem->make_ptr()->_ptr))) {
tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable); tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable);
} }
return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot, speculative, depth); return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot, speculative, depth);

View file

@ -166,6 +166,7 @@ private:
#endif #endif
const Type *meet_helper(const Type *t, bool include_speculative) const; const Type *meet_helper(const Type *t, bool include_speculative) const;
void check_symmetrical(const Type *t, const Type *mt) const;
protected: protected:
// Each class of type is also identified by its base. // Each class of type is also identified by its base.

View file

@ -0,0 +1,70 @@
/*
* Copyright (c) 2020, Red Hat, 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8240676
* @summary Meet not symmetric failure when running lucene on jdk8
*
* @run main/othervm -XX:-BackgroundCompilation TestArrayMeetNotSymmetrical
*
*/
public class TestArrayMeetNotSymmetrical {
private static final Object field = new Object[0];
private static final Object field2 = new A[0];
public static void main(String[] args) {
Object array = new A[10];
for (int i = 0; i < 20_000; i++) {
test1(true, 10);
test1(false, 10);
test2(true);
test2(false);
}
}
private static Object test1(boolean flag, int len) {
Object o;
if (flag) {
o = field;
} else {
o = new A[len];
}
return o;
}
private static Object test2(boolean flag) {
Object o;
if (flag) {
o = field;
} else {
o = field2;
}
return o;
}
private static class A {
}
}