diff --git a/src/hotspot/share/c1/c1_Instruction.cpp b/src/hotspot/share/c1/c1_Instruction.cpp index 8c7b199b8a2..cda2b544be4 100644 --- a/src/hotspot/share/c1/c1_Instruction.cpp +++ b/src/hotspot/share/c1/c1_Instruction.cpp @@ -137,14 +137,16 @@ bool Instruction::maybe_flat_array() { if (UseArrayFlattening) { ciType* type = declared_type(); if (type != nullptr) { - if (type->is_obj_array_klass()) { - // Due to array covariance, the runtime type might be a flat array. + if (type->is_ref_array_klass()) { + return false; + } else if (type->is_flat_array_klass()) { + return true; + } else if (type->is_obj_array_klass()) { + // This is the unrefined array type ciKlass* element_klass = type->as_obj_array_klass()->element_klass(); if (element_klass->can_be_inline_klass() && (!element_klass->is_inlinetype() || element_klass->as_inline_klass()->maybe_flat_in_array())) { return true; } - } else if (type->is_flat_array_klass()) { - return true; } else if (type->is_klass() && type->as_klass()->is_java_lang_Object()) { // This can happen as a parameter to System.arraycopy() return true; diff --git a/src/hotspot/share/ci/ciArrayKlass.cpp b/src/hotspot/share/ci/ciArrayKlass.cpp index 794b413bdc7..f7fb28f489e 100644 --- a/src/hotspot/share/ci/ciArrayKlass.cpp +++ b/src/hotspot/share/ci/ciArrayKlass.cpp @@ -75,14 +75,12 @@ ciType* ciArrayKlass::element_type() { ciType* ciArrayKlass::base_element_type() { if (is_type_array_klass()) { return ciType::make(as_type_array_klass()->element_type()); - } else if (is_obj_array_klass()) { + } else { ciKlass* ek = as_obj_array_klass()->base_element_klass(); if (ek->is_type_array_klass()) { return ciType::make(ek->as_type_array_klass()->element_type()); } return ek; - } else { - return as_flat_array_klass()->base_element_klass(); } } diff --git a/src/hotspot/share/ci/ciClassList.hpp b/src/hotspot/share/ci/ciClassList.hpp index 511e4dfb9b9..e0b78b7586b 100644 --- a/src/hotspot/share/ci/ciClassList.hpp +++ b/src/hotspot/share/ci/ciClassList.hpp @@ -65,8 +65,9 @@ class ciKlass; class ciInstanceKlass; class ciInlineKlass; class ciArrayKlass; -class ciFlatArrayKlass; class ciObjArrayKlass; +class ciFlatArrayKlass; +class ciRefArrayKlass; class ciTypeArrayKlass; // Simulate Java Language style package-private access with diff --git a/src/hotspot/share/ci/ciEnv.hpp b/src/hotspot/share/ci/ciEnv.hpp index c8fd26e2c1d..b427374264a 100644 --- a/src/hotspot/share/ci/ciEnv.hpp +++ b/src/hotspot/share/ci/ciEnv.hpp @@ -199,13 +199,18 @@ class ciEnv : StackObj { if (o == nullptr) return nullptr; return get_object(o)->as_instance(); } + ciObjArrayKlass* get_obj_array_klass(Klass* o) { + if (o == nullptr) return nullptr; + assert(o->is_objArray_klass() && !o->is_flatArray_klass() && !o->is_refArray_klass(), "must be exact"); + return get_metadata(o)->as_obj_array_klass(); + } ciFlatArrayKlass* get_flat_array_klass(Klass* o) { if (o == nullptr) return nullptr; return get_metadata(o)->as_flat_array_klass(); } - ciObjArrayKlass* get_obj_array_klass(Klass* o) { + ciRefArrayKlass* get_ref_array_klass(Klass* o) { if (o == nullptr) return nullptr; - return get_metadata(o)->as_obj_array_klass(); + return get_metadata(o)->as_ref_array_klass(); } ciTypeArrayKlass* get_type_array_klass(Klass* o) { if (o == nullptr) return nullptr; diff --git a/src/hotspot/share/ci/ciFlatArrayKlass.cpp b/src/hotspot/share/ci/ciFlatArrayKlass.cpp deleted file mode 100644 index c6c0b7c75b1..00000000000 --- a/src/hotspot/share/ci/ciFlatArrayKlass.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2016, 2021, 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. - * - * 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. - * - */ - -#include "ci/ciFlatArrayKlass.hpp" -#include "ci/ciInlineKlass.hpp" -#include "ci/ciInstanceKlass.hpp" -#include "ci/ciObjArrayKlass.hpp" -#include "ci/ciSymbol.hpp" -#include "ci/ciUtilities.hpp" -#include "ci/ciUtilities.inline.hpp" -#include "oops/flatArrayKlass.hpp" -#include "oops/inlineKlass.inline.hpp" - -// ciFlatArrayKlass -// -// This class represents a Klass* in the HotSpot virtual machine -// whose Klass part is a FlatArrayKlass. - -// ------------------------------------------------------------------ -// ciFlatArrayKlass::ciFlatArrayKlass -// -// Constructor for loaded inline type array klasses. -ciFlatArrayKlass::ciFlatArrayKlass(Klass* h_k) : ciArrayKlass(h_k) { - assert(get_Klass()->is_flatArray_klass(), "wrong type"); - InlineKlass* element_Klass = get_FlatArrayKlass()->element_klass(); - _base_element_klass = CURRENT_ENV->get_klass(element_Klass); - assert(_base_element_klass->is_inlinetype(), "bad base klass"); - if (dimension() == 1) { - _element_klass = _base_element_klass; - } else { - _element_klass = nullptr; - } - if (!ciObjectFactory::is_initialized()) { - assert(_element_klass->is_java_lang_Object(), "only arrays of object are shared"); - } -} - -// ------------------------------------------------------------------ -// ciFlatArrayKlass::element_klass -// -// What is the one-level element type of this array? -ciKlass* ciFlatArrayKlass::element_klass() { - if (_element_klass == nullptr) { - assert(dimension() > 1, "_element_klass should not be nullptr"); - assert(is_loaded(), "FlatArrayKlass must be loaded"); - // Produce the element klass. - VM_ENTRY_MARK; - Klass* element_Klass = get_FlatArrayKlass()->element_klass(); - _element_klass = CURRENT_THREAD_ENV->get_klass(element_Klass); - } - return _element_klass; -} - -ciKlass* ciFlatArrayKlass::exact_klass() { - assert(element_klass()->is_loaded() && element_klass()->as_inline_klass()->exact_klass() != nullptr, "must have exact klass"); - return this; -} diff --git a/src/hotspot/share/ci/ciFlatArrayKlass.hpp b/src/hotspot/share/ci/ciFlatArrayKlass.hpp index df64fb5457f..f993cba2741 100644 --- a/src/hotspot/share/ci/ciFlatArrayKlass.hpp +++ b/src/hotspot/share/ci/ciFlatArrayKlass.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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 @@ -25,56 +25,45 @@ #ifndef SHARE_VM_CI_CIFLATARRAYKLASS_HPP #define SHARE_VM_CI_CIFLATARRAYKLASS_HPP -#include "ci/ciArrayKlass.hpp" +#include "ci/ciInlineKlass.hpp" +#include "ci/ciObjArrayKlass.hpp" #include "oops/flatArrayKlass.hpp" // ciFlatArrayKlass // // This class represents a Klass* in the HotSpot virtual machine // whose Klass part is a FlatArrayKlass. -class ciFlatArrayKlass : public ciArrayKlass { +class ciFlatArrayKlass : public ciObjArrayKlass { CI_PACKAGE_ACCESS friend class ciEnv; -private: - ciKlass* _element_klass; - ciKlass* _base_element_klass; - protected: - ciFlatArrayKlass(Klass* h_k); + ciFlatArrayKlass(Klass* k) : ciObjArrayKlass(k) { + assert(k->is_flatArray_klass(), "wrong type"); + } const FlatArrayKlass* get_FlatArrayKlass() const { return FlatArrayKlass::cast(get_Klass()); } - const char* type_string() { return "ciFlatArrayKlass"; } - - oop loader() { return _base_element_klass->loader(); } - jobject loader_handle() { return _base_element_klass->loader_handle(); } + virtual const char* type_string() override { return "ciFlatArrayKlass"; } public: LayoutKind layout_kind() const { return get_FlatArrayKlass()->layout_kind(); } - // The one-level type of the array elements. - ciKlass* element_klass(); - int log2_element_size() { return Klass::layout_helper_log2_element_size(layout_helper()); } - int element_byte_size() { return 1 << log2_element_size(); } - // The innermost type of the array elements. - ciKlass* base_element_klass() { return _base_element_klass; } + int element_byte_size() { return 1 << log2_element_size(); } // What kind of ciObject is this? - bool is_flat_array_klass() const { return true; } + virtual bool is_flat_array_klass() const override { return true; } - virtual ciKlass* exact_klass(); - - virtual bool can_be_inline_array_klass() { - return true; + virtual ciKlass* exact_klass() override { + assert(element_klass()->as_inline_klass()->exact_klass() != nullptr, "must have exact klass"); + return this; } }; - #endif // SHARE_VM_CI_CIFLATARRAYKLASS_HPP diff --git a/src/hotspot/share/ci/ciMetadata.hpp b/src/hotspot/share/ci/ciMetadata.hpp index de02d780dc8..c0fe6f9a468 100644 --- a/src/hotspot/share/ci/ciMetadata.hpp +++ b/src/hotspot/share/ci/ciMetadata.hpp @@ -57,8 +57,9 @@ class ciMetadata: public ciBaseObject { virtual bool is_instance_klass() const { return false; } virtual bool is_inlinetype() const { return false; } virtual bool is_array_klass() const { return false; } - virtual bool is_flat_array_klass() const { return false; } virtual bool is_obj_array_klass() const { return false; } + virtual bool is_flat_array_klass() const { return false; } + virtual bool is_ref_array_klass() const { return false; } virtual bool is_type_array_klass() const { return false; } virtual bool is_early_larval() const { return false; } virtual bool maybe_flat_in_array() const { return false; } @@ -96,13 +97,17 @@ class ciMetadata: public ciBaseObject { assert(is_array_klass(), "bad cast"); return (ciArrayKlass*)this; } + ciObjArrayKlass* as_obj_array_klass() { + assert(is_obj_array_klass(), "bad cast"); + return (ciObjArrayKlass*)this; + } ciFlatArrayKlass* as_flat_array_klass() { assert(is_flat_array_klass(), "bad cast"); return (ciFlatArrayKlass*)this; } - ciObjArrayKlass* as_obj_array_klass() { - assert(is_obj_array_klass(), "bad cast"); - return (ciObjArrayKlass*)this; + ciRefArrayKlass* as_ref_array_klass() { + assert(is_ref_array_klass(), "bad cast"); + return (ciRefArrayKlass*)this; } ciTypeArrayKlass* as_type_array_klass() { assert(is_type_array_klass(), "bad cast"); diff --git a/src/hotspot/share/ci/ciObjArrayKlass.cpp b/src/hotspot/share/ci/ciObjArrayKlass.cpp index 33dab779fcb..c94c986d08b 100644 --- a/src/hotspot/share/ci/ciObjArrayKlass.cpp +++ b/src/hotspot/share/ci/ciObjArrayKlass.cpp @@ -25,9 +25,10 @@ #include "ci/ciFlatArrayKlass.hpp" #include "ci/ciInstanceKlass.hpp" #include "ci/ciObjArrayKlass.hpp" +#include "ci/ciRefArrayKlass.hpp" #include "ci/ciSymbol.hpp" +#include "ci/ciUtilities.hpp" #include "ci/ciUtilities.inline.hpp" -#include "oops/inlineKlass.inline.hpp" #include "oops/objArrayKlass.hpp" #include "runtime/signature.hpp" @@ -68,7 +69,8 @@ ciObjArrayKlass::ciObjArrayKlass(ciSymbol* array_name, _base_element_klass = base_element_klass; assert(_base_element_klass->is_instance_klass() || _base_element_klass->is_type_array_klass() || - _base_element_klass->is_flat_array_klass(), "bad base klass"); + _base_element_klass->is_flat_array_klass() || + _base_element_klass->is_ref_array_klass(), "bad base klass"); if (dimension == 1) { _element_klass = base_element_klass; } else { @@ -135,7 +137,7 @@ ciSymbol* ciObjArrayKlass::construct_array_name(ciSymbol* element_name, // ciObjArrayKlass::make_impl // // Implementation of make. -ciArrayKlass* ciObjArrayKlass::make_impl(ciKlass* element_klass, bool refined_type, bool null_free, bool atomic) { +ciObjArrayKlass* ciObjArrayKlass::make_impl(ciKlass* element_klass, bool refined_type, bool null_free, bool atomic) { if (element_klass->is_loaded()) { EXCEPTION_CONTEXT; // The element klass is loaded @@ -145,22 +147,24 @@ ciArrayKlass* ciObjArrayKlass::make_impl(ciKlass* element_klass, bool refined_ty CURRENT_THREAD_ENV->record_out_of_memory_failure(); return ciEnv::unloaded_ciobjarrayklass(); } - if (refined_type) { - ArrayKlass::ArrayProperties props = ArrayKlass::ArrayProperties::DEFAULT; - if (null_free) { - assert(element_klass->is_inlinetype(), "Only value class arrays can be null free"); - props = (ArrayKlass::ArrayProperties)(props | ArrayKlass::ArrayProperties::NULL_RESTRICTED); - } - if (!atomic) { - assert(element_klass->is_inlinetype(), "Only value class arrays can be non-atomic"); - props = (ArrayKlass::ArrayProperties)(props | ArrayKlass::ArrayProperties::NON_ATOMIC); - } - array = ObjArrayKlass::cast(array)->klass_with_properties(props, THREAD); + if (!refined_type) { + return CURRENT_THREAD_ENV->get_obj_array_klass(array); + } + + ArrayKlass::ArrayProperties props = ArrayKlass::ArrayProperties::DEFAULT; + if (null_free) { + assert(element_klass->is_inlinetype(), "Only value class arrays can be null free"); + props = (ArrayKlass::ArrayProperties)(props | ArrayKlass::ArrayProperties::NULL_RESTRICTED); } + if (!atomic) { + assert(element_klass->is_inlinetype(), "Only value class arrays can be non-atomic"); + props = (ArrayKlass::ArrayProperties)(props | ArrayKlass::ArrayProperties::NON_ATOMIC); + } + array = ObjArrayKlass::cast(array)->klass_with_properties(props, THREAD); if (array->is_flatArray_klass()) { return CURRENT_THREAD_ENV->get_flat_array_klass(array); } else { - return CURRENT_THREAD_ENV->get_obj_array_klass(array); + return CURRENT_THREAD_ENV->get_ref_array_klass(array); } } @@ -178,7 +182,7 @@ ciArrayKlass* ciObjArrayKlass::make_impl(ciKlass* element_klass, bool refined_ty // ciObjArrayKlass::make // // Make an array klass corresponding to the specified primitive type. -ciArrayKlass* ciObjArrayKlass::make(ciKlass* element_klass, bool refined_type, bool null_free, bool atomic) { +ciObjArrayKlass* ciObjArrayKlass::make(ciKlass* element_klass, bool refined_type, bool null_free, bool atomic) { GUARDED_VM_ENTRY(return make_impl(element_klass, refined_type, null_free, atomic);) } @@ -191,5 +195,6 @@ ciArrayKlass* ciObjArrayKlass::make(ciKlass* element_klass, int dims) { } ciKlass* ciObjArrayKlass::exact_klass() { - return (is_loaded() && is_refined()) ? this : nullptr; + // This cannot be an exact klass because the refined types subtype it + return nullptr; } diff --git a/src/hotspot/share/ci/ciObjArrayKlass.hpp b/src/hotspot/share/ci/ciObjArrayKlass.hpp index 698d9e443ca..b2f14bd8ed0 100644 --- a/src/hotspot/share/ci/ciObjArrayKlass.hpp +++ b/src/hotspot/share/ci/ciObjArrayKlass.hpp @@ -26,6 +26,7 @@ #define SHARE_CI_CIOBJARRAYKLASS_HPP #include "ci/ciArrayKlass.hpp" +#include "oops/objArrayKlass.hpp" // ciObjArrayKlass // @@ -46,10 +47,10 @@ class ciObjArrayKlass : public ciArrayKlass { int dimension); ObjArrayKlass* get_ObjArrayKlass() { - return (ObjArrayKlass*)get_Klass(); + return ObjArrayKlass::cast(get_Klass()); } - static ciArrayKlass* make_impl(ciKlass* element_klass, bool refined_type = false, bool null_free = false, bool atomic = true); + static ciObjArrayKlass* make_impl(ciKlass* element_klass, bool refined_type = false, bool null_free = false, bool atomic = true); static ciSymbol* construct_array_name(ciSymbol* element_name, int dimension); @@ -68,7 +69,7 @@ class ciObjArrayKlass : public ciArrayKlass { // What kind of ciObject is this? bool is_obj_array_klass() const { return true; } - static ciArrayKlass* make(ciKlass* element_klass, bool refined_type = true, bool null_free = false, bool atomic = true); + static ciObjArrayKlass* make(ciKlass* element_klass, bool refined_type = true, bool null_free = false, bool atomic = true); static ciArrayKlass* make(ciKlass* element_klass, int dims); virtual ciKlass* exact_klass(); diff --git a/src/hotspot/share/ci/ciObjectFactory.cpp b/src/hotspot/share/ci/ciObjectFactory.cpp index 3234125bd6f..0f82e850369 100644 --- a/src/hotspot/share/ci/ciObjectFactory.cpp +++ b/src/hotspot/share/ci/ciObjectFactory.cpp @@ -38,6 +38,7 @@ #include "ci/ciObjArrayKlass.hpp" #include "ci/ciObject.hpp" #include "ci/ciObjectFactory.hpp" +#include "ci/ciRefArrayKlass.hpp" #include "ci/ciReplay.hpp" #include "ci/ciSymbol.hpp" #include "ci/ciSymbols.hpp" @@ -411,10 +412,14 @@ ciMetadata* ciObjectFactory::create_new_metadata(Metadata* o) { } else if (k->is_instance_klass()) { assert(!ReplayCompiles || ciReplay::no_replay_state() || !ciReplay::is_klass_unresolved((InstanceKlass*)k), "must be whitelisted for replay compilation"); return new (arena()) ciInstanceKlass(k); - } else if (k->is_flatArray_klass()) { - return new (arena()) ciFlatArrayKlass(k); - } else if (k->is_refArray_klass() || k->is_objArray_klass()) { - return new (arena()) ciObjArrayKlass(k); + } else if (k->is_objArray_klass()) { + if (k->is_flatArray_klass()) { + return new (arena()) ciFlatArrayKlass(k); + } else if (k->is_refArray_klass()) { + return new (arena()) ciRefArrayKlass(k); + } else { + return new (arena()) ciObjArrayKlass(k); + } } else if (k->is_typeArray_klass()) { return new (arena()) ciTypeArrayKlass(k); } diff --git a/src/hotspot/share/ci/ciRefArrayKlass.hpp b/src/hotspot/share/ci/ciRefArrayKlass.hpp new file mode 100644 index 00000000000..647c841018f --- /dev/null +++ b/src/hotspot/share/ci/ciRefArrayKlass.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2025, 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. + * + * 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. + * + */ + +#ifndef SHARE_VM_CI_CIREFARRAYKLASS_HPP +#define SHARE_VM_CI_CIREFARRAYKLASS_HPP + +#include "ci/ciObjArrayKlass.hpp" + +// A ciRefArrayKlass represents the klass of a refined array in which the elements are stored as +// reference +class ciRefArrayKlass : public ciObjArrayKlass { +private: + CI_PACKAGE_ACCESS + friend class ciEnv; + +protected: + ciRefArrayKlass(Klass* k) : ciObjArrayKlass(k) { + assert(k->is_refArray_klass(), "wrong type"); + } + + virtual const char* type_string() override { return "ciRefArrayKlass"; } + +public: + virtual bool is_ref_array_klass() const override { return true; } + + virtual ciKlass* exact_klass() override { + return this; + } +}; + +#endif // SHARE_VM_CI_CIREFARRAYKLASS_HPP diff --git a/src/hotspot/share/ci/ciTypeFlow.cpp b/src/hotspot/share/ci/ciTypeFlow.cpp index f4289bee8b3..dc16c859792 100644 --- a/src/hotspot/share/ci/ciTypeFlow.cpp +++ b/src/hotspot/share/ci/ciTypeFlow.cpp @@ -319,11 +319,10 @@ ciType* ciTypeFlow::StateVector::type_meet_internal(ciType* t1, ciType* t2, ciTy return object_klass; } else if (k1->is_array_klass() || k2->is_array_klass()) { // When an array meets a non-array, we get Object. - // When (obj/flat)Array meets typeArray, we also get Object. + // When objArray meets typeArray, we also get Object. // And when typeArray meets different typeArray, we again get Object. - // But when (obj/flat)Array meets (obj/flat)Array, we look carefully at element types. - if ((k1->is_obj_array_klass() || k1->is_flat_array_klass()) && - (k2->is_obj_array_klass() || k2->is_flat_array_klass())) { + // But when objArray meets objArray, we look carefully at element types. + if (k1->is_obj_array_klass() && k2->is_obj_array_klass()) { ciType* elem1 = k1->as_array_klass()->element_klass(); ciType* elem2 = k2->as_array_klass()->element_klass(); ciType* elem = elem1; diff --git a/src/hotspot/share/ci/ciTypeFlow.hpp b/src/hotspot/share/ci/ciTypeFlow.hpp index 724913a0ddc..d31399c4681 100644 --- a/src/hotspot/share/ci/ciTypeFlow.hpp +++ b/src/hotspot/share/ci/ciTypeFlow.hpp @@ -340,8 +340,7 @@ class ciTypeFlow : public ArenaObj { ciArrayKlass* pop_objOrFlatArray() { ciType* array = pop_value(); if (array == null_type()) return nullptr; - assert(array->is_obj_array_klass() || array->is_flat_array_klass(), - "must be a flat or an object array type"); + assert(array->is_obj_array_klass(), "must be an object array type"); return array->as_array_klass(); } ciTypeArrayKlass* pop_typeArray() { diff --git a/src/hotspot/share/opto/callnode.cpp b/src/hotspot/share/opto/callnode.cpp index b9b98e69c78..d2be2b231a3 100644 --- a/src/hotspot/share/opto/callnode.cpp +++ b/src/hotspot/share/opto/callnode.cpp @@ -494,14 +494,8 @@ void JVMState::format(PhaseRegAlloc *regalloc, const Node *n, outputStream* st) while (ndim-- > 0) { st->print("[]"); } - } else if (cik->is_flat_array_klass()) { - ciKlass* cie = cik->as_flat_array_klass()->base_element_klass(); - cie->print_name_on(st); - st->print("[%d]", spobj->n_fields()); - int ndim = cik->as_array_klass()->dimension() - 1; - while (ndim-- > 0) { - st->print("[]"); - } + } else { + assert(false, "unexpected type %s", cik->name()->as_utf8()); } st->print("={"); uint nf = spobj->n_fields(); diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index f77e799ef5f..1672bf96ecf 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -3683,9 +3683,7 @@ TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, const TypeInterfaces* inter assert(this->isa_aryptr(), "only arrays without klass"); _is_ptr_to_narrowoop = UseCompressedOops; } else if (UseCompressedOops && this->isa_aryptr() && this->offset() != arrayOopDesc::length_offset_in_bytes()) { - if (klass()->is_obj_array_klass()) { - _is_ptr_to_narrowoop = true; - } else if (klass()->is_flat_array_klass() && field_offset != Offset::top && field_offset != Offset::bottom) { + if (klass()->is_flat_array_klass() && field_offset != Offset::top && field_offset != Offset::bottom) { // Check if the field of the inline type array element contains oops ciInlineKlass* vk = klass()->as_flat_array_klass()->element_klass()->as_inline_klass(); int foffset = field_offset.get() + vk->payload_offset(); @@ -3698,6 +3696,8 @@ TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, const TypeInterfaces* inter field_bt = T_BOOLEAN; } _is_ptr_to_narrowoop = UseCompressedOops && ::is_reference_type(field_bt); + } else if (klass()->is_obj_array_klass()) { + _is_ptr_to_narrowoop = UseCompressedOops; } } else if (klass()->is_instance_klass()) { if (this->isa_klassptr()) { @@ -3908,23 +3908,41 @@ const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_ return TypeInstPtr::make(TypePtr::BotPTR, klass, interfaces, klass_is_exact, nullptr, Offset(0), flat_in_array); } else if (klass->is_obj_array_klass()) { // Element is an object or inline type array. Recursively call ourself. - const TypeOopPtr* etype = TypeOopPtr::make_from_klass_common(klass->as_array_klass()->element_klass(), /* klass_change= */ false, try_for_exact, interface_handling); - bool xk = klass->is_loaded() && klass->as_obj_array_klass()->is_refined(); + ciObjArrayKlass* array_klass = klass->as_obj_array_klass(); + const TypeOopPtr* etype = TypeOopPtr::make_from_klass_common(array_klass->element_klass(), /* klass_change= */ false, try_for_exact, interface_handling); + bool xk = array_klass->is_loaded() && array_klass->is_refined(); + // Determine null-free/flat properties - const bool is_null_free = xk && klass->as_array_klass()->is_elem_null_free(); - if (is_null_free) { - etype = etype->join_speculative(NOTNULL)->is_oopptr(); - } - const TypeOopPtr* exact_etype = etype; - if (etype->can_be_inline_type()) { - // Use exact type if element can be an inline type - exact_etype = TypeOopPtr::make_from_klass_common(klass->as_array_klass()->element_klass(), /* klass_change= */ true, /* try_for_exact= */ true, interface_handling); + bool flat; + bool not_flat; + bool is_null_free; + bool not_null_free; + bool atomic; + if (xk) { + flat = array_klass->is_flat_array_klass(); + not_flat = !flat; + is_null_free = array_klass->is_elem_null_free(); + not_null_free = !is_null_free; + atomic = array_klass->is_elem_atomic(); + + if (is_null_free) { + etype = etype->join_speculative(NOTNULL)->is_oopptr(); + } + } else { + const TypeOopPtr* exact_etype = etype; + if (etype->can_be_inline_type()) { + // Use exact type if element can be an inline type + exact_etype = TypeOopPtr::make_from_klass_common(klass->as_array_klass()->element_klass(), /* klass_change= */ true, /* try_for_exact= */ true, interface_handling); + } + + flat = false; + bool not_inline = !exact_etype->can_be_inline_type(); + not_null_free = not_inline; + not_flat = !UseArrayFlattening || not_inline || (exact_etype->is_inlinetypeptr() && !exact_etype->inline_klass()->maybe_flat_in_array()); + atomic = not_flat; } - bool not_inline = !exact_etype->can_be_inline_type(); - bool not_null_free = xk ? !is_null_free : not_inline; - bool not_flat = xk || !UseArrayFlattening || not_inline || (exact_etype->is_inlinetypeptr() && !exact_etype->inline_klass()->maybe_flat_in_array()); - bool atomic = not_flat; - const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS, /* stable= */ false, /* flat= */ false, not_flat, not_null_free, atomic); + + const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS, /* stable= */ false, flat, not_flat, not_null_free, atomic); // We used to pass NotNull in here, asserting that the sub-arrays // are all not-null. This is not true in generally, as code can // slam nullptrs down in the subarrays. @@ -3939,16 +3957,6 @@ const TypeOopPtr* TypeOopPtr::make_from_klass_common(ciKlass *klass, bool klass_ // is not-null. That was not true in general. const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::BotPTR, arr0, klass, true, Offset(0)); return arr; - } else if (klass->is_flat_array_klass()) { - const TypeOopPtr* etype = TypeOopPtr::make_from_klass_raw(klass->as_array_klass()->element_klass(), trust_interfaces); - const bool is_null_free = klass->as_array_klass()->is_elem_null_free(); - if (is_null_free) { - etype = etype->join_speculative(NOTNULL)->is_oopptr(); - } - bool atomic = klass->as_array_klass()->is_elem_atomic(); - const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS, /* stable= */ false, /* flat= */ true, /* not_flat= */ false, /* not_null_free= */ !is_null_free, atomic); - const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::BotPTR, arr0, klass, true, Offset(0)); - return arr; } else { ShouldNotReachHere(); return nullptr; @@ -3979,7 +3987,7 @@ const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_const etype = etype->join_speculative(TypePtr::NOTNULL)->is_oopptr(); } bool is_atomic = o->as_array()->is_atomic(); - const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()), /* stable= */ false, /* flat= */ false, + const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()), /* stable= */ false, /* flat= */ is_flat, /* not_flat= */ !is_flat, /* not_null_free= */ !is_null_free, /* atomic= */ is_atomic); // We used to pass NotNull in here, asserting that the sub-arrays // are all not-null. This is not true in generally, as code can @@ -4001,23 +4009,6 @@ const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, bool require_const } else { return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, Offset(0)); } - } else if (klass->is_flat_array_klass()) { - const TypeOopPtr* etype = TypeOopPtr::make_from_klass_raw(klass->as_array_klass()->element_klass(), trust_interfaces); - bool is_null_free = o->as_array()->is_null_free(); - if (is_null_free) { - etype = etype->join_speculative(TypePtr::NOTNULL)->is_oopptr(); - } - bool is_atomic = o->as_array()->is_atomic(); - const TypeAry* arr0 = TypeAry::make(etype, TypeInt::make(o->as_array()->length()), /* stable= */ false, /* flat= */ true, - /* not_flat= */ false, /* not_null_free= */ !is_null_free, /* atomic= */ is_atomic); - // We used to pass NotNull in here, asserting that the sub-arrays - // are all not-null. This is not true in generally, as code can - // slam nullptrs down in the subarrays. - if (make_constant) { - return TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, Offset(0)); - } else { - return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, Offset(0)); - } } fatal("unhandled object type"); @@ -6649,10 +6640,6 @@ const TypeAryKlassPtr* TypeAryKlassPtr::make(PTR ptr, ciKlass* k, Offset offset, } else if (k->is_type_array_klass()) { // Element is an typeArray etype = get_const_basic_type(k->as_type_array_klass()->element_type()); - } else if (k->is_flat_array_klass()) { - ciKlass* eklass = k->as_flat_array_klass()->element_klass(); - etype = TypeKlassPtr::make(eklass, interface_handling)->cast_to_exactness(false); - k = nullptr; } else { ShouldNotReachHere(); } @@ -6683,7 +6670,7 @@ const TypeAryKlassPtr* TypeAryKlassPtr::cast_to_non_refined() const { // Get the (non-)refined array klass ptr const TypeAryKlassPtr* TypeAryKlassPtr::cast_to_refined_array_klass_ptr(bool refined) const { - if ((refined == is_refined_type()) || !klass_is_exact() || (!exact_klass()->is_obj_array_klass() && !exact_klass()->is_flat_array_klass())) { + if ((refined == is_refined_type()) || !klass_is_exact() || !exact_klass()->is_obj_array_klass()) { return this; } ciArrayKlass* k = exact_klass()->as_array_klass();