--- old/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp 2014-11-05 11:50:16.144334245 +0100 +++ new/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp 2014-11-05 11:50:15.988334241 +0100 @@ -54,13 +54,14 @@ // 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))) { + if (method->is_accessor() || + method->is_constant_getter()) { + return true; + } + MethodData* mdo = method->method_data(); + if (mdo != NULL && mdo->stats_valid() && mdo->num_loops() == 0 && + (method->code_size() < 5 || ((mdo->num_blocks() < 4) && (method->code_size() < 15)))) { return !mdo->would_profile(); - } } return false; } --- old/src/share/vm/oops/method.hpp 2014-11-05 11:50:16.164334246 +0100 +++ new/src/share/vm/oops/method.hpp 2014-11-05 11:50:15.964334240 +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 ( or ). bool is_initializer() const; --- old/src/share/vm/runtime/advancedThresholdPolicy.cpp 2014-11-05 11:50:16.192334247 +0100 +++ new/src/share/vm/runtime/advancedThresholdPolicy.cpp 2014-11-05 11:50:15.964334240 +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 --- old/src/share/vm/ci/ciMethodData.cpp 2014-11-05 11:50:16.204334247 +0100 +++ new/src/share/vm/ci/ciMethodData.cpp 2014-11-05 11:50:15.920334239 +0100 @@ -393,6 +393,7 @@ if (mdo != NULL) { mdo->set_num_loops(loops); mdo->set_num_blocks(blocks); + mdo->set_stats_valid(true); } } --- old/test/compiler/whitebox/IsMethodCompilableTest.java 2014-11-05 11:50:16.276334249 +0100 +++ new/test/compiler/whitebox/IsMethodCompilableTest.java 2014-11-05 11:50:16.136334245 +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 */ --- old/src/share/vm/oops/methodData.cpp 2014-11-05 11:50:16.304334250 +0100 +++ new/src/share/vm/oops/methodData.cpp 2014-11-05 11:50:16.076334243 +0100 @@ -1134,6 +1134,7 @@ _tenure_traps = 0; _num_loops = 0; _num_blocks = 0; + _stats_valid = false; _would_profile = true; #if INCLUDE_RTM_OPT --- old/src/share/vm/oops/methodData.hpp 2014-11-05 11:50:16.288334250 +0100 +++ new/src/share/vm/oops/methodData.hpp 2014-11-05 11:50:16.076334243 +0100 @@ -2095,6 +2095,7 @@ // time with C1. It is used to determine if method is trivial. short _num_loops; short _num_blocks; + bool _stats_valid; // determines if above values are set // Does this method contain anything worth profiling? bool _would_profile; @@ -2277,6 +2278,8 @@ void set_num_loops(int n) { _num_loops = n; } int num_blocks() const { return _num_blocks; } void set_num_blocks(int n) { _num_blocks = n; } + bool stats_valid() const { return _stats_valid; } + void set_stats_valid(bool valid) { _stats_valid = valid; } bool is_mature() const; // consult mileage and ProfileMaturityPercentage static int mileage_of(Method* m); --- old/src/share/vm/interpreter/bytecodes.hpp 2014-11-05 11:50:16.308334250 +0100 +++ new/src/share/vm/interpreter/bytecodes.hpp 2014-11-05 11:50:16.000334241 +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 || --- old/src/share/vm/oops/method.cpp 2014-11-05 11:50:16.340334251 +0100 +++ new/src/share/vm/oops/method.cpp 2014-11-05 11:50:16.184334247 +0100 @@ -565,6 +565,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();