提交 2a0e5163 编写于 作者: T twisti

7078382: JSR 292: don't count method handle adapters against inlining budgets

Reviewed-by: kvn, never
上级 1d3045c9
...@@ -3430,7 +3430,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) { ...@@ -3430,7 +3430,7 @@ bool GraphBuilder::try_inline_full(ciMethod* callee, bool holder_known) {
} else { } else {
if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("too-deep inlining"); if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("too-deep inlining");
if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("too-deep recursive inlining"); if (recursive_inline_level(callee) > MaxRecursiveInlineLevel) INLINE_BAILOUT("too-deep recursive inlining");
if (callee->code_size() > max_inline_size() ) INLINE_BAILOUT("callee is too large"); if (callee->code_size_for_inlining() > max_inline_size() ) INLINE_BAILOUT("callee is too large");
// don't inline throwable methods unless the inlining tree is rooted in a throwable class // don't inline throwable methods unless the inlining tree is rooted in a throwable class
if (callee->name() == ciSymbol::object_initializer_name() && if (callee->name() == ciSymbol::object_initializer_name() &&
......
...@@ -1016,6 +1016,34 @@ int ciMethod::highest_osr_comp_level() { ...@@ -1016,6 +1016,34 @@ int ciMethod::highest_osr_comp_level() {
return get_methodOop()->highest_osr_comp_level(); return get_methodOop()->highest_osr_comp_level();
} }
// ------------------------------------------------------------------
// ciMethod::code_size_for_inlining
//
// Code size for inlining decisions.
//
// Don't fully count method handle adapters against inlining budgets:
// the metric we use here is the number of call sites in the adapter
// as they are probably the instructions which generate some code.
int ciMethod::code_size_for_inlining() {
check_is_loaded();
// Method handle adapters
if (is_method_handle_adapter()) {
// Count call sites
int call_site_count = 0;
ciBytecodeStream iter(this);
while (iter.next() != ciBytecodeStream::EOBC()) {
if (Bytecodes::is_invoke(iter.cur_bc())) {
call_site_count++;
}
}
return call_site_count;
}
// Normal method
return code_size();
}
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// ciMethod::instructions_size // ciMethod::instructions_size
// //
......
...@@ -157,6 +157,9 @@ class ciMethod : public ciObject { ...@@ -157,6 +157,9 @@ class ciMethod : public ciObject {
int interpreter_invocation_count() const { check_is_loaded(); return _interpreter_invocation_count; } int interpreter_invocation_count() const { check_is_loaded(); return _interpreter_invocation_count; }
int interpreter_throwout_count() const { check_is_loaded(); return _interpreter_throwout_count; } int interpreter_throwout_count() const { check_is_loaded(); return _interpreter_throwout_count; }
// Code size for inlining decisions.
int code_size_for_inlining();
int comp_level(); int comp_level();
int highest_osr_comp_level(); int highest_osr_comp_level();
......
...@@ -129,7 +129,8 @@ public: ...@@ -129,7 +129,8 @@ public:
// Return current ByteCode and increment PC to next bytecode, skipping all // Return current ByteCode and increment PC to next bytecode, skipping all
// intermediate constants. Returns EOBC at end. // intermediate constants. Returns EOBC at end.
// Expected usage: // Expected usage:
// while( (bc = iter.next()) != EOBC() ) { ... } // ciBytecodeStream iter(m);
// while (iter.next() != ciBytecodeStream::EOBC()) { ... }
Bytecodes::Code next() { Bytecodes::Code next() {
_bc_start = _pc; // Capture start of bc _bc_start = _pc; // Capture start of bc
if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes
......
...@@ -419,6 +419,8 @@ class Bytecodes: AllStatic { ...@@ -419,6 +419,8 @@ class Bytecodes: AllStatic {
static bool is_zero_const (Code code) { return (code == _aconst_null || code == _iconst_0 static bool is_zero_const (Code code) { return (code == _aconst_null || code == _iconst_0
|| code == _fconst_0 || code == _dconst_0); } || code == _fconst_0 || code == _dconst_0); }
static bool is_invoke (Code code) { return (_invokevirtual <= code && code <= _invokedynamic); }
static int compute_flags (const char* format, int more_flags = 0); // compute the flags static int compute_flags (const char* format, int more_flags = 0); // compute the flags
static int flags (int code, bool is_wide) { static int flags (int code, bool is_wide) {
assert(code == (u_char)code, "must be a byte"); assert(code == (u_char)code, "must be a byte");
......
...@@ -45,7 +45,7 @@ InlineTree::InlineTree(Compile* c, ...@@ -45,7 +45,7 @@ InlineTree::InlineTree(Compile* c,
_method(callee), _method(callee),
_site_invoke_ratio(site_invoke_ratio), _site_invoke_ratio(site_invoke_ratio),
_max_inline_level(max_inline_level), _max_inline_level(max_inline_level),
_count_inline_bcs(method()->code_size()) _count_inline_bcs(method()->code_size_for_inlining())
{ {
NOT_PRODUCT(_count_inlines = 0;) NOT_PRODUCT(_count_inlines = 0;)
if (_caller_jvms != NULL) { if (_caller_jvms != NULL) {
...@@ -107,7 +107,7 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_ ...@@ -107,7 +107,7 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_
// positive filter: should send be inlined? returns NULL (--> yes) // positive filter: should send be inlined? returns NULL (--> yes)
// or rejection msg // or rejection msg
int size = callee_method->code_size(); int size = callee_method->code_size_for_inlining();
// Check for too many throws (and not too huge) // Check for too many throws (and not too huge)
if(callee_method->interpreter_throwout_count() > InlineThrowCount && if(callee_method->interpreter_throwout_count() > InlineThrowCount &&
...@@ -244,7 +244,7 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal ...@@ -244,7 +244,7 @@ const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* cal
} }
// use frequency-based objections only for non-trivial methods // use frequency-based objections only for non-trivial methods
if (callee_method->code_size() <= MaxTrivialSize) return NULL; if (callee_method->code_size_for_inlining() <= MaxTrivialSize) return NULL;
// don't use counts with -Xcomp or CTW // don't use counts with -Xcomp or CTW
if (UseInterpreter && !CompileTheWorld) { if (UseInterpreter && !CompileTheWorld) {
...@@ -305,7 +305,7 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_ ...@@ -305,7 +305,7 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
} }
// suppress a few checks for accessors and trivial methods // suppress a few checks for accessors and trivial methods
if (callee_method->code_size() > MaxTrivialSize) { if (callee_method->code_size_for_inlining() > MaxTrivialSize) {
// don't inline into giant methods // don't inline into giant methods
if (C->unique() > (uint)NodeCountInliningCutoff) { if (C->unique() > (uint)NodeCountInliningCutoff) {
...@@ -349,7 +349,7 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_ ...@@ -349,7 +349,7 @@ const char* InlineTree::try_to_inline(ciMethod* callee_method, ciMethod* caller_
} }
} }
int size = callee_method->code_size(); int size = callee_method->code_size_for_inlining();
if (UseOldInlining && ClipInlining if (UseOldInlining && ClipInlining
&& (int)count_inline_bcs() + size >= DesiredMethodLimit) { && (int)count_inline_bcs() + size >= DesiredMethodLimit) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册