hotspot/src/share/vm/opto/callGenerator.cpp
changeset 35086 bbf32241d851
parent 33589 7cbd1b2c139b
child 35846 f5a8b47778ef
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Fri Dec 04 16:38:04 2015 +0100
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Fri Dec 04 23:46:19 2015 +0300
@@ -46,6 +46,11 @@
   return TypeFunc::make(method());
 }
 
+bool CallGenerator::is_inlined_mh_linker(JVMState* jvms, ciMethod* callee) {
+  ciMethod* symbolic_info = jvms->method()->get_method_at_bci(jvms->bci());
+  return symbolic_info->is_method_handle_intrinsic() && !callee->is_method_handle_intrinsic();
+}
+
 //-----------------------------ParseGenerator---------------------------------
 // Internal class which handles all direct bytecode traversal.
 class ParseGenerator : public InlineCallGenerator {
@@ -137,6 +142,13 @@
   }
 
   CallStaticJavaNode *call = new CallStaticJavaNode(kit.C, tf(), target, method(), kit.bci());
+  if (is_inlined_mh_linker(jvms, method())) {
+    // To be able to issue a direct call and skip a call to MH.linkTo*/invokeBasic adapter,
+    // additional information about the method being invoked should be attached
+    // to the call site to make resolution logic work
+    // (see SharedRuntime::resolve_static_call_C).
+    call->set_override_symbolic_info(true);
+  }
   _call_node = call;  // Save the call node in case we need it later
   if (!is_static) {
     // Make an explicit receiver null_check as part of this call.
@@ -192,7 +204,10 @@
   // the call instruction will have a seemingly deficient out-count.
   // (The bailout says something misleading about an "infinite loop".)
   if (kit.gvn().type(receiver)->higher_equal(TypePtr::NULL_PTR)) {
-    kit.inc_sp(method()->arg_size());  // restore arguments
+    assert(Bytecodes::is_invoke(kit.java_bc()), "%d: %s", kit.java_bc(), Bytecodes::name(kit.java_bc()));
+    ciMethod* declared_method = kit.method()->get_method_at_bci(kit.bci());
+    int arg_size = declared_method->signature()->arg_size_for_bc(kit.java_bc());
+    kit.inc_sp(arg_size);  // restore arguments
     kit.uncommon_trap(Deoptimization::Reason_null_check,
                       Deoptimization::Action_none,
                       NULL, "null receiver");
@@ -226,6 +241,13 @@
   address target = SharedRuntime::get_resolve_virtual_call_stub();
   // Normal inline cache used for call
   CallDynamicJavaNode *call = new CallDynamicJavaNode(tf(), target, method(), _vtable_index, kit.bci());
+  if (is_inlined_mh_linker(jvms, method())) {
+    // To be able to issue a direct call (optimized virtual or virtual)
+    // and skip a call to MH.linkTo*/invokeBasic adapter, additional information
+    // about the method being invoked should be attached to the call site to
+    // make resolution logic work (see SharedRuntime::resolve_{virtual,opt_virtual}_call_C).
+    call->set_override_symbolic_info(true);
+  }
   kit.set_arguments_for_java_call(call);
   kit.set_edges_for_java_call(call);
   Node* ret = kit.set_results_for_java_call(call);
@@ -463,8 +485,8 @@
     _attempt++;
   }
 
-  if (cg != NULL) {
-    assert(!cg->is_late_inline() && cg->is_inline(), "we're doing late inlining");
+  if (cg != NULL && cg->is_inline()) {
+    assert(!cg->is_late_inline(), "we're doing late inlining");
     _inline_cg = cg;
     Compile::current()->dec_number_of_mh_late_inlines();
     return true;
@@ -807,8 +829,7 @@
         const int vtable_index = Method::invalid_vtable_index;
         CallGenerator* cg = C->call_generator(target, vtable_index, false, jvms, true, PROB_ALWAYS, NULL, true, true);
         assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
-        if (cg != NULL && cg->is_inline())
-          return cg;
+        return cg;
       } else {
         const char* msg = "receiver not constant";
         if (PrintInlining)  C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg);
@@ -829,7 +850,7 @@
         const TypeOopPtr* oop_ptr = member_name->bottom_type()->is_oopptr();
         ciMethod* target = oop_ptr->const_oop()->as_member_name()->get_vmtarget();
 
-        // In lamda forms we erase signature types to avoid resolving issues
+        // In lambda forms we erase signature types to avoid resolving issues
         // involving class loaders.  When we optimize a method handle invoke
         // to a direct call we must cast the receiver and arguments to its
         // actual types.
@@ -882,10 +903,9 @@
           // provide us with a type
           speculative_receiver_type = (receiver_type != NULL) ? receiver_type->speculative_type() : NULL;
         }
-        CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, true, PROB_ALWAYS, speculative_receiver_type, true, true);
+        CallGenerator* cg = C->call_generator(target, vtable_index, call_does_dispatch, jvms, /*allow_inline=*/true, PROB_ALWAYS, speculative_receiver_type, true, true);
         assert(cg == NULL || !cg->is_late_inline() || cg->is_mh_late_inline(), "no late inline here");
-        if (cg != NULL && cg->is_inline())
-          return cg;
+        return cg;
       } else {
         const char* msg = "member_name not constant";
         if (PrintInlining)  C->print_inlining(callee, jvms->depth() - 1, jvms->bci(), msg);