提交 9b29dcd9 编写于 作者: R roland

8031754: Type speculation should favor profile data from outermost inlined method

Summary: favor profile data coming from outer most method
Reviewed-by: kvn, twisti
上级 9b81c37a
......@@ -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)
......
......@@ -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;
}
......
此差异已折叠。
......@@ -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;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册