changeset 2731:de847cac9235

7078382: JSR 292: don't count method handle adapters against inlining budgets Reviewed-by: kvn, never
author twisti
date Wed, 31 Aug 2011 01:40:45 -0700
parents b346f13112d8
children a64d352d1118
files src/share/vm/c1/c1_GraphBuilder.cpp src/share/vm/ci/ciMethod.cpp src/share/vm/ci/ciMethod.hpp src/share/vm/ci/ciStreams.hpp src/share/vm/interpreter/bytecodes.hpp src/share/vm/opto/bytecodeInfo.cpp
diffstat 6 files changed, 41 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Aug 30 19:01:58 2011 -0700
+++ b/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/src/share/vm/ci/ciMethod.cpp	Tue Aug 30 19:01:58 2011 -0700
+++ b/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/src/share/vm/ci/ciMethod.hpp	Tue Aug 30 19:01:58 2011 -0700
+++ b/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/src/share/vm/ci/ciStreams.hpp	Tue Aug 30 19:01:58 2011 -0700
+++ b/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/src/share/vm/interpreter/bytecodes.hpp	Tue Aug 30 19:01:58 2011 -0700
+++ b/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/src/share/vm/opto/bytecodeInfo.cpp	Tue Aug 30 19:01:58 2011 -0700
+++ b/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) {