From 9b29dcd9f19410df12f38df4328e5d9d598293f9 Mon Sep 17 00:00:00 2001 From: roland Date: Fri, 14 Mar 2014 17:15:32 +0100 Subject: [PATCH] 8031754: Type speculation should favor profile data from outermost inlined method Summary: favor profile data coming from outer most method Reviewed-by: kvn, twisti --- src/share/vm/opto/c2_globals.hpp | 7 +- src/share/vm/opto/graphKit.cpp | 29 +++-- src/share/vm/opto/type.cpp | 213 +++++++++++++++++++++++-------- src/share/vm/opto/type.hpp | 47 +++++-- 4 files changed, 218 insertions(+), 78 deletions(-) diff --git a/src/share/vm/opto/c2_globals.hpp b/src/share/vm/opto/c2_globals.hpp index 83e5fbbf6..76e1ec4c6 100644 --- a/src/share/vm/opto/c2_globals.hpp +++ b/src/share/vm/opto/c2_globals.hpp @@ -644,7 +644,12 @@ "Propagate type improvements in callers of inlinee if possible") \ \ experimental(bool, UseTypeSpeculation, false, \ - "Speculatively propagate types from profiles") + "Speculatively propagate types from profiles") \ + \ + diagnostic(bool, UseInlineDepthForSpeculativeTypes, true, \ + "Carry inline depth of profile point with speculative type " \ + "and give priority to profiling from lower inline depth") \ + C2_FLAGS(DECLARE_DEVELOPER_FLAG, DECLARE_PD_DEVELOPER_FLAG, DECLARE_PRODUCT_FLAG, DECLARE_PD_PRODUCT_FLAG, DECLARE_DIAGNOSTIC_FLAG, DECLARE_EXPERIMENTAL_FLAG, DECLARE_NOTPRODUCT_FLAG) diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp index 0dbaeca8a..7a154c557 100644 --- a/src/share/vm/opto/graphKit.cpp +++ b/src/share/vm/opto/graphKit.cpp @@ -2109,30 +2109,33 @@ void GraphKit::round_double_arguments(ciMethod* dest_method) { * @return node with improved type */ Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) { - const TypeOopPtr* current_type = _gvn.type(n)->isa_oopptr(); + const Type* current_type = _gvn.type(n); assert(UseTypeSpeculation, "type speculation must be on"); - if (exact_kls != NULL && - // nothing to improve if type is already exact - (current_type == NULL || - (!current_type->klass_is_exact() && - (current_type->speculative() == NULL || - !current_type->speculative()->klass_is_exact())))) { + + const TypeOopPtr* speculative = current_type->speculative(); + + if (current_type->would_improve_type(exact_kls, jvms()->depth())) { const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls); const TypeOopPtr* xtype = tklass->as_instance_type(); assert(xtype->klass_is_exact(), "Should be exact"); + // record the new speculative type's depth + speculative = xtype->with_inline_depth(jvms()->depth()); + } + if (speculative != current_type->speculative()) { // Build a type with a speculative type (what we think we know // about the type but will need a guard when we use it) - const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, xtype); - // We're changing the type, we need a new cast node to carry the - // new type. The new type depends on the control: what profiling - // tells us is only valid from here as far as we can tell. - Node* cast = new(C) CastPPNode(n, spec_type); - cast->init_req(0, control()); + const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, speculative); + // We're changing the type, we need a new CheckCast node to carry + // the new type. The new type depends on the control: what + // profiling tells us is only valid from here as far as we can + // tell. + Node* cast = new(C) CheckCastPPNode(control(), n, current_type->remove_speculative()->join_speculative(spec_type)); cast = _gvn.transform(cast); replace_in_map(n, cast); n = cast; } + return n; } diff --git a/src/share/vm/opto/type.cpp b/src/share/vm/opto/type.cpp index 751b3cc09..b19d9c9a9 100644 --- a/src/share/vm/opto/type.cpp +++ b/src/share/vm/opto/type.cpp @@ -2457,7 +2457,7 @@ void TypeRawPtr::dump2( Dict &d, uint depth, outputStream *st ) const { const TypeOopPtr *TypeOopPtr::BOTTOM; //------------------------------TypeOopPtr------------------------------------- -TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative) +TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) : TypePtr(t, ptr, offset), _const_oop(o), _klass(k), _klass_is_exact(xk), @@ -2465,7 +2465,8 @@ TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int o _is_ptr_to_narrowklass(false), _is_ptr_to_boxed_value(false), _instance_id(instance_id), - _speculative(speculative) { + _speculative(speculative), + _inline_depth(inline_depth){ if (Compile::current()->eliminate_boxing() && (t == InstPtr) && (offset > 0) && xk && (k != 0) && k->is_instance_klass()) { _is_ptr_to_boxed_value = k->as_instance_klass()->is_boxed_value_offset(offset); @@ -2532,12 +2533,12 @@ TypeOopPtr::TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int o //------------------------------make------------------------------------------- const TypeOopPtr *TypeOopPtr::make(PTR ptr, - int offset, int instance_id, const TypeOopPtr* speculative) { + int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) { assert(ptr != Constant, "no constant generic pointers"); ciKlass* k = Compile::current()->env()->Object_klass(); bool xk = false; ciObject* o = NULL; - return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id, speculative))->hashcons(); + return (TypeOopPtr*)(new TypeOopPtr(OopPtr, ptr, k, xk, o, offset, instance_id, speculative, inline_depth))->hashcons(); } @@ -2545,7 +2546,7 @@ const TypeOopPtr *TypeOopPtr::make(PTR ptr, const Type *TypeOopPtr::cast_to_ptr_type(PTR ptr) const { assert(_base == OopPtr, "subclass must override cast_to_ptr_type"); if( ptr == _ptr ) return this; - return make(ptr, _offset, _instance_id, _speculative); + return make(ptr, _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------cast_to_instance_id---------------------------- @@ -2642,7 +2643,7 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const { case AnyNull: { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = _speculative; - return make(ptr, offset, instance_id, speculative); + return make(ptr, offset, instance_id, speculative, _inline_depth); } case BotPTR: case NotNull: @@ -2655,7 +2656,8 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const { const TypeOopPtr *tp = t->is_oopptr(); int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); - return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative); + int depth = meet_inline_depth(tp->inline_depth()); + return make(meet_ptr(tp->ptr()), meet_offset(tp->offset()), instance_id, speculative, depth); } case InstPtr: // For these, flip the call around to cut down @@ -2672,7 +2674,7 @@ const Type *TypeOopPtr::xmeet_helper(const Type *t) const { const Type *TypeOopPtr::xdual() const { assert(klass() == Compile::current()->env()->Object_klass(), "no klasses here"); assert(const_oop() == NULL, "no constants here"); - return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative()); + return new TypeOopPtr(_base, dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative(), dual_inline_depth()); } //--------------------------make_from_klass_common----------------------------- @@ -2763,7 +2765,7 @@ const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o, } else if (!o->should_be_constant()) { return TypeAryPtr::make(TypePtr::NotNull, arr0, klass, true, 0); } - const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, NULL, is_autobox_cache); + const TypeAryPtr* arr = TypeAryPtr::make(TypePtr::Constant, o, arr0, klass, true, 0, InstanceBot, NULL, InlineDepthBottom, is_autobox_cache); return arr; } else if (klass->is_type_array_klass()) { // Element is an typeArray @@ -2852,7 +2854,8 @@ bool TypeOopPtr::eq( const Type *t ) const { const TypeOopPtr *a = (const TypeOopPtr*)t; if (_klass_is_exact != a->_klass_is_exact || _instance_id != a->_instance_id || - !eq_speculative(a)) return false; + !eq_speculative(a) || + _inline_depth != a->_inline_depth) return false; ciObject* one = const_oop(); ciObject* two = a->const_oop(); if (one == NULL || two == NULL) { @@ -2870,6 +2873,7 @@ int TypeOopPtr::hash(void) const { _klass_is_exact + _instance_id + hash_speculative() + + _inline_depth + TypePtr::hash(); } @@ -2890,6 +2894,7 @@ void TypeOopPtr::dump2( Dict &d, uint depth, outputStream *st ) const { else if (_instance_id != InstanceBot) st->print(",iid=%d",_instance_id); + dump_inline_depth(st); dump_speculative(st); } @@ -2903,6 +2908,16 @@ void TypeOopPtr::dump_speculative(outputStream *st) const { st->print(")"); } } + +void TypeOopPtr::dump_inline_depth(outputStream *st) const { + if (_inline_depth != InlineDepthBottom) { + if (_inline_depth == InlineDepthTop) { + st->print(" (inline_depth=InlineDepthTop)"); + } else { + st->print(" (inline_depth=%d)", _inline_depth); + } + } +} #endif //------------------------------singleton-------------------------------------- @@ -2916,7 +2931,7 @@ bool TypeOopPtr::singleton(void) const { //------------------------------add_offset------------------------------------- const TypePtr *TypeOopPtr::add_offset(intptr_t offset) const { - return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset)); + return make(_ptr, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth); } /** @@ -2926,7 +2941,52 @@ const Type* TypeOopPtr::remove_speculative() const { if (_speculative == NULL) { return this; } - return make(_ptr, _offset, _instance_id, NULL); + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); + return make(_ptr, _offset, _instance_id, NULL, _inline_depth); +} + +/** + * Return same type but with a different inline depth (used for speculation) + * + * @param depth depth to meet with + */ +const TypeOopPtr* TypeOopPtr::with_inline_depth(int depth) const { + if (!UseInlineDepthForSpeculativeTypes) { + return this; + } + return make(_ptr, _offset, _instance_id, _speculative, depth); +} + +/** + * Check whether new profiling would improve speculative type + * + * @param exact_kls class from profiling + * @param inline_depth inlining depth of profile point + * + * @return true if type profile is valuable + */ +bool TypeOopPtr::would_improve_type(ciKlass* exact_kls, int inline_depth) const { + // no way to improve an already exact type + if (klass_is_exact()) { + return false; + } + // no profiling? + if (exact_kls == NULL) { + return false; + } + // no speculative type or non exact speculative type? + if (speculative_type() == NULL) { + return true; + } + // If the node already has an exact speculative type keep it, + // unless it was provided by profiling that is at a deeper + // inlining level. Profiling at a higher inlining depth is + // expected to be less accurate. + if (_speculative->inline_depth() == InlineDepthBottom) { + return false; + } + assert(_speculative->inline_depth() != InlineDepthTop, "can't do the comparison"); + return inline_depth < _speculative->inline_depth(); } //------------------------------meet_instance_id-------------------------------- @@ -3029,6 +3089,21 @@ int TypeOopPtr::hash_speculative() const { return _speculative->hash(); } +/** + * dual of the inline depth for this type (used for speculation) + */ +int TypeOopPtr::dual_inline_depth() const { + return -inline_depth(); +} + +/** + * meet of 2 inline depth (used for speculation) + * + * @param depth depth to meet with + */ +int TypeOopPtr::meet_inline_depth(int depth) const { + return MAX2(inline_depth(), depth); +} //============================================================================= // Convenience common pre-built types. @@ -3039,8 +3114,8 @@ const TypeInstPtr *TypeInstPtr::MARK; const TypeInstPtr *TypeInstPtr::KLASS; //------------------------------TypeInstPtr------------------------------------- -TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative) - : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative), _name(k->name()) { +TypeInstPtr::TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int off, int instance_id, const TypeOopPtr* speculative, int inline_depth) + : TypeOopPtr(InstPtr, ptr, k, xk, o, off, instance_id, speculative, inline_depth), _name(k->name()) { assert(k != NULL && (k->is_loaded() || o == NULL), "cannot have constants with non-loaded klass"); @@ -3053,7 +3128,8 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr, ciObject* o, int offset, int instance_id, - const TypeOopPtr* speculative) { + const TypeOopPtr* speculative, + int inline_depth) { assert( !k->is_loaded() || k->is_instance_klass(), "Must be for instance"); // Either const_oop() is NULL or else ptr is Constant assert( (!o && ptr != Constant) || (o && ptr == Constant), @@ -3074,7 +3150,7 @@ const TypeInstPtr *TypeInstPtr::make(PTR ptr, // Now hash this baby TypeInstPtr *result = - (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id, speculative))->hashcons(); + (TypeInstPtr*)(new TypeInstPtr(ptr, k, xk, o ,offset, instance_id, speculative, inline_depth))->hashcons(); return result; } @@ -3107,7 +3183,7 @@ const Type *TypeInstPtr::cast_to_ptr_type(PTR ptr) const { if( ptr == _ptr ) return this; // Reconstruct _sig info here since not a problem with later lazy // construction, _sig will show up on demand. - return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative); + return make(ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, _inline_depth); } @@ -3119,13 +3195,13 @@ const Type *TypeInstPtr::cast_to_exactness(bool klass_is_exact) const { ciInstanceKlass* ik = _klass->as_instance_klass(); if( (ik->is_final() || _const_oop) ) return this; // cannot clear xk if( ik->is_interface() ) return this; // cannot set xk - return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id, _speculative); + return make(ptr(), klass(), klass_is_exact, const_oop(), _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------cast_to_instance_id---------------------------- const TypeOopPtr *TypeInstPtr::cast_to_instance_id(int instance_id) const { if( instance_id == _instance_id ) return this; - return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative); + return make(_ptr, klass(), _klass_is_exact, const_oop(), _offset, instance_id, _speculative, _inline_depth); } //------------------------------xmeet_unloaded--------------------------------- @@ -3136,6 +3212,7 @@ const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const { PTR ptr = meet_ptr(tinst->ptr()); int instance_id = meet_instance_id(tinst->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tinst); + int depth = meet_inline_depth(tinst->inline_depth()); const TypeInstPtr *loaded = is_loaded() ? this : tinst; const TypeInstPtr *unloaded = is_loaded() ? tinst : this; @@ -3156,7 +3233,7 @@ const TypeInstPtr *TypeInstPtr::xmeet_unloaded(const TypeInstPtr *tinst) const { assert(loaded->ptr() != TypePtr::Null, "insanity check"); // if( loaded->ptr() == TypePtr::TopPTR ) { return unloaded; } - else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, instance_id, speculative); } + else if (loaded->ptr() == TypePtr::AnyNull) { return TypeInstPtr::make(ptr, unloaded->klass(), false, NULL, off, instance_id, speculative, depth); } else if (loaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; } else if (loaded->ptr() == TypePtr::Constant || loaded->ptr() == TypePtr::NotNull) { if (unloaded->ptr() == TypePtr::BotPTR ) { return TypeInstPtr::BOTTOM; } @@ -3213,6 +3290,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) { case TopPTR: case AnyNull: // Fall 'down' to dual of object klass @@ -3220,12 +3298,12 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { // below the centerline when the superclass is exact. We need to // do the same here. if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { - return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative); + return TypeAryPtr::make(ptr, tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative, depth); } else { // cannot subclass, so the meet has to fall badly below the centerline ptr = NotNull; instance_id = InstanceBot; - return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative); + return TypeInstPtr::make( ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth); } case Constant: case NotNull: @@ -3240,7 +3318,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { if (klass()->equals(ciEnv::current()->Object_klass()) && !klass_is_exact()) { // that is, tp's array type is a subtype of my klass return TypeAryPtr::make(ptr, (ptr == Constant ? tp->const_oop() : NULL), - tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative); + tp->ary(), tp->klass(), tp->klass_is_exact(), offset, instance_id, speculative, depth); } } // The other case cannot happen, since I cannot be a subtype of an array. @@ -3248,7 +3326,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { if( ptr == Constant ) ptr = NotNull; instance_id = InstanceBot; - return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative); + return make(ptr, ciEnv::current()->Object_klass(), false, NULL, offset, instance_id, speculative, depth); default: typerr(t); } } @@ -3263,14 +3341,16 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { case AnyNull: { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); return make(ptr, klass(), klass_is_exact(), - (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative); + (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, depth); } case NotNull: case BotPTR: { int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); - return TypeOopPtr::make(ptr, offset, instance_id, speculative); + int depth = meet_inline_depth(tp->inline_depth()); + return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth); } default: typerr(t); } @@ -3290,7 +3370,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = _speculative; return make(ptr, klass(), klass_is_exact(), - (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative); + (ptr == Constant ? const_oop() : NULL), offset, instance_id, speculative, _inline_depth); } case NotNull: case BotPTR: @@ -3322,13 +3402,14 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { PTR ptr = meet_ptr( tinst->ptr() ); int instance_id = meet_instance_id(tinst->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tinst); + int depth = meet_inline_depth(tinst->inline_depth()); // Check for easy case; klasses are equal (and perhaps not loaded!) // If we have constants, then we created oops so classes are loaded // and we can handle the constants further down. This case handles // both-not-loaded or both-loaded classes if (ptr != Constant && klass()->equals(tinst->klass()) && klass_is_exact() == tinst->klass_is_exact()) { - return make(ptr, klass(), klass_is_exact(), NULL, off, instance_id, speculative); + return make(ptr, klass(), klass_is_exact(), NULL, off, instance_id, speculative, depth); } // Classes require inspection in the Java klass hierarchy. Must be loaded. @@ -3392,7 +3473,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { // Find out which constant. o = (this_klass == klass()) ? const_oop() : tinst->const_oop(); } - return make(ptr, k, xk, o, off, instance_id, speculative); + return make(ptr, k, xk, o, off, instance_id, speculative, depth); } // Either oop vs oop or interface vs interface or interface vs Object @@ -3469,7 +3550,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { else ptr = NotNull; } - return make(ptr, this_klass, this_xk, o, off, instance_id, speculative); + return make(ptr, this_klass, this_xk, o, off, instance_id, speculative, depth); } // Else classes are not equal // Since klasses are different, we require a LCA in the Java @@ -3480,7 +3561,7 @@ const Type *TypeInstPtr::xmeet_helper(const Type *t) const { // Now we find the LCA of Java classes ciKlass* k = this_klass->least_common_ancestor(tinst_klass); - return make(ptr, k, false, NULL, off, instance_id, speculative); + return make(ptr, k, false, NULL, off, instance_id, speculative, depth); } // End of case InstPtr } // End of switch @@ -3504,7 +3585,7 @@ ciType* TypeInstPtr::java_mirror_type() const { // Dual: do NOT dual on klasses. This means I do NOT understand the Java // inheritance mechanism. const Type *TypeInstPtr::xdual() const { - return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative()); + return new TypeInstPtr(dual_ptr(), klass(), klass_is_exact(), const_oop(), dual_offset(), dual_instance_id(), dual_speculative(), dual_inline_depth()); } //------------------------------eq--------------------------------------------- @@ -3561,6 +3642,7 @@ void TypeInstPtr::dump2( Dict &d, uint depth, outputStream *st ) const { else if (_instance_id != InstanceBot) st->print(",iid=%d",_instance_id); + dump_inline_depth(st); dump_speculative(st); } #endif @@ -3574,7 +3656,15 @@ const Type *TypeInstPtr::remove_speculative() const { if (_speculative == NULL) { return this; } - return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL); + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); + return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, NULL, _inline_depth); +} + +const TypeOopPtr *TypeInstPtr::with_inline_depth(int depth) const { + if (!UseInlineDepthForSpeculativeTypes) { + return this; + } + return make(_ptr, klass(), klass_is_exact(), const_oop(), _offset, _instance_id, _speculative, depth); } //============================================================================= @@ -3591,30 +3681,30 @@ const TypeAryPtr *TypeAryPtr::FLOATS; const TypeAryPtr *TypeAryPtr::DOUBLES; //------------------------------make------------------------------------------- -const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative) { +const TypeAryPtr *TypeAryPtr::make(PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); if (!xk) xk = ary->ary_must_be_exact(); assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); if (!UseExactTypes) xk = (ptr == Constant); - return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false, speculative))->hashcons(); + return (TypeAryPtr*)(new TypeAryPtr(ptr, NULL, ary, k, xk, offset, instance_id, false, speculative, inline_depth))->hashcons(); } //------------------------------make------------------------------------------- -const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, bool is_autobox_cache) { +const TypeAryPtr *TypeAryPtr::make(PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth, bool is_autobox_cache) { assert(!(k == NULL && ary->_elem->isa_int()), "integral arrays must be pre-equipped with a class"); assert( (ptr==Constant && o) || (ptr!=Constant && !o), "" ); if (!xk) xk = (o != NULL) || ary->ary_must_be_exact(); assert(instance_id <= 0 || xk || !UseExactTypes, "instances are always exactly typed"); if (!UseExactTypes) xk = (ptr == Constant); - return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache, speculative))->hashcons(); + return (TypeAryPtr*)(new TypeAryPtr(ptr, o, ary, k, xk, offset, instance_id, is_autobox_cache, speculative, inline_depth))->hashcons(); } //------------------------------cast_to_ptr_type------------------------------- const Type *TypeAryPtr::cast_to_ptr_type(PTR ptr) const { if( ptr == _ptr ) return this; - return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative); + return make(ptr, const_oop(), _ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); } @@ -3623,13 +3713,13 @@ const Type *TypeAryPtr::cast_to_exactness(bool klass_is_exact) const { if( klass_is_exact == _klass_is_exact ) return this; if (!UseExactTypes) return this; if (_ary->ary_must_be_exact()) return this; // cannot clear xk - return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative); + return make(ptr(), const_oop(), _ary, klass(), klass_is_exact, _offset, _instance_id, _speculative, _inline_depth); } //-----------------------------cast_to_instance_id---------------------------- const TypeOopPtr *TypeAryPtr::cast_to_instance_id(int instance_id) const { if( instance_id == _instance_id ) return this; - return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative); + return make(_ptr, const_oop(), _ary, klass(), _klass_is_exact, _offset, instance_id, _speculative, _inline_depth); } //-----------------------------narrow_size_type------------------------------- @@ -3692,7 +3782,7 @@ const TypeAryPtr* TypeAryPtr::cast_to_size(const TypeInt* new_size) const { new_size = narrow_size_type(new_size); if (new_size == size()) return this; const TypeAry* new_ary = TypeAry::make(elem(), new_size, is_stable()); - return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative); + return make(ptr(), const_oop(), new_ary, klass(), klass_is_exact(), _offset, _instance_id, _speculative, _inline_depth); } @@ -3771,19 +3861,20 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { const TypeOopPtr *tp = t->is_oopptr(); int offset = meet_offset(tp->offset()); PTR ptr = meet_ptr(tp->ptr()); + int depth = meet_inline_depth(tp->inline_depth()); switch (tp->ptr()) { case TopPTR: case AnyNull: { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = xmeet_speculative(tp); return make(ptr, (ptr == Constant ? const_oop() : NULL), - _ary, _klass, _klass_is_exact, offset, instance_id, speculative); + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } case BotPTR: case NotNull: { int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); - return TypeOopPtr::make(ptr, offset, instance_id, speculative); + return TypeOopPtr::make(ptr, offset, instance_id, speculative, depth); } default: ShouldNotReachHere(); } @@ -3807,7 +3898,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { int instance_id = meet_instance_id(InstanceTop); const TypeOopPtr* speculative = _speculative; return make(ptr, (ptr == Constant ? const_oop() : NULL), - _ary, _klass, _klass_is_exact, offset, instance_id, speculative); + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, _inline_depth); } default: ShouldNotReachHere(); } @@ -3824,6 +3915,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { PTR ptr = meet_ptr(tap->ptr()); int instance_id = meet_instance_id(tap->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tap); + int depth = meet_inline_depth(tap->inline_depth()); ciKlass* lazy_klass = NULL; if (tary->_elem->isa_int()) { // Integral array element types have irrelevant lattice relations. @@ -3864,7 +3956,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { } else { xk = (tap->_klass_is_exact | this->_klass_is_exact); } - return make(ptr, const_oop(), tary, lazy_klass, xk, off, instance_id, speculative); + return make(ptr, const_oop(), tary, lazy_klass, xk, off, instance_id, speculative, depth); case Constant: { ciObject* o = const_oop(); if( _ptr == Constant ) { @@ -3883,7 +3975,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { // Only precise for identical arrays xk = this->_klass_is_exact && (klass() == tap->klass()); } - return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, instance_id, speculative); + return TypeAryPtr::make(ptr, o, tary, lazy_klass, xk, off, instance_id, speculative, depth); } case NotNull: case BotPTR: @@ -3892,7 +3984,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { xk = tap->_klass_is_exact; else xk = (tap->_klass_is_exact & this->_klass_is_exact) && (klass() == tap->klass()); // Only precise for identical arrays - return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, instance_id, speculative); + return TypeAryPtr::make(ptr, NULL, tary, lazy_klass, xk, off, instance_id, speculative, depth); default: ShouldNotReachHere(); } } @@ -3904,6 +3996,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { PTR ptr = meet_ptr(tp->ptr()); int instance_id = meet_instance_id(tp->instance_id()); const TypeOopPtr* speculative = xmeet_speculative(tp); + int depth = meet_inline_depth(tp->inline_depth()); switch (ptr) { case TopPTR: case AnyNull: // Fall 'down' to dual of object klass @@ -3911,12 +4004,12 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { // below the centerline when the superclass is exact. We need to // do the same here. if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { - return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, instance_id, speculative); + return TypeAryPtr::make(ptr, _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } else { // cannot subclass, so the meet has to fall badly below the centerline ptr = NotNull; instance_id = InstanceBot; - return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative); + return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative, depth); } case Constant: case NotNull: @@ -3931,7 +4024,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { if (tp->klass()->equals(ciEnv::current()->Object_klass()) && !tp->klass_is_exact()) { // that is, my array type is a subtype of 'tp' klass return make(ptr, (ptr == Constant ? const_oop() : NULL), - _ary, _klass, _klass_is_exact, offset, instance_id, speculative); + _ary, _klass, _klass_is_exact, offset, instance_id, speculative, depth); } } // The other case cannot happen, since t cannot be a subtype of an array. @@ -3939,7 +4032,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { if( ptr == Constant ) ptr = NotNull; instance_id = InstanceBot; - return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative); + return TypeInstPtr::make(ptr, ciEnv::current()->Object_klass(), false, NULL,offset, instance_id, speculative, depth); default: typerr(t); } } @@ -3950,7 +4043,7 @@ const Type *TypeAryPtr::xmeet_helper(const Type *t) const { //------------------------------xdual------------------------------------------ // Dual: compute field-by-field dual const Type *TypeAryPtr::xdual() const { - return new TypeAryPtr(dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache(), dual_speculative()); + return new TypeAryPtr(dual_ptr(), _const_oop, _ary->dual()->is_ary(),_klass, _klass_is_exact, dual_offset(), dual_instance_id(), is_autobox_cache(), dual_speculative(), dual_inline_depth()); } //----------------------interface_vs_oop--------------------------------------- @@ -4003,6 +4096,7 @@ void TypeAryPtr::dump2( Dict &d, uint depth, outputStream *st ) const { else if (_instance_id != InstanceBot) st->print(",iid=%d",_instance_id); + dump_inline_depth(st); dump_speculative(st); } #endif @@ -4014,11 +4108,22 @@ bool TypeAryPtr::empty(void) const { //------------------------------add_offset------------------------------------- const TypePtr *TypeAryPtr::add_offset(intptr_t offset) const { - return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset)); + return make(_ptr, _const_oop, _ary, _klass, _klass_is_exact, xadd_offset(offset), _instance_id, add_offset_speculative(offset), _inline_depth); } const Type *TypeAryPtr::remove_speculative() const { - return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL); + if (_speculative == NULL) { + return this; + } + assert(_inline_depth == InlineDepthTop || _inline_depth == InlineDepthBottom, "non speculative type shouldn't have inline depth"); + return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, NULL, _inline_depth); +} + +const TypeOopPtr *TypeAryPtr::with_inline_depth(int depth) const { + if (!UseInlineDepthForSpeculativeTypes) { + return this; + } + return make(_ptr, _const_oop, _ary->remove_speculative()->is_ary(), _klass, _klass_is_exact, _offset, _instance_id, _speculative, depth); } //============================================================================= diff --git a/src/share/vm/opto/type.hpp b/src/share/vm/opto/type.hpp index 418dd495d..0563927c5 100644 --- a/src/share/vm/opto/type.hpp +++ b/src/share/vm/opto/type.hpp @@ -415,10 +415,15 @@ public: bool is_autobox_cache = false); // Speculative type. See TypeInstPtr + virtual const TypeOopPtr* speculative() const { return NULL; } virtual ciKlass* speculative_type() const { return NULL; } const Type* maybe_remove_speculative(bool include_speculative) const; virtual const Type* remove_speculative() const { return this; } + virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const { + return exact_kls != NULL; + } + private: // support arrays static const BasicType _basic_type[]; @@ -842,7 +847,7 @@ public: // Some kind of oop (Java pointer), either klass or instance or array. class TypeOopPtr : public TypePtr { protected: - TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative); + TypeOopPtr(TYPES t, PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); public: virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -853,6 +858,10 @@ public: }; protected: + enum { + InlineDepthBottom = INT_MAX, + InlineDepthTop = -InlineDepthBottom + }; // Oop is NULL, unless this is a constant oop. ciObject* _const_oop; // Constant oop // If _klass is NULL, then so is _sig. This is an unloaded klass. @@ -873,6 +882,11 @@ protected: // use it, then we have to emit a guard: this part of the type is // not something we know but something we speculate about the type. const TypeOopPtr* _speculative; + // For speculative types, we record at what inlining depth the + // profiling point that provided the data is. We want to favor + // profile data coming from outer scopes which are likely better for + // the current compilation. + int _inline_depth; static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact); @@ -888,6 +902,12 @@ protected: #ifndef PRODUCT void dump_speculative(outputStream *st) const; #endif + // utility methods to work on the inline depth of the type + int dual_inline_depth() const; + int meet_inline_depth(int depth) const; +#ifndef PRODUCT + void dump_inline_depth(outputStream *st) const; +#endif // Do not allow interface-vs.-noninterface joins to collapse to top. virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; @@ -918,7 +938,7 @@ public: bool not_null_elements = false); // Make a generic (unclassed) pointer to an oop. - static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative); + static const TypeOopPtr* make(PTR ptr, int offset, int instance_id, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); ciObject* const_oop() const { return _const_oop; } virtual ciKlass* klass() const { return _klass; } @@ -932,7 +952,7 @@ public: bool is_known_instance() const { return _instance_id > 0; } int instance_id() const { return _instance_id; } bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; } - const TypeOopPtr* speculative() const { return _speculative; } + virtual const TypeOopPtr* speculative() const { return _speculative; } virtual intptr_t get_con() const; @@ -965,18 +985,23 @@ public: if (_speculative != NULL) { const TypeOopPtr* speculative = _speculative->join(this)->is_oopptr(); if (speculative->klass_is_exact()) { - return speculative->klass(); + return speculative->klass(); } } return NULL; } + int inline_depth() const { + return _inline_depth; + } + virtual const TypeOopPtr* with_inline_depth(int depth) const; + virtual bool would_improve_type(ciKlass* exact_kls, int inline_depth) const; }; //------------------------------TypeInstPtr------------------------------------ // Class of Java object pointers, pointing either to non-array Java instances // or to a Klass* (including array klasses). class TypeInstPtr : public TypeOopPtr { - TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative); + TypeInstPtr(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id, const TypeOopPtr* speculative, int inline_depth); virtual bool eq( const Type *t ) const; virtual int hash() const; // Type specific hashing @@ -1012,7 +1037,7 @@ class TypeInstPtr : public TypeOopPtr { } // Make a pointer to an oop. - static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL); + static const TypeInstPtr *make(PTR ptr, ciKlass* k, bool xk, ciObject* o, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); /** Create constant type for a constant boxed value */ const Type* get_const_boxed_value() const; @@ -1031,6 +1056,7 @@ class TypeInstPtr : public TypeOopPtr { virtual const TypePtr *add_offset( intptr_t offset ) const; // Return same type without a speculative part virtual const Type* remove_speculative() const; + virtual const TypeOopPtr* with_inline_depth(int depth) const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; @@ -1052,8 +1078,8 @@ class TypeInstPtr : public TypeOopPtr { // Class of Java array pointers class TypeAryPtr : public TypeOopPtr { TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, - int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative) - : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative), + int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* speculative, int inline_depth) + : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative, inline_depth), _ary(ary), _is_autobox_cache(is_autobox_cache) { @@ -1091,9 +1117,9 @@ public: bool is_autobox_cache() const { return _is_autobox_cache; } - static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL); + static const TypeAryPtr *make( PTR ptr, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom); // Constant pointer to array - static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, bool is_autobox_cache = false); + static const TypeAryPtr *make( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, int offset, int instance_id = InstanceBot, const TypeOopPtr* speculative = NULL, int inline_depth = InlineDepthBottom, bool is_autobox_cache= false); // Return a 'ptr' version of this type virtual const Type *cast_to_ptr_type(PTR ptr) const; @@ -1109,6 +1135,7 @@ public: virtual const TypePtr *add_offset( intptr_t offset ) const; // Return same type without a speculative part virtual const Type* remove_speculative() const; + virtual const TypeOopPtr* with_inline_depth(int depth) const; // the core of the computation of the meet of 2 types virtual const Type *xmeet_helper(const Type *t) const; -- GitLab