Tue, 30 Jun 2020 18:05:34 +0200
8240676: Meet not symmetric failure when running lucene on jdk8
Reviewed-by: kvn, thartmann
1.1 --- a/src/share/vm/opto/compile.cpp Fri Aug 21 09:07:53 2020 +0200 1.2 +++ b/src/share/vm/opto/compile.cpp Tue Jun 30 18:05:34 2020 +0200 1.3 @@ -1162,6 +1162,9 @@ 1.4 _expensive_nodes = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); 1.5 _range_check_casts = new(comp_arena()) GrowableArray<Node*>(comp_arena(), 8, 0, NULL); 1.6 register_library_intrinsics(); 1.7 +#ifdef ASSERT 1.8 + _type_verify_symmetry = true; 1.9 +#endif 1.10 } 1.11 1.12 //---------------------------init_start----------------------------------------
2.1 --- a/src/share/vm/opto/compile.hpp Fri Aug 21 09:07:53 2020 +0200 2.2 +++ b/src/share/vm/opto/compile.hpp Tue Jun 30 18:05:34 2020 +0200 2.3 @@ -1224,6 +1224,9 @@ 2.4 2.5 // Auxiliary method for randomized fuzzing/stressing 2.6 static bool randomized_select(int count); 2.7 +#ifdef ASSERT 2.8 + bool _type_verify_symmetry; 2.9 +#endif 2.10 }; 2.11 2.12 #endif // SHARE_VM_OPTO_COMPILE_HPP
3.1 --- a/src/share/vm/opto/type.cpp Fri Aug 21 09:07:53 2020 +0200 3.2 +++ b/src/share/vm/opto/type.cpp Tue Jun 30 18:05:34 2020 +0200 3.3 @@ -668,6 +668,35 @@ 3.4 3.5 #endif 3.6 3.7 +void Type::check_symmetrical(const Type *t, const Type *mt) const { 3.8 +#ifdef ASSERT 3.9 + assert(mt == t->xmeet(this), "meet not commutative"); 3.10 + const Type* dual_join = mt->_dual; 3.11 + const Type *t2t = dual_join->xmeet(t->_dual); 3.12 + const Type *t2this = dual_join->xmeet(this->_dual); 3.13 + 3.14 + // Interface meet Oop is Not Symmetric: 3.15 + // Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull 3.16 + // Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull 3.17 + 3.18 + if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != this->_dual) ) { 3.19 + tty->print_cr("=== Meet Not Symmetric ==="); 3.20 + tty->print("t = "); t->dump(); tty->cr(); 3.21 + tty->print("this= "); dump(); tty->cr(); 3.22 + tty->print("mt=(t meet this)= "); mt->dump(); tty->cr(); 3.23 + 3.24 + tty->print("t_dual= "); t->_dual->dump(); tty->cr(); 3.25 + tty->print("this_dual= "); _dual->dump(); tty->cr(); 3.26 + tty->print("mt_dual= "); mt->_dual->dump(); tty->cr(); 3.27 + 3.28 + tty->print("mt_dual meet t_dual= "); t2t ->dump(); tty->cr(); 3.29 + tty->print("mt_dual meet this_dual= "); t2this ->dump(); tty->cr(); 3.30 + 3.31 + fatal("meet not symmetric" ); 3.32 + } 3.33 +#endif 3.34 +} 3.35 + 3.36 //------------------------------meet------------------------------------------- 3.37 // Compute the MEET of two types. NOT virtual. It enforces that meet is 3.38 // commutative and the lattice is symmetric. 3.39 @@ -685,33 +714,28 @@ 3.40 t = t->maybe_remove_speculative(include_speculative); 3.41 3.42 const Type *mt = this_t->xmeet(t); 3.43 +#ifdef ASSERT 3.44 if (isa_narrowoop() || t->isa_narrowoop()) return mt; 3.45 if (isa_narrowklass() || t->isa_narrowklass()) return mt; 3.46 -#ifdef ASSERT 3.47 - assert(mt == t->xmeet(this_t), "meet not commutative"); 3.48 - const Type* dual_join = mt->_dual; 3.49 - const Type *t2t = dual_join->xmeet(t->_dual); 3.50 - const Type *t2this = dual_join->xmeet(this_t->_dual); 3.51 - 3.52 - // Interface meet Oop is Not Symmetric: 3.53 - // Interface:AnyNull meet Oop:AnyNull == Interface:AnyNull 3.54 - // Interface:NotNull meet Oop:NotNull == java/lang/Object:NotNull 3.55 - 3.56 - if( !interface_vs_oop(t) && (t2t != t->_dual || t2this != this_t->_dual) ) { 3.57 - tty->print_cr("=== Meet Not Symmetric ==="); 3.58 - tty->print("t = "); t->dump(); tty->cr(); 3.59 - tty->print("this= "); this_t->dump(); tty->cr(); 3.60 - tty->print("mt=(t meet this)= "); mt->dump(); tty->cr(); 3.61 - 3.62 - tty->print("t_dual= "); t->_dual->dump(); tty->cr(); 3.63 - tty->print("this_dual= "); this_t->_dual->dump(); tty->cr(); 3.64 - tty->print("mt_dual= "); mt->_dual->dump(); tty->cr(); 3.65 - 3.66 - tty->print("mt_dual meet t_dual= "); t2t ->dump(); tty->cr(); 3.67 - tty->print("mt_dual meet this_dual= "); t2this ->dump(); tty->cr(); 3.68 - 3.69 - fatal("meet not symmetric" ); 3.70 + Compile* C = Compile::current(); 3.71 + if (!C->_type_verify_symmetry) { 3.72 + return mt; 3.73 } 3.74 + this_t->check_symmetrical(t, mt); 3.75 + // In the case of an array, computing the meet above, caused the 3.76 + // computation of the meet of the elements which at verification 3.77 + // time caused the computation of the meet of the dual of the 3.78 + // elements. Computing the meet of the dual of the arrays here 3.79 + // causes the meet of the dual of the elements to be computed which 3.80 + // would cause the meet of the dual of the dual of the elements, 3.81 + // that is the meet of the elements already computed above to be 3.82 + // computed. Avoid redundant computations by requesting no 3.83 + // verification. 3.84 + C->_type_verify_symmetry = false; 3.85 + const Type *mt_dual = this_t->_dual->xmeet(t->_dual); 3.86 + this_t->_dual->check_symmetrical(t->_dual, mt_dual); 3.87 + assert(!C->_type_verify_symmetry, "shouldn't have changed"); 3.88 + C->_type_verify_symmetry = true; 3.89 #endif 3.90 return mt; 3.91 } 3.92 @@ -3966,10 +3990,10 @@ 3.93 (tap->_klass_is_exact && !tap->klass()->is_subtype_of(klass())) || 3.94 // 'this' is exact and super or unrelated: 3.95 (this->_klass_is_exact && !klass()->is_subtype_of(tap->klass())))) { 3.96 - if (above_centerline(ptr)) { 3.97 + if (above_centerline(ptr) || (tary->_elem->make_ptr() && above_centerline(tary->_elem->make_ptr()->_ptr))) { 3.98 tary = TypeAry::make(Type::BOTTOM, tary->_size, tary->_stable); 3.99 } 3.100 - return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot); 3.101 + return make(NotNull, NULL, tary, lazy_klass, false, off, InstanceBot, speculative, depth); 3.102 } 3.103 3.104 bool xk = false;
4.1 --- a/src/share/vm/opto/type.hpp Fri Aug 21 09:07:53 2020 +0200 4.2 +++ b/src/share/vm/opto/type.hpp Tue Jun 30 18:05:34 2020 +0200 4.3 @@ -165,6 +165,7 @@ 4.4 #endif 4.5 4.6 const Type *meet_helper(const Type *t, bool include_speculative) const; 4.7 + void check_symmetrical(const Type *t, const Type *mt) const; 4.8 4.9 protected: 4.10 // Each class of type is also identified by its base.
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/compiler/types/TestArrayMeetNotSymmetrical.java Tue Jun 30 18:05:34 2020 +0200 5.3 @@ -0,0 +1,70 @@ 5.4 +/* 5.5 + * Copyright (c) 2020, Red Hat, Inc. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +/** 5.28 + * @test 5.29 + * @bug 8240676 5.30 + * @summary Meet not symmetric failure when running lucene on jdk8 5.31 + * 5.32 + * @run main/othervm -XX:-BackgroundCompilation TestArrayMeetNotSymmetrical 5.33 + * 5.34 + */ 5.35 + 5.36 +public class TestArrayMeetNotSymmetrical { 5.37 + private static final Object field = new Object[0]; 5.38 + private static final Object field2 = new A[0]; 5.39 + 5.40 + public static void main(String[] args) { 5.41 + Object array = new A[10]; 5.42 + for (int i = 0; i < 20_000; i++) { 5.43 + test1(true, 10); 5.44 + test1(false, 10); 5.45 + test2(true); 5.46 + test2(false); 5.47 + } 5.48 + } 5.49 + 5.50 + private static Object test1(boolean flag, int len) { 5.51 + Object o; 5.52 + if (flag) { 5.53 + o = field; 5.54 + } else { 5.55 + o = new A[len]; 5.56 + } 5.57 + return o; 5.58 + } 5.59 + 5.60 + private static Object test2(boolean flag) { 5.61 + Object o; 5.62 + if (flag) { 5.63 + o = field; 5.64 + } else { 5.65 + o = field2; 5.66 + } 5.67 + return o; 5.68 + } 5.69 + 5.70 + 5.71 + private static class A { 5.72 + } 5.73 +}