aboutsummaryrefslogtreecommitdiff
path: root/src/share/vm/opto
diff options
context:
space:
mode:
authornever <none@none>2011-09-02 20:58:21 -0700
committernever <none@none>2011-09-02 20:58:21 -0700
commit9cc4c68d691c2267459454f044e604dd527038e6 (patch)
treeae459dfe73f89f30fc03be85f6c2007f1222d511 /src/share/vm/opto
parent06f7502a13c323f57fbc3a583b797ba63a7edfc0 (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.cpp16
-rw-r--r--src/share/vm/opto/callGenerator.cpp28
-rw-r--r--src/share/vm/opto/idealGraphPrinter.cpp23
-rw-r--r--src/share/vm/opto/idealGraphPrinter.hpp4
-rw-r--r--src/share/vm/opto/matcher.cpp3
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;