7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites
authortwisti
Tue, 28 Aug 2012 15:24:39 -0700
changeset 13522 5ad4627e792a
parent 13521 97a23be06f4e
child 13523 6a7f3e56a242
7192406: JSR 292: C2 needs exact return type information for invokedynamic and invokehandle call sites Reviewed-by: kvn
hotspot/src/share/vm/c1/c1_GraphBuilder.cpp
hotspot/src/share/vm/c1/c1_GraphBuilder.hpp
hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp
hotspot/src/share/vm/ci/ciEnv.cpp
hotspot/src/share/vm/ci/ciEnv.hpp
hotspot/src/share/vm/ci/ciMethod.cpp
hotspot/src/share/vm/ci/ciStreams.cpp
hotspot/src/share/vm/ci/ciStreams.hpp
hotspot/src/share/vm/ci/ciTypeFlow.cpp
hotspot/src/share/vm/interpreter/bytecodes.hpp
hotspot/src/share/vm/opto/doCall.cpp
hotspot/src/share/vm/opto/graphKit.cpp
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.cpp	Tue Aug 28 15:24:39 2012 -0700
@@ -1646,15 +1646,15 @@
 
 
 void GraphBuilder::invoke(Bytecodes::Code code) {
-  const bool is_invokedynamic = (code == Bytecodes::_invokedynamic);
-
   bool will_link;
-  ciMethod*             target = stream()->get_method(will_link);
+  ciSignature* declared_signature = NULL;
+  ciMethod*             target = stream()->get_method(will_link, &declared_signature);
   ciKlass*              holder = stream()->get_declared_method_holder();
   const Bytecodes::Code bc_raw = stream()->cur_bc_raw();
+  assert(declared_signature != NULL, "cannot be null");
 
   // FIXME bail out for now
-  if ((bc_raw == Bytecodes::_invokehandle || is_invokedynamic) && !will_link) {
+  if (Bytecodes::has_optional_appendix(bc_raw) && !will_link) {
     BAILOUT("unlinked call site (FIXME needs patching or recompile support)");
   }
 
@@ -1840,7 +1840,7 @@
       bool success = false;
       if (target->is_method_handle_intrinsic()) {
         // method handle invokes
-        success = for_method_handle_inline(target);
+        success = try_method_handle_inline(target);
       } else {
         // static binding => check if callee is ok
         success = try_inline(inline_target, (cha_monomorphic_target != NULL) || (exact_target != NULL), code, better_receiver);
@@ -1877,7 +1877,7 @@
 
   // inlining not successful => standard invoke
   bool is_loaded = target->is_loaded();
-  ValueType* result_type = as_ValueType(target->return_type());
+  ValueType* result_type = as_ValueType(declared_signature->return_type());
   ValueStack* state_before = copy_state_exhandling();
 
   // The bytecode (code) might change in this method so we are checking this very late.
@@ -3823,7 +3823,7 @@
 }
 
 
-bool GraphBuilder::for_method_handle_inline(ciMethod* callee) {
+bool GraphBuilder::try_method_handle_inline(ciMethod* callee) {
   ValueStack* state_before = state()->copy_for_parsing();
   vmIntrinsics::ID iid = callee->intrinsic_id();
   switch (iid) {
@@ -3858,7 +3858,7 @@
         // If the target is another method handle invoke try recursivly to get
         // a better target.
         if (target->is_method_handle_intrinsic()) {
-          if (for_method_handle_inline(target)) {
+          if (try_method_handle_inline(target)) {
             return true;
           }
         } else {
--- a/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/c1/c1_GraphBuilder.hpp	Tue Aug 28 15:24:39 2012 -0700
@@ -346,7 +346,7 @@
   const char* should_not_inline(ciMethod* callee) const;
 
   // JSR 292 support
-  bool for_method_handle_inline(ciMethod* callee);
+  bool try_method_handle_inline(ciMethod* callee);
 
   // helpers
   void inline_bailout(const char* msg);
--- a/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/ci/bcEscapeAnalyzer.cpp	Tue Aug 28 15:24:39 2012 -0700
@@ -236,12 +236,16 @@
   ciInstanceKlass* callee_holder = ciEnv::get_instance_klass_for_declared_method_holder(holder);
   ciInstanceKlass* actual_recv = callee_holder;
 
-  // some methods are obviously bindable without any type checks so
-  // convert them directly to an invokespecial.
+  // Some methods are obviously bindable without any type checks so
+  // convert them directly to an invokespecial or invokestatic.
   if (target->is_loaded() && !target->is_abstract() && target->can_be_statically_bound()) {
     switch (code) {
-    case Bytecodes::_invokevirtual:  code = Bytecodes::_invokespecial;  break;
-    case Bytecodes::_invokehandle:   code = Bytecodes::_invokestatic;   break;
+    case Bytecodes::_invokevirtual:
+      code = Bytecodes::_invokespecial;
+      break;
+    case Bytecodes::_invokehandle:
+      code = target->is_static() ? Bytecodes::_invokestatic : Bytecodes::_invokespecial;
+      break;
     }
   }
 
@@ -826,8 +830,8 @@
         break;
       case Bytecodes::_getstatic:
       case Bytecodes::_getfield:
-        { bool will_link;
-          ciField* field = s.get_field(will_link);
+        { bool ignored_will_link;
+          ciField* field = s.get_field(ignored_will_link);
           BasicType field_type = field->type()->basic_type();
           if (s.cur_bc() != Bytecodes::_getstatic) {
             set_method_escape(state.apop());
@@ -865,16 +869,21 @@
       case Bytecodes::_invokestatic:
       case Bytecodes::_invokedynamic:
       case Bytecodes::_invokeinterface:
-        { bool will_link;
-          ciMethod* target = s.get_method(will_link);
-          ciKlass* holder = s.get_declared_method_holder();
+        { bool ignored_will_link;
+          ciSignature* declared_signature = NULL;
+          ciMethod* target = s.get_method(ignored_will_link, &declared_signature);
+          ciKlass*  holder = s.get_declared_method_holder();
+          assert(declared_signature != NULL, "cannot be null");
           // Push appendix argument, if one.
           if (s.has_appendix()) {
             state.apush(unknown_obj);
           }
           // Pass in raw bytecode because we need to see invokehandle instructions.
           invoke(state, s.cur_bc_raw(), target, holder);
-          ciType* return_type = target->return_type();
+          // We are using the return type of the declared signature here because
+          // it might be a more concrete type than the one from the target (for
+          // e.g. invokedynamic and invokehandle).
+          ciType* return_type = declared_signature->return_type();
           if (!return_type->is_primitive_type()) {
             state.apush(unknown_obj);
           } else if (return_type->is_one_word()) {
--- a/hotspot/src/share/vm/ci/ciEnv.cpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.cpp	Tue Aug 28 15:24:39 2012 -0700
@@ -738,91 +738,81 @@
 ciMethod* ciEnv::get_method_by_index_impl(constantPoolHandle cpool,
                                           int index, Bytecodes::Code bc,
                                           ciInstanceKlass* accessor) {
-  int holder_index = cpool->klass_ref_index_at(index);
-  bool holder_is_accessible;
-  ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
-  ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
-
-  // Get the method's name and signature.
-  Symbol* name_sym = cpool->name_ref_at(index);
-  Symbol* sig_sym  = cpool->signature_ref_at(index);
-
-  if (cpool->has_preresolution()
-      || (holder == ciEnv::MethodHandle_klass() &&
-          MethodHandles::is_signature_polymorphic_name(holder->get_klassOop(), name_sym))) {
-    // Short-circuit lookups for JSR 292-related call sites.
-    // That is, do not rely only on name-based lookups, because they may fail
-    // if the names are not resolvable in the boot class loader (7056328).
-    switch (bc) {
-    case Bytecodes::_invokevirtual:
-    case Bytecodes::_invokeinterface:
-    case Bytecodes::_invokespecial:
-    case Bytecodes::_invokestatic:
-      {
-        oop appendix_oop = NULL;
-        methodOop m = constantPoolOopDesc::method_at_if_loaded(cpool, index);
-        if (m != NULL) {
-          return get_object(m)->as_method();
-        }
-      }
-      break;
-    }
-  }
+  if (bc == Bytecodes::_invokedynamic) {
+    ConstantPoolCacheEntry* secondary_entry = cpool->cache()->secondary_entry_at(index);
+    const bool is_resolved = !secondary_entry->is_f1_null();
+    // FIXME: code generation could allow for null (unlinked) call site
+    // The call site could be made patchable as follows:
+    // Load the appendix argument from the constant pool.
+    // Test the appendix argument and jump to a known deopt routine if it is null.
+    // Jump through a patchable call site, which is initially a deopt routine.
+    // Patch the call site to the nmethod entry point of the static compiled lambda form.
+    // As with other two-component call sites, both values must be independently verified.
 
-  if (holder_is_accessible) { // Our declared holder is loaded.
-    instanceKlass* lookup = declared_holder->get_instanceKlass();
-    methodOop m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
-    if (m != NULL &&
-        (bc == Bytecodes::_invokestatic
-         ?  instanceKlass::cast(m->method_holder())->is_not_initialized()
-         : !instanceKlass::cast(m->method_holder())->is_loaded())) {
-      m = NULL;
+    if (is_resolved) {
+      // Get the invoker methodOop and the extra argument from the constant pool.
+      methodOop adapter = secondary_entry->f2_as_vfinal_method();
+      return get_object(adapter)->as_method();
     }
-    if (m != NULL) {
-      // We found the method.
-      return get_object(m)->as_method();
-    }
-  }
-
-  // Either the declared holder was not loaded, or the method could
-  // not be found.  Create a dummy ciMethod to represent the failed
-  // lookup.
-  ciSymbol* name      = get_symbol(name_sym);
-  ciSymbol* signature = get_symbol(sig_sym);
-  return get_unloaded_method(declared_holder, name, signature, accessor);
-}
 
-
-// ------------------------------------------------------------------
-// ciEnv::get_fake_invokedynamic_method_impl
-ciMethod* ciEnv::get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
-                                                    int index, Bytecodes::Code bc,
-                                                    ciInstanceKlass* accessor) {
-  // Compare the following logic with InterpreterRuntime::resolve_invokedynamic.
-  assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
-
-  ConstantPoolCacheEntry* secondary_entry = cpool->cache()->secondary_entry_at(index);
-  bool is_resolved = !secondary_entry->is_f1_null();
-  // FIXME: code generation could allow for null (unlinked) call site
-  // The call site could be made patchable as follows:
-  // Load the appendix argument from the constant pool.
-  // Test the appendix argument and jump to a known deopt routine if it is null.
-  // Jump through a patchable call site, which is initially a deopt routine.
-  // Patch the call site to the nmethod entry point of the static compiled lambda form.
-  // As with other two-component call sites, both values must be independently verified.
-
-  // Call site might not be resolved yet.
-  // Stop the code path here with an unlinked method.
-  if (!is_resolved) {
+    // Fake a method that is equivalent to a declared method.
     ciInstanceKlass* holder    = get_object(SystemDictionary::MethodHandle_klass())->as_instance_klass();
     ciSymbol*        name      = ciSymbol::invokeBasic_name();
     ciSymbol*        signature = get_symbol(cpool->signature_ref_at(index));
     return get_unloaded_method(holder, name, signature, accessor);
-  }
+  } else {
+    const int holder_index = cpool->klass_ref_index_at(index);
+    bool holder_is_accessible;
+    ciKlass* holder = get_klass_by_index_impl(cpool, holder_index, holder_is_accessible, accessor);
+    ciInstanceKlass* declared_holder = get_instance_klass_for_declared_method_holder(holder);
+
+    // Get the method's name and signature.
+    Symbol* name_sym = cpool->name_ref_at(index);
+    Symbol* sig_sym  = cpool->signature_ref_at(index);
 
-  // Get the invoker methodOop and the extra argument from the constant pool.
-  methodOop adapter = secondary_entry->f2_as_vfinal_method();
-  return get_object(adapter)->as_method();
+    if (cpool->has_preresolution()
+        || (holder == ciEnv::MethodHandle_klass() &&
+            MethodHandles::is_signature_polymorphic_name(holder->get_klassOop(), name_sym))) {
+      // Short-circuit lookups for JSR 292-related call sites.
+      // That is, do not rely only on name-based lookups, because they may fail
+      // if the names are not resolvable in the boot class loader (7056328).
+      switch (bc) {
+      case Bytecodes::_invokevirtual:
+      case Bytecodes::_invokeinterface:
+      case Bytecodes::_invokespecial:
+      case Bytecodes::_invokestatic:
+        {
+          methodOop m = constantPoolOopDesc::method_at_if_loaded(cpool, index);
+          if (m != NULL) {
+            return get_object(m)->as_method();
+          }
+        }
+        break;
+      }
+    }
+
+    if (holder_is_accessible) {  // Our declared holder is loaded.
+      instanceKlass* lookup = declared_holder->get_instanceKlass();
+      methodOop m = lookup_method(accessor->get_instanceKlass(), lookup, name_sym, sig_sym, bc);
+      if (m != NULL &&
+          (bc == Bytecodes::_invokestatic
+           ?  instanceKlass::cast(m->method_holder())->is_not_initialized()
+           : !instanceKlass::cast(m->method_holder())->is_loaded())) {
+        m = NULL;
+      }
+      if (m != NULL) {
+        // We found the method.
+        return get_object(m)->as_method();
+      }
+    }
+
+    // Either the declared holder was not loaded, or the method could
+    // not be found.  Create a dummy ciMethod to represent the failed
+    // lookup.
+    ciSymbol* name      = get_symbol(name_sym);
+    ciSymbol* signature = get_symbol(sig_sym);
+    return get_unloaded_method(declared_holder, name, signature, accessor);
+  }
 }
 
 
@@ -853,11 +843,7 @@
 ciMethod* ciEnv::get_method_by_index(constantPoolHandle cpool,
                                      int index, Bytecodes::Code bc,
                                      ciInstanceKlass* accessor) {
-  if (bc == Bytecodes::_invokedynamic) {
-    GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(cpool, index, bc, accessor);)
-  } else {
-    GUARDED_VM_ENTRY(return get_method_by_index_impl(          cpool, index, bc, accessor);)
-  }
+  GUARDED_VM_ENTRY(return get_method_by_index_impl(cpool, index, bc, accessor);)
 }
 
 
--- a/hotspot/src/share/vm/ci/ciEnv.hpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciEnv.hpp	Tue Aug 28 15:24:39 2012 -0700
@@ -152,9 +152,6 @@
   ciMethod*  get_method_by_index_impl(constantPoolHandle cpool,
                                       int method_index, Bytecodes::Code bc,
                                       ciInstanceKlass* loading_klass);
-  ciMethod*  get_fake_invokedynamic_method_impl(constantPoolHandle cpool,
-                                                int index, Bytecodes::Code bc,
-                                                ciInstanceKlass* accessor);
 
   // Helper methods
   bool       check_klass_accessibility(ciKlass* accessing_klass,
--- a/hotspot/src/share/vm/ci/ciMethod.cpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciMethod.cpp	Tue Aug 28 15:24:39 2012 -0700
@@ -1215,9 +1215,10 @@
   holder()->print_name_on(st);
   st->print(" signature=");
   signature()->as_symbol()->print_symbol_on(st);
-  st->print(" arg_size=%d", arg_size());
   if (is_loaded()) {
-    st->print(" loaded=true flags=");
+    st->print(" loaded=true");
+    st->print(" arg_size=%d", arg_size());
+    st->print(" flags=");
     flags().print_member_flags(st);
   } else {
     st->print(" loaded=false");
--- a/hotspot/src/share/vm/ci/ciStreams.cpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.cpp	Tue Aug 28 15:24:39 2012 -0700
@@ -355,11 +355,23 @@
 // ciBytecodeStream::get_method
 //
 // If this is a method invocation bytecode, get the invoked method.
-ciMethod* ciBytecodeStream::get_method(bool& will_link) {
+// Additionally return the declared signature to get more concrete
+// type information if required (Cf. invokedynamic and invokehandle).
+ciMethod* ciBytecodeStream::get_method(bool& will_link, ciSignature* *declared_signature_result) {
   VM_ENTRY_MARK;
+  ciEnv* env = CURRENT_ENV;
   constantPoolHandle cpool(_method->get_methodOop()->constants());
-  ciMethod* m = CURRENT_ENV->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
+  ciMethod* m = env->get_method_by_index(cpool, get_method_index(), cur_bc(), _holder);
   will_link = m->is_loaded();
+  // Get declared method signature and return it.
+  if (has_optional_appendix()) {
+    const int sig_index = get_method_signature_index();
+    Symbol* sig_sym = cpool->symbol_at(sig_index);
+    ciKlass* pool_holder = env->get_object(cpool->pool_holder())->as_klass();
+    (*declared_signature_result) = new (env->arena()) ciSignature(pool_holder, cpool, env->get_symbol(sig_sym));
+  } else {
+    (*declared_signature_result) = m->signature();
+  }
   return m;
 }
 
@@ -419,35 +431,18 @@
 }
 
 // ------------------------------------------------------------------
-// ciBytecodeStream::get_declared_method_signature
-//
-// Get the declared signature of the currently referenced method.
-//
-// This is always the same as the signature of the resolved method
-// itself, except for _invokehandle and _invokedynamic calls.
-//
-ciSignature* ciBytecodeStream::get_declared_method_signature() {
-  int sig_index = get_method_signature_index();
-  VM_ENTRY_MARK;
-  ciEnv* env = CURRENT_ENV;
-  constantPoolHandle cpool(_method->get_methodOop()->constants());
-  Symbol* sig_sym = cpool->symbol_at(sig_index);
-  ciKlass* pool_holder = env->get_object(cpool->pool_holder())->as_klass();
-  return new (env->arena()) ciSignature(pool_holder, cpool, env->get_symbol(sig_sym));
-}
-
-// ------------------------------------------------------------------
 // ciBytecodeStream::get_method_signature_index
 //
 // Get the constant pool index of the signature of the method
 // referenced by the current bytecode.  Used for generating
 // deoptimization information.
 int ciBytecodeStream::get_method_signature_index() {
-  VM_ENTRY_MARK;
-  constantPoolOop cpool = _holder->get_instanceKlass()->constants();
-  int method_index = get_method_index();
-  int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
-  return cpool->signature_ref_index_at(name_and_type_index);
+  GUARDED_VM_ENTRY(
+    constantPoolOop cpool = _holder->get_instanceKlass()->constants();
+    const int method_index = get_method_index();
+    const int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
+    return cpool->signature_ref_index_at(name_and_type_index);
+  )
 }
 
 // ------------------------------------------------------------------
--- a/hotspot/src/share/vm/ci/ciStreams.hpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.hpp	Tue Aug 28 15:24:39 2012 -0700
@@ -151,6 +151,8 @@
   // Does this instruction contain an index which refes into the CP cache?
   bool has_cache_index() const { return Bytecodes::uses_cp_cache(cur_bc_raw()); }
 
+  bool has_optional_appendix() { return Bytecodes::has_optional_appendix(cur_bc_raw()); }
+
   int get_index_u1() const {
     return bytecode().get_index_u1(cur_bc_raw());
   }
@@ -257,13 +259,11 @@
   int      get_field_holder_index();
   int      get_field_signature_index();
 
-  // If this is a method invocation bytecode, get the invoked method.
-  ciMethod* get_method(bool& will_link);
+  ciMethod* get_method(bool& will_link, ciSignature* *declared_signature_result);
   bool      has_appendix();
   ciObject* get_appendix();
   ciKlass*  get_declared_method_holder();
   int       get_method_holder_index();
-  ciSignature* get_declared_method_signature();
   int       get_method_signature_index();
 
   ciCPCache*  get_cpcache() const;
--- a/hotspot/src/share/vm/ci/ciTypeFlow.cpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciTypeFlow.cpp	Tue Aug 28 15:24:39 2012 -0700
@@ -643,9 +643,11 @@
 // ------------------------------------------------------------------
 // ciTypeFlow::StateVector::do_invoke
 void ciTypeFlow::StateVector::do_invoke(ciBytecodeStream* str,
-                                        bool has_receiver_foo) {
+                                        bool has_receiver) {
   bool will_link;
-  ciMethod* callee = str->get_method(will_link);
+  ciSignature* declared_signature = NULL;
+  ciMethod* callee = str->get_method(will_link, &declared_signature);
+  assert(declared_signature != NULL, "cannot be null");
   if (!will_link) {
     // We weren't able to find the method.
     if (str->cur_bc() == Bytecodes::_invokedynamic) {
@@ -658,22 +660,12 @@
       trap(str, unloaded_holder, str->get_method_holder_index());
     }
   } else {
-    // TODO Use Bytecode_invoke after metadata changes.
-    //Bytecode_invoke inv(str->method(), str->cur_bci());
-    //const bool has_receiver = callee->is_loaded() ? !callee->is_static() : inv.has_receiver();
-    Bytecode inv(str);
-    Bytecodes::Code code = inv.invoke_code();
-    const bool has_receiver = callee->is_loaded() ? !callee->is_static() : code != Bytecodes::_invokestatic && code != Bytecodes::_invokedynamic;
-
-    ciSignature* signature = callee->signature();
-    ciSignatureStream sigstr(signature);
-    // Push appendix argument, if one.
-    if (str->has_appendix()) {
-      ciObject* appendix = str->get_appendix();
-      push_object(appendix->klass());
-    }
-    int arg_size = signature->size();
-    int stack_base = stack_size() - arg_size;
+    // We are using the declared signature here because it might be
+    // different from the callee signature (Cf. invokedynamic and
+    // invokehandle).
+    ciSignatureStream sigstr(declared_signature);
+    const int arg_size = declared_signature->size();
+    const int stack_base = stack_size() - arg_size;
     int i = 0;
     for( ; !sigstr.at_return_type(); sigstr.next()) {
       ciType* type = sigstr.type();
@@ -689,7 +681,6 @@
     for (int j = 0; j < arg_size; j++) {
       pop();
     }
-    assert(!callee->is_loaded() || has_receiver == !callee->is_static(), "mismatch");
     if (has_receiver) {
       // Check this?
       pop_object();
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp	Tue Aug 28 15:24:39 2012 -0700
@@ -424,6 +424,8 @@
                                                            || code == _fconst_0 || code == _dconst_0); }
   static bool        is_invoke      (Code code)    { return (_invokevirtual <= code && code <= _invokedynamic); }
 
+  static bool        has_optional_appendix(Code code) { return code == _invokedynamic || code == _invokehandle; }
+
   static int         compute_flags  (const char* format, int more_flags = 0);  // compute the flags
   static int         flags          (int code, bool is_wide) {
     assert(code == (u_char)code, "must be a byte");
--- a/hotspot/src/share/vm/opto/doCall.cpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Tue Aug 28 15:24:39 2012 -0700
@@ -341,25 +341,26 @@
   kill_dead_locals();
 
   // Set frequently used booleans
-  bool is_virtual = bc() == Bytecodes::_invokevirtual;
-  bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface;
-  bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial;
-  bool is_invokedynamic = bc() == Bytecodes::_invokedynamic;
+  const bool is_virtual = bc() == Bytecodes::_invokevirtual;
+  const bool is_virtual_or_interface = is_virtual || bc() == Bytecodes::_invokeinterface;
+  const bool has_receiver = is_virtual_or_interface || bc() == Bytecodes::_invokespecial;
 
   // Find target being called
   bool             will_link;
-  ciMethod*        bc_callee    = iter().get_method(will_link);  // actual callee from bytecode
-  ciInstanceKlass* holder_klass = bc_callee->holder();
-  ciKlass* holder = iter().get_declared_method_holder();
+  ciSignature*     declared_signature = NULL;
+  ciMethod*        orig_callee  = iter().get_method(will_link, &declared_signature);  // callee in the bytecode
+  ciInstanceKlass* holder_klass = orig_callee->holder();
+  ciKlass*         holder       = iter().get_declared_method_holder();
   ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
+  assert(declared_signature != NULL, "cannot be null");
 
   // uncommon-trap when callee is unloaded, uninitialized or will not link
   // bailout when too many arguments for register representation
-  if (!will_link || can_not_compile_call_site(bc_callee, klass)) {
+  if (!will_link || can_not_compile_call_site(orig_callee, klass)) {
 #ifndef PRODUCT
     if (PrintOpto && (Verbose || WizardMode)) {
       method()->print_name(); tty->print_cr(" can not compile call at bci %d to:", bci());
-      bc_callee->print_name(); tty->cr();
+      orig_callee->print_name(); tty->cr();
     }
 #endif
     return;
@@ -372,7 +373,7 @@
   // Note:  In the absence of miranda methods, an abstract class K can perform
   // an invokevirtual directly on an interface method I.m if K implements I.
 
-  const int nargs = bc_callee->arg_size();
+  const int nargs = orig_callee->arg_size();
 
   // Push appendix argument (MethodType, CallSite, etc.), if one.
   if (iter().has_appendix()) {
@@ -392,13 +393,13 @@
   // Choose call strategy.
   bool call_is_virtual = is_virtual_or_interface;
   int vtable_index = methodOopDesc::invalid_vtable_index;
-  ciMethod* callee = bc_callee;
+  ciMethod* callee = orig_callee;
 
   // Try to get the most accurate receiver type
   if (is_virtual_or_interface) {
     Node*             receiver_node = stack(sp() - nargs);
     const TypeOopPtr* receiver_type = _gvn.type(receiver_node)->isa_oopptr();
-    ciMethod* optimized_virtual_method = optimize_inlining(method(), bci(), klass, bc_callee, receiver_type);
+    ciMethod* optimized_virtual_method = optimize_inlining(method(), bci(), klass, orig_callee, receiver_type);
 
     // Have the call been sufficiently improved such that it is no longer a virtual?
     if (optimized_virtual_method != NULL) {
@@ -425,7 +426,8 @@
   // It decides whether inlining is desirable or not.
   CallGenerator* cg = C->call_generator(callee, vtable_index, call_is_virtual, jvms, try_inline, prof_factor());
 
-  bc_callee = callee = NULL;  // don't use bc_callee and callee after this point
+  // NOTE:  Don't use orig_callee and callee after this point!  Use cg->method() instead.
+  orig_callee = callee = NULL;
 
   // ---------------------
   // Round double arguments before call
@@ -497,9 +499,9 @@
     round_double_result(cg->method());
 
     ciType* rtype = cg->method()->return_type();
-    if (iter().cur_bc_raw() == Bytecodes::_invokehandle || is_invokedynamic) {
+    if (Bytecodes::has_optional_appendix(iter().cur_bc_raw())) {
       // Be careful here with return types.
-      ciType* ctype = iter().get_declared_method_signature()->return_type();
+      ciType* ctype = declared_signature->return_type();
       if (ctype != rtype) {
         BasicType rt = rtype->basic_type();
         BasicType ct = ctype->basic_type();
@@ -528,15 +530,13 @@
         } else if (rt == T_OBJECT || rt == T_ARRAY) {
           assert(ct == T_OBJECT || ct == T_ARRAY, err_msg_res("rt=%s, ct=%s", type2name(rt), type2name(ct)));
           if (ctype->is_loaded()) {
-            Node* if_fail = top();
-            retnode = gen_checkcast(retnode, makecon(TypeKlassPtr::make(ctype->as_klass())), &if_fail);
-            if (if_fail != top()) {
-              PreserveJVMState pjvms(this);
-              set_control(if_fail);
-              builtin_throw(Deoptimization::Reason_class_check);
+            const TypeOopPtr* arg_type = TypeOopPtr::make_from_klass(rtype->as_klass());
+            const Type*       sig_type = TypeOopPtr::make_from_klass(ctype->as_klass());
+            if (arg_type != NULL && !arg_type->higher_equal(sig_type)) {
+              Node* cast_obj = _gvn.transform(new (C, 2) CheckCastPPNode(control(), retnode, sig_type));
+              pop();
+              push(cast_obj);
             }
-            pop();
-            push(retnode);
           }
         } else {
           assert(ct == rt, err_msg_res("unexpected mismatch rt=%d, ct=%d", rt, ct));
--- a/hotspot/src/share/vm/opto/graphKit.cpp	Mon Aug 27 15:17:17 2012 -0700
+++ b/hotspot/src/share/vm/opto/graphKit.cpp	Tue Aug 28 15:24:39 2012 -0700
@@ -1006,11 +1006,11 @@
   case Bytecodes::_putfield:
     {
       bool is_get = (depth >= 0), is_static = (depth & 1);
-      bool ignore;
       ciBytecodeStream iter(method());
       iter.reset_to_bci(bci());
       iter.next();
-      ciField* field = iter.get_field(ignore);
+      bool ignored_will_link;
+      ciField* field = iter.get_field(ignored_will_link);
       int      size  = field->type()->size();
       inputs  = (is_static ? 0 : 1);
       if (is_get) {
@@ -1028,11 +1028,13 @@
   case Bytecodes::_invokedynamic:
   case Bytecodes::_invokeinterface:
     {
-      bool ignore;
       ciBytecodeStream iter(method());
       iter.reset_to_bci(bci());
       iter.next();
-      ciMethod* callee = iter.get_method(ignore);
+      bool ignored_will_link;
+      ciSignature* declared_signature = NULL;
+      ciMethod* callee = iter.get_method(ignored_will_link, &declared_signature);
+      assert(declared_signature != NULL, "cannot be null");
       // (Do not use ciMethod::arg_size(), because
       // it might be an unloaded method, which doesn't
       // know whether it is static or not.)
@@ -1046,7 +1048,7 @@
         //         remove any appendix arguments that were popped.
         inputs = callee->invoke_arg_size(code) - (callee->has_member_arg() ? 1 : 0);
       }
-      int size = callee->return_type()->size();
+      int size = declared_signature->return_type()->size();
       depth = size - inputs;
     }
     break;