diff options
author | never <none@none> | 2011-09-02 20:58:21 -0700 |
---|---|---|
committer | never <none@none> | 2011-09-02 20:58:21 -0700 |
commit | 9cc4c68d691c2267459454f044e604dd527038e6 (patch) | |
tree | ae459dfe73f89f30fc03be85f6c2007f1222d511 /src/share/vm/opto | |
parent | 06f7502a13c323f57fbc3a583b797ba63a7edfc0 (diff) |
7071307: MethodHandle bimorphic inlining should consider the frequency
Reviewed-by: twisti, roland, kvn, iveresov
Diffstat (limited to 'src/share/vm/opto')
-rw-r--r-- | src/share/vm/opto/bytecodeInfo.cpp | 16 | ||||
-rw-r--r-- | src/share/vm/opto/callGenerator.cpp | 28 | ||||
-rw-r--r-- | src/share/vm/opto/idealGraphPrinter.cpp | 23 | ||||
-rw-r--r-- | src/share/vm/opto/idealGraphPrinter.hpp | 4 | ||||
-rw-r--r-- | src/share/vm/opto/matcher.cpp | 3 |
5 files changed, 49 insertions, 25 deletions
diff --git a/src/share/vm/opto/bytecodeInfo.cpp b/src/share/vm/opto/bytecodeInfo.cpp index d21f6d04a..a29159686 100644 --- a/src/share/vm/opto/bytecodeInfo.cpp +++ b/src/share/vm/opto/bytecodeInfo.cpp @@ -141,7 +141,21 @@ const char* InlineTree::should_inline(ciMethod* callee_method, ciMethod* caller_ assert(mha_profile, "must exist"); CounterData* cd = mha_profile->as_CounterData(); invoke_count = cd->count(); - call_site_count = invoke_count; // use the same value + if (invoke_count == 0) { + return "method handle not reached"; + } + + if (_caller_jvms != NULL && _caller_jvms->method() != NULL && + _caller_jvms->method()->method_data() != NULL && + !_caller_jvms->method()->method_data()->is_empty()) { + ciMethodData* mdo = _caller_jvms->method()->method_data(); + ciProfileData* mha_profile = mdo->bci_to_data(_caller_jvms->bci()); + assert(mha_profile, "must exist"); + CounterData* cd = mha_profile->as_CounterData(); + call_site_count = cd->count(); + } else { + call_site_count = invoke_count; // use the same value + } } assert(invoke_count != 0, "require invocation count greater than zero"); diff --git a/src/share/vm/opto/callGenerator.cpp b/src/share/vm/opto/callGenerator.cpp index dc02770a9..150aa923d 100644 --- a/src/share/vm/opto/callGenerator.cpp +++ b/src/share/vm/opto/callGenerator.cpp @@ -149,7 +149,6 @@ JVMState* DirectCallGenerator::generate(JVMState* jvms) { call->set_optimized_virtual(true); if (method()->is_method_handle_invoke()) { call->set_method_handle_invoke(true); - kit.C->set_has_method_handle_invokes(true); } } kit.set_arguments_for_java_call(call); @@ -207,7 +206,6 @@ JVMState* DynamicCallGenerator::generate(JVMState* jvms) { call->set_optimized_virtual(true); // Take extra care (in the presence of argument motion) not to trash the SP: call->set_method_handle_invoke(true); - kit.C->set_has_method_handle_invokes(true); // Pass the target MethodHandle as first argument and shift the // other arguments. @@ -706,18 +704,30 @@ CallGenerator* CallGenerator::for_method_handle_inline(Node* method_handle, JVMS } } else if (method_handle->Opcode() == Op_Phi && method_handle->req() == 3 && method_handle->in(1)->Opcode() == Op_ConP && method_handle->in(2)->Opcode() == Op_ConP) { + float prob = PROB_FAIR; + Node* meth_region = method_handle->in(0); + if (meth_region->is_Region() && + meth_region->in(1)->is_Proj() && meth_region->in(2)->is_Proj() && + meth_region->in(1)->in(0) == meth_region->in(2)->in(0) && + meth_region->in(1)->in(0)->is_If()) { + // If diamond, so grab the probability of the test to drive the inlining below + prob = meth_region->in(1)->in(0)->as_If()->_prob; + if (meth_region->in(1)->is_IfTrue()) { + prob = 1 - prob; + } + } + // selectAlternative idiom merging two constant MethodHandles. // Generate a guard so that each can be inlined. We might want to // do more inputs at later point but this gets the most common // case. - const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); - ciObject* const_oop = oop_ptr->const_oop(); - ciMethodHandle* mh = const_oop->as_method_handle(); - - CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile); - CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile); + CallGenerator* cg1 = for_method_handle_inline(method_handle->in(1), jvms, caller, callee, profile.rescale(1.0 - prob)); + CallGenerator* cg2 = for_method_handle_inline(method_handle->in(2), jvms, caller, callee, profile.rescale(prob)); if (cg1 != NULL && cg2 != NULL) { - return new PredictedDynamicCallGenerator(mh, cg2, cg1, PROB_FAIR); + const TypeOopPtr* oop_ptr = method_handle->in(1)->bottom_type()->is_oopptr(); + ciObject* const_oop = oop_ptr->const_oop(); + ciMethodHandle* mh = const_oop->as_method_handle(); + return new PredictedDynamicCallGenerator(mh, cg2, cg1, prob); } } return NULL; diff --git a/src/share/vm/opto/idealGraphPrinter.cpp b/src/share/vm/opto/idealGraphPrinter.cpp index 74595348f..a5a0c6588 100644 --- a/src/share/vm/opto/idealGraphPrinter.cpp +++ b/src/share/vm/opto/idealGraphPrinter.cpp @@ -375,9 +375,9 @@ intptr_t IdealGraphPrinter::get_node_id(Node *n) { return (intptr_t)(n); } -void IdealGraphPrinter::visit_node(Node *n, void *param) { +void IdealGraphPrinter::visit_node(Node *n, bool edges, VectorSet* temp_set) { - if(param) { + if (edges) { // Output edge intptr_t dest_id = get_node_id(n); @@ -599,16 +599,11 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) { #ifdef ASSERT if (node->debug_orig() != NULL) { + temp_set->Clear(); stringStream dorigStream; Node* dorig = node->debug_orig(); - if (dorig) { + while (dorig && temp_set->test_set(dorig->_idx)) { dorigStream.print("%d ", dorig->_idx); - Node* first = dorig; - dorig = first->debug_orig(); - while (dorig && dorig != first) { - dorigStream.print("%d ", dorig->_idx); - dorig = dorig->debug_orig(); - } } print_prop("debug_orig", dorigStream.as_string()); } @@ -629,7 +624,7 @@ void IdealGraphPrinter::visit_node(Node *n, void *param) { } } -void IdealGraphPrinter::walk_nodes(Node *start, void *param) { +void IdealGraphPrinter::walk_nodes(Node *start, bool edges, VectorSet* temp_set) { VectorSet visited(Thread::current()->resource_area()); @@ -650,7 +645,7 @@ void IdealGraphPrinter::walk_nodes(Node *start, void *param) { while(nodeStack.length() > 0) { Node *n = nodeStack.pop(); - visit_node(n, param); + visit_node(n, edges, temp_set); if (_traverse_outs) { for (DUIterator i = n->outs(); n->has_out(i); i++) { @@ -689,12 +684,14 @@ void IdealGraphPrinter::print(Compile* compile, const char *name, Node *node, in print_attr(GRAPH_NAME_PROPERTY, (const char *)name); end_head(); + VectorSet temp_set(Thread::current()->resource_area()); + head(NODES_ELEMENT); - walk_nodes(node, NULL); + walk_nodes(node, false, &temp_set); tail(NODES_ELEMENT); head(EDGES_ELEMENT); - walk_nodes(node, (void *)1); + walk_nodes(node, true, &temp_set); tail(EDGES_ELEMENT); if (C->cfg() != NULL) { head(CONTROL_FLOW_ELEMENT); diff --git a/src/share/vm/opto/idealGraphPrinter.hpp b/src/share/vm/opto/idealGraphPrinter.hpp index 6115e6d38..7d1863f4a 100644 --- a/src/share/vm/opto/idealGraphPrinter.hpp +++ b/src/share/vm/opto/idealGraphPrinter.hpp @@ -104,8 +104,8 @@ private: void print_indent(); void print_method(ciMethod *method, int bci, InlineTree *tree); void print_inline_tree(InlineTree *tree); - void visit_node(Node *n, void *param); - void walk_nodes(Node *start, void *param); + void visit_node(Node *n, bool edges, VectorSet* temp_set); + void walk_nodes(Node *start, bool edges, VectorSet* temp_set); void begin_elem(const char *s); void end_elem(); void begin_head(const char *s); diff --git a/src/share/vm/opto/matcher.cpp b/src/share/vm/opto/matcher.cpp index 1faf3b908..4b16bbad2 100644 --- a/src/share/vm/opto/matcher.cpp +++ b/src/share/vm/opto/matcher.cpp @@ -1106,6 +1106,9 @@ MachNode *Matcher::match_sfpt( SafePointNode *sfpt ) { mcall_java->_optimized_virtual = call_java->is_optimized_virtual(); is_method_handle_invoke = call_java->is_method_handle_invoke(); mcall_java->_method_handle_invoke = is_method_handle_invoke; + if (is_method_handle_invoke) { + C->set_has_method_handle_invokes(true); + } if( mcall_java->is_MachCallStaticJava() ) mcall_java->as_MachCallStaticJava()->_name = call_java->as_CallStaticJava()->_name; |