8056071: compiler/whitebox/IsMethodCompilableTest.java fails with 'method() is not compilable after 3 iterations'
authorthartmann
Tue, 11 Nov 2014 11:05:41 +0100
changeset 27643 fe8f95a2d9bc
parent 27642 8c9eff693145
child 27644 f4aa22a934e4
8056071: compiler/whitebox/IsMethodCompilableTest.java fails with 'method() is not compilable after 3 iterations' Summary: Always use MDO if valid and always compile trivial methods with C1 if available. Reviewed-by: kvn, iveresov
hotspot/src/share/vm/interpreter/bytecodes.hpp
hotspot/src/share/vm/oops/method.cpp
hotspot/src/share/vm/oops/method.hpp
hotspot/src/share/vm/oops/methodData.cpp
hotspot/src/share/vm/oops/methodData.hpp
hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp
hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp
hotspot/test/compiler/whitebox/IsMethodCompilableTest.java
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp	Mon Nov 10 19:04:38 2014 +0300
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp	Tue Nov 11 11:05:41 2014 +0100
@@ -401,8 +401,10 @@
   static bool        is_astore      (Code code)    { return (code == _astore || code == _astore_0 || code == _astore_1
                                                                              || code == _astore_2 || code == _astore_3); }
 
+  static bool        is_const       (Code code)    { return (_aconst_null <= code && code <= _ldc2_w); }
   static bool        is_zero_const  (Code code)    { return (code == _aconst_null || code == _iconst_0
                                                            || code == _fconst_0 || code == _dconst_0); }
+  static bool        is_return      (Code code)    { return (_ireturn <= code && code <= _return); }
   static bool        is_invoke      (Code code)    { return (_invokevirtual <= code && code <= _invokedynamic); }
   static bool        has_receiver   (Code code)    { assert(is_invoke(code), "");  return code == _invokevirtual ||
                                                                                           code == _invokespecial ||
--- a/hotspot/src/share/vm/oops/method.cpp	Mon Nov 10 19:04:38 2014 +0300
+++ b/hotspot/src/share/vm/oops/method.cpp	Tue Nov 11 11:05:41 2014 +0100
@@ -588,6 +588,15 @@
   return true;
 }
 
+bool Method::is_constant_getter() const {
+  int last_index = code_size() - 1;
+  // Check if the first 1-3 bytecodes are a constant push
+  // and the last bytecode is a return.
+  return (2 <= code_size() && code_size() <= 4 &&
+          Bytecodes::is_const(java_code_at(0)) &&
+          Bytecodes::length_for(java_code_at(0)) == last_index &&
+          Bytecodes::is_return(java_code_at(last_index)));
+}
 
 bool Method::is_initializer() const {
   return name() == vmSymbols::object_initializer_name() || is_static_initializer();
--- a/hotspot/src/share/vm/oops/method.hpp	Mon Nov 10 19:04:38 2014 +0300
+++ b/hotspot/src/share/vm/oops/method.hpp	Tue Nov 11 11:05:41 2014 +0100
@@ -595,6 +595,9 @@
   // returns true if the method is an accessor function (setter/getter).
   bool is_accessor() const;
 
+  // returns true if the method does nothing but return a constant of primitive type
+  bool is_constant_getter() const;
+
   // returns true if the method is an initializer (<init> or <clinit>).
   bool is_initializer() const;
 
--- a/hotspot/src/share/vm/oops/methodData.cpp	Mon Nov 10 19:04:38 2014 +0300
+++ b/hotspot/src/share/vm/oops/methodData.cpp	Tue Nov 11 11:05:41 2014 +0100
@@ -1134,7 +1134,7 @@
   _tenure_traps = 0;
   _num_loops = 0;
   _num_blocks = 0;
-  _would_profile = true;
+  _would_profile = unknown;
 
 #if INCLUDE_RTM_OPT
   _rtm_state = NoRTM; // No RTM lock eliding by default
--- a/hotspot/src/share/vm/oops/methodData.hpp	Mon Nov 10 19:04:38 2014 +0300
+++ b/hotspot/src/share/vm/oops/methodData.hpp	Tue Nov 11 11:05:41 2014 +0100
@@ -2096,7 +2096,8 @@
   short             _num_loops;
   short             _num_blocks;
   // Does this method contain anything worth profiling?
-  bool              _would_profile;
+  enum WouldProfile {unknown, no_profile, profile};
+  WouldProfile      _would_profile;
 
   // Size of _data array in bytes.  (Excludes header and extra_data fields.)
   int _data_size;
@@ -2270,8 +2271,8 @@
   }
 #endif
 
-  void set_would_profile(bool p)              { _would_profile = p;    }
-  bool would_profile() const                  { return _would_profile; }
+  void set_would_profile(bool p)              { _would_profile = p ? profile : no_profile; }
+  bool would_profile() const                  { return _would_profile != no_profile; }
 
   int num_loops() const                       { return _num_loops;  }
   void set_num_loops(int n)                   { _num_loops = n;     }
--- a/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Mon Nov 10 19:04:38 2014 +0300
+++ b/hotspot/src/share/vm/runtime/advancedThresholdPolicy.cpp	Tue Nov 11 11:05:41 2014 +0100
@@ -317,8 +317,8 @@
  * c. 0 -> (3->2) -> 4.
  *    In this case we enqueue a method for compilation at level 3, but the C1 queue is long enough
  *    to enable the profiling to fully occur at level 0. In this case we change the compilation level
- *    of the method to 2, because it'll allow it to run much faster without full profiling while c2
- *    is compiling.
+ *    of the method to 2 while the request is still in-queue, because it'll allow it to run much faster
+ *    without full profiling while c2 is compiling.
  *
  * d. 0 -> 3 -> 1 or 0 -> 2 -> 1.
  *    After a method was once compiled with C1 it can be identified as trivial and be compiled to
--- a/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Mon Nov 10 19:04:38 2014 +0300
+++ b/hotspot/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp	Tue Nov 11 11:05:41 2014 +0100
@@ -54,13 +54,17 @@
 // Simple methods are as good being compiled with C1 as C2.
 // Determine if a given method is such a case.
 bool SimpleThresholdPolicy::is_trivial(Method* method) {
-  if (method->is_accessor()) return true;
-  if (method->code() != NULL) {
-    MethodData* mdo = method->method_data();
-    if (mdo != NULL && mdo->num_loops() == 0 &&
-        (method->code_size() < 5  || (mdo->num_blocks() < 4) && (method->code_size() < 15))) {
-      return !mdo->would_profile();
-    }
+  if (method->is_accessor() ||
+      method->is_constant_getter()) {
+    return true;
+  }
+  if (method->has_loops() || method->code_size() >= 15) {
+    return false;
+  }
+  MethodData* mdo = method->method_data();
+  if (mdo != NULL && !mdo->would_profile() &&
+      (method->code_size() < 5  || (mdo->num_blocks() < 4))) {
+    return true;
   }
   return false;
 }
--- a/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java	Mon Nov 10 19:04:38 2014 +0300
+++ b/hotspot/test/compiler/whitebox/IsMethodCompilableTest.java	Tue Nov 11 11:05:41 2014 +0100
@@ -29,7 +29,7 @@
  * @run main ClassFileInstaller sun.hotspot.WhiteBox
  *                              sun.hotspot.WhiteBox$WhiteBoxPermission
  * @run main ClassFileInstaller com.oracle.java.testlibrary.Platform
- * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -Xmixed -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:PerMethodRecompilationCutoff=3 -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* IsMethodCompilableTest
+ * @run main/othervm/timeout=2400 -Xbootclasspath/a:. -Xmixed -XX:-TieredCompilation -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:PerMethodRecompilationCutoff=3 -XX:CompileCommand=compileonly,SimpleTestCase$Helper::* IsMethodCompilableTest
  * @summary testing of WB::isMethodCompilable()
  * @author igor.ignatyev@oracle.com
  */