提交 b447fa3d 编写于 作者: T thartmann

8056071: compiler/whitebox/IsMethodCompilableTest.java fails with 'method() is...

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
上级 7d9ef496
...@@ -420,8 +420,10 @@ class Bytecodes: AllStatic { ...@@ -420,8 +420,10 @@ class Bytecodes: AllStatic {
static bool is_astore (Code code) { return (code == _astore || code == _astore_0 || code == _astore_1 static bool is_astore (Code code) { return (code == _astore || code == _astore_0 || code == _astore_1
|| code == _astore_2 || code == _astore_3); } || 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 static bool is_zero_const (Code code) { return (code == _aconst_null || code == _iconst_0
|| code == _fconst_0 || code == _dconst_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 is_invoke (Code code) { return (_invokevirtual <= code && code <= _invokedynamic); }
static bool has_receiver (Code code) { assert(is_invoke(code), ""); return code == _invokevirtual || static bool has_receiver (Code code) { assert(is_invoke(code), ""); return code == _invokevirtual ||
code == _invokespecial || code == _invokespecial ||
......
...@@ -558,6 +558,15 @@ bool Method::is_accessor() const { ...@@ -558,6 +558,15 @@ bool Method::is_accessor() const {
return true; 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 { bool Method::is_initializer() const {
return name() == vmSymbols::object_initializer_name() || is_static_initializer(); return name() == vmSymbols::object_initializer_name() || is_static_initializer();
......
...@@ -619,6 +619,9 @@ class Method : public Metadata { ...@@ -619,6 +619,9 @@ class Method : public Metadata {
// returns true if the method is an accessor function (setter/getter). // returns true if the method is an accessor function (setter/getter).
bool is_accessor() const; 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>). // returns true if the method is an initializer (<init> or <clinit>).
bool is_initializer() const; bool is_initializer() const;
......
...@@ -1153,7 +1153,7 @@ void MethodData::init() { ...@@ -1153,7 +1153,7 @@ void MethodData::init() {
_backedge_counter_start = 0; _backedge_counter_start = 0;
_num_loops = 0; _num_loops = 0;
_num_blocks = 0; _num_blocks = 0;
_would_profile = true; _would_profile = unknown;
#if INCLUDE_RTM_OPT #if INCLUDE_RTM_OPT
_rtm_state = NoRTM; // No RTM lock eliding by default _rtm_state = NoRTM; // No RTM lock eliding by default
......
...@@ -2099,7 +2099,8 @@ private: ...@@ -2099,7 +2099,8 @@ private:
short _num_loops; short _num_loops;
short _num_blocks; short _num_blocks;
// Does this method contain anything worth profiling? // 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.) // Size of _data array in bytes. (Excludes header and extra_data fields.)
int _data_size; int _data_size;
...@@ -2268,8 +2269,8 @@ public: ...@@ -2268,8 +2269,8 @@ public:
} }
#endif #endif
void set_would_profile(bool p) { _would_profile = p; } void set_would_profile(bool p) { _would_profile = p ? profile : no_profile; }
bool would_profile() const { return _would_profile; } bool would_profile() const { return _would_profile != no_profile; }
int num_loops() const { return _num_loops; } int num_loops() const { return _num_loops; }
void set_num_loops(int n) { _num_loops = n; } void set_num_loops(int n) { _num_loops = n; }
......
...@@ -316,8 +316,8 @@ void AdvancedThresholdPolicy::create_mdo(methodHandle mh, JavaThread* THREAD) { ...@@ -316,8 +316,8 @@ void AdvancedThresholdPolicy::create_mdo(methodHandle mh, JavaThread* THREAD) {
* c. 0 -> (3->2) -> 4. * c. 0 -> (3->2) -> 4.
* In this case we enqueue a method for compilation at level 3, but the C1 queue is long enough * 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 * 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 * of the method to 2 while the request is still in-queue, because it'll allow it to run much faster
* is compiling. * without full profiling while c2 is compiling.
* *
* d. 0 -> 3 -> 1 or 0 -> 2 -> 1. * 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 * After a method was once compiled with C1 it can be identified as trivial and be compiled to
......
...@@ -54,13 +54,17 @@ bool SimpleThresholdPolicy::loop_predicate_helper(int i, int b, double scale) { ...@@ -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. // Simple methods are as good being compiled with C1 as C2.
// Determine if a given method is such a case. // Determine if a given method is such a case.
bool SimpleThresholdPolicy::is_trivial(Method* method) { bool SimpleThresholdPolicy::is_trivial(Method* method) {
if (method->is_accessor()) return true; if (method->is_accessor() ||
if (method->code() != NULL) { method->is_constant_getter()) {
MethodData* mdo = method->method_data(); return true;
if (mdo != NULL && mdo->num_loops() == 0 && }
(method->code_size() < 5 || (mdo->num_blocks() < 4) && (method->code_size() < 15))) { if (method->has_loops() || method->code_size() >= 15) {
return !mdo->would_profile(); 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; return false;
} }
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
* @build IsMethodCompilableTest * @build IsMethodCompilableTest
* @run main ClassFileInstaller sun.hotspot.WhiteBox * @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main ClassFileInstaller com.oracle.java.testlibrary.Platform * @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() * @summary testing of WB::isMethodCompilable()
* @author igor.ignatyev@oracle.com * @author igor.ignatyev@oracle.com
*/ */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册