7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path
authortwisti
Mon, 01 Oct 2012 14:50:10 -0700
changeset 13929 8da0dc50a6e4
parent 13918 b01a48301e67
child 13930 8df570f94294
7200949: JSR 292: rubybench/bench/time/bench_base64.rb fails with jruby.jar not on boot class path Reviewed-by: jrose, kvn
hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp
hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
hotspot/src/share/vm/ci/ciClassList.hpp
hotspot/src/share/vm/ci/ciMethodType.hpp
hotspot/src/share/vm/ci/ciObject.hpp
hotspot/src/share/vm/ci/ciObjectFactory.cpp
hotspot/src/share/vm/ci/ciSignature.cpp
hotspot/src/share/vm/ci/ciSignature.hpp
hotspot/src/share/vm/ci/ciStreams.cpp
hotspot/src/share/vm/ci/ciStreams.hpp
hotspot/src/share/vm/classfile/systemDictionary.cpp
hotspot/src/share/vm/classfile/systemDictionary.hpp
hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
hotspot/src/share/vm/interpreter/linkResolver.cpp
hotspot/src/share/vm/interpreter/linkResolver.hpp
hotspot/src/share/vm/interpreter/rewriter.cpp
hotspot/src/share/vm/interpreter/rewriter.hpp
hotspot/src/share/vm/oops/constantPool.cpp
hotspot/src/share/vm/oops/constantPool.hpp
hotspot/src/share/vm/oops/cpCache.cpp
hotspot/src/share/vm/oops/cpCache.hpp
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -2936,6 +2936,7 @@
     // Push the appendix as a trailing parameter.
     // This must be done before we get the receiver,
     // since the parameter_size includes it.
+    assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
     __ load_resolved_reference_at_index(temp, index);
     __ verify_oop(temp);
     __ push_ptr(temp);  // push appendix (MethodType, CallSite, etc.)
@@ -3235,15 +3236,15 @@
   }
 
   const Register Rret       = Lscratch;
-  const Register G4_mtype   = G4_scratch;  // f1
+  const Register G4_mtype   = G4_scratch;
   const Register O0_recv    = O0;
   const Register Rscratch   = G3_scratch;
 
   prepare_invoke(byte_no, G5_method, Rret, G4_mtype, O0_recv);
   __ null_check(O0_recv);
 
-  // G4: MethodType object (from cpool->resolved_references[])
-  // G5: MH.linkToCallSite method (from f2)
+  // G4: MethodType object (from cpool->resolved_references[f1], if necessary)
+  // G5: MH.invokeExact_MT method (from f2)
 
   // Note:  G4_mtype is already pushed (if necessary) by prepare_invoke
 
@@ -3275,8 +3276,8 @@
 
   prepare_invoke(byte_no, G5_method, Rret, G4_callsite);
 
-  // G4: CallSite object (from cpool->resolved_references[])
-  // G5: MH.linkToCallSite method (from f1)
+  // G4: CallSite object (from cpool->resolved_references[f1])
+  // G5: MH.linkToCallSite method (from f2)
 
   // Note:  G4_callsite is already pushed by prepare_invoke
 
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -2139,7 +2139,7 @@
   const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
                                     ConstantPoolCacheEntry::f2_offset());
 
-    size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
+  size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
   resolve_cache_and_index(byte_no, cache, index, index_size);
     __ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
 
@@ -2876,6 +2876,7 @@
     // since the parameter_size includes it.
     __ push(rbx);
     __ mov(rbx, index);
+    assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
     __ load_resolved_reference_at_index(index, rbx);
     __ pop(rbx);
     __ push(index);  // push appendix (MethodType, CallSite, etc.)
@@ -3093,8 +3094,8 @@
 void TemplateTable::invokehandle(int byte_no) {
   transition(vtos, vtos);
   assert(byte_no == f1_byte, "use this argument");
-  const Register rbx_method = rbx;  // (from f2)
-  const Register rax_mtype  = rax;  // (from f1)
+  const Register rbx_method = rbx;
+  const Register rax_mtype  = rax;
   const Register rcx_recv   = rcx;
   const Register rdx_flags  = rdx;
 
@@ -3104,13 +3105,14 @@
     return;
   }
 
-  prepare_invoke(byte_no,
-                 rbx_method, rax_mtype,  // get f2 Method*, f1 MethodType
-                 rcx_recv);
+  prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv);
   __ verify_method_ptr(rbx_method);
   __ verify_oop(rcx_recv);
   __ null_check(rcx_recv);
 
+  // rax: MethodType object (from cpool->resolved_references[f1], if necessary)
+  // rbx: MH.invokeExact_MT method (from f2)
+
   // Note:  rax_mtype is already pushed (if necessary) by prepare_invoke
 
   // FIXME: profile the LambdaForm also
@@ -3140,7 +3142,7 @@
 
   prepare_invoke(byte_no, rbx_method, rax_callsite);
 
-  // rax: CallSite object (from cpool->resolved_references[])
+  // rax: CallSite object (from cpool->resolved_references[f1])
   // rbx: MH.linkToCallSite method (from f2)
 
   // Note:  rax_callsite is already pushed by prepare_invoke
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -2184,7 +2184,7 @@
   const int index_offset = in_bytes(ConstantPoolCache::base_offset() +
                                     ConstantPoolCacheEntry::f2_offset());
 
-    size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
+  size_t index_size = (is_invokedynamic ? sizeof(u4) : sizeof(u2));
   resolve_cache_and_index(byte_no, cache, index, index_size);
     __ movptr(method, Address(cache, index, Address::times_ptr, method_offset));
 
@@ -2926,6 +2926,7 @@
     // since the parameter_size includes it.
     __ push(rbx);
     __ mov(rbx, index);
+    assert(ConstantPoolCacheEntry::_indy_resolved_references_appendix_offset == 0, "appendix expected at index+0");
     __ load_resolved_reference_at_index(index, rbx);
     __ pop(rbx);
     __ push(index);  // push appendix (MethodType, CallSite, etc.)
@@ -3144,8 +3145,8 @@
 void TemplateTable::invokehandle(int byte_no) {
   transition(vtos, vtos);
   assert(byte_no == f1_byte, "use this argument");
-  const Register rbx_method = rbx;  // f2
-  const Register rax_mtype  = rax;  // f1
+  const Register rbx_method = rbx;
+  const Register rax_mtype  = rax;
   const Register rcx_recv   = rcx;
   const Register rdx_flags  = rdx;
 
@@ -3155,13 +3156,14 @@
     return;
   }
 
-  prepare_invoke(byte_no,
-                 rbx_method, rax_mtype,  // get f2 Method*, f1 MethodType
-                 rcx_recv);
+  prepare_invoke(byte_no, rbx_method, rax_mtype, rcx_recv);
   __ verify_method_ptr(rbx_method);
   __ verify_oop(rcx_recv);
   __ null_check(rcx_recv);
 
+  // rax: MethodType object (from cpool->resolved_references[f1], if necessary)
+  // rbx: MH.invokeExact_MT method (from f2)
+
   // Note:  rax_mtype is already pushed (if necessary) by prepare_invoke
 
   // FIXME: profile the LambdaForm also
@@ -3191,7 +3193,7 @@
 
   prepare_invoke(byte_no, rbx_method, rax_callsite);
 
-  // rax: CallSite object (from cpool->resolved_references[])
+  // rax: CallSite object (from cpool->resolved_references[f1])
   // rbx: MH.linkToCallSite method (from f2)
 
   // Note:  rax_callsite is already pushed by prepare_invoke
--- a/hotspot/src/share/vm/ci/ciClassList.hpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciClassList.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -49,6 +49,7 @@
 class     ciCallSite;
 class     ciMemberName;
 class     ciMethodHandle;
+class     ciMethodType;
 class     ciArray;
 class       ciObjArray;
 class       ciTypeArray;
@@ -99,6 +100,7 @@
 friend class ciMethod;                 \
 friend class ciMethodData;             \
 friend class ciMethodHandle;           \
+friend class ciMethodType;             \
 friend class ciReceiverTypeData;       \
 friend class ciSymbol;                 \
 friend class ciArray;                  \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/src/share/vm/ci/ciMethodType.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ *
+ */
+
+#ifndef SHARE_VM_CI_CIMETHODTYPE_HPP
+#define SHARE_VM_CI_CIMETHODTYPE_HPP
+
+#include "ci/ciInstance.hpp"
+#include "ci/ciUtilities.hpp"
+#include "classfile/javaClasses.hpp"
+
+// ciMethodType
+//
+// The class represents a java.lang.invoke.MethodType object.
+class ciMethodType : public ciInstance {
+private:
+  ciType* class_to_citype(oop klass_oop) const {
+    if (java_lang_Class::is_primitive(klass_oop)) {
+      BasicType bt = java_lang_Class::primitive_type(klass_oop);
+      return ciType::make(bt);
+    } else {
+      Klass* k = java_lang_Class::as_Klass(klass_oop);
+      return CURRENT_ENV->get_klass(k);
+    }
+  }
+
+public:
+  ciMethodType(instanceHandle h_i) : ciInstance(h_i) {}
+
+  // What kind of ciObject is this?
+  bool is_method_type() const { return true; }
+
+  ciType* rtype() const {
+    GUARDED_VM_ENTRY(
+      oop rtype = java_lang_invoke_MethodType::rtype(get_oop());
+      return class_to_citype(rtype);
+    )
+  }
+
+  int ptype_count() const {
+    GUARDED_VM_ENTRY(return java_lang_invoke_MethodType::ptype_count(get_oop());)
+  }
+
+  int ptype_slot_count() const {
+    GUARDED_VM_ENTRY(return java_lang_invoke_MethodType::ptype_slot_count(get_oop());)
+  }
+
+  ciType* ptype_at(int index) const {
+    GUARDED_VM_ENTRY(
+      oop ptype = java_lang_invoke_MethodType::ptype(get_oop(), index);
+      return class_to_citype(ptype);
+    )
+  }
+};
+
+#endif // SHARE_VM_CI_CIMETHODTYPE_HPP
--- a/hotspot/src/share/vm/ci/ciObject.hpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciObject.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -123,6 +123,7 @@
   virtual bool is_instance()                { return false; }
   virtual bool is_member_name()       const { return false; }
   virtual bool is_method_handle()     const { return false; }
+  virtual bool is_method_type()       const { return false; }
   virtual bool is_array()                   { return false; }
   virtual bool is_obj_array()               { return false; }
   virtual bool is_type_array()              { return false; }
@@ -142,35 +143,39 @@
   }
 
   // Subclass casting with assertions.
-  ciNullObject*            as_null_object() {
+  ciNullObject* as_null_object() {
     assert(is_null_object(), "bad cast");
     return (ciNullObject*)this;
   }
-  ciCallSite*              as_call_site() {
+  ciCallSite* as_call_site() {
     assert(is_call_site(), "bad cast");
-    return (ciCallSite*) this;
+    return (ciCallSite*)this;
   }
-  ciInstance*              as_instance() {
+  ciInstance* as_instance() {
     assert(is_instance(), "bad cast");
     return (ciInstance*)this;
   }
-  ciMemberName*            as_member_name() {
+  ciMemberName* as_member_name() {
     assert(is_member_name(), "bad cast");
     return (ciMemberName*)this;
   }
-  ciMethodHandle*          as_method_handle() {
+  ciMethodHandle* as_method_handle() {
     assert(is_method_handle(), "bad cast");
-    return (ciMethodHandle*) this;
+    return (ciMethodHandle*)this;
   }
-  ciArray*                 as_array() {
+  ciMethodType* as_method_type() {
+    assert(is_method_type(), "bad cast");
+    return (ciMethodType*)this;
+  }
+  ciArray* as_array() {
     assert(is_array(), "bad cast");
     return (ciArray*)this;
   }
-  ciObjArray*              as_obj_array() {
+  ciObjArray* as_obj_array() {
     assert(is_obj_array(), "bad cast");
     return (ciObjArray*)this;
   }
-  ciTypeArray*             as_type_array() {
+  ciTypeArray* as_type_array() {
     assert(is_type_array(), "bad cast");
     return (ciTypeArray*)this;
   }
--- a/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciObjectFactory.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -30,6 +30,7 @@
 #include "ci/ciMethod.hpp"
 #include "ci/ciMethodData.hpp"
 #include "ci/ciMethodHandle.hpp"
+#include "ci/ciMethodType.hpp"
 #include "ci/ciNullObject.hpp"
 #include "ci/ciObjArray.hpp"
 #include "ci/ciObjArrayKlass.hpp"
@@ -237,23 +238,23 @@
 
   assert(key == NULL || Universe::heap()->is_in_reserved(key), "must be");
 
-    NonPermObject* &bucket = find_non_perm(key);
-    if (bucket != NULL) {
-      return bucket->object();
-    }
+  NonPermObject* &bucket = find_non_perm(key);
+  if (bucket != NULL) {
+    return bucket->object();
+  }
 
-    // The ciObject does not yet exist.  Create it and insert it
-    // into the cache.
-    Handle keyHandle(key);
-    ciObject* new_object = create_new_object(keyHandle());
-    assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
-    init_ident_of(new_object);
+  // The ciObject does not yet exist.  Create it and insert it
+  // into the cache.
+  Handle keyHandle(key);
+  ciObject* new_object = create_new_object(keyHandle());
+  assert(keyHandle() == new_object->get_oop(), "must be properly recorded");
+  init_ident_of(new_object);
   assert(Universe::heap()->is_in_reserved(new_object->get_oop()), "must be");
 
-      // Not a perm-space object.
-      insert_non_perm(bucket, keyHandle(), new_object);
-      return new_object;
-    }
+  // Not a perm-space object.
+  insert_non_perm(bucket, keyHandle(), new_object);
+  return new_object;
+}
 
 // ------------------------------------------------------------------
 // ciObjectFactory::get
@@ -324,6 +325,8 @@
       return new (arena()) ciMemberName(h_i);
     else if (java_lang_invoke_MethodHandle::is_instance(o))
       return new (arena()) ciMethodHandle(h_i);
+    else if (java_lang_invoke_MethodType::is_instance(o))
+      return new (arena()) ciMethodType(h_i);
     else
       return new (arena()) ciInstance(h_i);
   } else if (o->is_objArray()) {
--- a/hotspot/src/share/vm/ci/ciSignature.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciSignature.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -23,6 +23,7 @@
  */
 
 #include "precompiled.hpp"
+#include "ci/ciMethodType.hpp"
 #include "ci/ciSignature.hpp"
 #include "ci/ciUtilities.hpp"
 #include "memory/allocation.inline.hpp"
@@ -80,6 +81,24 @@
 }
 
 // ------------------------------------------------------------------
+// ciSignature::ciSignature
+ciSignature::ciSignature(ciKlass* accessing_klass, ciSymbol* symbol, ciMethodType* method_type) :
+  _symbol(symbol),
+  _accessing_klass(accessing_klass),
+  _size( method_type->ptype_slot_count()),
+  _count(method_type->ptype_count())
+{
+  ASSERT_IN_VM;
+  EXCEPTION_CONTEXT;
+  Arena* arena = CURRENT_ENV->arena();
+  _types = new (arena) GrowableArray<ciType*>(arena, _count + 1, 0, NULL);
+  for (int i = 0; i < _count; i++) {
+    _types->append(method_type->ptype_at(i));
+  }
+  _types->append(method_type->rtype());
+}
+
+// ------------------------------------------------------------------
 // ciSignature::return_type
 //
 // What is the return type of this signature?
--- a/hotspot/src/share/vm/ci/ciSignature.hpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciSignature.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -47,6 +47,7 @@
   friend class ciObjectFactory;
 
   ciSignature(ciKlass* accessing_klass, constantPoolHandle cpool, ciSymbol* signature);
+  ciSignature(ciKlass* accessing_klass,                           ciSymbol* signature, ciMethodType* method_type);
 
   void get_all_klasses();
 
--- a/hotspot/src/share/vm/ci/ciStreams.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -364,12 +364,15 @@
   constantPoolHandle cpool(_method->get_Method()->constants());
   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_klass(cpool->pool_holder());
-    (*declared_signature_result) = new (env->arena()) ciSignature(pool_holder, cpool, env->get_symbol(sig_sym));
+
+  // Use the MethodType stored in the CP cache to create a signature
+  // with correct types (in respect to class loaders).
+  if (has_method_type()) {
+    ciSymbol*     sig_sym     = env->get_symbol(cpool->symbol_at(get_method_signature_index()));
+    ciKlass*      pool_holder = env->get_klass(cpool->pool_holder());
+    ciMethodType* method_type = get_method_type();
+    ciSignature* declared_signature = new (env->arena()) ciSignature(pool_holder, sig_sym, method_type);
+    (*declared_signature_result) = declared_signature;
   } else {
     (*declared_signature_result) = m->signature();
   }
@@ -400,6 +403,31 @@
 }
 
 // ------------------------------------------------------------------
+// ciBytecodeStream::has_method_type
+//
+// Returns true if there is a MethodType argument stored in the
+// constant pool cache at the current bci.
+bool ciBytecodeStream::has_method_type() {
+  GUARDED_VM_ENTRY(
+    constantPoolHandle cpool(_method->get_Method()->constants());
+    return ConstantPool::has_method_type_at_if_loaded(cpool, get_method_index());
+  )
+}
+
+// ------------------------------------------------------------------
+// ciBytecodeStream::get_method_type
+//
+// Return the MethodType stored in the constant pool cache at
+// the current bci.
+ciMethodType* ciBytecodeStream::get_method_type() {
+  GUARDED_VM_ENTRY(
+    constantPoolHandle cpool(_method->get_Method()->constants());
+    oop method_type_oop = ConstantPool::method_type_at_if_loaded(cpool, get_method_index());
+    return CURRENT_ENV->get_object(method_type_oop)->as_method_type();
+  )
+}
+
+// ------------------------------------------------------------------
 // ciBytecodeStream::get_declared_method_holder
 //
 // Get the declared holder of the currently referenced method.
--- a/hotspot/src/share/vm/ci/ciStreams.hpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/ci/ciStreams.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -257,12 +257,14 @@
   int      get_field_holder_index();
   int      get_field_signature_index();
 
-  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();
-  int       get_method_signature_index();
+  ciMethod*     get_method(bool& will_link, ciSignature* *declared_signature_result);
+  bool          has_appendix();
+  ciObject*     get_appendix();
+  bool          has_method_type();
+  ciMethodType* get_method_type();
+  ciKlass*      get_declared_method_holder();
+  int           get_method_holder_index();
+  int           get_method_signature_index();
 
   // Get the resolved references arrays from the constant pool
   ciObjArray* get_resolved_references();
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -2429,7 +2429,8 @@
 methodHandle SystemDictionary::find_method_handle_invoker(Symbol* name,
                                                           Symbol* signature,
                                                           KlassHandle accessing_klass,
-                                                          Handle* appendix_result,
+                                                          Handle *appendix_result,
+                                                          Handle *method_type_result,
                                                           TRAPS) {
   methodHandle empty;
   assert(EnableInvokeDynamic, "");
@@ -2461,6 +2462,7 @@
                          vmSymbols::linkMethod_signature(),
                          &args, CHECK_(empty));
   Handle mname(THREAD, (oop) result.get_jobject());
+  (*method_type_result) = method_type;
   return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD);
 }
 
@@ -2607,7 +2609,8 @@
                                                               Handle bootstrap_specifier,
                                                               Symbol* name,
                                                               Symbol* type,
-                                                              Handle* appendix_result,
+                                                              Handle *appendix_result,
+                                                              Handle *method_type_result,
                                                               TRAPS) {
   methodHandle empty;
   Handle bsm, info;
@@ -2650,6 +2653,7 @@
                          vmSymbols::linkCallSite_signature(),
                          &args, CHECK_(empty));
   Handle mname(THREAD, (oop) result.get_jobject());
+  (*method_type_result) = method_type;
   return unpack_method_and_appendix(mname, appendix_box, appendix_result, THREAD);
 }
 
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -497,6 +497,7 @@
                                                  Symbol* signature,
                                                  KlassHandle accessing_klass,
                                                  Handle *appendix_result,
+                                                 Handle *method_type_result,
                                                  TRAPS);
   // for a given signature, find the internal MethodHandle method (linkTo* or invokeBasic)
   // (does not ask Java, since this is a low-level intrinsic defined by the JVM)
@@ -523,6 +524,7 @@
                                                      Symbol* name,
                                                      Symbol* type,
                                                      Handle *appendix_result,
+                                                     Handle *method_type_result,
                                                      TRAPS);
 
   // Utility for printing loader "name" as part of tracing constraints
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -737,6 +737,7 @@
       pool,
       info.resolved_method(),
       info.resolved_appendix(),
+      info.resolved_method_type(),
       pool->resolved_references());
 }
 IRT_END
@@ -765,6 +766,7 @@
       pool,
       info.resolved_method(),
       info.resolved_appendix(),
+      info.resolved_method_type(),
       pool->resolved_references());
 }
 IRT_END
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -99,7 +99,7 @@
   assert(!resolved_method->is_compiled_lambda_form(), "these must be handled via an invokehandle call");
 }
 
-void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix, TRAPS) {
+void CallInfo::set_handle(methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS) {
   if (resolved_method.is_null()) {
     THROW_MSG(vmSymbols::java_lang_InternalError(), "resolved method is null");
   }
@@ -110,7 +110,8 @@
   int vtable_index = Method::nonvirtual_vtable_index;
   assert(resolved_method->vtable_index() == vtable_index, "");
   set_common(resolved_klass, resolved_klass, resolved_method, resolved_method, vtable_index, CHECK);
-  _resolved_appendix = resolved_appendix;
+  _resolved_appendix    = resolved_appendix;
+  _resolved_method_type = resolved_method_type;
 }
 
 void CallInfo::set_common(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS) {
@@ -221,7 +222,8 @@
 void LinkResolver::lookup_polymorphic_method(methodHandle& result,
                                              KlassHandle klass, Symbol* name, Symbol* full_signature,
                                              KlassHandle current_klass,
-                                             Handle* appendix_result_or_null,
+                                             Handle *appendix_result_or_null,
+                                             Handle *method_type_result,
                                              TRAPS) {
   vmIntrinsics::ID iid = MethodHandles::signature_polymorphic_name_id(name);
   if (TraceMethodHandles) {
@@ -275,10 +277,12 @@
       }
 
       Handle appendix;
+      Handle method_type;
       result = SystemDictionary::find_method_handle_invoker(name,
                                                             full_signature,
                                                             current_klass,
                                                             &appendix,
+                                                            &method_type,
                                                             CHECK);
       if (TraceMethodHandles) {
         tty->print("lookup_polymorphic_method => (via Java) ");
@@ -307,6 +311,7 @@
 
         assert(appendix_result_or_null != NULL, "");
         (*appendix_result_or_null) = appendix;
+        (*method_type_result)      = method_type;
         return;
       }
     }
@@ -419,7 +424,7 @@
     if (resolved_method.is_null()) {
       // JSR 292:  see if this is an implicitly generated method MethodHandle.linkToVirtual(*...), etc
       lookup_polymorphic_method(resolved_method, resolved_klass, method_name, method_signature,
-                                current_klass, (Handle*)NULL, THREAD);
+                                current_klass, (Handle*)NULL, (Handle*)NULL, THREAD);
       if (HAS_PENDING_EXCEPTION) {
         nested_exception = Handle(THREAD, PENDING_EXCEPTION);
         CLEAR_PENDING_EXCEPTION;
@@ -1207,11 +1212,12 @@
   assert(resolved_klass() == SystemDictionary::MethodHandle_klass(), "");
   assert(MethodHandles::is_signature_polymorphic_name(method_name), "");
   methodHandle resolved_method;
-  Handle resolved_appendix;
+  Handle       resolved_appendix;
+  Handle       resolved_method_type;
   lookup_polymorphic_method(resolved_method, resolved_klass,
                             method_name, method_signature,
-                            current_klass, &resolved_appendix, CHECK);
-  result.set_handle(resolved_method, resolved_appendix, CHECK);
+                            current_klass, &resolved_appendix, &resolved_method_type, CHECK);
+  result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
 }
 
 
@@ -1219,7 +1225,7 @@
   assert(EnableInvokeDynamic, "");
   pool->set_invokedynamic();    // mark header to flag active call sites
 
-  //resolve_pool(<resolved_klass>, method_name,  method_signature, current_klass, pool, index, CHECK);
+  //resolve_pool(<resolved_klass>, method_name, method_signature, current_klass, pool, index, CHECK);
   Symbol* method_name       = pool->name_ref_at(index);
   Symbol* method_signature  = pool->signature_ref_at(index);
   KlassHandle current_klass = KlassHandle(THREAD, pool->pool_holder());
@@ -1236,9 +1242,10 @@
     bootstrap_specifier = Handle(THREAD, bsm_info);
   }
   if (!cpce->is_f1_null()) {
-    methodHandle method(THREAD, cpce->f1_as_method());
-    Handle appendix(THREAD, cpce->appendix_if_resolved(pool));
-    result.set_handle(method, appendix, CHECK);
+    methodHandle method(     THREAD, cpce->f1_as_method());
+    Handle       appendix(   THREAD, cpce->appendix_if_resolved(pool));
+    Handle       method_type(THREAD, cpce->method_type_if_resolved(pool));
+    result.set_handle(method, appendix, method_type, CHECK);
     return;
   }
 
@@ -1260,11 +1267,13 @@
   // JSR 292:  this must resolve to an implicitly generated method MH.linkToCallSite(*...)
   // The appendix argument is likely to be a freshly-created CallSite.
   Handle       resolved_appendix;
+  Handle       resolved_method_type;
   methodHandle resolved_method =
     SystemDictionary::find_dynamic_call_site_invoker(current_klass,
                                                      bootstrap_specifier,
                                                      method_name, method_signature,
                                                      &resolved_appendix,
+                                                     &resolved_method_type,
                                                      THREAD);
   if (HAS_PENDING_EXCEPTION) {
     if (TraceMethodHandles) {
@@ -1284,7 +1293,7 @@
     CLEAR_PENDING_EXCEPTION;
     THROW_CAUSE(vmSymbols::java_lang_BootstrapMethodError(), nested_exception)
   }
-  result.set_handle(resolved_method, resolved_appendix, CHECK);
+  result.set_handle(resolved_method, resolved_appendix, resolved_method_type, CHECK);
 }
 
 //------------------------------------------------------------------------------------------------------------------------
--- a/hotspot/src/share/vm/interpreter/linkResolver.hpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/linkResolver.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -76,12 +76,13 @@
   methodHandle _selected_method;        // dynamic (actual) target method
   int          _vtable_index;           // vtable index of selected method
   Handle       _resolved_appendix;      // extra argument in constant pool (if CPCE::has_appendix)
+  Handle       _resolved_method_type;   // MethodType (for invokedynamic and invokehandle call sites)
 
-  void         set_static(   KlassHandle resolved_klass,                             methodHandle resolved_method                                                , TRAPS);
-  void         set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method                  , TRAPS);
-  void         set_virtual(  KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS);
-  void         set_handle(                                                           methodHandle resolved_method,   Handle resolved_appendix,                     TRAPS);
-  void         set_common(   KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index, TRAPS);
+  void         set_static(   KlassHandle resolved_klass,                             methodHandle resolved_method                                                       , TRAPS);
+  void         set_interface(KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method                         , TRAPS);
+  void         set_virtual(  KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index       , TRAPS);
+  void         set_handle(                                                           methodHandle resolved_method, Handle resolved_appendix, Handle resolved_method_type, TRAPS);
+  void         set_common(   KlassHandle resolved_klass, KlassHandle selected_klass, methodHandle resolved_method, methodHandle selected_method, int vtable_index       , TRAPS);
 
   friend class LinkResolver;
 
@@ -91,6 +92,7 @@
   methodHandle resolved_method() const           { return _resolved_method; }
   methodHandle selected_method() const           { return _selected_method; }
   Handle       resolved_appendix() const         { return _resolved_appendix; }
+  Handle       resolved_method_type() const      { return _resolved_method_type; }
 
   BasicType    result_type() const               { return selected_method()->result_type(); }
   bool         has_vtable_index() const          { return _vtable_index >= 0; }
@@ -113,7 +115,7 @@
   static void lookup_instance_method_in_klasses (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
   static void lookup_method_in_interfaces       (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
   static void lookup_polymorphic_method         (methodHandle& result, KlassHandle klass, Symbol* name, Symbol* signature,
-                                                 KlassHandle current_klass, Handle* appendix_result_or_null, TRAPS);
+                                                 KlassHandle current_klass, Handle *appendix_result_or_null, Handle *method_type_result, TRAPS);
 
   static int vtable_index_of_miranda_method(KlassHandle klass, Symbol* name, Symbol* signature, TRAPS);
 
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -179,7 +179,7 @@
             MethodHandles::is_signature_polymorphic_name(SystemDictionary::MethodHandle_klass(),
                                                          _pool->name_ref_at(cp_index))) {
           // we may need a resolved_refs entry for the appendix
-          add_invokedynamic_resolved_references_entry(cp_index, cache_index);
+          add_invokedynamic_resolved_references_entries(cp_index, cache_index);
           status = +1;
         } else {
           status = -1;
@@ -211,7 +211,7 @@
   if (!reverse) {
     int cp_index = Bytes::get_Java_u2(p);
     int cache_index = add_invokedynamic_cp_cache_entry(cp_index);
-    add_invokedynamic_resolved_references_entry(cp_index, cache_index);
+    add_invokedynamic_resolved_references_entries(cp_index, cache_index);
     // Replace the trailing four bytes with a CPC index for the dynamic
     // call site.  Unlike other CPC entries, there is one per bytecode,
     // not just one per distinct CP entry.  In other words, the
--- a/hotspot/src/share/vm/interpreter/rewriter.hpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/interpreter/rewriter.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -113,12 +113,19 @@
     return ref_index;
   }
 
-  // add a new entry to the resolved_references map (for invokedynamic only)
-  int add_invokedynamic_resolved_references_entry(int cp_index, int cache_index) {
+  // add a new entries to the resolved_references map (for invokedynamic and invokehandle only)
+  int add_invokedynamic_resolved_references_entries(int cp_index, int cache_index) {
     assert(_resolved_reference_limit >= 0, "must add indy refs after first iteration");
-    int ref_index = _resolved_references_map.append(cp_index);  // many-to-one
-    assert(ref_index >= _resolved_reference_limit, "");
-    _invokedynamic_references_map.at_put_grow(ref_index, cache_index, -1);
+    int ref_index = -1;
+    for (int entry = 0; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) {
+      const int index = _resolved_references_map.append(cp_index);  // many-to-one
+      assert(index >= _resolved_reference_limit, "");
+      if (entry == 0) {
+        ref_index = index;
+      }
+      assert((index - entry) == ref_index, "entries must be consecutive");
+      _invokedynamic_references_map.at_put_grow(index, cache_index, -1);
+    }
     return ref_index;
   }
 
@@ -127,15 +134,6 @@
     return cp_index;
   }
 
-  // invokedynamic support - append the cpCache entry (encoded) in object map.
-  // The resolved_references_map should still be in ascending order
-  // The resolved_references has the invokedynamic call site objects appended after
-  // the objects that are resolved in the constant pool.
-  int add_callsite_entry(int main_cpc_entry) {
-    int ref_index = _resolved_references_map.append(main_cpc_entry);
-    return ref_index;
-  }
-
   // Access the contents of _cp_cache_map to determine CP cache layout.
   int cp_cache_entry_pool_index(int cache_index) {
     int cp_index = _cp_cache_map[cache_index];
--- a/hotspot/src/share/vm/oops/constantPool.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -445,7 +445,6 @@
   return e->has_appendix();
 }
 
-
 oop ConstantPool::appendix_at_if_loaded(constantPoolHandle cpool, int which) {
   if (cpool->cache() == NULL)  return NULL;  // nothing to load yet
   int cache_index = decode_cpcache_index(which, true);
@@ -454,6 +453,21 @@
 }
 
 
+bool ConstantPool::has_method_type_at_if_loaded(constantPoolHandle cpool, int which) {
+  if (cpool->cache() == NULL)  return false;  // nothing to load yet
+  int cache_index = decode_cpcache_index(which, true);
+  ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index);
+  return e->has_method_type();
+}
+
+oop ConstantPool::method_type_at_if_loaded(constantPoolHandle cpool, int which) {
+  if (cpool->cache() == NULL)  return NULL;  // nothing to load yet
+  int cache_index = decode_cpcache_index(which, true);
+  ConstantPoolCacheEntry* e = cpool->cache()->entry_at(cache_index);
+  return e->method_type_if_resolved(cpool);
+}
+
+
 Symbol* ConstantPool::impl_name_ref_at(int which, bool uncached) {
   int name_index = name_ref_index_at(impl_name_and_type_ref_index_at(which, uncached));
   return symbol_at(name_index);
--- a/hotspot/src/share/vm/oops/constantPool.hpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/oops/constantPool.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -694,13 +694,15 @@
   friend class SystemDictionary;
 
   // Used by compiler to prevent classloading.
-  static Method*         method_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static bool      has_appendix_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static oop           appendix_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static Klass*           klass_at_if_loaded      (constantPoolHandle this_oop, int which);
-  static Klass*       klass_ref_at_if_loaded      (constantPoolHandle this_oop, int which);
+  static Method*          method_at_if_loaded      (constantPoolHandle this_oop, int which);
+  static bool       has_appendix_at_if_loaded      (constantPoolHandle this_oop, int which);
+  static oop            appendix_at_if_loaded      (constantPoolHandle this_oop, int which);
+  static bool    has_method_type_at_if_loaded      (constantPoolHandle this_oop, int which);
+  static oop         method_type_at_if_loaded      (constantPoolHandle this_oop, int which);
+  static Klass*            klass_at_if_loaded      (constantPoolHandle this_oop, int which);
+  static Klass*        klass_ref_at_if_loaded      (constantPoolHandle this_oop, int which);
   // Same as above - but does LinkResolving.
-  static Klass*       klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int which, TRAPS);
+  static Klass*        klass_ref_at_if_loaded_check(constantPoolHandle this_oop, int which, TRAPS);
 
   // Routines currently used for annotations (only called by jvm.cpp) but which might be used in the
   // future by other Java code. These take constant pool indices rather than
--- a/hotspot/src/share/vm/oops/cpCache.cpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/oops/cpCache.cpp	Mon Oct 01 14:50:10 2012 -0700
@@ -244,21 +244,23 @@
 
 
 void ConstantPoolCacheEntry::set_method_handle(constantPoolHandle cpool,
-                                               methodHandle adapter, Handle appendix,
+                                               methodHandle adapter,
+                                               Handle appendix, Handle method_type,
                                                objArrayHandle resolved_references) {
-  set_method_handle_common(cpool, Bytecodes::_invokehandle, adapter, appendix, resolved_references);
+  set_method_handle_common(cpool, Bytecodes::_invokehandle, adapter, appendix, method_type, resolved_references);
 }
 
 void ConstantPoolCacheEntry::set_dynamic_call(constantPoolHandle cpool,
-                                              methodHandle adapter, Handle appendix,
+                                              methodHandle adapter,
+                                              Handle appendix, Handle method_type,
                                               objArrayHandle resolved_references) {
-  set_method_handle_common(cpool, Bytecodes::_invokedynamic, adapter, appendix, resolved_references);
+  set_method_handle_common(cpool, Bytecodes::_invokedynamic, adapter, appendix, method_type, resolved_references);
 }
 
 void ConstantPoolCacheEntry::set_method_handle_common(constantPoolHandle cpool,
                                                       Bytecodes::Code invoke_code,
                                                       methodHandle adapter,
-                                                      Handle appendix,
+                                                      Handle appendix, Handle method_type,
                                                       objArrayHandle resolved_references) {
   // NOTE: This CPCE can be the subject of data races.
   // There are three words to update: flags, refs[f2], f1 (in that order).
@@ -274,18 +276,21 @@
     return;
   }
 
-  bool has_appendix = appendix.not_null();
+  const bool has_appendix    = appendix.not_null();
+  const bool has_method_type = method_type.not_null();
 
   // Write the flags.
   set_method_flags(as_TosState(adapter->result_type()),
-                   ((has_appendix ?  1 : 0) << has_appendix_shift) |
-                   (                 1      << is_final_shift),
+                   ((has_appendix    ? 1 : 0) << has_appendix_shift   ) |
+                   ((has_method_type ? 1 : 0) << has_method_type_shift) |
+                   (                   1      << is_final_shift       ),
                    adapter->size_of_parameters());
 
   if (TraceInvokeDynamic) {
-    tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method="PTR_FORMAT" ",
+    tty->print_cr("set_method_handle bc=%d appendix="PTR_FORMAT"%s method_type="PTR_FORMAT"%s method="PTR_FORMAT" ",
                   invoke_code,
-                  (intptr_t)appendix(), (has_appendix ? "" : " (unused)"),
+                  (intptr_t)appendix(),    (has_appendix    ? "" : " (unused)"),
+                  (intptr_t)method_type(), (has_method_type ? "" : " (unused)"),
                   (intptr_t)adapter());
     adapter->print();
     if (has_appendix)  appendix()->print();
@@ -310,17 +315,26 @@
   // This allows us to create fewer method oops, while keeping type safety.
   //
 
+  // Store appendix, if any.
   if (has_appendix) {
-    int ref_index = f2_as_index();
-    assert(ref_index >= 0 && ref_index < resolved_references->length(), "oob");
-    assert(resolved_references->obj_at(ref_index) == NULL, "init just once");
-    resolved_references->obj_at_put(ref_index, appendix());
+    const int appendix_index = f2_as_index() + _indy_resolved_references_appendix_offset;
+    assert(appendix_index >= 0 && appendix_index < resolved_references->length(), "oob");
+    assert(resolved_references->obj_at(appendix_index) == NULL, "init just once");
+    resolved_references->obj_at_put(appendix_index, appendix());
+  }
+
+  // Store MethodType, if any.
+  if (has_method_type) {
+    const int method_type_index = f2_as_index() + _indy_resolved_references_method_type_offset;
+    assert(method_type_index >= 0 && method_type_index < resolved_references->length(), "oob");
+    assert(resolved_references->obj_at(method_type_index) == NULL, "init just once");
+    resolved_references->obj_at_put(method_type_index, method_type());
   }
 
   release_set_f1(adapter());  // This must be the last one to set (see NOTE above)!
 
-    // The interpreter assembly code does not check byte_2,
-    // but it is used by is_resolved, method_if_resolved, etc.
+  // The interpreter assembly code does not check byte_2,
+  // but it is used by is_resolved, method_if_resolved, etc.
   set_bytecode_1(invoke_code);
   NOT_PRODUCT(verify(tty));
   if (TraceInvokeDynamic) {
@@ -376,7 +390,16 @@
 oop ConstantPoolCacheEntry::appendix_if_resolved(constantPoolHandle cpool) {
   if (is_f1_null() || !has_appendix())
     return NULL;
-  int ref_index = f2_as_index();
+  const int ref_index = f2_as_index() + _indy_resolved_references_appendix_offset;
+  objArrayOop resolved_references = cpool->resolved_references();
+  return resolved_references->obj_at(ref_index);
+}
+
+
+oop ConstantPoolCacheEntry::method_type_if_resolved(constantPoolHandle cpool) {
+  if (is_f1_null() || !has_method_type())
+    return NULL;
+  const int ref_index = f2_as_index() + _indy_resolved_references_method_type_offset;
   objArrayOop resolved_references = cpool->resolved_references();
   return resolved_references->obj_at(ref_index);
 }
@@ -513,13 +536,23 @@
   for (int i = 0; i < length(); i++) {
     ConstantPoolCacheEntry* e = entry_at(i);
     int original_index = inverse_index_map[i];
-      e->initialize_entry(original_index);
+    e->initialize_entry(original_index);
     assert(entry_at(i) == e, "sanity");
-    }
+  }
   for (int ref = 0; ref < invokedynamic_references_map.length(); ref++) {
-    int cpci = invokedynamic_references_map[ref];
-    if (cpci >= 0)
+    const int cpci = invokedynamic_references_map[ref];
+    if (cpci >= 0) {
+#ifdef ASSERT
+      // invokedynamic and invokehandle have more entries; check if they
+      // all point to the same constant pool cache entry.
+      for (int entry = 1; entry < ConstantPoolCacheEntry::_indy_resolved_references_entries; entry++) {
+        const int cpci_next = invokedynamic_references_map[ref + entry];
+        assert(cpci == cpci_next, err_msg_res("%d == %d", cpci, cpci_next));
+      }
+#endif
       entry_at(cpci)->initialize_resolved_reference_index(ref);
+      ref += ConstantPoolCacheEntry::_indy_resolved_references_entries - 1;  // skip extra entries
+    }
   }
 }
 
--- a/hotspot/src/share/vm/oops/cpCache.hpp	Fri Sep 28 14:36:20 2012 -0700
+++ b/hotspot/src/share/vm/oops/cpCache.hpp	Mon Oct 01 14:50:10 2012 -0700
@@ -42,10 +42,10 @@
 // _indices   [ b2 | b1 |  index  ]  index = constant_pool_index
 // _f1        [  entry specific   ]  metadata ptr (method or klass)
 // _f2        [  entry specific   ]  vtable or res_ref index, or vfinal method ptr
-// _flags     [tos|0|F=1|0|0|f|v|0 |00000|field_index] (for field entries)
-// bit length [ 4 |1| 1 |1|1|1|1|1 |--5--|----16-----]
-// _flags     [tos|0|F=0|A|I|f|0|vf|00000|00000|psize] (for method entries)
-// bit length [ 4 |1| 1 |1|1|1|1|1 |--5--|--8--|--8--]
+// _flags     [tos|0|F=1|0|0|0|f|v|0 |0000|field_index] (for field entries)
+// bit length [ 4 |1| 1 |1|1|1|1|1|1 |-4--|----16-----]
+// _flags     [tos|0|F=0|M|A|I|f|0|vf|0000|00000|psize] (for method entries)
+// bit length [ 4 |1| 1 |1|1|1|1|1|1 |-4--|--8--|--8--]
 
 // --------------------------------
 //
@@ -166,11 +166,12 @@
     tos_state_shift            = BitsPerInt - tos_state_bits,  // see verify_tos_state_shift below
     // misc. option bits; can be any bit position in [16..27]
     is_field_entry_shift       = 26,  // (F) is it a field or a method?
-    has_appendix_shift         = 25,  // (A) does the call site have an appendix argument?
-    is_forced_virtual_shift    = 24,  // (I) is the interface reference forced to virtual mode?
-    is_final_shift             = 23,  // (f) is the field or method final?
-    is_volatile_shift          = 22,  // (v) is the field volatile?
-    is_vfinal_shift            = 21,  // (vf) did the call resolve to a final method?
+    has_method_type_shift      = 25,  // (M) does the call site have a MethodType?
+    has_appendix_shift         = 24,  // (A) does the call site have an appendix argument?
+    is_forced_virtual_shift    = 23,  // (I) is the interface reference forced to virtual mode?
+    is_final_shift             = 22,  // (f) is the field or method final?
+    is_volatile_shift          = 21,  // (v) is the field volatile?
+    is_vfinal_shift            = 20,  // (vf) did the call resolve to a final method?
     // low order bits give field index (for FieldInfo) or method parameter size:
     field_index_bits           = 16,
     field_index_mask           = right_n_bits(field_index_bits),
@@ -223,14 +224,16 @@
   void set_method_handle(
     constantPoolHandle cpool,                    // holding constant pool (required for locking)
     methodHandle method,                         // adapter for invokeExact, etc.
-    Handle appendix,                             // stored in refs[f2]; could be a java.lang.invoke.MethodType
+    Handle appendix,                             // stored in refs[f2+0]; could be a java.lang.invoke.MethodType
+    Handle method_type,                          // stored in refs[f2+1]; is a java.lang.invoke.MethodType
     objArrayHandle resolved_references
   );
 
   void set_dynamic_call(
     constantPoolHandle cpool,                    // holding constant pool (required for locking)
     methodHandle method,                         // adapter for this call site
-    Handle appendix,                             // stored in refs[f2]; could be a java.lang.invoke.CallSite
+    Handle appendix,                             // stored in refs[f2+0]; could be a java.lang.invoke.CallSite
+    Handle method_type,                          // stored in refs[f2+1]; is a java.lang.invoke.MethodType
     objArrayHandle resolved_references
   );
 
@@ -253,12 +256,24 @@
     constantPoolHandle cpool,                    // holding constant pool (required for locking)
     Bytecodes::Code invoke_code,                 // _invokehandle or _invokedynamic
     methodHandle adapter,                        // invoker method (f1)
-    Handle appendix,                             // appendix such as CallSite, MethodType, etc. (refs[f2])
+    Handle appendix,                             // appendix such as CallSite, MethodType, etc. (refs[f2+0])
+    Handle method_type,                          // MethodType (refs[f2+1])
     objArrayHandle resolved_references
   );
 
-  Method* method_if_resolved(constantPoolHandle cpool);
-  oop appendix_if_resolved(constantPoolHandle cpool);
+  // invokedynamic and invokehandle call sites have two entries in the
+  // resolved references array:
+  //   appendix   (at index+0)
+  //   MethodType (at index+1)
+  enum {
+    _indy_resolved_references_appendix_offset    = 0,
+    _indy_resolved_references_method_type_offset = 1,
+    _indy_resolved_references_entries
+  };
+
+  Method*      method_if_resolved(constantPoolHandle cpool);
+  oop        appendix_if_resolved(constantPoolHandle cpool);
+  oop     method_type_if_resolved(constantPoolHandle cpool);
 
   void set_parameter_size(int value);
 
@@ -270,11 +285,11 @@
       case Bytecodes::_getfield        :    // fall through
       case Bytecodes::_invokespecial   :    // fall through
       case Bytecodes::_invokestatic    :    // fall through
+      case Bytecodes::_invokehandle    :    // fall through
+      case Bytecodes::_invokedynamic   :    // fall through
       case Bytecodes::_invokeinterface : return 1;
       case Bytecodes::_putstatic       :    // fall through
       case Bytecodes::_putfield        :    // fall through
-      case Bytecodes::_invokehandle    :    // fall through
-      case Bytecodes::_invokedynamic   :    // fall through
       case Bytecodes::_invokevirtual   : return 2;
       default                          : break;
     }
@@ -307,6 +322,7 @@
   bool is_forced_virtual() const                 { return (_flags & (1 << is_forced_virtual_shift)) != 0; }
   bool is_vfinal() const                         { return (_flags & (1 << is_vfinal_shift))         != 0; }
   bool has_appendix() const                      { return (_flags & (1 << has_appendix_shift))      != 0; }
+  bool has_method_type() const                   { return (_flags & (1 << has_method_type_shift))   != 0; }
   bool is_method_entry() const                   { return (_flags & (1 << is_field_entry_shift))    == 0; }
   bool is_field_entry() const                    { return (_flags & (1 << is_field_entry_shift))    != 0; }
   bool is_byte() const                           { return flag_state() == btos; }