aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm
diff options
context:
space:
mode:
authorroland <none@none>2014-03-17 11:54:14 -0700
committerroland <none@none>2014-03-17 11:54:14 -0700
commitb061c49652fe5bafea4214529f6f590f9cfb5295 (patch)
tree51ce414c85e6ebe15827c5928a8c3260adf4da59 /src/share/vm
parent952eae2b093e9a5fd350442c33d9383eb5d4fe90 (diff)
parentdbf6cb66a5c66c491319e17c0c47ddc35e569dc3 (diff)
Merge
Diffstat (limited to 'src/share/vm')
-rw-r--r--src/share/vm/opto/c2_globals.hpp7
-rw-r--r--src/share/vm/opto/graphKit.cpp29
-rw-r--r--src/share/vm/opto/type.cpp213
-rw-r--r--src/share/vm/opto/type.hpp47
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;