7078382: JSR 292: don't count method handle adapters against inlining budgets
Reviewed-by: kvn, never
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Tue Aug 30 19:01:58 2011 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp Wed Aug 31 01:40:45 2011 -0700
@@ -3430,7 +3430,7 @@
} else {
if (inline_level() > MaxInlineLevel ) INLINE_BAILOUT("too-deep 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
if (callee->name() == ciSymbol::object_initializer_name() &&
--- a/hotspot/src/share/vm/ci/ciMethod.cpp Tue Aug 30 19:01:58 2011 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp Wed Aug 31 01:40:45 2011 -0700
@@ -1017,6 +1017,34 @@
}
// ------------------------------------------------------------------
+// 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
//
// This is a rough metric for "fat" methods, compared before inlining
--- a/hotspot/src/share/vm/ci/ciMethod.hpp Tue Aug 30 19:01:58 2011 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.hpp Wed Aug 31 01:40:45 2011 -0700
@@ -157,6 +157,9 @@
int interpreter_invocation_count() const { check_is_loaded(); return _interpreter_invocation_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 highest_osr_comp_level();
--- a/hotspot/src/share/vm/ci/ciStreams.hpp Tue Aug 30 19:01:58 2011 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.hpp Wed Aug 31 01:40:45 2011 -0700
@@ -129,7 +129,8 @@
// Return current ByteCode and increment PC to next bytecode, skipping all
// intermediate constants. Returns EOBC at end.
// Expected usage:
- // while( (bc = iter.next()) != EOBC() ) { ... }
+ // ciBytecodeStream iter(m);
+ // while (iter.next() != ciBytecodeStream::EOBC()) { ... }
Bytecodes::Code next() {
_bc_start = _pc; // Capture start of bc
if( _pc >= _end ) return EOBC(); // End-Of-Bytecodes
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp Tue Aug 30 19:01:58 2011 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp Wed Aug 31 01:40:45 2011 -0700
@@ -419,6 +419,8 @@
static bool is_zero_const (Code code) { return (code == _aconst_null || code == _iconst_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 flags (int code, bool is_wide) {
assert(code == (u_char)code, "must be a byte");
--- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp Tue Aug 30 19:01:58 2011 -0700
+++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp Wed Aug 31 01:40:45 2011 -0700
@@ -45,7 +45,7 @@
_method(callee),
_site_invoke_ratio(site_invoke_ratio),
_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;)
if (_caller_jvms != NULL) {
@@ -107,7 +107,7 @@
// positive filter: should send be inlined? returns NULL (--> yes)
// 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)
if(callee_method->interpreter_throwout_count() > InlineThrowCount &&
@@ -244,7 +244,7 @@
}
// 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
if (UseInterpreter && !CompileTheWorld) {
@@ -305,7 +305,7 @@
}
// 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
if (C->unique() > (uint)NodeCountInliningCutoff) {
@@ -349,7 +349,7 @@
}
}
- int size = callee_method->code_size();
+ int size = callee_method->code_size_for_inlining();
if (UseOldInlining && ClipInlining
&& (int)count_inline_bcs() + size >= DesiredMethodLimit) {