diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 9763911e581..84d092f2ffd 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -4664,7 +4664,7 @@ template bool TypePtr::is_meet_subtype_of_helper_for_array } if (other_elem == nullptr && this_elem == nullptr) { - return this_one->_klass->is_subtype_of(other->_klass); + return this_one->klass()->is_subtype_of(other->klass()); } return false; @@ -5993,7 +5993,7 @@ template bool TypePtr::is_java_subtype_of_helper_for_instan return true; } - return this_one->_klass->is_subtype_of(other->_klass) && this_one->_interfaces->contains(other->_interfaces); + return this_one->klass()->is_subtype_of(other->klass()) && this_one->_interfaces->contains(other->_interfaces); } bool TypeInstKlassPtr::is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const { @@ -6008,7 +6008,7 @@ template bool TypePtr::is_same_java_type_as_helper_for_inst if (!this_one->is_instance_type(other)) { return false; } - return this_one->_klass->equals(other->_klass) && this_one->_interfaces->eq(other->_interfaces); + return this_one->klass()->equals(other->klass()) && this_one->_interfaces->eq(other->_interfaces); } bool TypeInstKlassPtr::is_same_java_type_as_helper(const TypeKlassPtr* other) const { @@ -6022,7 +6022,7 @@ template bool TypePtr::maybe_java_subtype_of_helper_for_ins } if (this_one->is_array_type(other)) { - return !this_exact && this_one->_klass->equals(ciEnv::current()->Object_klass()) && other->_interfaces->contains(this_one->_interfaces); + return !this_exact && this_one->klass()->equals(ciEnv::current()->Object_klass()) && other->_interfaces->contains(this_one->_interfaces); } assert(this_one->is_instance_type(other), "unsupported"); @@ -6031,12 +6031,12 @@ template bool TypePtr::maybe_java_subtype_of_helper_for_ins return this_one->is_java_subtype_of(other); } - if (!this_one->_klass->is_subtype_of(other->_klass) && !other->_klass->is_subtype_of(this_one->_klass)) { + if (!this_one->klass()->is_subtype_of(other->klass()) && !other->klass()->is_subtype_of(this_one->klass())) { return false; } if (this_exact) { - return this_one->_klass->is_subtype_of(other->_klass) && this_one->_interfaces->contains(other->_interfaces); + return this_one->klass()->is_subtype_of(other->klass()) && this_one->_interfaces->contains(other->_interfaces); } return true; @@ -6116,7 +6116,7 @@ uint TypeAryKlassPtr::hash(void) const { //----------------------compute_klass------------------------------------------ // Compute the defining klass for this class -ciKlass* TypeAryPtr::compute_klass(DEBUG_ONLY(bool verify)) const { +ciKlass* TypeAryPtr::compute_klass() const { // Compute _klass based on element type. ciKlass* k_ary = nullptr; const TypeInstPtr *tinst; @@ -6137,28 +6137,7 @@ ciKlass* TypeAryPtr::compute_klass(DEBUG_ONLY(bool verify)) const { // and object; Top occurs when doing join on Bottom. // Leave k_ary at null. } else { - // Cannot compute array klass directly from basic type, - // since subtypes of TypeInt all have basic type T_INT. -#ifdef ASSERT - if (verify && el->isa_int()) { - // Check simple cases when verifying klass. - BasicType bt = T_ILLEGAL; - if (el == TypeInt::BYTE) { - bt = T_BYTE; - } else if (el == TypeInt::SHORT) { - bt = T_SHORT; - } else if (el == TypeInt::CHAR) { - bt = T_CHAR; - } else if (el == TypeInt::INT) { - bt = T_INT; - } else { - return _klass; // just return specified klass - } - return ciTypeArrayKlass::make(bt); - } -#endif - assert(!el->isa_int(), - "integral arrays must be pre-equipped with a class"); + assert(!el->isa_int(), "integral arrays must be pre-equipped with a class"); // Compute array klass directly from basic type k_ary = ciTypeArrayKlass::make(el->basic_type()); } @@ -6434,7 +6413,7 @@ template bool TypePtr::is_java_subtype_of_helper_for_array( return this_one->is_reference_type(this_elem)->is_java_subtype_of_helper(this_one->is_reference_type(other_elem), this_exact, other_exact); } if (this_elem == nullptr && other_elem == nullptr) { - return this_one->_klass->is_subtype_of(other->_klass); + return this_one->klass()->is_subtype_of(other->klass()); } return false; } @@ -6466,8 +6445,7 @@ template bool TypePtr::is_same_java_type_as_helper_for_arra return this_one->is_reference_type(this_elem)->is_same_java_type_as(this_one->is_reference_type(other_elem)); } if (other_elem == nullptr && this_elem == nullptr) { - assert(this_one->_klass != nullptr && other->_klass != nullptr, ""); - return this_one->_klass->equals(other->_klass); + return this_one->klass()->equals(other->klass()); } return false; } @@ -6487,7 +6465,7 @@ template bool TypePtr::maybe_java_subtype_of_helper_for_arr return true; } if (this_one->is_instance_type(other)) { - return other->_klass->equals(ciEnv::current()->Object_klass()) && other->_interfaces->intersection_with(this_one->_interfaces)->eq(other->_interfaces); + return other->klass()->equals(ciEnv::current()->Object_klass()) && other->_interfaces->intersection_with(this_one->_interfaces)->eq(other->_interfaces); } assert(this_one->is_array_type(other), ""); @@ -6506,7 +6484,7 @@ template bool TypePtr::maybe_java_subtype_of_helper_for_arr return this_one->is_reference_type(this_elem)->maybe_java_subtype_of_helper(this_one->is_reference_type(other_elem), this_exact, other_exact); } if (other_elem == nullptr && this_elem == nullptr) { - return this_one->_klass->is_subtype_of(other->_klass); + return this_one->klass()->is_subtype_of(other->klass()); } return false; } diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index c65ff4af012..de9b52b4cc4 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -1413,7 +1413,7 @@ class TypeAryPtr : public TypeOopPtr { const TypeAry *_ary; // Array we point into const bool _is_autobox_cache; - ciKlass* compute_klass(DEBUG_ONLY(bool verify = false)) const; + ciKlass* compute_klass() const; // A pointer to delay allocation to Type::Initialize_shared() diff --git a/test/hotspot/jtreg/compiler/c2/TestUninitializedKlassField.java b/test/hotspot/jtreg/compiler/c2/TestUninitializedKlassField.java new file mode 100644 index 00000000000..3bad2bde7b1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestUninitializedKlassField.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 8321974 + * @summary Test that the TypeAryPtr::_klass field is properly initialized on use. + * @comment This test only reproduces the issue with release builds of the JVM because + * verification code in debug builds leads to eager initialization of the field. + * @run main/othervm -Xbatch -XX:CompileCommand=compileonly,TestUninitializedKlassField::test* + * -XX:-TieredCompilation TestUninitializedKlassField + */ + +public class TestUninitializedKlassField { + static void test(long array2[]) { + long array1[] = new long[1]; + // Loop is needed to create a backedge phi that is processed only during IGVN. + for (int i = 0; i < 1; i++) { + // CmpPNode::sub will check if classes of array1 and array2 are unrelated + // and the subtype checks will crash if the _klass field is not initialized. + if (array2 != array1) { + array1 = new long[2]; + } + } + } + + public static void main(String[] args) { + for (int i = 0; i < 50_000; ++i) { + test(null); + } + } +}