indy.compiler: First commit, not enabled in series file.
authortwisti
Wed Jun 17 15:24:43 2009 +0200 (9 months ago)
changeset 52aeb8308e7dfe
parent 51ef9d5753e526
child 539de72da6d165
indy.compiler: First commit, not enabled in series file.
indy.compiler.patch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/indy.compiler.patch Wed Jun 17 15:24:43 2009 +0200
@@ -0,0 +1,885 @@
+diff --git a/src/share/vm/ci/ciCPCache.cpp b/src/share/vm/ci/ciCPCache.cpp
+new file mode 100644
+--- /dev/null
++++ b/src/share/vm/ci/ciCPCache.cpp
+@@ -0,0 +1,56 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
++ * CA 95054 USA or visit www.sun.com if you need additional information or
++ * have any questions.
++ *
++ */
++
++#include "incls/_precompiled.incl"
++#include "incls/_ciCPCache.cpp.incl"
++
++// ciCPCache
++
++// ------------------------------------------------------------------
++// ciCPCache::get_f1_offset
++size_t ciCPCache::get_f1_offset(int index) {
++ int entry_index;
++ // If the index is a secondary index, decode it.
++ if (constantPoolCacheOopDesc::is_secondary_index(index))
++ entry_index = constantPoolCacheOopDesc::decode_secondary_index(index);
++ else
++ entry_index = index;
++
++ // Calculate the offset from the constantPoolCacheOop to the f1
++ // field.
++ ByteSize f1_offset =
++ constantPoolCacheOopDesc::base_offset() +
++ ConstantPoolCacheEntry::size_in_bytes() * entry_index +
++ ConstantPoolCacheEntry::f1_offset();
++
++ return in_bytes(f1_offset);
++}
++
++// ------------------------------------------------------------------
++// ciCPCache::print
++//
++// Print debugging information about the cache.
++void ciCPCache::print() {
++ Unimplemented();
++}
+diff --git a/src/share/vm/ci/ciCPCache.hpp b/src/share/vm/ci/ciCPCache.hpp
+new file mode 100644
+--- /dev/null
++++ b/src/share/vm/ci/ciCPCache.hpp
+@@ -0,0 +1,45 @@
++/*
++ * Copyright 2009 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
++ * CA 95054 USA or visit www.sun.com if you need additional information or
++ * have any questions.
++ *
++ */
++
++// ciCPCache
++//
++// The class represents and entry in the constant pool cache.
++//
++// Note: This class is called ciCPCache as ciConstantPoolCache is used
++// for something different.
++class ciCPCache : public ciObject {
++private:
++
++public:
++ ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {}
++
++ // What kind of ciObject is this?
++ bool is_cpcache() const { return true; }
++
++ // Get the offset in bytes from the oop to the f1 field of the
++ // requested entry.
++ size_t get_f1_offset(int index);
++
++ void print();
++};
+diff --git a/src/share/vm/ci/ciClassList.hpp b/src/share/vm/ci/ciClassList.hpp
+--- a/src/share/vm/ci/ciClassList.hpp
++++ b/src/share/vm/ci/ciClassList.hpp
+@@ -25,6 +25,7 @@
+ class ciEnv;
+ class ciObjectFactory;
+ class ciConstantPoolCache;
++class ciCPCache;
+
+ class ciField;
+ class ciConstant;
+diff --git a/src/share/vm/ci/ciEnv.cpp b/src/share/vm/ci/ciEnv.cpp
+--- a/src/share/vm/ci/ciEnv.cpp
++++ b/src/share/vm/ci/ciEnv.cpp
+@@ -41,6 +41,7 @@ ciObjArrayKlassKlass* ciEnv::_obj_array
+ ciInstanceKlass* ciEnv::_ArrayStoreException;
+ ciInstanceKlass* ciEnv::_Class;
+ ciInstanceKlass* ciEnv::_ClassCastException;
++ciInstanceKlass* ciEnv::_InvokeDynamic;
+ ciInstanceKlass* ciEnv::_Object;
+ ciInstanceKlass* ciEnv::_Throwable;
+ ciInstanceKlass* ciEnv::_Thread;
+@@ -687,6 +688,32 @@ ciMethod* ciEnv::get_method_by_index_imp
+
+
+ // ------------------------------------------------------------------
++// ciEnv::get_fake_invokedynamic_method_impl
++ciMethod* ciEnv::get_fake_invokedynamic_method_impl(ciInstanceKlass* accessor,
++ int index, Bytecodes::Code bc) {
++ assert(bc == Bytecodes::_invokedynamic, "must be invokedynamic");
++ assert(accessor->get_instanceKlass()->is_linked(), "must be linked before accessing constant pool");
++ constantPoolHandle cpool = accessor->get_instanceKlass()->constants();
++
++ // Get the CallSite from the constant pool cache.
++ assert(constantPoolCacheOopDesc::is_secondary_index(index), "must be secondary index");
++ int call_site_index = constantPoolCacheOopDesc::decode_secondary_index(index);
++ ConstantPoolCacheEntry* cpc_entry = cpool->cache()->entry_at(call_site_index);
++ assert(cpc_entry != NULL, "sanity");
++ Handle call_site = cpc_entry->f1();
++
++ // Get the methodOop from the CallSite.
++ methodOop method_oop = (methodOop) sun_dyn_CallSiteImpl::vmmethod(call_site());
++ assert(method_oop != NULL, "sanity");
++ assert(method_oop->is_method_handle_invoke(), "consistent");
++
++ // Get a fake invokedynamic ciMethod.
++// return get_fake_invokedynamic_method(method_oop);
++ return get_object(method_oop)->as_method();
++}
++
++
++// ------------------------------------------------------------------
+ // ciEnv::get_instance_klass_for_declared_method_holder
+ ciInstanceKlass* ciEnv::get_instance_klass_for_declared_method_holder(ciKlass* method_holder) {
+ // For the case of <array>.clone(), the method holder can be a ciArrayKlass
+@@ -708,15 +735,18 @@ ciInstanceKlass* ciEnv::get_instance_kla
+ }
+
+
+-
+-
+ // ------------------------------------------------------------------
+ // ciEnv::get_method_by_index
+ ciMethod* ciEnv::get_method_by_index(ciInstanceKlass* accessor,
+ int index, Bytecodes::Code bc) {
+- GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, bc);)
++ if (bc == Bytecodes::_invokedynamic) {
++ GUARDED_VM_ENTRY(return get_fake_invokedynamic_method_impl(accessor, index, bc);)
++ } else {
++ GUARDED_VM_ENTRY(return get_method_by_index_impl(accessor, index, bc);)
++ }
+ }
+
++
+ // ------------------------------------------------------------------
+ // ciEnv::name_buffer
+ char *ciEnv::name_buffer(int req_len) {
+diff --git a/src/share/vm/ci/ciEnv.hpp b/src/share/vm/ci/ciEnv.hpp
+--- a/src/share/vm/ci/ciEnv.hpp
++++ b/src/share/vm/ci/ciEnv.hpp
+@@ -65,6 +65,7 @@ private:
+ static ciInstanceKlass* _ArrayStoreException;
+ static ciInstanceKlass* _Class;
+ static ciInstanceKlass* _ClassCastException;
++ static ciInstanceKlass* _InvokeDynamic;
+ static ciInstanceKlass* _Object;
+ static ciInstanceKlass* _Throwable;
+ static ciInstanceKlass* _Thread;
+@@ -133,6 +134,8 @@ private:
+ int field_index);
+ ciMethod* get_method_by_index_impl(ciInstanceKlass* loading_klass,
+ int method_index, Bytecodes::Code bc);
++ ciMethod* get_fake_invokedynamic_method_impl(ciInstanceKlass* accessor,
++ int index, Bytecodes::Code bc);
+
+ // Helper methods
+ bool check_klass_accessibility(ciKlass* accessing_klass,
+@@ -166,6 +169,11 @@ private:
+ return _factory->get_unloaded_method(holder, name, signature);
+ }
+
++ // Get a fake ciMethod for an invokedynamic callsite.
++ ciMethod* get_fake_invokedynamic_method(methodOop method_oop) {
++ return _factory->get_fake_invokedynamic_method(method_oop);
++ }
++
+ // Get a ciKlass representing an unloaded klass.
+ // Ensures uniqueness of the result.
+ ciKlass* get_unloaded_klass(ciKlass* accessing_klass,
+@@ -269,6 +277,9 @@ public:
+ ciInstanceKlass* ClassCastException_klass() {
+ return _ClassCastException;
+ }
++ ciInstanceKlass* InvokeDynamic_klass() {
++ return _InvokeDynamic;
++ }
+ ciInstanceKlass* Object_klass() {
+ return _Object;
+ }
+diff --git a/src/share/vm/ci/ciMethod.cpp b/src/share/vm/ci/ciMethod.cpp
+--- a/src/share/vm/ci/ciMethod.cpp
++++ b/src/share/vm/ci/ciMethod.cpp
+@@ -131,6 +131,47 @@ ciMethod::ciMethod(ciInstanceKlass* hold
+
+
+ // ------------------------------------------------------------------
++// ciMethod::ciMethod
++//
++// Fake invokedynamic method.
++//
++// Note: We initialize ciObject with the methodOop so that
++// ciObject.is_loaded() returns true.
++ciMethod::ciMethod(methodOop method_oop) : ciObject(method_oop) {
++ ciEnv* cienv = CURRENT_ENV;
++
++ ciInstanceKlass* holder = cienv->InvokeDynamic_klass(); // This is always java.dyn.InvokeDynamic
++
++ symbolOop name_symbol = method_oop->name();
++ symbolOop signature_symbol = method_oop->signature();
++ ciSymbol* name = cienv->get_object(name_symbol)->as_symbol();
++ ciSymbol* signature = cienv->get_object(signature_symbol)->as_symbol();
++
++ // invokedynamics are treated as invokestatics in the compiler
++ // (e.g. static R InvokeDynamic.#"Q"(SIG)).
++ int flags_bits = (JVM_MH_INVOKE_BITS | JVM_ACC_PUBLIC | JVM_ACC_FINAL | JVM_ACC_STATIC);
++ AccessFlags flags = accessFlags_from(flags_bits);
++
++ // These fields are important.
++ _flags = ciFlags(flags);
++ _name = name;
++ _holder = holder;
++ _signature = new (cienv->arena()) ciSignature(_holder, signature);
++
++ // Default values.
++ _intrinsic_id = vmIntrinsics::_none;
++ _liveness = NULL;
++ _can_be_statically_bound = false;
++ _bcea = NULL;
++ _method_blocks = NULL;
++ _method_data = NULL;
++#ifdef COMPILER2
++ _flow = NULL;
++#endif // COMPILER2
++}
++
++
++// ------------------------------------------------------------------
+ // ciMethod::load_code
+ //
+ // Load the bytecodes and exception handler table for this method.
+@@ -677,7 +718,7 @@ int ciMethod::scale_count(int count, flo
+ // ------------------------------------------------------------------
+ // invokedynamic support
+ //
+-bool ciMethod::is_method_handle_invoke() {
++bool ciMethod::is_method_handle_invoke() const {
+ check_is_loaded();
+ bool flag = ((flags().as_int() & JVM_MH_INVOKE_BITS) == JVM_MH_INVOKE_BITS);
+ #ifdef ASSERT
+diff --git a/src/share/vm/ci/ciMethod.hpp b/src/share/vm/ci/ciMethod.hpp
+--- a/src/share/vm/ci/ciMethod.hpp
++++ b/src/share/vm/ci/ciMethod.hpp
+@@ -75,6 +75,7 @@ class ciMethod : public ciObject {
+
+ ciMethod(methodHandle h_m);
+ ciMethod(ciInstanceKlass* holder, ciSymbol* name, ciSymbol* signature);
++ ciMethod(methodOop method_oop);
+
+ methodOop get_methodOop() const {
+ methodOop m = (methodOop)get_oop();
+@@ -207,7 +208,7 @@ class ciMethod : public ciObject {
+ bool check_call(int refinfo_index, bool is_static) const;
+ void build_method_data(); // make sure it exists in the VM also
+ int scale_count(int count, float prof_factor = 1.); // make MDO count commensurate with IIC
+- bool is_method_handle_invoke();
++ bool is_method_handle_invoke() const;
+ ciInstance* method_handle_type();
+
+ // What kind of ciObject is this?
+diff --git a/src/share/vm/ci/ciObject.hpp b/src/share/vm/ci/ciObject.hpp
+--- a/src/share/vm/ci/ciObject.hpp
++++ b/src/share/vm/ci/ciObject.hpp
+@@ -113,6 +113,7 @@ public:
+
+ // What kind of ciObject is this?
+ virtual bool is_null_object() const { return false; }
++ virtual bool is_cpcache() const { return false; }
+ virtual bool is_instance() { return false; }
+ virtual bool is_method() { return false; }
+ virtual bool is_method_data() { return false; }
+@@ -167,6 +168,10 @@ public:
+ assert(is_null_object(), "bad cast");
+ return (ciNullObject*)this;
+ }
++ ciCPCache* as_cpcache() {
++ assert(is_cpcache(), "bad cast");
++ return (ciCPCache*) this;
++ }
+ ciInstance* as_instance() {
+ assert(is_instance(), "bad cast");
+ return (ciInstance*)this;
+diff --git a/src/share/vm/ci/ciObjectFactory.cpp b/src/share/vm/ci/ciObjectFactory.cpp
+--- a/src/share/vm/ci/ciObjectFactory.cpp
++++ b/src/share/vm/ci/ciObjectFactory.cpp
+@@ -153,6 +153,10 @@ void ciObjectFactory::init_shared_object
+ ciEnv::_ClassCastException =
+ get(SystemDictionary::ClassCastException_klass())
+ ->as_instance_klass();
++ if (EnableInvokeDynamic) {
++ ciEnv::_InvokeDynamic =
++ get(SystemDictionary::InvokeDynamic_klass())->as_instance_klass();
++ }
+ ciEnv::_Object =
+ get(SystemDictionary::object_klass())
+ ->as_instance_klass();
+@@ -329,6 +333,9 @@ ciObject* ciObjectFactory::create_new_ob
+ } else if (o->is_typeArray()) {
+ typeArrayHandle h_ta(THREAD, (typeArrayOop)o);
+ return new (arena()) ciTypeArray(h_ta);
++ } else if (o->is_constantPoolCache()) {
++ constantPoolCacheHandle h_cpc(THREAD, (constantPoolCacheOop) o);
++ return new (arena()) ciCPCache(h_cpc);
+ }
+
+ // The oop is of some type not supported by the compiler interface.
+@@ -368,6 +375,44 @@ ciMethod* ciObjectFactory::get_unloaded_
+ }
+
+ //------------------------------------------------------------------
++// ciObjectFactory::get_fake_invokedynamic_method
++//
++// Get the ciMethod representing a fake invokedynamic method.
++//
++// Implementation note: unloaded methods are currently stored in
++// an unordered array, requiring a linear-time lookup for each
++// unloaded method. This may need to change.
++ciMethod* ciObjectFactory::get_fake_invokedynamic_method(methodOop method_oop) {
++ ciEnv* cienv = CURRENT_ENV;
++
++ ciInstanceKlass* holder = cienv->InvokeDynamic_klass(); // This is always java.dyn.InvokeDynamic
++
++ symbolOop name_symbol = method_oop->name();
++ symbolOop signature_symbol = method_oop->signature();
++ ciSymbol* name = cienv->get_object(name_symbol)->as_symbol();
++ ciSymbol* signature = cienv->get_object(signature_symbol)->as_symbol();
++
++ for (int i = 0; i < _unloaded_methods->length(); i++) {
++ ciMethod* entry = _unloaded_methods->at(i);
++ if (entry->holder()->equals(holder) &&
++ entry->name()->equals(name) &&
++ entry->signature()->as_symbol()->equals(signature)) {
++ // We've found a match.
++ return entry;
++ }
++ }
++
++ // This is a new fake invokedynamic method. Create it and stick it
++ // in the cache.
++ ciMethod* new_method = new (arena()) ciMethod(method_oop);
++
++ init_ident_of(new_method);
++ _unloaded_methods->append(new_method);
++
++ return new_method;
++}
++
++//------------------------------------------------------------------
+ // ciObjectFactory::get_unloaded_klass
+ //
+ // Get a ciKlass representing an unloaded klass.
+diff --git a/src/share/vm/ci/ciObjectFactory.hpp b/src/share/vm/ci/ciObjectFactory.hpp
+--- a/src/share/vm/ci/ciObjectFactory.hpp
++++ b/src/share/vm/ci/ciObjectFactory.hpp
+@@ -93,6 +93,9 @@ public:
+ ciSymbol* name,
+ ciSymbol* signature);
+
++ // Get the ciMethod representing a fake invokedynamic method.
++ ciMethod* get_fake_invokedynamic_method(methodOop method_oop);
++
+ // Get a ciKlass representing an unloaded klass.
+ ciKlass* get_unloaded_klass(ciKlass* accessing_klass,
+ ciSymbol* name,
+diff --git a/src/share/vm/ci/ciStreams.cpp b/src/share/vm/ci/ciStreams.cpp
+--- a/src/share/vm/ci/ciStreams.cpp
++++ b/src/share/vm/ci/ciStreams.cpp
+@@ -321,7 +321,7 @@ int ciBytecodeStream::get_method_index()
+ //
+ // If this is a method invocation bytecode, get the invoked method.
+ ciMethod* ciBytecodeStream::get_method(bool& will_link) {
+- ciMethod* m = CURRENT_ENV->get_method_by_index(_holder, get_method_index(),cur_bc());
++ ciMethod* m = CURRENT_ENV->get_method_by_index(_holder, get_method_index(), cur_bc());
+ will_link = m->is_loaded();
+ return m;
+ }
+@@ -339,9 +339,9 @@ ciMethod* ciBytecodeStream::get_method(b
+ // for checking linkability when retrieving the associated method.
+ ciKlass* ciBytecodeStream::get_declared_method_holder() {
+ bool ignore;
+- // report as Dynamic for invokedynamic, which is syntactically classless
++ // report as InvokeDynamic for invokedynamic, which is syntactically classless
+ if (cur_bc() == Bytecodes::_invokedynamic)
+- return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_Dynamic(), false);
++ return CURRENT_ENV->get_klass_by_name(_holder, ciSymbol::java_dyn_InvokeDynamic(), false);
+ return CURRENT_ENV->get_klass_by_index(_holder, get_method_holder_index(), ignore);
+ }
+
+@@ -370,3 +370,14 @@ int ciBytecodeStream::get_method_signatu
+ int name_and_type_index = cpool->name_and_type_ref_index_at(method_index);
+ return cpool->signature_ref_index_at(name_and_type_index);
+ }
++
++// ------------------------------------------------------------------
++// ciBytecodeStream::get_cpcache
++ciCPCache* ciBytecodeStream::get_cpcache() {
++ VM_ENTRY_MARK;
++ // Get the constant pool.
++ constantPoolOop cpool = _holder->get_instanceKlass()->constants();
++ constantPoolCacheOop cpcache = cpool->cache();
++
++ return CURRENT_ENV->get_object(cpcache)->as_cpcache();
++}
+diff --git a/src/share/vm/ci/ciStreams.hpp b/src/share/vm/ci/ciStreams.hpp
+--- a/src/share/vm/ci/ciStreams.hpp
++++ b/src/share/vm/ci/ciStreams.hpp
+@@ -232,6 +232,8 @@ public:
+ int get_method_holder_index();
+ int get_method_signature_index();
+
++ ciCPCache* get_cpcache();
++
+ private:
+ void assert_index_size(int required_size) const {
+ #ifdef ASSERT
+diff --git a/src/share/vm/ci/ciTypeFlow.cpp b/src/share/vm/ci/ciTypeFlow.cpp
+--- a/src/share/vm/ci/ciTypeFlow.cpp
++++ b/src/share/vm/ci/ciTypeFlow.cpp
+@@ -1292,8 +1292,8 @@ bool ciTypeFlow::StateVector::apply_one_
+ case Bytecodes::_invokeinterface: do_invoke(str, true); break;
+ case Bytecodes::_invokespecial: do_invoke(str, true); break;
+ case Bytecodes::_invokestatic: do_invoke(str, false); break;
+-
+ case Bytecodes::_invokevirtual: do_invoke(str, true); break;
++ case Bytecodes::_invokedynamic: do_invoke(str, false); break;
+
+ case Bytecodes::_istore: store_local_int(str->get_index()); break;
+ case Bytecodes::_istore_0: store_local_int(0); break;
+diff --git a/src/share/vm/classfile/systemDictionary.cpp b/src/share/vm/classfile/systemDictionary.cpp
+--- a/src/share/vm/classfile/systemDictionary.cpp
++++ b/src/share/vm/classfile/systemDictionary.cpp
+@@ -1952,7 +1952,7 @@ void SystemDictionary::initialize_preloa
+ scan = WKID(meth_group_end+1);
+ }
+ WKID indy_group_start = WK_KLASS_ENUM_NAME(Linkage_klass);
+- WKID indy_group_end = WK_KLASS_ENUM_NAME(Dynamic_klass);
++ WKID indy_group_end = WK_KLASS_ENUM_NAME(InvokeDynamic_klass);
+ initialize_wk_klasses_until(indy_group_start, scan, CHECK);
+ if (EnableInvokeDynamic) {
+ initialize_wk_klasses_through(indy_group_start, scan, CHECK);
+diff --git a/src/share/vm/classfile/systemDictionary.hpp b/src/share/vm/classfile/systemDictionary.hpp
+--- a/src/share/vm/classfile/systemDictionary.hpp
++++ b/src/share/vm/classfile/systemDictionary.hpp
+@@ -144,9 +144,9 @@ class SymbolPropertyTable;
+ template(WrongMethodTypeException_klass, java_dyn_WrongMethodTypeException, Opt) \
+ template(Linkage_klass, java_dyn_Linkage, Opt) \
+ template(CallSite_klass, java_dyn_CallSite, Opt) \
+- template(CallSiteImpl_klass, sun_dyn_CallSiteImpl, Opt) \
+- template(Dynamic_klass, java_dyn_Dynamic, Opt) \
+- /* Note: MethodHandle must be first, and Dynamic last in group */ \
++ template(CallSiteImpl_klass, sun_dyn_CallSiteImpl, Opt) \
++ template(InvokeDynamic_klass, java_dyn_InvokeDynamic, Opt) \
++ /* Note: MethodHandle must be first, and InvokeDynamic last in group */ \
+ \
+ template(vector_klass, java_util_Vector, Pre) \
+ template(hashtable_klass, java_util_Hashtable, Pre) \
+diff --git a/src/share/vm/classfile/vmSymbols.hpp b/src/share/vm/classfile/vmSymbols.hpp
+--- a/src/share/vm/classfile/vmSymbols.hpp
++++ b/src/share/vm/classfile/vmSymbols.hpp
+@@ -217,7 +217,7 @@
+ template(base_name, "base") \
+ \
+ /* Support for JSR 292 & invokedynamic (JDK 1.7 and above) */ \
+- template(java_dyn_Dynamic, "java/dyn/Dynamic") \
++ template(java_dyn_InvokeDynamic, "java/dyn/InvokeDynamic") \
+ template(java_dyn_Linkage, "java/dyn/Linkage") \
+ template(java_dyn_CallSite, "java/dyn/CallSite") \
+ template(java_dyn_MethodHandle, "java/dyn/MethodHandle") \
+diff --git a/src/share/vm/compiler/methodLiveness.cpp b/src/share/vm/compiler/methodLiveness.cpp
+--- a/src/share/vm/compiler/methodLiveness.cpp
++++ b/src/share/vm/compiler/methodLiveness.cpp
+@@ -782,6 +782,7 @@ void MethodLiveness::BasicBlock::compute
+ case Bytecodes::_invokespecial:
+ case Bytecodes::_invokestatic:
+ case Bytecodes::_invokeinterface:
++ case Bytecodes::_invokedynamic:
+ case Bytecodes::_newarray:
+ case Bytecodes::_anewarray:
+ case Bytecodes::_checkcast:
+diff --git a/src/share/vm/includeDB_compiler2 b/src/share/vm/includeDB_compiler2
+--- a/src/share/vm/includeDB_compiler2
++++ b/src/share/vm/includeDB_compiler2
+@@ -154,6 +154,7 @@ callGenerator.cpp
+ callGenerator.cpp cfgnode.hpp
+ callGenerator.cpp compileLog.hpp
+ callGenerator.cpp connode.hpp
++callGenerator.cpp ciCPCache.hpp
+ callGenerator.cpp parse.hpp
+ callGenerator.cpp rootnode.hpp
+ callGenerator.cpp runtime.hpp
+diff --git a/src/share/vm/includeDB_core b/src/share/vm/includeDB_core
+--- a/src/share/vm/includeDB_core
++++ b/src/share/vm/includeDB_core
+@@ -532,6 +532,12 @@ ciConstantPoolCache.cpp
+ ciConstantPoolCache.hpp growableArray.hpp
+ ciConstantPoolCache.hpp resourceArea.hpp
+
++ciCPCache.cpp cpCacheOop.hpp
++ciCPCache.cpp ciCPCache.hpp
++
++ciCPCache.hpp ciClassList.hpp
++ciCPCache.hpp ciObject.hpp
++
+ ciEnv.cpp allocation.inline.hpp
+ ciEnv.cpp ciConstant.hpp
+ ciEnv.cpp ciEnv.hpp
+@@ -755,6 +761,7 @@ ciObject.hpp
+ ciObject.hpp jniHandles.hpp
+
+ ciObjectFactory.cpp allocation.inline.hpp
++ciObjectFactory.cpp ciCPCache.hpp
+ ciObjectFactory.cpp ciInstance.hpp
+ ciObjectFactory.cpp ciInstanceKlass.hpp
+ ciObjectFactory.cpp ciInstanceKlassKlass.hpp
+diff --git a/src/share/vm/interpreter/bytecode.cpp b/src/share/vm/interpreter/bytecode.cpp
+--- a/src/share/vm/interpreter/bytecode.cpp
++++ b/src/share/vm/interpreter/bytecode.cpp
+@@ -102,7 +102,9 @@ methodHandle Bytecode_invoke::static_tar
+ KlassHandle resolved_klass;
+ constantPoolHandle constants(THREAD, _method->constants());
+
+- if (adjusted_invoke_code() != Bytecodes::_invokeinterface) {
++ if (adjusted_invoke_code() == Bytecodes::_invokedynamic) {
++ LinkResolver::resolve_dynamic_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
++ } else if (adjusted_invoke_code() != Bytecodes::_invokeinterface) {
+ LinkResolver::resolve_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
+ } else {
+ LinkResolver::resolve_interface_method(m, resolved_klass, constants, index(), CHECK_(methodHandle()));
+diff --git a/src/share/vm/interpreter/bytecode.hpp b/src/share/vm/interpreter/bytecode.hpp
+--- a/src/share/vm/interpreter/bytecode.hpp
++++ b/src/share/vm/interpreter/bytecode.hpp
+@@ -210,7 +210,8 @@ class Bytecode_invoke: public ResourceOb
+ bool is_valid() const { return is_invokeinterface() ||
+ is_invokevirtual() ||
+ is_invokestatic() ||
+- is_invokespecial(); }
++ is_invokespecial() ||
++ is_invokedynamic(); }
+
+ // Creation
+ inline friend Bytecode_invoke* Bytecode_invoke_at(methodHandle method, int bci);
+diff --git a/src/share/vm/interpreter/bytecodes.cpp b/src/share/vm/interpreter/bytecodes.cpp
+--- a/src/share/vm/interpreter/bytecodes.cpp
++++ b/src/share/vm/interpreter/bytecodes.cpp
+@@ -357,7 +357,7 @@ void Bytecodes::initialize() {
+ def(_invokespecial , "invokespecial" , "bjj" , NULL , T_ILLEGAL, -1, true);
+ def(_invokestatic , "invokestatic" , "bjj" , NULL , T_ILLEGAL, 0, true);
+ def(_invokeinterface , "invokeinterface" , "bjj__", NULL , T_ILLEGAL, -1, true);
+- def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, -1, true );
++ def(_invokedynamic , "invokedynamic" , "bjjjj", NULL , T_ILLEGAL, 0, true );
+ def(_new , "new" , "bii" , NULL , T_OBJECT , 1, true );
+ def(_newarray , "newarray" , "bc" , NULL , T_OBJECT , 0, true );
+ def(_anewarray , "anewarray" , "bii" , NULL , T_OBJECT , 0, true );
+diff --git a/src/share/vm/interpreter/linkResolver.cpp b/src/share/vm/interpreter/linkResolver.cpp
+--- a/src/share/vm/interpreter/linkResolver.cpp
++++ b/src/share/vm/interpreter/linkResolver.cpp
+@@ -223,6 +223,21 @@ void LinkResolver::resolve_method(method
+ resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
+ }
+
++void LinkResolver::resolve_dynamic_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) {
++ // The class is java.dyn.MethodHandle
++ resolved_klass = SystemDictionaryHandles::MethodHandle_klass();
++
++ symbolHandle method_name = vmSymbolHandles::invoke_name();
++
++ assert(constantPoolCacheOopDesc::is_secondary_index(index), "must be secondary index");
++ int nt_index = pool->map_instruction_operand_to_index(index);
++
++ symbolHandle method_signature(THREAD, pool->nt_signature_ref_at(nt_index));
++ KlassHandle current_klass (THREAD, pool->pool_holder());
++
++ resolve_method(resolved_method, resolved_klass, method_name, method_signature, current_klass, true, CHECK);
++}
++
+ void LinkResolver::resolve_interface_method(methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS) {
+
+ // resolve klass
+diff --git a/src/share/vm/interpreter/linkResolver.hpp b/src/share/vm/interpreter/linkResolver.hpp
+--- a/src/share/vm/interpreter/linkResolver.hpp
++++ b/src/share/vm/interpreter/linkResolver.hpp
+@@ -133,6 +133,7 @@ class LinkResolver: AllStatic {
+
+ // static resolving for all calls except interface calls
+ static void resolve_method (methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS);
++ static void resolve_dynamic_method (methodHandle& resolved_method, KlassHandle& resolved_klass, constantPoolHandle pool, int index, TRAPS);
+ static void resolve_interface_method(methodHandle& method_result, KlassHandle& klass_result, constantPoolHandle pool, int index, TRAPS);
+
+ // runtime/static resolving for fields
+diff --git a/src/share/vm/oops/cpCacheOop.hpp b/src/share/vm/oops/cpCacheOop.hpp
+--- a/src/share/vm/oops/cpCacheOop.hpp
++++ b/src/share/vm/oops/cpCacheOop.hpp
+@@ -251,6 +251,7 @@ class ConstantPoolCacheEntry VALUE_OBJ_C
+
+ // Code generation support
+ static WordSize size() { return in_WordSize(sizeof(ConstantPoolCacheEntry) / HeapWordSize); }
++ static ByteSize size_in_bytes() { return in_ByteSize(sizeof(ConstantPoolCacheEntry)); }
+ static ByteSize indices_offset() { return byte_offset_of(ConstantPoolCacheEntry, _indices); }
+ static ByteSize f1_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f1); }
+ static ByteSize f2_offset() { return byte_offset_of(ConstantPoolCacheEntry, _f2); }
+diff --git a/src/share/vm/opto/callGenerator.cpp b/src/share/vm/opto/callGenerator.cpp
+--- a/src/share/vm/opto/callGenerator.cpp
++++ b/src/share/vm/opto/callGenerator.cpp
+@@ -1,5 +1,5 @@
+ /*
+- * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
++ * Copyright 2000-2009 Sun Microsystems, Inc. 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
+@@ -135,6 +135,68 @@ JVMState* DirectCallGenerator::generate(
+ return kit.transfer_exceptions_into_jvms();
+ }
+
++//---------------------------DynamicCallGenerator-----------------------------
++// Internal class which handles all out-of-line dynamic calls.
++class DynamicCallGenerator : public CallGenerator {
++public:
++ DynamicCallGenerator(ciMethod* method)
++ : CallGenerator(method)
++ {
++ }
++ virtual JVMState* generate(JVMState* jvms);
++};
++
++JVMState* DynamicCallGenerator::generate(JVMState* jvms) {
++ GraphKit kit(jvms);
++
++ if (kit.C->log() != NULL) {
++ kit.C->log()->elem("dynamic_call bci='%d'", jvms->bci());
++ }
++
++ // Get the constant pool cache from the caller class.
++ ciMethod* caller_method = jvms->method();
++ ciBytecodeStream str(caller_method);
++ str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
++ ciCPCache* cpcache = str.get_cpcache();
++
++ // Get the offset of the CallSite from the constant pool cache
++ // pointer.
++ int index = str.get_method_index();
++ size_t call_site_offset = cpcache->get_f1_offset(index);
++
++ // Load the CallSite object from the constant pool cache.
++ const TypeOopPtr* cpcache_ptr = TypeOopPtr::make_from_constant(cpcache);
++ Node* cpc = kit.makecon(cpcache_ptr);
++ Node* adr = kit.basic_plus_adr(cpc, cpc, call_site_offset);
++ Node* call_site = kit.make_load(kit.control(), adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
++
++ // Load the MethodHandle (target) from the CallSite object.
++ Node* mh_adr = kit.basic_plus_adr(call_site, call_site, sun_dyn_CallSiteImpl::target_offset_in_bytes());
++ Node* mh = kit.make_load(kit.control(), mh_adr, TypeInstPtr::BOTTOM, T_OBJECT);
++
++ address stub = SharedRuntime::get_resolve_opt_virtual_call_stub();
++
++ CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), stub, method(), kit.bci());
++ // invokedynamic is treated as an optimized invokevirtual.
++ call->set_optimized_virtual(true);
++
++ // Pass the MethodHandle as first argument and shift the other
++ // arguments.
++ call->init_req(0 + TypeFunc::Parms, mh);
++ uint nargs = call->method()->arg_size();
++ for (uint i = 1; i < nargs; i++) {
++ Node* arg = kit.argument(i - 1);
++ call->init_req(i + TypeFunc::Parms, arg);
++ }
++
++ kit.set_edges_for_java_call(call);
++ Node* ret = kit.set_results_for_java_call(call);
++ kit.push_node(method()->return_type()->basic_type(), ret);
++ return kit.transfer_exceptions_into_jvms();
++}
++
++//--------------------------VirtualCallGenerator------------------------------
++// Internal class which handles all out-of-line calls checking receiver type.
+ class VirtualCallGenerator : public CallGenerator {
+ private:
+ int _vtable_index;
+@@ -149,8 +211,6 @@ public:
+ virtual JVMState* generate(JVMState* jvms);
+ };
+
+-//--------------------------VirtualCallGenerator------------------------------
+-// Internal class which handles all out-of-line calls checking receiver type.
+ JVMState* VirtualCallGenerator::generate(JVMState* jvms) {
+ GraphKit kit(jvms);
+ Node* receiver = kit.argument(0);
+@@ -243,6 +303,11 @@ CallGenerator* CallGenerator::for_direct
+ return new DirectCallGenerator(m);
+ }
+
++CallGenerator* CallGenerator::for_dynamic_call(ciMethod* m) {
++ assert(m->is_method_handle_invoke(), "for_dynamic_call mismatch");
++ return new DynamicCallGenerator(m);
++}
++
+ CallGenerator* CallGenerator::for_virtual_call(ciMethod* m, int vtable_index) {
+ assert(!m->is_static(), "for_virtual_call mismatch");
+ return new VirtualCallGenerator(m, vtable_index);
+diff --git a/src/share/vm/opto/callGenerator.hpp b/src/share/vm/opto/callGenerator.hpp
+--- a/src/share/vm/opto/callGenerator.hpp
++++ b/src/share/vm/opto/callGenerator.hpp
+@@ -93,6 +93,7 @@ class CallGenerator : public ResourceObj
+
+ // How to generate vanilla out-of-line call sites:
+ static CallGenerator* for_direct_call(ciMethod* m); // static, special
++ static CallGenerator* for_dynamic_call(ciMethod* m); // invokedynamic
+ static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index); // virtual, interface
+
+ // How to make a call but defer the decision whether to inline or not.
+diff --git a/src/share/vm/opto/doCall.cpp b/src/share/vm/opto/doCall.cpp
+--- a/src/share/vm/opto/doCall.cpp
++++ b/src/share/vm/opto/doCall.cpp
+@@ -222,6 +222,8 @@ CallGenerator* Compile::call_generator(c
+ // Use a more generic tactic, like a simple call.
+ if (call_is_virtual) {
+ return CallGenerator::for_virtual_call(call_method, vtable_index);
++ } else if (call_method->is_method_handle_invoke()) {
++ return CallGenerator::for_dynamic_call(call_method);
+ } else {
+ // Class Hierarchy Analysis or Type Profile reveals a unique target,
+ // or it is a static or special call.
+@@ -240,7 +242,7 @@ bool Parse::can_not_compile_call_site(ci
+ // Interface classes can be loaded & linked and never get around to
+ // being initialized. Uncommon-trap for not-initialized static or
+ // v-calls. Let interface calls happen.
+- ciInstanceKlass* holder_klass = dest_method->holder();
++ ciInstanceKlass* holder_klass = dest_method->holder();
+ if (!holder_klass->is_initialized() &&
+ !holder_klass->is_interface()) {
+ uncommon_trap(Deoptimization::Reason_uninitialized,
+@@ -248,14 +250,6 @@ bool Parse::can_not_compile_call_site(ci
+ holder_klass);
+ return true;
+ }
+- if (dest_method->is_method_handle_invoke()
+- && holder_klass->name() == ciSymbol::java_dyn_Dynamic()) {
+- // FIXME: NYI
+- uncommon_trap(Deoptimization::Reason_unhandled,
+- Deoptimization::Action_none,
+- holder_klass);
+- return true;
+- }
+
+ assert(dest_method->will_link(method()->holder(), klass, bc()), "dest_method: typeflow responsibility");
+ return false;
+@@ -282,7 +276,8 @@ void Parse::do_call() {
+ ciKlass* holder = iter().get_declared_method_holder();
+ ciInstanceKlass* klass = ciEnv::get_instance_klass_for_declared_method_holder(holder);
+
+- int nargs = dest_method->arg_size();
++ int nargs = dest_method->arg_size();
++ if (bc() == Bytecodes::_invokedynamic) nargs -= 1;
+
+ // uncommon-trap when callee is unloaded, uninitialized or will not link
+ // bailout when too many arguments for register representation
+@@ -296,7 +291,7 @@ void Parse::do_call() {
+ return;
+ }
+ assert(holder_klass->is_loaded(), "");
+- assert(dest_method->is_static() == !has_receiver, "must match bc");
++ assert((dest_method->is_static() || bc() == Bytecodes::_invokedynamic) == !has_receiver , "must match bc");
+ // Note: this takes into account invokeinterface of methods declared in java/lang/Object,
+ // which should be invokevirtuals but according to the VM spec may be invokeinterfaces
+ assert(holder_klass->is_interface() || holder_klass->super() == NULL || (bc() != Bytecodes::_invokeinterface), "must match bc");
+diff --git a/src/share/vm/opto/graphKit.cpp b/src/share/vm/opto/graphKit.cpp
+--- a/src/share/vm/opto/graphKit.cpp
++++ b/src/share/vm/opto/graphKit.cpp
+@@ -950,14 +950,13 @@ bool GraphKit::compute_stack_effects(int
+ case Bytecodes::_invokedynamic:
+ case Bytecodes::_invokeinterface:
+ {
+- bool is_static = (depth == 0);
+ bool ignore;
+ ciBytecodeStream iter(method());
+ iter.reset_to_bci(bci());
+ iter.next();
+ ciMethod* method = iter.get_method(ignore);
+- inputs = method->arg_size_no_receiver();
+- if (!is_static) inputs += 1;
++ inputs = method->arg_size();
++ if (code == Bytecodes::_invokedynamic) inputs -= 1;
+ int size = method->return_type()->size();
+ depth = size - inputs;
+ }
+diff --git a/src/share/vm/opto/type.cpp b/src/share/vm/opto/type.cpp
+--- a/src/share/vm/opto/type.cpp
++++ b/src/share/vm/opto/type.cpp
+@@ -2391,7 +2391,7 @@ const TypeOopPtr* TypeOopPtr::make_from_
+ //------------------------------make_from_constant-----------------------------
+ // Make a java pointer from an oop constant
+ const TypeOopPtr* TypeOopPtr::make_from_constant(ciObject* o) {
+- if (o->is_method_data() || o->is_method()) {
++ if (o->is_method_data() || o->is_method() || o->is_cpcache()) {
+ // Treat much like a typeArray of bytes, like below, but fake the type...
+ assert(o->has_encoding(), "must be a perm space object");
+ const Type* etype = (Type*)get_const_basic_type(T_BYTE);
+@@ -3903,7 +3903,7 @@ const TypeFunc *TypeFunc::make(ciMethod*
+ const TypeFunc* tf = C->last_tf(method); // check cache
+ if (tf != NULL) return tf; // The hit rate here is almost 50%.
+ const TypeTuple *domain;
+- if (method->flags().is_static()) {
++ if (method->is_static()) {
+ domain = TypeTuple::make_domain(NULL, method->signature());
+ } else {
+ domain = TypeTuple::make_domain(method->holder(), method->signature());
+diff --git a/src/share/vm/runtime/sharedRuntime.cpp b/src/share/vm/runtime/sharedRuntime.cpp
+--- a/src/share/vm/runtime/sharedRuntime.cpp
++++ b/src/share/vm/runtime/sharedRuntime.cpp
+@@ -801,7 +801,7 @@ Handle SharedRuntime::find_callee_info_h
+
+ #ifdef ASSERT
+ // Check that the receiver klass is of the right subtype and that it is initialized for virtual calls
+- if (bc != Bytecodes::_invokestatic) {
++ if (bc != Bytecodes::_invokestatic && bc != Bytecodes::_invokedynamic) {
+ assert(receiver.not_null(), "should have thrown exception");
+ KlassHandle receiver_klass (THREAD, receiver->klass());
+ klassOop rk = constants->klass_ref_at(bytecode_index, CHECK_(nullHandle));
+diff --git a/src/share/vm/runtime/thread.cpp b/src/share/vm/runtime/thread.cpp
+--- a/src/share/vm/runtime/thread.cpp
++++ b/src/share/vm/runtime/thread.cpp
+@@ -3050,6 +3050,12 @@ jint Threads::create_vm(JavaVMInitArgs*
+ warning("java.lang.ArithmeticException has not been initialized");
+ warning("java.lang.StackOverflowError has not been initialized");
+ }
++
++ if (EnableInvokeDynamic) {
++ // JSR 292: An intialized java.dyn.InvokeDynamic is required in
++ // the compiler.
++ initialize_class(vmSymbolHandles::java_dyn_InvokeDynamic(), CHECK_0);
++ }
+ }
+
+ // See : bugid 4211085.