--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/indy.compiler.inline.patch Wed Jul 08 16:45:11 2009 +0200
@@ -0,0 +1,716 @@
+diff --git a/src/share/vm/ci/ciCPCache.cpp b/src/share/vm/ci/ciCPCache.cpp
+--- a/src/share/vm/ci/ciCPCache.cpp
++++ b/src/share/vm/ci/ciCPCache.cpp
+@@ -39,6 +39,7 @@
+ return in_bytes(f1_offset);
+ }
+
++
+ // ------------------------------------------------------------------
+ // ciCPCache::print
+ //
+diff --git a/src/share/vm/ci/ciCPCache.hpp b/src/share/vm/ci/ciCPCache.hpp
+--- a/src/share/vm/ci/ciCPCache.hpp
++++ b/src/share/vm/ci/ciCPCache.hpp
+@@ -29,8 +29,6 @@
+ // Note: This class is called ciCPCache as ciConstantPoolCache is used
+ // for something different.
+ class ciCPCache : public ciObject {
+-private:
+-
+ public:
+ ciCPCache(constantPoolCacheHandle cpcache) : ciObject(cpcache) {}
+
+diff --git a/src/share/vm/ci/ciCallSite.cpp b/src/share/vm/ci/ciCallSite.cpp
+new file mode 100644
+--- /dev/null
++++ b/src/share/vm/ci/ciCallSite.cpp
+@@ -0,0 +1,47 @@
++/*
++ * 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/_ciCallSite.cpp.incl"
++
++// ciCallSite
++
++// ------------------------------------------------------------------
++// ciCallSite::get_target
++//
++// Return the target MethodHandle of this CallSite.
++ciMethodHandle* ciCallSite::get_target() const {
++ VM_ENTRY_MARK;
++ oop call_site = get_oop();
++ oop method_handle = java_dyn_CallSite::target(call_site);
++ return CURRENT_ENV->get_object(method_handle)->as_method_handle();
++}
++
++// ------------------------------------------------------------------
++// ciCallSite::print
++//
++// Print debugging information about the CallSite.
++void ciCallSite::print() {
++ Unimplemented();
++}
+diff --git a/src/share/vm/ci/ciCallSite.hpp b/src/share/vm/ci/ciCallSite.hpp
+new file mode 100644
+--- /dev/null
++++ b/src/share/vm/ci/ciCallSite.hpp
+@@ -0,0 +1,41 @@
++/*
++ * 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.
++ *
++ */
++
++// ciCallSite
++//
++// The class represents a java.dyn.CallSite object.
++class ciCallSite : public ciInstance {
++private:
++
++public:
++ ciCallSite(instanceHandle h_i) : ciInstance(h_i) {}
++
++ // What kind of ciObject is this?
++ bool is_call_site() const { return true; }
++
++ // Return the target MethodHandle of this CallSite.
++ ciMethodHandle* get_target() const;
++
++ 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
+@@ -43,6 +43,8 @@
+ class ciObject;
+ class ciNullObject;
+ class ciInstance;
++class ciCallSite;
++class ciMethodHandle;
+ class ciMethod;
+ class ciMethodData;
+ class ciReceiverTypeData; // part of ciMethodData
+@@ -79,6 +81,7 @@
+ // Any more access must be given explicitly.
+ #define CI_PACKAGE_ACCESS_TO \
+ friend class ciObjectFactory; \
++friend class ciCallSite; \
+ friend class ciConstantPoolCache; \
+ friend class ciField; \
+ friend class ciConstant; \
+@@ -94,6 +97,7 @@
+ friend class ciInstance; \
+ friend class ciMethod; \
+ friend class ciMethodData; \
++friend class ciMethodHandle; \
+ friend class ciReceiverTypeData; \
+ friend class ciSymbol; \
+ friend class ciArray; \
+diff --git a/src/share/vm/ci/ciMethodHandle.cpp b/src/share/vm/ci/ciMethodHandle.cpp
+new file mode 100644
+--- /dev/null
++++ b/src/share/vm/ci/ciMethodHandle.cpp
+@@ -0,0 +1,50 @@
++/*
++ * 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/_ciMethodHandle.cpp.incl"
++
++// ciMethodHandle
++
++// ------------------------------------------------------------------
++// ciMethodHandle::ciMethodHandle
++//
++// Decode the MethodHandle and store the information.
++ciMethodHandle::ciMethodHandle(instanceHandle h_i) : ciInstance(h_i),
++ _receiver_limit(0),
++ _decode_flags(0) {
++ oop method_handle = get_oop();
++ methodOop m = MethodHandles::decode_MethodHandle(method_handle, _receiver_limit, _decode_flags);
++ _method = CURRENT_ENV->get_object(m)->as_method();
++}
++
++
++// ------------------------------------------------------------------
++// ciMethodHandle::print_impl
++//
++// Implementation of the print method.
++void ciMethodHandle::print_impl(outputStream* st) {
++ st->print(" type=");
++ get_oop()->print();
++}
+diff --git a/src/share/vm/ci/ciMethodHandle.hpp b/src/share/vm/ci/ciMethodHandle.hpp
+new file mode 100644
+--- /dev/null
++++ b/src/share/vm/ci/ciMethodHandle.hpp
+@@ -0,0 +1,54 @@
++/*
++ * 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.
++ *
++ */
++
++// ciMethodHandle
++//
++// The class represents a java.dyn.MethodHandle object.
++class ciMethodHandle : public ciInstance {
++private:
++ ciMethod* _method;
++ klassOop _receiver_limit;
++ int _decode_flags; // Flags of MethodHandles::decode
++
++protected:
++ void print_impl(outputStream* st);
++
++public:
++ ciMethodHandle(instanceHandle h_i);
++
++ // What kind of ciObject is this?
++ bool is_method_handle() const { return true; }
++
++ // Does the MethodHandle perform a virtual or interface dispatch?
++ bool does_dispatch() const {
++ assert(_method != NULL, "must be decoded");
++ return (_decode_flags & MethodHandles::_dmf_does_dispatch) != 0;
++ }
++
++ // Return the decoded method of this MethodHandle.
++ ciMethod* get_method() const {
++ assert(_method != NULL, "must be decoded");
++ return _method;
++ }
++};
+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
+@@ -114,10 +114,12 @@
+
+ // What kind of ciObject is this?
+ virtual bool is_null_object() const { return false; }
++ virtual bool is_call_site() 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; }
++ virtual bool is_method_handle() const { return false; }
+ virtual bool is_array() { return false; }
+ virtual bool is_obj_array() { return false; }
+ virtual bool is_type_array() { return false; }
+@@ -169,6 +171,10 @@
+ assert(is_null_object(), "bad cast");
+ return (ciNullObject*)this;
+ }
++ ciCallSite* as_call_site() {
++ assert(is_call_site(), "bad cast");
++ return (ciCallSite*) this;
++ }
+ ciCPCache* as_cpcache() {
+ assert(is_cpcache(), "bad cast");
+ return (ciCPCache*) this;
+@@ -185,6 +191,10 @@
+ assert(is_method_data(), "bad cast");
+ return (ciMethodData*)this;
+ }
++ ciMethodHandle* as_method_handle() {
++ assert(is_method_handle(), "bad cast");
++ return (ciMethodHandle*) this;
++ }
+ ciArray* as_array() {
+ assert(is_array(), "bad cast");
+ return (ciArray*)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
+@@ -326,7 +326,12 @@
+ return new (arena()) ciMethodData(h_md);
+ } else if (o->is_instance()) {
+ instanceHandle h_i(THREAD, (instanceOop)o);
+- return new (arena()) ciInstance(h_i);
++ if (java_dyn_CallSite::is_instance(o))
++ return new (arena()) ciCallSite(h_i);
++ else if (java_dyn_MethodHandle::is_instance(o))
++ return new (arena()) ciMethodHandle(h_i);
++ else
++ return new (arena()) ciInstance(h_i);
+ } else if (o->is_objArray()) {
+ objArrayHandle h_oa(THREAD, (objArrayOop)o);
+ return new (arena()) ciObjArray(h_oa);
+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
+@@ -381,3 +381,20 @@
+
+ return CURRENT_ENV->get_object(cpcache)->as_cpcache();
+ }
++
++// ------------------------------------------------------------------
++// ciBytecodeStream::get_call_site
++ciCallSite* ciBytecodeStream::get_call_site() {
++ VM_ENTRY_MARK;
++ // Get the constant pool.
++ constantPoolOop cpool = _holder->get_instanceKlass()->constants();
++ constantPoolCacheOop cpcache = cpool->cache();
++
++ // Get the CallSite from the constant pool cache.
++ int method_index = get_method_index();
++ ConstantPoolCacheEntry* cpcache_entry = cpcache->secondary_entry_at(method_index);
++ oop call_site = cpcache_entry->f1();
++
++ // Return the CallSite.
++ return CURRENT_ENV->get_object(call_site)->as_call_site();
++}
+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,7 +232,8 @@
+ int get_method_holder_index();
+ int get_method_signature_index();
+
+- ciCPCache* get_cpcache();
++ ciCPCache* get_cpcache();
++ ciCallSite* get_call_site();
+
+ private:
+ void assert_index_size(int required_size) const {
+diff --git a/src/share/vm/classfile/javaClasses.hpp b/src/share/vm/classfile/javaClasses.hpp
+--- a/src/share/vm/classfile/javaClasses.hpp
++++ b/src/share/vm/classfile/javaClasses.hpp
+@@ -1083,6 +1083,14 @@
+ static oop vmmethod(oop site);
+ static void set_vmmethod(oop site, oop ref);
+
++ // Testers
++ static bool is_subclass(klassOop klass) {
++ return Klass::cast(klass)->is_subclass_of(SystemDictionary::CallSite_klass());
++ }
++ static bool is_instance(oop obj) {
++ return obj != NULL && is_subclass(obj->klass());
++ }
++
+ // Accessors for code generation:
+ static int target_offset_in_bytes() { return _target_offset; }
+ static int type_offset_in_bytes() { return _type_offset; }
+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
+@@ -155,6 +155,8 @@
+ callGenerator.cpp compileLog.hpp
+ callGenerator.cpp connode.hpp
+ callGenerator.cpp ciCPCache.hpp
++callGenerator.cpp ciMethodHandle.hpp
++callGenerator.cpp javaClasses.hpp
+ callGenerator.cpp parse.hpp
+ callGenerator.cpp rootnode.hpp
+ callGenerator.cpp runtime.hpp
+@@ -390,6 +392,9 @@
+
+ doCall.cpp addnode.hpp
+ doCall.cpp callGenerator.hpp
++doCall.cpp ciCallSite.hpp
++doCall.cpp ciCPCache.hpp
++doCall.cpp ciMethodHandle.hpp
+ doCall.cpp cfgnode.hpp
+ doCall.cpp compileLog.hpp
+ doCall.cpp linkResolver.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
+@@ -516,6 +516,8 @@
+
+ ciCallProfile.hpp ciClassList.hpp
+
++ciCallSite.cpp ciCallSite.hpp
++
+ ciConstant.cpp allocation.hpp
+ ciConstant.cpp allocation.inline.hpp
+ ciConstant.cpp ciConstant.hpp
+@@ -716,6 +718,12 @@
+ ciMethodKlass.hpp ciKlass.hpp
+ ciMethodKlass.hpp ciSymbol.hpp
+
++ciMethodHandle.cpp ciClassList.hpp
++ciMethodHandle.cpp ciMethodHandle.hpp
++ciMethodHandle.cpp methodHandles.hpp
++
++ciMethodHandle.hpp methodHandles.hpp
++
+ ciNullObject.cpp ciNullObject.hpp
+
+ ciNullObject.hpp ciClassList.hpp
+@@ -761,12 +769,14 @@
+ ciObject.hpp jniHandles.hpp
+
+ ciObjectFactory.cpp allocation.inline.hpp
++ciObjectFactory.cpp ciCallSite.hpp
+ ciObjectFactory.cpp ciCPCache.hpp
+ ciObjectFactory.cpp ciInstance.hpp
+ ciObjectFactory.cpp ciInstanceKlass.hpp
+ ciObjectFactory.cpp ciInstanceKlassKlass.hpp
+ ciObjectFactory.cpp ciMethod.hpp
+ ciObjectFactory.cpp ciMethodData.hpp
++ciObjectFactory.cpp ciMethodHandle.hpp
+ ciObjectFactory.cpp ciMethodKlass.hpp
+ ciObjectFactory.cpp ciNullObject.hpp
+ ciObjectFactory.cpp ciObjArray.hpp
+@@ -801,6 +811,7 @@
+ ciSignature.hpp globalDefinitions.hpp
+ ciSignature.hpp growableArray.hpp
+
++ciStreams.cpp ciCallSite.hpp
+ ciStreams.cpp ciConstant.hpp
+ ciStreams.cpp ciField.hpp
+ ciStreams.cpp ciStreams.hpp
+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
+@@ -138,7 +138,7 @@
+ }
+
+ //---------------------------DynamicCallGenerator-----------------------------
+-// Internal class which handles all out-of-line dynamic calls.
++// Internal class which handles all out-of-line invokedynamic calls.
+ class DynamicCallGenerator : public CallGenerator {
+ public:
+ DynamicCallGenerator(ciMethod* method)
+@@ -169,25 +169,25 @@
+
+ // 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);
++ Node* cpcache_adr = kit.makecon(cpcache_ptr);
++ Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
++ Node* call_site = kit.make_load(kit.control(), call_site_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, java_dyn_CallSite::target_offset_in_bytes());
+- Node* mh = kit.make_load(kit.control(), mh_adr, TypeInstPtr::BOTTOM, T_OBJECT);
++ // Load the target MethodHandle from the CallSite object.
++ Node* target_mh_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
++ Node* target_mh = kit.make_load(kit.control(), target_mh_adr, TypeInstPtr::BOTTOM, T_OBJECT);
+
+- address stub = SharedRuntime::get_resolve_opt_virtual_call_stub();
++ address resolve_stub = SharedRuntime::get_resolve_opt_virtual_call_stub();
+
+- CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), stub, method(), kit.bci());
++ CallStaticJavaNode *call = new (kit.C, tf()->domain()->cnt()) CallStaticJavaNode(tf(), resolve_stub, method(), kit.bci());
+ // invokedynamic is treated as an optimized invokevirtual.
+ call->set_optimized_virtual(true);
+ // Take extra care (in the presence of argument motion) not to trash the SP:
+ call->set_method_handle_invoke(true);
+
+- // Pass the MethodHandle as first argument and shift the other
+- // arguments.
+- call->init_req(0 + TypeFunc::Parms, mh);
++ // Pass the target MethodHandle as first argument and shift the
++ // other arguments.
++ call->init_req(0 + TypeFunc::Parms, target_mh);
+ uint nargs = call->method()->arg_size();
+ for (uint i = 1; i < nargs; i++) {
+ Node* arg = kit.argument(i - 1);
+@@ -598,6 +598,155 @@
+ }
+
+
++//------------------------PredictedDynamicCallGenerator-----------------------
++// Internal class which handles all out-of-line calls checking receiver type.
++class PredictedDynamicCallGenerator : public CallGenerator {
++ ciMethodHandle* _predicted_method_handle;
++ CallGenerator* _if_missed;
++ CallGenerator* _if_hit;
++ float _hit_prob;
++
++public:
++ PredictedDynamicCallGenerator(ciMethodHandle* predicted_method_handle,
++ CallGenerator* if_missed,
++ CallGenerator* if_hit,
++ float hit_prob)
++ : CallGenerator(if_missed->method()),
++ _predicted_method_handle(predicted_method_handle),
++ _if_missed(if_missed),
++ _if_hit(if_hit),
++ _hit_prob(hit_prob)
++ {}
++
++ virtual bool is_inline() const { return _if_hit->is_inline(); }
++ virtual bool is_deferred() const { return _if_hit->is_deferred(); }
++
++ virtual JVMState* generate(JVMState* jvms);
++};
++
++
++CallGenerator* CallGenerator::for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
++ CallGenerator* if_missed,
++ CallGenerator* if_hit,
++ float hit_prob) {
++ return new PredictedDynamicCallGenerator(predicted_method_handle, if_missed, if_hit, hit_prob);
++}
++
++
++JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
++ GraphKit kit(jvms);
++ PhaseGVN& gvn = kit.gvn();
++
++ CompileLog* log = kit.C->log();
++ if (log != NULL) {
++ log->elem("predicted_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* cpcache_adr = kit.makecon(cpcache_ptr);
++ Node* call_site_adr = kit.basic_plus_adr(cpcache_adr, cpcache_adr, call_site_offset);
++ Node* call_site = kit.make_load(kit.control(), call_site_adr, TypeInstPtr::BOTTOM, T_OBJECT, Compile::AliasIdxRaw);
++
++ // Load the target MethodHandle from the CallSite object.
++ Node* target_adr = kit.basic_plus_adr(call_site, call_site, java_dyn_CallSite::target_offset_in_bytes());
++ Node* target_mh = kit.make_load(kit.control(), target_adr, TypeInstPtr::BOTTOM, T_OBJECT);
++
++ // Check if the MethodHandle is still the same.
++ const TypeOopPtr* predicted_mh_ptr = TypeOopPtr::make_from_constant(_predicted_method_handle);
++ Node* predicted_mh = kit.makecon(predicted_mh_ptr);
++
++ Node* cmp = gvn.transform(new(kit.C, 3) CmpPNode(target_mh, predicted_mh));
++ Node* bol = gvn.transform(new(kit.C, 2) BoolNode(cmp, BoolTest::eq) );
++ IfNode* iff = kit.create_and_xform_if(kit.control(), bol, _hit_prob, COUNT_UNKNOWN);
++ kit.set_control( gvn.transform(new(kit.C, 1) IfTrueNode (iff)));
++ Node* slow_ctl = gvn.transform(new(kit.C, 1) IfFalseNode(iff));
++
++ SafePointNode* slow_map = NULL;
++ JVMState* slow_jvms;
++ { PreserveJVMState pjvms(&kit);
++ kit.set_control(slow_ctl);
++ if (!kit.stopped()) {
++ slow_jvms = _if_missed->generate(kit.sync_jvms());
++ assert(slow_jvms != NULL, "miss path must not fail to generate");
++ kit.add_exception_states_from(slow_jvms);
++ kit.set_map(slow_jvms->map());
++ if (!kit.stopped())
++ slow_map = kit.stop();
++ }
++ }
++
++ if (kit.stopped()) {
++ // Instance exactly does not matches the desired type.
++ kit.set_jvms(slow_jvms);
++ return kit.transfer_exceptions_into_jvms();
++ }
++
++ // Make the hot call:
++ JVMState* new_jvms = _if_hit->generate(kit.sync_jvms());
++ if (new_jvms == NULL) {
++ // Inline failed, so make a direct call.
++ assert(_if_hit->is_inline(), "must have been a failed inline");
++ CallGenerator* cg = CallGenerator::for_direct_call(_if_hit->method());
++ new_jvms = cg->generate(kit.sync_jvms());
++ }
++ kit.add_exception_states_from(new_jvms);
++ kit.set_jvms(new_jvms);
++
++ // Need to merge slow and fast?
++ if (slow_map == NULL) {
++ // The fast path is the only path remaining.
++ return kit.transfer_exceptions_into_jvms();
++ }
++
++ if (kit.stopped()) {
++ // Inlined method threw an exception, so it's just the slow path after all.
++ kit.set_jvms(slow_jvms);
++ return kit.transfer_exceptions_into_jvms();
++ }
++
++ // Finish the diamond.
++ kit.C->set_has_split_ifs(true); // Has chance for split-if optimization
++ RegionNode* region = new (kit.C, 3) RegionNode(3);
++ region->init_req(1, kit.control());
++ region->init_req(2, slow_map->control());
++ kit.set_control(gvn.transform(region));
++ Node* iophi = PhiNode::make(region, kit.i_o(), Type::ABIO);
++ iophi->set_req(2, slow_map->i_o());
++ kit.set_i_o(gvn.transform(iophi));
++ kit.merge_memory(slow_map->merged_memory(), region, 2);
++ uint tos = kit.jvms()->stkoff() + kit.sp();
++ uint limit = slow_map->req();
++ for (uint i = TypeFunc::Parms; i < limit; i++) {
++ // Skip unused stack slots; fast forward to monoff();
++ if (i == tos) {
++ i = kit.jvms()->monoff();
++ if( i >= limit ) break;
++ }
++ Node* m = kit.map()->in(i);
++ Node* n = slow_map->in(i);
++ if (m != n) {
++ const Type* t = gvn.type(m)->meet(gvn.type(n));
++ Node* phi = PhiNode::make(region, m, t);
++ phi->set_req(2, n);
++ kit.map()->set_req(i, gvn.transform(phi));
++ }
++ }
++ return kit.transfer_exceptions_into_jvms();
++}
++
++
+ //-------------------------UncommonTrapCallGenerator-----------------------------
+ // Internal class which handles all out-of-line calls checking receiver type.
+ class UncommonTrapCallGenerator : public CallGenerator {
+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
+@@ -107,6 +107,12 @@
+ CallGenerator* if_hit,
+ float hit_prob);
+
++ // How to make a call that optimistically assumes a MethodHandle target:
++ static CallGenerator* for_predicted_dynamic_call(ciMethodHandle* predicted_method_handle,
++ CallGenerator* if_missed,
++ CallGenerator* if_hit,
++ float hit_prob);
++
+ // How to make a call that gives up and goes back to the interpreter:
+ static CallGenerator* for_uncommon_trap(ciMethod* m,
+ Deoptimization::DeoptReason reason,
+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
+@@ -218,16 +218,42 @@
+ }
+ }
+
++ // Do MethodHandle calls.
++ if (call_method->is_method_handle_invoke()) {
++ if (jvms->method()->java_code_at_bci(jvms->bci()) != Bytecodes::_invokedynamic) {
++ // %%% if the target MH is a compile-time constant, we should try to inline it
++ return CallGenerator::for_direct_call(call_method);
++ }
++ else {
++ // Get the MethodHandle from the CallSite.
++ ciMethod* caller_method = jvms->method();
++ ciBytecodeStream str(caller_method);
++ str.force_bci(jvms->bci()); // Set the stream to the invokedynamic bci.
++ ciCallSite* call_site = str.get_call_site();
++ ciMethodHandle* method_handle = call_site->get_target();
++
++ // Get the target method from the MethodHandle.
++ ciMethod* target_method = method_handle->get_method();
++
++ // Currently we online support DirectMethodHandles which are
++ // bound to a methodOop.
++ if (!method_handle->does_dispatch()) {
++ CallGenerator* hit_cg = this->call_generator(target_method, vtable_index, false, jvms, true, prof_factor);
++ if (hit_cg != NULL && hit_cg->is_inline()) {
++ CallGenerator* miss_cg = CallGenerator::for_dynamic_call(call_method);
++ return CallGenerator::for_predicted_dynamic_call(method_handle, miss_cg, hit_cg, prof_factor);
++ }
++ }
++
++ // If something failed, generate a normal dynamic call.
++ return CallGenerator::for_dynamic_call(call_method);
++ }
++ }
++
+ // There was no special inlining tactic, or it bailed out.
+ // 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()) {
+- if (jvms->method()->java_code_at_bci(jvms->bci()) == Bytecodes::_invokedynamic)
+- return CallGenerator::for_dynamic_call(call_method);
+- else
+- // %%% if the target MH is a compile-time constant, we should try to inline it
+- return CallGenerator::for_direct_call(call_method);
+ } else {
+ // Class Hierarchy Analysis or Type Profile reveals a unique target,
+ // or it is a static or special call.