From b447fa3d2137ffc5d50b72ff25e19932b86b51c1 Mon Sep 17 00:00:00 2001 From: thartmann Date: Tue, 11 Nov 2014 11:05:41 +0100 Subject: [PATCH] 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 --- src/share/vm/interpreter/bytecodes.hpp | 2 ++ src/share/vm/oops/method.cpp | 9 +++++++++ src/share/vm/oops/method.hpp | 3 +++ src/share/vm/oops/methodData.cpp | 2 +- src/share/vm/oops/methodData.hpp | 7 ++++--- .../vm/runtime/advancedThresholdPolicy.cpp | 4 ++-- .../runtime/simpleThresholdPolicy.inline.hpp | 18 +++++++++++------- .../whitebox/IsMethodCompilableTest.java | 2 +- 8 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/share/vm/interpreter/bytecodes.hpp b/src/share/vm/interpreter/bytecodes.hpp index 707f210e8..a43033c07 100644 --- a/src/share/vm/interpreter/bytecodes.hpp +++ b/src/share/vm/interpreter/bytecodes.hpp @@ -420,8 +420,10 @@ class Bytecodes: AllStatic { 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 || diff --git a/src/share/vm/oops/method.cpp b/src/share/vm/oops/method.cpp index 58ab6e210..25fc780c0 100644 --- a/src/share/vm/oops/method.cpp +++ b/src/share/vm/oops/method.cpp @@ -558,6 +558,15 @@ bool Method::is_accessor() const { 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(); diff --git a/src/share/vm/oops/method.hpp b/src/share/vm/oops/method.hpp index 3bbff0b21..fb2af30ce 100644 --- a/src/share/vm/oops/method.hpp +++ b/src/share/vm/oops/method.hpp @@ -619,6 +619,9 @@ class Method : public Metadata { // 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 ( or ). bool is_initializer() const; diff --git a/src/share/vm/oops/methodData.cpp b/src/share/vm/oops/methodData.cpp index 16cd13478..f8ec09b26 100644 --- a/src/share/vm/oops/methodData.cpp +++ b/src/share/vm/oops/methodData.cpp @@ -1153,7 +1153,7 @@ void MethodData::init() { _backedge_counter_start = 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 diff --git a/src/share/vm/oops/methodData.hpp b/src/share/vm/oops/methodData.hpp index 7896c9785..dd4ca1fcb 100644 --- a/src/share/vm/oops/methodData.hpp +++ b/src/share/vm/oops/methodData.hpp @@ -2099,7 +2099,8 @@ private: 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; @@ -2268,8 +2269,8 @@ public: } #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; } diff --git a/src/share/vm/runtime/advancedThresholdPolicy.cpp b/src/share/vm/runtime/advancedThresholdPolicy.cpp index 01ad19686..a57c12ae2 100644 --- a/src/share/vm/runtime/advancedThresholdPolicy.cpp +++ b/src/share/vm/runtime/advancedThresholdPolicy.cpp @@ -316,8 +316,8 @@ void AdvancedThresholdPolicy::create_mdo(methodHandle mh, JavaThread* THREAD) { * 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 diff --git a/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp b/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp index 4917f766f..90052ad55 100644 --- a/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp +++ b/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp @@ -54,13 +54,17 @@ bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale) { // 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; } diff --git a/test/compiler/whitebox/IsMethodCompilableTest.java b/test/compiler/whitebox/IsMethodCompilableTest.java index c07848fef..da05d73b3 100644 --- a/test/compiler/whitebox/IsMethodCompilableTest.java +++ b/test/compiler/whitebox/IsMethodCompilableTest.java @@ -28,7 +28,7 @@ * @build IsMethodCompilableTest * @run main ClassFileInstaller sun.hotspot.WhiteBox * @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 */ -- GitLab