提交 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 @@ ...@@ -644,7 +644,12 @@
"Propagate type improvements in callers of inlinee if possible") \ "Propagate type improvements in callers of inlinee if possible") \
\ \
experimental(bool, UseTypeSpeculation, false, \ 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) 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) { ...@@ -2109,30 +2109,33 @@ void GraphKit::round_double_arguments(ciMethod* dest_method) {
* @return node with improved type * @return node with improved type
*/ */
Node* GraphKit::record_profile_for_speculation(Node* n, ciKlass* exact_kls) { 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"); assert(UseTypeSpeculation, "type speculation must be on");
if (exact_kls != NULL &&
// nothing to improve if type is already exact const TypeOopPtr* speculative = current_type->speculative();
(current_type == NULL ||
(!current_type->klass_is_exact() && if (current_type->would_improve_type(exact_kls, jvms()->depth())) {
(current_type->speculative() == NULL ||
!current_type->speculative()->klass_is_exact())))) {
const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls); const TypeKlassPtr* tklass = TypeKlassPtr::make(exact_kls);
const TypeOopPtr* xtype = tklass->as_instance_type(); const TypeOopPtr* xtype = tklass->as_instance_type();
assert(xtype->klass_is_exact(), "Should be exact"); 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 // Build a type with a speculative type (what we think we know
// about the type but will need a guard when we use it) // 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); const TypeOopPtr* spec_type = TypeOopPtr::make(TypePtr::BotPTR, Type::OffsetBot, TypeOopPtr::InstanceBot, speculative);
// We're changing the type, we need a new cast node to carry the // We're changing the type, we need a new CheckCast node to carry
// new type. The new type depends on the control: what profiling // the new type. The new type depends on the control: what
// tells us is only valid from here as far as we can tell. // profiling tells us is only valid from here as far as we can
Node* cast = new(C) CastPPNode(n, spec_type); // tell.
cast->init_req(0, control()); Node* cast = new(C) CheckCastPPNode(control(), n, current_type->remove_speculative()->join_speculative(spec_type));
cast = _gvn.transform(cast); cast = _gvn.transform(cast);
replace_in_map(n, cast); replace_in_map(n, cast);
n = cast; n = cast;
} }
return n; return n;
} }
......
此差异已折叠。
...@@ -415,10 +415,15 @@ public: ...@@ -415,10 +415,15 @@ public:
bool is_autobox_cache = false); bool is_autobox_cache = false);
// Speculative type. See TypeInstPtr // Speculative type. See TypeInstPtr
virtual const TypeOopPtr* speculative() const { return NULL; }
virtual ciKlass* speculative_type() const { return NULL; } virtual ciKlass* speculative_type() const { return NULL; }
const Type* maybe_remove_speculative(bool include_speculative) const; const Type* maybe_remove_speculative(bool include_speculative) const;
virtual const Type* remove_speculative() const { return this; } 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: private:
// support arrays // support arrays
static const BasicType _basic_type[]; static const BasicType _basic_type[];
...@@ -842,7 +847,7 @@ public: ...@@ -842,7 +847,7 @@ public:
// Some kind of oop (Java pointer), either klass or instance or array. // Some kind of oop (Java pointer), either klass or instance or array.
class TypeOopPtr : public TypePtr { class TypeOopPtr : public TypePtr {
protected: 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: public:
virtual bool eq( const Type *t ) const; virtual bool eq( const Type *t ) const;
virtual int hash() const; // Type specific hashing virtual int hash() const; // Type specific hashing
...@@ -853,6 +858,10 @@ public: ...@@ -853,6 +858,10 @@ public:
}; };
protected: protected:
enum {
InlineDepthBottom = INT_MAX,
InlineDepthTop = -InlineDepthBottom
};
// Oop is NULL, unless this is a constant oop. // Oop is NULL, unless this is a constant oop.
ciObject* _const_oop; // Constant oop ciObject* _const_oop; // Constant oop
// If _klass is NULL, then so is _sig. This is an unloaded klass. // If _klass is NULL, then so is _sig. This is an unloaded klass.
...@@ -873,6 +882,11 @@ protected: ...@@ -873,6 +882,11 @@ protected:
// use it, then we have to emit a guard: this part of the type is // 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. // not something we know but something we speculate about the type.
const TypeOopPtr* _speculative; 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); static const TypeOopPtr* make_from_klass_common(ciKlass* klass, bool klass_change, bool try_for_exact);
...@@ -888,6 +902,12 @@ protected: ...@@ -888,6 +902,12 @@ protected:
#ifndef PRODUCT #ifndef PRODUCT
void dump_speculative(outputStream *st) const; void dump_speculative(outputStream *st) const;
#endif #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. // Do not allow interface-vs.-noninterface joins to collapse to top.
virtual const Type *filter_helper(const Type *kills, bool include_speculative) const; virtual const Type *filter_helper(const Type *kills, bool include_speculative) const;
...@@ -918,7 +938,7 @@ public: ...@@ -918,7 +938,7 @@ public:
bool not_null_elements = false); bool not_null_elements = false);
// Make a generic (unclassed) pointer to an oop. // 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; } ciObject* const_oop() const { return _const_oop; }
virtual ciKlass* klass() const { return _klass; } virtual ciKlass* klass() const { return _klass; }
...@@ -932,7 +952,7 @@ public: ...@@ -932,7 +952,7 @@ public:
bool is_known_instance() const { return _instance_id > 0; } bool is_known_instance() const { return _instance_id > 0; }
int instance_id() const { return _instance_id; } int instance_id() const { return _instance_id; }
bool is_known_instance_field() const { return is_known_instance() && _offset >= 0; } 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; virtual intptr_t get_con() const;
...@@ -970,13 +990,18 @@ public: ...@@ -970,13 +990,18 @@ public:
} }
return NULL; 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------------------------------------ //------------------------------TypeInstPtr------------------------------------
// Class of Java object pointers, pointing either to non-array Java instances // Class of Java object pointers, pointing either to non-array Java instances
// or to a Klass* (including array klasses). // or to a Klass* (including array klasses).
class TypeInstPtr : public TypeOopPtr { 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 bool eq( const Type *t ) const;
virtual int hash() const; // Type specific hashing virtual int hash() const; // Type specific hashing
...@@ -1012,7 +1037,7 @@ class TypeInstPtr : public TypeOopPtr { ...@@ -1012,7 +1037,7 @@ class TypeInstPtr : public TypeOopPtr {
} }
// Make a pointer to an oop. // 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 */ /** Create constant type for a constant boxed value */
const Type* get_const_boxed_value() const; const Type* get_const_boxed_value() const;
...@@ -1031,6 +1056,7 @@ class TypeInstPtr : public TypeOopPtr { ...@@ -1031,6 +1056,7 @@ class TypeInstPtr : public TypeOopPtr {
virtual const TypePtr *add_offset( intptr_t offset ) const; virtual const TypePtr *add_offset( intptr_t offset ) const;
// Return same type without a speculative part // Return same type without a speculative part
virtual const Type* remove_speculative() const; 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 // the core of the computation of the meet of 2 types
virtual const Type *xmeet_helper(const Type *t) const; virtual const Type *xmeet_helper(const Type *t) const;
...@@ -1052,8 +1078,8 @@ class TypeInstPtr : public TypeOopPtr { ...@@ -1052,8 +1078,8 @@ class TypeInstPtr : public TypeOopPtr {
// Class of Java array pointers // Class of Java array pointers
class TypeAryPtr : public TypeOopPtr { class TypeAryPtr : public TypeOopPtr {
TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk, TypeAryPtr( PTR ptr, ciObject* o, const TypeAry *ary, ciKlass* k, bool xk,
int offset, int instance_id, bool is_autobox_cache, const TypeOopPtr* 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), : TypeOopPtr(AryPtr,ptr,k,xk,o,offset, instance_id, speculative, inline_depth),
_ary(ary), _ary(ary),
_is_autobox_cache(is_autobox_cache) _is_autobox_cache(is_autobox_cache)
{ {
...@@ -1091,9 +1117,9 @@ public: ...@@ -1091,9 +1117,9 @@ public:
bool is_autobox_cache() const { return _is_autobox_cache; } 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 // 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 // Return a 'ptr' version of this type
virtual const Type *cast_to_ptr_type(PTR ptr) const; virtual const Type *cast_to_ptr_type(PTR ptr) const;
...@@ -1109,6 +1135,7 @@ public: ...@@ -1109,6 +1135,7 @@ public:
virtual const TypePtr *add_offset( intptr_t offset ) const; virtual const TypePtr *add_offset( intptr_t offset ) const;
// Return same type without a speculative part // Return same type without a speculative part
virtual const Type* remove_speculative() const; 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 // the core of the computation of the meet of 2 types
virtual const Type *xmeet_helper(const Type *t) const; 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.
先完成此消息的编辑!
想要评论请 注册