diff --git a/src/hotspot/share/ci/ciMetadata.hpp b/src/hotspot/share/ci/ciMetadata.hpp index 62b67d65483b5..2e232c591887d 100644 --- a/src/hotspot/share/ci/ciMetadata.hpp +++ b/src/hotspot/share/ci/ciMetadata.hpp @@ -103,7 +103,7 @@ class ciMetadata: public ciBaseObject { Metadata* constant_encoding() { return _metadata; } - bool equals(ciMetadata* obj) const { return (this == obj); } + bool equals(const ciMetadata* obj) const { return (this == obj); } uint hash() { return ident() * 31; } // ??? diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 708225ba3aa9f..783631bf08d89 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -4305,12 +4305,7 @@ Node* LibraryCallKit::generate_array_guard_common(Node* kls, RegionNode* region, if (obj != nullptr && is_array_ctrl != nullptr && is_array_ctrl != top()) { // Keep track of the fact that 'obj' is an array to prevent // array specific accesses from floating above the guard. - Node* cast = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM)); - // Check for top because in rare cases, the type system can determine that - // the object can't be an array but the layout helper check is not folded. - if (!cast->is_top()) { - *obj = cast; - } + *obj = _gvn.transform(new CastPPNode(is_array_ctrl, *obj, TypeAryPtr::BOTTOM)); } return ctrl; } diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index a19dbd664eb09..5736213740276 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2211,10 +2211,8 @@ const Type* LoadNode::Value(PhaseGVN* phase) const { // This will help short-circuit some reflective code. if (tkls->offset() == in_bytes(Klass::layout_helper_offset()) && tkls->isa_instklassptr() && // not directly typed as an array - !tkls->is_instklassptr()->instance_klass()->is_java_lang_Object() // not the supertype of all T[] and specifically not Serializable & Cloneable - ) { - // Note: When interfaces are reliable, we can narrow the interface - // test to (klass != Serializable && klass != Cloneable). + !tkls->is_instklassptr()->might_be_an_array() // not the supertype of all T[] (java.lang.Object) or has an interface that is not Serializable or Cloneable + ) { assert(Opcode() == Op_LoadI, "must load an int from _layout_helper"); jint min_size = Klass::instance_layout_helper(oopDesc::header_size(), false); // The key property of this type is that it folds up tests diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 474145f2d0620..4556555aceade 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -3685,6 +3685,12 @@ bool TypeInterfaces::singleton(void) const { return Type::singleton(); } +bool TypeInterfaces::has_non_array_interface() const { + assert(TypeAryPtr::_array_interfaces != nullptr, "How come Type::Initialize_shared wasn't called yet?"); + + return !TypeAryPtr::_array_interfaces->contains(this); +} + //------------------------------TypeOopPtr------------------------------------- TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, const TypeInterfaces* interfaces, bool xk, ciObject* o, int offset, int instance_id, const TypePtr* speculative, int inline_depth) @@ -6197,6 +6203,19 @@ template bool TypePtr::is_java_subtype_of_helper_for_instan return this_one->klass()->is_subtype_of(other->klass()) && this_one->_interfaces->contains(other->_interfaces); } +bool TypeInstKlassPtr::might_be_an_array() const { + if (!instance_klass()->is_java_lang_Object()) { + // TypeInstKlassPtr can be an array only if it is java.lang.Object: the only supertype of array types. + return false; + } + if (interfaces()->has_non_array_interface()) { + // Arrays only implement Cloneable and Serializable. If we see any other interface, [this] cannot be an array. + return false; + } + // Cannot prove it's not an array. + return true; +} + bool TypeInstKlassPtr::is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const { return TypePtr::is_java_subtype_of_helper_for_instance(this, other, this_exact, other_exact); } diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index fe460cfb1d43d..9c40e1ab3cdd7 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -943,6 +943,7 @@ class TypeInterfaces : public Type { const Type* xmeet(const Type* t) const; bool singleton(void) const; + bool has_non_array_interface() const; }; //------------------------------TypePtr---------------------------------------- @@ -1420,6 +1421,7 @@ class TypeInstPtr : public TypeOopPtr { class TypeAryPtr : public TypeOopPtr { friend class Type; friend class TypePtr; + friend class TypeInterfaces; TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, bool is_autobox_cache, @@ -1692,6 +1694,8 @@ class TypeInstKlassPtr : public TypeKlassPtr { return klass()->as_instance_klass(); } + bool might_be_an_array() const; + bool is_same_java_type_as_helper(const TypeKlassPtr* other) const; bool is_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const; bool maybe_java_subtype_of_helper(const TypeKlassPtr* other, bool this_exact, bool other_exact) const;