7042122: JSR 292: adjust various inline thresholds for JSR 292 API methods and method handle adapters
Reviewed-by: jrose, never, kvn
--- a/hotspot/src/share/vm/ci/ciMethodHandle.cpp Mon May 09 19:45:52 2011 -0700
+++ b/hotspot/src/share/vm/ci/ciMethodHandle.cpp Tue May 10 00:45:03 2011 -0700
@@ -42,7 +42,7 @@
methodHandle callee(_callee->get_methodOop());
// We catch all exceptions here that could happen in the method
// handle compiler and stop the VM.
- MethodHandleCompiler mhc(h, callee, is_invokedynamic, THREAD);
+ MethodHandleCompiler mhc(h, callee, call_profile()->count(), is_invokedynamic, THREAD);
if (!HAS_PENDING_EXCEPTION) {
methodHandle m = mhc.compile(THREAD);
if (!HAS_PENDING_EXCEPTION) {
--- a/hotspot/src/share/vm/ci/ciMethodHandle.hpp Mon May 09 19:45:52 2011 -0700
+++ b/hotspot/src/share/vm/ci/ciMethodHandle.hpp Tue May 10 00:45:03 2011 -0700
@@ -25,6 +25,7 @@
#ifndef SHARE_VM_CI_CIMETHODHANDLE_HPP
#define SHARE_VM_CI_CIMETHODHANDLE_HPP
+#include "ci/ciCallProfile.hpp"
#include "ci/ciInstance.hpp"
#include "prims/methodHandles.hpp"
@@ -33,7 +34,8 @@
// The class represents a java.lang.invoke.MethodHandle object.
class ciMethodHandle : public ciInstance {
private:
- ciMethod* _callee;
+ ciMethod* _callee;
+ ciCallProfile* _profile;
// Return an adapter for this MethodHandle.
ciMethod* get_adapter(bool is_invokedynamic) const;
@@ -50,6 +52,9 @@
ciMethod* callee() const { return _callee; }
void set_callee(ciMethod* m) { _callee = m; }
+ ciCallProfile* call_profile() const { return _profile; }
+ void set_call_profile(ciCallProfile* profile) { _profile = profile; }
+
// Return an adapter for a MethodHandle call.
ciMethod* get_method_handle_adapter() const {
return get_adapter(false);
--- a/hotspot/src/share/vm/opto/bytecodeInfo.cpp Mon May 09 19:45:52 2011 -0700
+++ b/hotspot/src/share/vm/opto/bytecodeInfo.cpp Tue May 10 00:45:03 2011 -0700
@@ -89,7 +89,7 @@
}
// positive filter: should send be inlined? returns NULL, if yes, or rejection msg
-const char* InlineTree::shouldInline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const {
+const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const {
// Allows targeted inlining
if(callee_method->should_inline()) {
*wci_result = *(WarmCallInfo::always_hot());
@@ -102,8 +102,7 @@
// positive filter: should send be inlined? returns NULL (--> yes)
// or rejection msg
- int max_size = C->max_inline_size();
- int size = callee_method->code_size();
+ int size = callee_method->code_size();
// Check for too many throws (and not too huge)
if(callee_method->interpreter_throwout_count() > InlineThrowCount &&
@@ -120,18 +119,36 @@
return NULL; // size and frequency are represented in a new way
}
+ int default_max_inline_size = C->max_inline_size();
+ int inline_small_code_size = InlineSmallCode / 4;
+ int max_inline_size = default_max_inline_size;
+
int call_site_count = method()->scale_count(profile.count());
int invoke_count = method()->interpreter_invocation_count();
- assert( invoke_count != 0, "Require invokation count greater than zero");
- int freq = call_site_count/invoke_count;
+
+ // Bytecoded method handle adapters do not have interpreter
+ // profiling data but only made up MDO data. Get the counter from
+ // there.
+ if (caller_method->is_method_handle_adapter()) {
+ assert(method()->method_data_or_null(), "must have an MDO");
+ ciMethodData* mdo = method()->method_data();
+ ciProfileData* mha_profile = mdo->bci_to_data(caller_bci);
+ assert(mha_profile, "must exist");
+ CounterData* cd = mha_profile->as_CounterData();
+ invoke_count = cd->count();
+ call_site_count = invoke_count; // use the same value
+ }
+
+ assert(invoke_count != 0, "require invocation count greater than zero");
+ int freq = call_site_count / invoke_count;
// bump the max size if the call is frequent
if ((freq >= InlineFrequencyRatio) ||
(call_site_count >= InlineFrequencyCount) ||
is_init_with_ea(callee_method, caller_method, C)) {
- max_size = C->freq_inline_size();
- if (size <= max_size && TraceFrequencyInlining) {
+ max_inline_size = C->freq_inline_size();
+ if (size <= max_inline_size && TraceFrequencyInlining) {
CompileTask::print_inline_indent(inline_depth());
tty->print_cr("Inlined frequent method (freq=%d count=%d):", freq, call_site_count);
CompileTask::print_inline_indent(inline_depth());
@@ -141,11 +158,11 @@
} else {
// Not hot. Check for medium-sized pre-existing nmethod at cold sites.
if (callee_method->has_compiled_code() &&
- callee_method->instructions_size(CompLevel_full_optimization) > InlineSmallCode/4)
+ callee_method->instructions_size(CompLevel_full_optimization) > inline_small_code_size)
return "already compiled into a medium method";
}
- if (size > max_size) {
- if (max_size > C->max_inline_size())
+ if (size > max_inline_size) {
+ if (max_inline_size > default_max_inline_size)
return "hot method too big";
return "too big";
}
@@ -154,7 +171,7 @@
// negative filter: should send NOT be inlined? returns NULL, ok to inline, or rejection msg
-const char* InlineTree::shouldNotInline(ciMethod *callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const {
+const char* InlineTree::should_not_inline(ciMethod *callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const {
// negative filter: should send NOT be inlined? returns NULL (--> inline) or rejection msg
if (!UseOldInlining) {
const char* fail = NULL;
@@ -269,14 +286,13 @@
}
const char *msg = NULL;
- if ((msg = shouldInline(callee_method, caller_method, caller_bci,
- profile, wci_result)) != NULL) {
+ msg = should_inline(callee_method, caller_method, caller_bci, profile, wci_result);
+ if (msg != NULL)
return msg;
- }
- if ((msg = shouldNotInline(callee_method, caller_method,
- wci_result)) != NULL) {
+
+ msg = should_not_inline(callee_method, caller_method, wci_result);
+ if (msg != NULL)
return msg;
- }
if (InlineAccessors && callee_method->is_accessor()) {
// accessor methods are not subject to any of the following limits.
@@ -492,9 +508,8 @@
new_depth_adjust -= 1; // don't count method handle calls from java.lang.invoke implem
}
if (new_depth_adjust != 0 && PrintInlining) {
- stringStream nm1; caller_jvms->method()->print_name(&nm1);
- stringStream nm2; callee_method->print_name(&nm2);
- tty->print_cr("discounting inlining depth from %s to %s", nm1.base(), nm2.base());
+ CompileTask::print_inline_indent(inline_depth());
+ tty->print_cr(" \\-> discounting inline depth");
}
if (new_depth_adjust != 0 && C->log()) {
int id1 = C->log()->identify(caller_jvms->method());
--- a/hotspot/src/share/vm/opto/doCall.cpp Mon May 09 19:45:52 2011 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp Tue May 10 00:45:03 2011 -0700
@@ -73,7 +73,8 @@
// Note: When we get profiling during stage-1 compiles, we want to pull
// from more specific profile data which pertains to this inlining.
// Right now, ignore the information in jvms->caller(), and do method[bci].
- ciCallProfile profile = jvms->method()->call_profile_at_bci(jvms->bci());
+ ciCallProfile profile = jvms->method()->call_profile_at_bci(jvms->bci());
+ Bytecodes::Code bytecode = jvms->method()->java_code_at_bci(jvms->bci());
// See how many times this site has been invoked.
int site_count = profile.count();
@@ -116,7 +117,7 @@
// MethodHandle.invoke* are native methods which obviously don't
// have bytecodes and so normal inlining fails.
if (call_method->is_method_handle_invoke()) {
- if (jvms->method()->java_code_at_bci(jvms->bci()) != Bytecodes::_invokedynamic) {
+ if (bytecode != Bytecodes::_invokedynamic) {
GraphKit kit(jvms);
Node* n = kit.argument(0);
@@ -128,14 +129,15 @@
// Set the actually called method to have access to the class
// and signature in the MethodHandleCompiler.
method_handle->set_callee(call_method);
+ method_handle->set_call_profile(&profile);
// Get an adapter for the MethodHandle.
ciMethod* target_method = method_handle->get_method_handle_adapter();
- CallGenerator* hit_cg = NULL;
- if (target_method != NULL)
- hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
- if (hit_cg != NULL && hit_cg->is_inline())
- return hit_cg;
+ if (target_method != NULL) {
+ CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
+ if (hit_cg != NULL && hit_cg->is_inline())
+ return hit_cg;
+ }
}
return CallGenerator::for_direct_call(call_method);
@@ -151,15 +153,16 @@
// Set the actually called method to have access to the class
// and signature in the MethodHandleCompiler.
method_handle->set_callee(call_method);
+ method_handle->set_call_profile(&profile);
// Get an adapter for the MethodHandle.
ciMethod* target_method = method_handle->get_invokedynamic_adapter();
- CallGenerator* hit_cg = NULL;
- if (target_method != NULL)
- hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
- if (hit_cg != NULL && hit_cg->is_inline()) {
- CallGenerator* miss_cg = CallGenerator::for_dynamic_call(call_method);
- return CallGenerator::for_predicted_dynamic_call(method_handle, miss_cg, hit_cg, prof_factor);
+ if (target_method != NULL) {
+ CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
+ if (hit_cg != NULL && hit_cg->is_inline()) {
+ CallGenerator* miss_cg = CallGenerator::for_dynamic_call(call_method);
+ return CallGenerator::for_predicted_dynamic_call(method_handle, miss_cg, hit_cg, prof_factor);
+ }
}
// If something failed, generate a normal dynamic call.
--- a/hotspot/src/share/vm/opto/parse.hpp Mon May 09 19:45:52 2011 -0700
+++ b/hotspot/src/share/vm/opto/parse.hpp Tue May 10 00:45:03 2011 -0700
@@ -68,8 +68,8 @@
JVMState* caller_jvms,
int caller_bci);
const char* try_to_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result);
- const char* shouldInline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const;
- const char* shouldNotInline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const;
+ const char* should_inline(ciMethod* callee_method, ciMethod* caller_method, int caller_bci, ciCallProfile& profile, WarmCallInfo* wci_result) const;
+ const char* should_not_inline(ciMethod* callee_method, ciMethod* caller_method, WarmCallInfo* wci_result) const;
void print_inlining(ciMethod *callee_method, int caller_bci, const char *failure_msg) const;
InlineTree *caller_tree() const { return _caller_tree; }
--- a/hotspot/src/share/vm/prims/methodHandleWalk.cpp Mon May 09 19:45:52 2011 -0700
+++ b/hotspot/src/share/vm/prims/methodHandleWalk.cpp Tue May 10 00:45:03 2011 -0700
@@ -616,9 +616,10 @@
// -----------------------------------------------------------------------------
// MethodHandleCompiler
-MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, bool is_invokedynamic, TRAPS)
+MethodHandleCompiler::MethodHandleCompiler(Handle root, methodHandle callee, int invoke_count, bool is_invokedynamic, TRAPS)
: MethodHandleWalker(root, is_invokedynamic, THREAD),
_callee(callee),
+ _invoke_count(invoke_count),
_thread(THREAD),
_bytecode(THREAD, 50),
_constants(THREAD, 10),
@@ -1182,7 +1183,7 @@
methodHandle MethodHandleCompiler::get_method_oop(TRAPS) const {
- methodHandle nullHandle;
+ methodHandle empty;
// Create a method that holds the generated bytecode. invokedynamic
// has no receiver, normal MH calls do.
int flags_bits;
@@ -1191,13 +1192,16 @@
else
flags_bits = (/*JVM_MH_INVOKE_BITS |*/ JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_SYNTHETIC);
- methodOop m_oop = oopFactory::new_method(bytecode_length(),
- accessFlags_from(flags_bits),
- 0, 0, 0, oopDesc::IsSafeConc, CHECK_(nullHandle));
- methodHandle m(THREAD, m_oop);
- m_oop = NULL; // oop not GC safe
+ // Create a new method
+ methodHandle m;
+ {
+ methodOop m_oop = oopFactory::new_method(bytecode_length(),
+ accessFlags_from(flags_bits),
+ 0, 0, 0, oopDesc::IsSafeConc, CHECK_(empty));
+ m = methodHandle(THREAD, m_oop);
+ }
- constantPoolHandle cpool = get_constant_pool(CHECK_(nullHandle));
+ constantPoolHandle cpool = get_constant_pool(CHECK_(empty));
m->set_constants(cpool());
m->set_name_index(_name_index);
@@ -1212,16 +1216,32 @@
typeArrayHandle exception_handlers(THREAD, Universe::the_empty_int_array());
m->set_exception_table(exception_handlers());
- // Set the carry bit of the invocation counter to force inlining of
- // the adapter.
+ // Set the invocation counter's count to the invoke count of the
+ // original call site.
InvocationCounter* ic = m->invocation_counter();
- ic->set_carry_flag();
+ ic->set(InvocationCounter::wait_for_compile, _invoke_count);
// Rewrite the method and set up the constant pool cache.
- objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(nullHandle));
+ objArrayOop m_array = oopFactory::new_system_objArray(1, CHECK_(empty));
objArrayHandle methods(THREAD, m_array);
methods->obj_at_put(0, m());
- Rewriter::rewrite(_target_klass(), cpool, methods, CHECK_(nullHandle)); // Use fake class.
+ Rewriter::rewrite(_target_klass(), cpool, methods, CHECK_(empty)); // Use fake class.
+
+ // Create a new MDO
+ {
+ methodDataOop mdo = oopFactory::new_methodData(m, CHECK_(empty));
+ assert(m->method_data() == NULL, "there should not be an MDO yet");
+ m->set_method_data(mdo);
+
+ // Iterate over all profile data and set the count of the counter
+ // data entries to the original call site counter.
+ for (ProfileData* pd = mdo->first_data(); mdo->is_valid(pd); pd = mdo->next_data(pd)) {
+ if (pd->is_CounterData()) {
+ CounterData* cd = pd->as_CounterData();
+ cd->set_count(_invoke_count);
+ }
+ }
+ }
#ifndef PRODUCT
if (TraceMethodHandles) {
--- a/hotspot/src/share/vm/prims/methodHandleWalk.hpp Mon May 09 19:45:52 2011 -0700
+++ b/hotspot/src/share/vm/prims/methodHandleWalk.hpp Tue May 10 00:45:03 2011 -0700
@@ -247,6 +247,7 @@
class MethodHandleCompiler : public MethodHandleWalker {
private:
methodHandle _callee;
+ int _invoke_count; // count the original call site has been executed
KlassHandle _rklass; // Return type for casting.
BasicType _rtype;
KlassHandle _target_klass;
@@ -416,7 +417,7 @@
methodHandle get_method_oop(TRAPS) const;
public:
- MethodHandleCompiler(Handle root, methodHandle call_method, bool for_invokedynamic, TRAPS);
+ MethodHandleCompiler(Handle root, methodHandle call_method, int invoke_count, bool for_invokedynamic, TRAPS);
// Compile the given MH chain into bytecode.
methodHandle compile(TRAPS);