diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index f9436f67667..c74dcd154f9 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2931,7 +2931,7 @@ Node* GraphKit::gen_subtype_check(Node* obj_or_subklass, Node* superklass) { MergeMemNode* mem = merged_memory(); Node* ctrl = control(); Node* subklass = obj_or_subklass; - if (!sub_t->isa_klassptr()) { + if (!sub_t->isa_klassptr() && !sub_t->isa_inlinetype()) { subklass = load_object_klass(obj_or_subklass); } Node* n = Phase::gen_subtype_check(subklass, superklass, &ctrl, mem, _gvn); diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 60714423ef0..c7245dea52e 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -2391,7 +2391,7 @@ const Type* LoadNode::klass_value_common(PhaseGVN* phase) const { return TypeKlassPtr::make(ak); } } - return TypeKlassPtr::make(TypePtr::NotNull, ak, Type::Offset(0)); + return TypeKlassPtr::make(TypePtr::NotNull, ak, Type::Offset(0), false, tary->is_not_flat(), tary->is_not_null_free()); } else if (ak->is_type_array_klass()) { return TypeKlassPtr::make(ak); // These are always precise } diff --git a/src/hotspot/share/opto/parseHelper.cpp b/src/hotspot/share/opto/parseHelper.cpp index 21e3db60033..fd842c9b619 100644 --- a/src/hotspot/share/opto/parseHelper.cpp +++ b/src/hotspot/share/opto/parseHelper.cpp @@ -219,20 +219,18 @@ Node* Parse::array_store_check() { reason = Deoptimization::Reason_array_check; } if (extak != NULL) { - always_see_exact_class = true; Node* con = makecon(extak); - Node* cmp = _gvn.transform(new CmpPNode( array_klass, con )); - Node* bol = _gvn.transform(new BoolNode( cmp, BoolTest::eq )); - Node* ctrl= control(); - { BuildCutout unless(this, bol, PROB_MAX); - uncommon_trap(reason, - Deoptimization::Action_maybe_recompile, - tak->klass()); - } - if (stopped()) { // MUST uncommon-trap? - set_control(ctrl); // Then Don't Do It, just fall into the normal checking - } else { // Cast array klass to exactness: - // Use the exact constant value we know it is. + Node* cmp = _gvn.transform(new CmpPNode(array_klass, con)); + Node* bol = _gvn.transform(new BoolNode(cmp, BoolTest::eq)); + // Only do it if the check does not always pass/fail + if (!bol->is_Con()) { + always_see_exact_class = true; + { BuildCutout unless(this, bol, PROB_MAX); + uncommon_trap(reason, + Deoptimization::Action_maybe_recompile, + tak->klass()); + } + // Cast array klass to exactness replace_in_map(array_klass,con); Node* cast = _gvn.transform(new CheckCastPPNode(control(), ary, extak->as_instance_type())); replace_in_map(ary, cast); @@ -242,7 +240,8 @@ Node* Parse::array_store_check() { log->elem("cast_up reason='monomorphic_array' from='%d' to='(exact)'", log->identify(tak->klass())); } - array_klass = con; // Use cast value moving forward + // Use cast value moving forward + array_klass = con; } } } diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index bfdf9a536fc..255ce81dbe2 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -977,6 +977,14 @@ const Type *CmpPNode::sub( const Type *t1, const Type *t2 ) const { (r1->flatten_array() && (!r0->can_be_inline_type() || (klass0->is_inlinetype() && !klass0->flatten_array())))) { // One type is flattened in arrays but the other type is not. Must be unrelated. unrelated_classes = true; + } else if ((r0->is_not_flat() && klass1->is_flat_array_klass()) || + (r1->is_not_flat() && klass0->is_flat_array_klass())) { + // One type is a non-flattened array and the other type is a flattened array. Must be unrelated. + unrelated_classes = true; + } else if ((r0->is_not_null_free() && klass1->is_obj_array_klass() && klass1->as_obj_array_klass()->element_klass()->is_inlinetype()) || + (r1->is_not_null_free() && klass0->is_obj_array_klass() && klass0->as_obj_array_klass()->element_klass()->is_inlinetype())) { + // One type is a non-null-free array and the other type is a null-free array. Must be unrelated. + unrelated_classes = true; } } if (unrelated_classes) { diff --git a/src/hotspot/share/opto/type.cpp b/src/hotspot/share/opto/type.cpp index 1cd4315583c..b25c3814433 100644 --- a/src/hotspot/share/opto/type.cpp +++ b/src/hotspot/share/opto/type.cpp @@ -5376,32 +5376,35 @@ const TypeKlassPtr *TypeKlassPtr::OBJECT; const TypeKlassPtr *TypeKlassPtr::OBJECT_OR_NULL; //------------------------------TypeKlassPtr----------------------------------- -TypeKlassPtr::TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array) - : TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant), _flatten_array(flatten_array) { +TypeKlassPtr::TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array, bool not_flat, bool not_null_free) + : TypePtr(KlassPtr, ptr, offset), _klass(klass), _klass_is_exact(ptr == Constant), + _flatten_array(flatten_array), _not_flat(not_flat), _not_null_free(not_null_free) { assert(!klass->flatten_array() || flatten_array, "Should be flat in array"); assert(!flatten_array || can_be_inline_type(), "Only inline types can be flat in array"); } //------------------------------make------------------------------------------- // ptr to klass 'k', if Constant, or possibly to a sub-klass if not a Constant -const TypeKlassPtr* TypeKlassPtr::make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array) { +const TypeKlassPtr* TypeKlassPtr::make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array, bool not_flat, bool not_null_free) { assert(k == NULL || k->is_instance_klass() || k->is_array_klass(), "Incorrect type of klass oop"); // Check if this type is known to be flat in arrays flatten_array = flatten_array || k->flatten_array(); - return (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset, flatten_array))->hashcons(); + return (TypeKlassPtr*)(new TypeKlassPtr(ptr, k, offset, flatten_array, not_flat, not_null_free))->hashcons(); } //------------------------------eq--------------------------------------------- // Structural equality check for Type representations bool TypeKlassPtr::eq( const Type *t ) const { const TypeKlassPtr *p = t->is_klassptr(); - return klass() == p->klass() && TypePtr::eq(p) && flatten_array() == p->flatten_array(); + return klass() == p->klass() && TypePtr::eq(p) && flatten_array() == p->flatten_array() && + is_not_flat() == p->is_not_flat() && is_not_null_free() == p->is_not_null_free(); } //------------------------------hash------------------------------------------- // Type-specific hashing function. int TypeKlassPtr::hash(void) const { - return java_add(java_add(klass() != NULL ? klass()->hash() : (jint)0, (jint)TypePtr::hash()), (jint)flatten_array()); + return java_add(java_add(java_add(java_add(klass() != NULL ? klass()->hash() : (jint)0, (jint)TypePtr::hash()), + (jint)flatten_array()), (jint)is_not_flat()), (jint)is_not_null_free()); } //------------------------------singleton-------------------------------------- @@ -5535,21 +5538,21 @@ ciKlass* TypeAryPtr::klass() const { //------------------------------add_offset------------------------------------- // Access internals of klass object const TypePtr *TypeKlassPtr::add_offset( intptr_t offset ) const { - return make(_ptr, klass(), xadd_offset(offset), flatten_array()); + return make(_ptr, klass(), xadd_offset(offset), flatten_array(), is_not_flat(), is_not_null_free()); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypeKlassPtr::cast_to_ptr_type(PTR ptr) const { assert(_base == KlassPtr, "subclass must override cast_to_ptr_type"); if( ptr == _ptr ) return this; - return make(ptr, _klass, _offset, _flatten_array); + return make(ptr, _klass, _offset, _flatten_array, _not_flat, _not_null_free); } //-----------------------------cast_to_exactness------------------------------- const Type *TypeKlassPtr::cast_to_exactness(bool klass_is_exact) const { if( klass_is_exact == _klass_is_exact ) return this; - return make(klass_is_exact ? Constant : NotNull, _klass, _offset, _flatten_array); + return make(klass_is_exact ? Constant : NotNull, _klass, _offset, _flatten_array, _not_flat, _not_null_free); } @@ -5560,12 +5563,15 @@ const TypeOopPtr* TypeKlassPtr::as_instance_type() const { ciKlass* k = klass(); assert(k != NULL, "klass should not be NULL"); bool xk = klass_is_exact(); - //return TypeInstPtr::make(TypePtr::NotNull, k, xk, NULL, 0); const TypeOopPtr* toop = TypeOopPtr::make_from_klass_raw(k); guarantee(toop != NULL, "need type for given klass"); toop = toop->cast_to_ptr_type(TypePtr::NotNull)->is_oopptr(); if (flatten_array() && !klass()->is_inlinetype()) { toop = toop->is_instptr()->cast_to_flatten_array(); + } else if (is_not_null_free()) { + toop = toop->is_aryptr()->cast_to_not_null_free(); + } else if (is_not_flat()) { + toop = toop->is_aryptr()->cast_to_not_flat(); } return toop->cast_to_exactness(xk)->is_oopptr(); } @@ -5609,7 +5615,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { case Null: if( ptr == Null ) return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); case AnyNull: - return make(ptr, klass(), offset, flatten_array()); + return make(ptr, klass(), offset, flatten_array(), is_not_flat(), is_not_null_free()); case BotPTR: case NotNull: return TypePtr::make(AnyPtr, ptr, offset, tp->speculative(), tp->inline_depth()); @@ -5657,8 +5663,8 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { // If we have constants, then we created oops so classes are loaded // and we can handle the constants further down. This case handles // not-loaded classes - if (ptr != Constant && tkls->klass()->equals(klass()) && flatten_array() == tkls->flatten_array()) { - return make(ptr, klass(), off, flatten_array()); + if (ptr != Constant && tkls->klass()->equals(klass()) && flatten_array() == tkls->flatten_array() && is_not_flat() == tkls->is_not_flat() && is_not_null_free() && tkls->is_not_null_free()) { + return make(ptr, klass(), off, flatten_array(), is_not_flat(), is_not_null_free()); } // Classes require inspection in the Java klass hierarchy. Must be loaded. @@ -5666,9 +5672,9 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { ciKlass* this_klass = this->klass(); assert( tkls_klass->is_loaded(), "This class should have been loaded."); assert( this_klass->is_loaded(), "This class should have been loaded."); - bool tkls_flatten_array = tkls->flatten_array(); - bool this_flatten_array = this->flatten_array(); - bool flatten_array = below_centerline(ptr) ? (this_flatten_array && tkls_flatten_array) : (this_flatten_array || tkls_flatten_array); + bool flatten_array = below_centerline(ptr) ? (this->flatten_array() && tkls->flatten_array()) : (this->flatten_array() || tkls->flatten_array()); + bool is_not_flat = this->is_not_flat() && tkls->is_not_flat(); + bool is_not_null_free = this->is_not_null_free() && tkls->is_not_null_free(); // If 'this' type is above the centerline and is a superclass of the // other, we can treat 'this' as having the same type as the other. @@ -5696,7 +5702,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { else ptr = NotNull; } - return make(ptr, this_klass, off, flatten_array); + return make(ptr, this_klass, off, flatten_array, is_not_flat, is_not_null_free); } // Else classes are not equal // Since klasses are different, we require the LCA in the Java @@ -5705,7 +5711,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { ptr = NotNull; // Now we find the LCA of Java classes ciKlass* k = this_klass->least_common_ancestor(tkls_klass); - return make(ptr, k, off); + return make(ptr, k, off, false, is_not_flat, is_not_null_free); } // End of case KlassPtr } // End of switch @@ -5715,7 +5721,7 @@ const Type *TypeKlassPtr::xmeet( const Type *t ) const { //------------------------------xdual------------------------------------------ // Dual: compute field-by-field dual const Type *TypeKlassPtr::xdual() const { - return new TypeKlassPtr(dual_ptr(), klass(), dual_offset(), flatten_array()); + return new TypeKlassPtr(dual_ptr(), klass(), dual_offset(), flatten_array(), !is_not_flat(), !is_not_null_free()); } //------------------------------get_con---------------------------------------- @@ -5763,6 +5769,11 @@ void TypeKlassPtr::dump2( Dict & d, uint depth, outputStream *st ) const { default: break; } + if (Verbose) { + if (_flatten_array) st->print(":flatten array"); + if (_not_flat) st->print(":not flat"); + if (_not_null_free) st->print(":not null free"); + } _offset.dump2(st); diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index e9817b69158..5484a243243 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -1017,6 +1017,8 @@ class TypePtr : public Type { virtual bool can_be_inline_type() const { return false; } virtual bool flatten_array() const { return false; } + virtual bool is_not_flat() const { return false; } + virtual bool is_not_null_free() const { return false; } // Tests for relation to centerline of type lattice: static bool above_centerline(PTR ptr) { return (ptr <= AnyNull); } @@ -1449,7 +1451,7 @@ class TypeMetadataPtr : public TypePtr { //------------------------------TypeKlassPtr----------------------------------- // Class of Java Klass pointers class TypeKlassPtr : public TypePtr { - TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array); + TypeKlassPtr(PTR ptr, ciKlass* klass, Offset offset, bool flatten_array, bool not_flat, bool not_null_free); protected: virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; @@ -1463,7 +1465,9 @@ class TypeKlassPtr : public TypePtr { // Does the type exclude subclasses of the klass? (Inexact == polymorphic.) bool _klass_is_exact; - bool _flatten_array; // Type is flat in arrays + const bool _flatten_array; // Type is flat in arrays + const bool _not_flat; // Array is never flattened + const bool _not_null_free; // Array is never null-free public: ciKlass* klass() const { return _klass; } @@ -1471,15 +1475,20 @@ class TypeKlassPtr : public TypePtr { virtual bool can_be_inline_type() const { return EnableValhalla && (_klass == NULL || _klass->can_be_inline_klass(_klass_is_exact)); } virtual bool flatten_array() const { return _flatten_array; } + virtual bool is_not_flat() const { return _not_flat; } + virtual bool is_not_null_free() const { return _not_null_free; } bool is_loaded() const { return klass() != NULL && klass()->is_loaded(); } // ptr to klass 'k' - static const TypeKlassPtr* make(ciKlass* k) { return make( TypePtr::Constant, k, Offset(0)); } - // ptr to klass 'k' with offset - static const TypeKlassPtr* make(ciKlass* k, Offset offset) { return make( TypePtr::Constant, k, offset); } + static const TypeKlassPtr* make(ciKlass* k) { + bool not_null_free = k->is_array_klass() && ( k->as_array_klass()->element_klass() == NULL || + !k->as_array_klass()->element_klass()->can_be_inline_klass(true)); + bool not_flat = k->is_array_klass() && !k->is_flat_array_klass(); + return make( TypePtr::Constant, k, Offset(0), false, not_flat, not_null_free); + } // ptr to klass 'k' or sub-klass - static const TypeKlassPtr* make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array = false); + static const TypeKlassPtr* make(PTR ptr, ciKlass* k, Offset offset, bool flatten_array = false, bool not_flat = false, bool not_null_free = false); virtual const Type *cast_to_ptr_type(PTR ptr) const;