--- old/src/share/vm/oops/methodData.hpp 2014-11-10 08:14:22.283448952 +0100 +++ new/src/share/vm/oops/methodData.hpp 2014-11-10 08:14:22.103448960 +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; } --- old/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp 2014-11-10 08:14:22.231448954 +0100 +++ new/src/share/vm/runtime/simpleThresholdPolicy.inline.hpp 2014-11-10 08:14:22.087448961 +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; } --- old/src/share/vm/interpreter/bytecodes.hpp 2014-11-10 08:14:22.203448955 +0100 +++ new/src/share/vm/interpreter/bytecodes.hpp 2014-11-10 08:14:22.087448961 +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.hpp 2014-11-10 08:14:22.267448952 +0100 +++ new/src/share/vm/oops/method.hpp 2014-11-10 08:14:22.107448960 +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/test/compiler/whitebox/IsMethodCompilableTest.java 2014-11-10 08:14:22.267448952 +0100 +++ new/test/compiler/whitebox/IsMethodCompilableTest.java 2014-11-10 08:14:22.087448961 +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/method.cpp 2014-11-10 08:14:22.343448949 +0100 +++ new/src/share/vm/oops/method.cpp 2014-11-10 08:14:22.167448957 +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(); --- old/src/share/vm/runtime/advancedThresholdPolicy.cpp 2014-11-10 08:14:22.343448949 +0100 +++ new/src/share/vm/runtime/advancedThresholdPolicy.cpp 2014-11-10 08:14:22.127448959 +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/oops/methodData.cpp 2014-11-10 08:14:22.379448947 +0100 +++ new/src/share/vm/oops/methodData.cpp 2014-11-10 08:14:22.199448955 +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