7071653: JSR 292: call site change notification should be pushed not pulled
authortwisti
Tue, 16 Aug 2011 04:14:05 -0700
changeset 10265 4c869854aebd
parent 10264 6879f93d268d
child 10266 2ea344c79e33
7071653: JSR 292: call site change notification should be pushed not pulled Reviewed-by: kvn, never, bdelsart
hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp
hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp
hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp
hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp
hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp
hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp
hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp
hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp
hotspot/src/share/vm/ci/ciCallSite.cpp
hotspot/src/share/vm/ci/ciCallSite.hpp
hotspot/src/share/vm/ci/ciField.hpp
hotspot/src/share/vm/classfile/systemDictionary.cpp
hotspot/src/share/vm/classfile/systemDictionary.hpp
hotspot/src/share/vm/classfile/vmSymbols.hpp
hotspot/src/share/vm/code/dependencies.cpp
hotspot/src/share/vm/code/dependencies.hpp
hotspot/src/share/vm/code/nmethod.cpp
hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
hotspot/src/share/vm/interpreter/templateTable.hpp
hotspot/src/share/vm/memory/universe.cpp
hotspot/src/share/vm/memory/universe.hpp
hotspot/src/share/vm/oops/instanceKlass.cpp
hotspot/src/share/vm/opto/callGenerator.cpp
hotspot/src/share/vm/opto/callGenerator.hpp
hotspot/src/share/vm/opto/doCall.cpp
hotspot/src/share/vm/opto/parse3.cpp
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -758,6 +758,20 @@
 }
 
 
+void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache,
+                                                                        Register temp,
+                                                                        Register bytecode,
+                                                                        int byte_no,
+                                                                        int bcp_offset,
+                                                                        size_t index_size) {
+  get_cache_and_index_at_bcp(cache, temp, bcp_offset, index_size);
+  ld_ptr(cache, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset(), bytecode);
+  const int shift_count = (1 + byte_no) * BitsPerByte;
+  srl( bytecode, shift_count, bytecode);
+  and3(bytecode,        0xFF, bytecode);
+}
+
+
 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
                                                                int bcp_offset, size_t index_size) {
   assert(bcp_offset > 0, "bcp is still pointing to start of bytecode");
--- a/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/cpu/sparc/vm/interp_masm_sparc.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -189,6 +189,7 @@
                                   setCCOrNot should_set_CC = dont_set_CC );
 
   void get_cache_and_index_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register temp, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2));
   void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
   void get_cache_index_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
 
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -149,36 +149,68 @@
 }
 
 
-void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register Rbyte_code,
-                                   Register Rscratch,
-                                   bool load_bc_into_scratch /*=true*/) {
+void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
+                                   Register temp_reg, bool load_bc_into_bc_reg/*=true*/,
+                                   int byte_no) {
   // With sharing on, may need to test methodOop flag.
-  if (!RewriteBytecodes) return;
-  if (load_bc_into_scratch) __ set(bc, Rbyte_code);
-  Label patch_done;
+  if (!RewriteBytecodes)  return;
+  Label L_patch_done;
+
+  switch (bc) {
+  case Bytecodes::_fast_aputfield:
+  case Bytecodes::_fast_bputfield:
+  case Bytecodes::_fast_cputfield:
+  case Bytecodes::_fast_dputfield:
+  case Bytecodes::_fast_fputfield:
+  case Bytecodes::_fast_iputfield:
+  case Bytecodes::_fast_lputfield:
+  case Bytecodes::_fast_sputfield:
+    {
+      // We skip bytecode quickening for putfield instructions when
+      // the put_code written to the constant pool cache is zero.
+      // This is required so that every execution of this instruction
+      // calls out to InterpreterRuntime::resolve_get_put to do
+      // additional, required work.
+      assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
+      assert(load_bc_into_bc_reg, "we use bc_reg as temp");
+      __ get_cache_and_index_and_bytecode_at_bcp(bc_reg, temp_reg, temp_reg, byte_no, 1);
+      __ set(bc, bc_reg);
+      __ cmp_and_br_short(temp_reg, 0, Assembler::equal, Assembler::pn, L_patch_done);  // don't patch
+    }
+    break;
+  default:
+    assert(byte_no == -1, "sanity");
+    if (load_bc_into_bc_reg) {
+      __ set(bc, bc_reg);
+    }
+  }
+
   if (JvmtiExport::can_post_breakpoint()) {
-    Label fast_patch;
-    __ ldub(at_bcp(0), Rscratch);
-    __ cmp_and_br_short(Rscratch, Bytecodes::_breakpoint, Assembler::notEqual, Assembler::pt, fast_patch);
+    Label L_fast_patch;
+    __ ldub(at_bcp(0), temp_reg);
+    __ cmp_and_br_short(temp_reg, Bytecodes::_breakpoint, Assembler::notEqual, Assembler::pt, L_fast_patch);
     // perform the quickening, slowly, in the bowels of the breakpoint table
-    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), Lmethod, Lbcp, Rbyte_code);
-    __ ba_short(patch_done);
-    __ bind(fast_patch);
+    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), Lmethod, Lbcp, bc_reg);
+    __ ba_short(L_patch_done);
+    __ bind(L_fast_patch);
   }
+
 #ifdef ASSERT
   Bytecodes::Code orig_bytecode =  Bytecodes::java_code(bc);
-  Label okay;
-  __ ldub(at_bcp(0), Rscratch);
-  __ cmp(Rscratch, orig_bytecode);
-  __ br(Assembler::equal, false, Assembler::pt, okay);
-  __ delayed() ->cmp(Rscratch, Rbyte_code);
-  __ br(Assembler::equal, false, Assembler::pt, okay);
+  Label L_okay;
+  __ ldub(at_bcp(0), temp_reg);
+  __ cmp(temp_reg, orig_bytecode);
+  __ br(Assembler::equal, false, Assembler::pt, L_okay);
+  __ delayed()->cmp(temp_reg, bc_reg);
+  __ br(Assembler::equal, false, Assembler::pt, L_okay);
   __ delayed()->nop();
-  __ stop("Rewriting wrong bytecode location");
-  __ bind(okay);
+  __ stop("patching the wrong bytecode");
+  __ bind(L_okay);
 #endif
-  __ stb(Rbyte_code, at_bcp(0));
-  __ bind(patch_done);
+
+  // patch bytecode
+  __ stb(bc_reg, at_bcp(0));
+  __ bind(L_patch_done);
 }
 
 //----------------------------------------------------------------------------------------------------
@@ -2061,12 +2093,12 @@
   // Depends on cpCacheOop layout!
   Label resolved;
 
-  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
   if (byte_no == f1_oop) {
     // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
     // This kind of CP cache entry does not need to match the flags byte, because
     // there is a 1-1 relation between bytecode type and CP entry type.
     assert_different_registers(result, Rcache);
+    __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
     __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() +
               ConstantPoolCacheEntry::f1_offset(), result);
     __ tst(result);
@@ -2075,15 +2107,9 @@
   } else {
     assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
     assert(result == noreg, "");  //else change code for setting result
-    const int shift_count = (1 + byte_no)*BitsPerByte;
-
-    __ ld_ptr(Rcache, constantPoolCacheOopDesc::base_offset() +
-              ConstantPoolCacheEntry::indices_offset(), Lbyte_code);
-
-    __ srl(  Lbyte_code, shift_count, Lbyte_code );
-    __ and3( Lbyte_code,        0xFF, Lbyte_code );
-    __ cmp(  Lbyte_code, (int)bytecode());
-    __ br(   Assembler::equal, false, Assembler::pt, resolved);
+    __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, Lbyte_code, byte_no, 1, index_size);
+    __ cmp(Lbyte_code, (int) bytecode());  // have we resolved this bytecode?
+    __ br(Assembler::equal, false, Assembler::pt, resolved);
     __ delayed()->set((int)bytecode(), O1);
   }
 
@@ -2618,150 +2644,162 @@
 
   if (is_static) {
     // putstatic with object type most likely, check that first
-    __ cmp(Rflags, atos );
+    __ cmp(Rflags, atos);
     __ br(Assembler::notEqual, false, Assembler::pt, notObj);
-    __ delayed() ->cmp(Rflags, itos );
+    __ delayed()->cmp(Rflags, itos);
 
     // atos
-    __ pop_ptr();
-    __ verify_oop(Otos_i);
-
-    do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
-
-    __ ba(checkVolatile);
-    __ delayed()->tst(Lscratch);
+    {
+      __ pop_ptr();
+      __ verify_oop(Otos_i);
+      do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
+      __ ba(checkVolatile);
+      __ delayed()->tst(Lscratch);
+    }
 
     __ bind(notObj);
-
-    // cmp(Rflags, itos );
+    // cmp(Rflags, itos);
     __ br(Assembler::notEqual, false, Assembler::pt, notInt);
-    __ delayed() ->cmp(Rflags, btos );
+    __ delayed()->cmp(Rflags, btos);
 
     // itos
-    __ pop_i();
-    __ st(Otos_i, Rclass, Roffset);
-    __ ba(checkVolatile);
-    __ delayed()->tst(Lscratch);
+    {
+      __ pop_i();
+      __ st(Otos_i, Rclass, Roffset);
+      __ ba(checkVolatile);
+      __ delayed()->tst(Lscratch);
+    }
 
     __ bind(notInt);
-
   } else {
     // putfield with int type most likely, check that first
-    __ cmp(Rflags, itos );
+    __ cmp(Rflags, itos);
     __ br(Assembler::notEqual, false, Assembler::pt, notInt);
-    __ delayed() ->cmp(Rflags, atos );
+    __ delayed()->cmp(Rflags, atos);
 
     // itos
-    __ pop_i();
-    pop_and_check_object(Rclass);
-    __ st(Otos_i, Rclass, Roffset);
-    patch_bytecode(Bytecodes::_fast_iputfield, G3_scratch, G4_scratch);
-    __ ba(checkVolatile);
-    __ delayed()->tst(Lscratch);
+    {
+      __ pop_i();
+      pop_and_check_object(Rclass);
+      __ st(Otos_i, Rclass, Roffset);
+      patch_bytecode(Bytecodes::_fast_iputfield, G3_scratch, G4_scratch, true, byte_no);
+      __ ba(checkVolatile);
+      __ delayed()->tst(Lscratch);
+    }
 
     __ bind(notInt);
-    // cmp(Rflags, atos );
+    // cmp(Rflags, atos);
     __ br(Assembler::notEqual, false, Assembler::pt, notObj);
-    __ delayed() ->cmp(Rflags, btos );
+    __ delayed()->cmp(Rflags, btos);
 
     // atos
-    __ pop_ptr();
-    pop_and_check_object(Rclass);
-    __ verify_oop(Otos_i);
-
-    do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
-
-    patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch);
-    __ ba(checkVolatile);
-    __ delayed()->tst(Lscratch);
+    {
+      __ pop_ptr();
+      pop_and_check_object(Rclass);
+      __ verify_oop(Otos_i);
+      do_oop_store(_masm, Rclass, Roffset, 0, Otos_i, G1_scratch, _bs->kind(), false);
+      patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch, true, byte_no);
+      __ ba(checkVolatile);
+      __ delayed()->tst(Lscratch);
+    }
 
     __ bind(notObj);
   }
 
-  // cmp(Rflags, btos );
+  // cmp(Rflags, btos);
   __ br(Assembler::notEqual, false, Assembler::pt, notByte);
-  __ delayed() ->cmp(Rflags, ltos );
+  __ delayed()->cmp(Rflags, ltos);
 
   // btos
-  __ pop_i();
-  if (!is_static) pop_and_check_object(Rclass);
-  __ stb(Otos_i, Rclass, Roffset);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_bputfield, G3_scratch, G4_scratch);
+  {
+    __ pop_i();
+    if (!is_static) pop_and_check_object(Rclass);
+    __ stb(Otos_i, Rclass, Roffset);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_bputfield, G3_scratch, G4_scratch, true, byte_no);
+    }
+    __ ba(checkVolatile);
+    __ delayed()->tst(Lscratch);
   }
-  __ ba(checkVolatile);
-  __ delayed()->tst(Lscratch);
 
   __ bind(notByte);
-
-  // cmp(Rflags, ltos );
+  // cmp(Rflags, ltos);
   __ br(Assembler::notEqual, false, Assembler::pt, notLong);
-  __ delayed() ->cmp(Rflags, ctos );
+  __ delayed()->cmp(Rflags, ctos);
 
   // ltos
-  __ pop_l();
-  if (!is_static) pop_and_check_object(Rclass);
-  __ st_long(Otos_l, Rclass, Roffset);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_lputfield, G3_scratch, G4_scratch);
+  {
+    __ pop_l();
+    if (!is_static) pop_and_check_object(Rclass);
+    __ st_long(Otos_l, Rclass, Roffset);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_lputfield, G3_scratch, G4_scratch, true, byte_no);
+    }
+    __ ba(checkVolatile);
+    __ delayed()->tst(Lscratch);
   }
-  __ ba(checkVolatile);
-  __ delayed()->tst(Lscratch);
 
   __ bind(notLong);
-
-  // cmp(Rflags, ctos );
+  // cmp(Rflags, ctos);
   __ br(Assembler::notEqual, false, Assembler::pt, notChar);
-  __ delayed() ->cmp(Rflags, stos );
+  __ delayed()->cmp(Rflags, stos);
 
   // ctos (char)
-  __ pop_i();
-  if (!is_static) pop_and_check_object(Rclass);
-  __ sth(Otos_i, Rclass, Roffset);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_cputfield, G3_scratch, G4_scratch);
+  {
+    __ pop_i();
+    if (!is_static) pop_and_check_object(Rclass);
+    __ sth(Otos_i, Rclass, Roffset);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_cputfield, G3_scratch, G4_scratch, true, byte_no);
+    }
+    __ ba(checkVolatile);
+    __ delayed()->tst(Lscratch);
   }
-  __ ba(checkVolatile);
-  __ delayed()->tst(Lscratch);
 
   __ bind(notChar);
-  // cmp(Rflags, stos );
+  // cmp(Rflags, stos);
   __ br(Assembler::notEqual, false, Assembler::pt, notShort);
-  __ delayed() ->cmp(Rflags, ftos );
-
-  // stos (char)
-  __ pop_i();
-  if (!is_static) pop_and_check_object(Rclass);
-  __ sth(Otos_i, Rclass, Roffset);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_sputfield, G3_scratch, G4_scratch);
+  __ delayed()->cmp(Rflags, ftos);
+
+  // stos (short)
+  {
+    __ pop_i();
+    if (!is_static) pop_and_check_object(Rclass);
+    __ sth(Otos_i, Rclass, Roffset);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_sputfield, G3_scratch, G4_scratch, true, byte_no);
+    }
+    __ ba(checkVolatile);
+    __ delayed()->tst(Lscratch);
   }
-  __ ba(checkVolatile);
-  __ delayed()->tst(Lscratch);
 
   __ bind(notShort);
-  // cmp(Rflags, ftos );
+  // cmp(Rflags, ftos);
   __ br(Assembler::notZero, false, Assembler::pt, notFloat);
   __ delayed()->nop();
 
   // ftos
-  __ pop_f();
-  if (!is_static) pop_and_check_object(Rclass);
-  __ stf(FloatRegisterImpl::S, Ftos_f, Rclass, Roffset);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_fputfield, G3_scratch, G4_scratch);
+  {
+    __ pop_f();
+    if (!is_static) pop_and_check_object(Rclass);
+    __ stf(FloatRegisterImpl::S, Ftos_f, Rclass, Roffset);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_fputfield, G3_scratch, G4_scratch, true, byte_no);
+    }
+    __ ba(checkVolatile);
+    __ delayed()->tst(Lscratch);
   }
-  __ ba(checkVolatile);
-  __ delayed()->tst(Lscratch);
 
   __ bind(notFloat);
 
   // dtos
-  __ pop_d();
-  if (!is_static) pop_and_check_object(Rclass);
-  __ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_dputfield, G3_scratch, G4_scratch);
+  {
+    __ pop_d();
+    if (!is_static) pop_and_check_object(Rclass);
+    __ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_dputfield, G3_scratch, G4_scratch, true, byte_no);
+    }
   }
 
   __ bind(checkVolatile);
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -233,7 +233,7 @@
 
 void InterpreterMacroAssembler::get_cache_and_index_at_bcp(Register cache, Register index,
                                                            int bcp_offset, size_t index_size) {
-  assert(cache != index, "must use different registers");
+  assert_different_registers(cache, index);
   get_cache_index_at_bcp(index, bcp_offset, index_size);
   movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
   assert(sizeof(ConstantPoolCacheEntry) == 4*wordSize, "adjust code below");
@@ -241,6 +241,20 @@
 }
 
 
+void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache,
+                                                                        Register index,
+                                                                        Register bytecode,
+                                                                        int byte_no,
+                                                                        int bcp_offset,
+                                                                        size_t index_size) {
+  get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size);
+  movptr(bytecode, Address(cache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
+  const int shift_count = (1 + byte_no) * BitsPerByte;
+  shrptr(bytecode, shift_count);
+  andptr(bytecode, 0xFF);
+}
+
+
 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
                                                                int bcp_offset, size_t index_size) {
   assert(cache != tmp, "must use different register");
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_32.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -83,6 +83,7 @@
   }
   void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
   void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2));
   void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
   void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2));
 
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -233,7 +233,7 @@
                                                            Register index,
                                                            int bcp_offset,
                                                            size_t index_size) {
-  assert(cache != index, "must use different registers");
+  assert_different_registers(cache, index);
   get_cache_index_at_bcp(index, bcp_offset, index_size);
   movptr(cache, Address(rbp, frame::interpreter_frame_cache_offset * wordSize));
   assert(sizeof(ConstantPoolCacheEntry) == 4 * wordSize, "adjust code below");
@@ -242,6 +242,22 @@
 }
 
 
+void InterpreterMacroAssembler::get_cache_and_index_and_bytecode_at_bcp(Register cache,
+                                                                        Register index,
+                                                                        Register bytecode,
+                                                                        int byte_no,
+                                                                        int bcp_offset,
+                                                                        size_t index_size) {
+  get_cache_and_index_at_bcp(cache, index, bcp_offset, index_size);
+  // We use a 32-bit load here since the layout of 64-bit words on
+  // little-endian machines allow us that.
+  movl(bytecode, Address(cache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
+  const int shift_count = (1 + byte_no) * BitsPerByte;
+  shrl(bytecode, shift_count);
+  andl(bytecode, 0xFF);
+}
+
+
 void InterpreterMacroAssembler::get_cache_entry_pointer_at_bcp(Register cache,
                                                                Register tmp,
                                                                int bcp_offset,
--- a/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/interp_masm_x86_64.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -100,13 +100,11 @@
   }
 
   void get_unsigned_2_byte_index_at_bcp(Register reg, int bcp_offset);
-  void get_cache_and_index_at_bcp(Register cache, Register index,
-                                  int bcp_offset, size_t index_size = sizeof(u2));
-  void get_cache_entry_pointer_at_bcp(Register cache, Register tmp,
-                                      int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_and_index_at_bcp(Register cache, Register index, int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_and_index_and_bytecode_at_bcp(Register cache, Register index, Register bytecode, int byte_no, int bcp_offset, size_t index_size = sizeof(u2));
+  void get_cache_entry_pointer_at_bcp(Register cache, Register tmp, int bcp_offset, size_t index_size = sizeof(u2));
   void get_cache_index_at_bcp(Register index, int bcp_offset, size_t index_size = sizeof(u2));
 
-
   void pop_ptr(Register r = rax);
   void pop_i(Register r = rax);
   void pop_l(Register r = rax);
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_32.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -202,45 +202,74 @@
 }
 
 
-void TemplateTable::patch_bytecode(Bytecodes::Code bytecode, Register bc,
-                                   Register scratch,
-                                   bool load_bc_into_scratch/*=true*/) {
-
-  if (!RewriteBytecodes) return;
-  // the pair bytecodes have already done the load.
-  if (load_bc_into_scratch) {
-    __ movl(bc, bytecode);
+void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
+                                   Register temp_reg, bool load_bc_into_bc_reg/*=true*/,
+                                   int byte_no) {
+  if (!RewriteBytecodes)  return;
+  Label L_patch_done;
+
+  switch (bc) {
+  case Bytecodes::_fast_aputfield:
+  case Bytecodes::_fast_bputfield:
+  case Bytecodes::_fast_cputfield:
+  case Bytecodes::_fast_dputfield:
+  case Bytecodes::_fast_fputfield:
+  case Bytecodes::_fast_iputfield:
+  case Bytecodes::_fast_lputfield:
+  case Bytecodes::_fast_sputfield:
+    {
+      // We skip bytecode quickening for putfield instructions when
+      // the put_code written to the constant pool cache is zero.
+      // This is required so that every execution of this instruction
+      // calls out to InterpreterRuntime::resolve_get_put to do
+      // additional, required work.
+      assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
+      assert(load_bc_into_bc_reg, "we use bc_reg as temp");
+      __ get_cache_and_index_and_bytecode_at_bcp(bc_reg, temp_reg, temp_reg, byte_no, 1);
+      __ movl(bc_reg, bc);
+      __ cmpl(temp_reg, (int) 0);
+      __ jcc(Assembler::zero, L_patch_done);  // don't patch
+    }
+    break;
+  default:
+    assert(byte_no == -1, "sanity");
+    // the pair bytecodes have already done the load.
+    if (load_bc_into_bc_reg) {
+      __ movl(bc_reg, bc);
+    }
   }
-  Label patch_done;
+
   if (JvmtiExport::can_post_breakpoint()) {
-    Label fast_patch;
+    Label L_fast_patch;
     // if a breakpoint is present we can't rewrite the stream directly
-    __ movzbl(scratch, at_bcp(0));
-    __ cmpl(scratch, Bytecodes::_breakpoint);
-    __ jcc(Assembler::notEqual, fast_patch);
-    __ get_method(scratch);
+    __ movzbl(temp_reg, at_bcp(0));
+    __ cmpl(temp_reg, Bytecodes::_breakpoint);
+    __ jcc(Assembler::notEqual, L_fast_patch);
+    __ get_method(temp_reg);
     // Let breakpoint table handling rewrite to quicker bytecode
-    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, rsi, bc);
+    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), temp_reg, rsi, bc_reg);
 #ifndef ASSERT
-    __ jmpb(patch_done);
+    __ jmpb(L_patch_done);
 #else
-    __ jmp(patch_done);
+    __ jmp(L_patch_done);
 #endif
-    __ bind(fast_patch);
+    __ bind(L_fast_patch);
   }
+
 #ifdef ASSERT
-  Label okay;
-  __ load_unsigned_byte(scratch, at_bcp(0));
-  __ cmpl(scratch, (int)Bytecodes::java_code(bytecode));
-  __ jccb(Assembler::equal, okay);
-  __ cmpl(scratch, bc);
-  __ jcc(Assembler::equal, okay);
+  Label L_okay;
+  __ load_unsigned_byte(temp_reg, at_bcp(0));
+  __ cmpl(temp_reg, (int)Bytecodes::java_code(bc));
+  __ jccb(Assembler::equal, L_okay);
+  __ cmpl(temp_reg, bc_reg);
+  __ jcc(Assembler::equal, L_okay);
   __ stop("patching the wrong bytecode");
-  __ bind(okay);
+  __ bind(L_okay);
 #endif
+
   // patch bytecode
-  __ movb(at_bcp(0), bc);
-  __ bind(patch_done);
+  __ movb(at_bcp(0), bc_reg);
+  __ bind(L_patch_done);
 }
 
 //----------------------------------------------------------------------------------------------------
@@ -2060,24 +2089,20 @@
   assert_different_registers(result, Rcache, index, temp);
 
   Label resolved;
-  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
   if (byte_no == f1_oop) {
     // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
     // This kind of CP cache entry does not need to match the flags byte, because
     // there is a 1-1 relation between bytecode type and CP entry type.
     assert(result != noreg, ""); //else do cmpptr(Address(...), (int32_t) NULL_WORD)
+    __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
     __ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()));
     __ testptr(result, result);
     __ jcc(Assembler::notEqual, resolved);
   } else {
     assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
     assert(result == noreg, "");  //else change code for setting result
-    const int shift_count = (1 + byte_no)*BitsPerByte;
-    __ movl(temp, Address(Rcache, index, Address::times_4, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
-    __ shrl(temp, shift_count);
-    // have we resolved this bytecode?
-    __ andl(temp, 0xFF);
-    __ cmpl(temp, (int)bytecode());
+    __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
+    __ cmpl(temp, (int) bytecode());  // have we resolved this bytecode?
     __ jcc(Assembler::equal, resolved);
   }
 
@@ -2453,138 +2478,153 @@
 
   __ shrl(flags, ConstantPoolCacheEntry::tosBits);
   assert(btos == 0, "change code, btos != 0");
-  // btos
   __ andl(flags, 0x0f);
   __ jcc(Assembler::notZero, notByte);
 
-  __ pop(btos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movb(lo, rax );
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_bputfield, rcx, rbx);
+  // btos
+  {
+    __ pop(btos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movb(lo, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_bputfield, rcx, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notByte);
-  // itos
-  __ cmpl(flags, itos );
+  __ cmpl(flags, itos);
   __ jcc(Assembler::notEqual, notInt);
 
-  __ pop(itos);
-  if (!is_static) pop_and_check_object(obj);
-
-  __ movl(lo, rax );
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_iputfield, rcx, rbx);
+  // itos
+  {
+    __ pop(itos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movl(lo, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_iputfield, rcx, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notInt);
-  // atos
-  __ cmpl(flags, atos );
+  __ cmpl(flags, atos);
   __ jcc(Assembler::notEqual, notObj);
 
-  __ pop(atos);
-  if (!is_static) pop_and_check_object(obj);
-
-  do_oop_store(_masm, lo, rax, _bs->kind(), false);
-
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_aputfield, rcx, rbx);
+  // atos
+  {
+    __ pop(atos);
+    if (!is_static) pop_and_check_object(obj);
+    do_oop_store(_masm, lo, rax, _bs->kind(), false);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_aputfield, rcx, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
 
-  __ jmp(Done);
-
   __ bind(notObj);
-  // ctos
-  __ cmpl(flags, ctos );
+  __ cmpl(flags, ctos);
   __ jcc(Assembler::notEqual, notChar);
 
-  __ pop(ctos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movw(lo, rax );
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_cputfield, rcx, rbx);
+  // ctos
+  {
+    __ pop(ctos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movw(lo, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_cputfield, rcx, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notChar);
-  // stos
-  __ cmpl(flags, stos );
+  __ cmpl(flags, stos);
   __ jcc(Assembler::notEqual, notShort);
 
-  __ pop(stos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movw(lo, rax );
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_sputfield, rcx, rbx);
+  // stos
+  {
+    __ pop(stos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movw(lo, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_sputfield, rcx, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notShort);
-  // ltos
-  __ cmpl(flags, ltos );
+  __ cmpl(flags, ltos);
   __ jcc(Assembler::notEqual, notLong);
 
-  Label notVolatileLong;
-  __ testl(rdx, rdx);
-  __ jcc(Assembler::zero, notVolatileLong);
-
-  __ pop(ltos);  // overwrites rdx, do this after testing volatile.
-  if (!is_static) pop_and_check_object(obj);
-
-  // Replace with real volatile test
-  __ push(rdx);
-  __ push(rax);                 // Must update atomically with FIST
-  __ fild_d(Address(rsp,0));    // So load into FPU register
-  __ fistp_d(lo);               // and put into memory atomically
-  __ addptr(rsp, 2*wordSize);
-  // volatile_barrier();
-  volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
-                                               Assembler::StoreStore));
-  // Don't rewrite volatile version
-  __ jmp(notVolatile);
-
-  __ bind(notVolatileLong);
-
-  __ pop(ltos);  // overwrites rdx
-  if (!is_static) pop_and_check_object(obj);
-  NOT_LP64(__ movptr(hi, rdx));
-  __ movptr(lo, rax);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_lputfield, rcx, rbx);
+  // ltos
+  {
+    Label notVolatileLong;
+    __ testl(rdx, rdx);
+    __ jcc(Assembler::zero, notVolatileLong);
+
+    __ pop(ltos);  // overwrites rdx, do this after testing volatile.
+    if (!is_static) pop_and_check_object(obj);
+
+    // Replace with real volatile test
+    __ push(rdx);
+    __ push(rax);                 // Must update atomically with FIST
+    __ fild_d(Address(rsp,0));    // So load into FPU register
+    __ fistp_d(lo);               // and put into memory atomically
+    __ addptr(rsp, 2*wordSize);
+    // volatile_barrier();
+    volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
+                                                 Assembler::StoreStore));
+    // Don't rewrite volatile version
+    __ jmp(notVolatile);
+
+    __ bind(notVolatileLong);
+
+    __ pop(ltos);  // overwrites rdx
+    if (!is_static) pop_and_check_object(obj);
+    NOT_LP64(__ movptr(hi, rdx));
+    __ movptr(lo, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_lputfield, rcx, rbx, true, byte_no);
+    }
+    __ jmp(notVolatile);
   }
-  __ jmp(notVolatile);
 
   __ bind(notLong);
-  // ftos
-  __ cmpl(flags, ftos );
+  __ cmpl(flags, ftos);
   __ jcc(Assembler::notEqual, notFloat);
 
-  __ pop(ftos);
-  if (!is_static) pop_and_check_object(obj);
-  __ fstp_s(lo);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_fputfield, rcx, rbx);
+  // ftos
+  {
+    __ pop(ftos);
+    if (!is_static) pop_and_check_object(obj);
+    __ fstp_s(lo);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_fputfield, rcx, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notFloat);
-  // dtos
-  __ cmpl(flags, dtos );
+#ifdef ASSERT
+  __ cmpl(flags, dtos);
   __ jcc(Assembler::notEqual, notDouble);
-
-  __ pop(dtos);
-  if (!is_static) pop_and_check_object(obj);
-  __ fstp_d(lo);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_dputfield, rcx, rbx);
+#endif
+
+  // dtos
+  {
+    __ pop(dtos);
+    if (!is_static) pop_and_check_object(obj);
+    __ fstp_d(lo);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_dputfield, rcx, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
-
+
+#ifdef ASSERT
   __ bind(notDouble);
-
   __ stop("Bad state");
+#endif
 
   __ bind(Done);
 
--- a/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86_64.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -203,46 +203,74 @@
   return Address(r13, offset);
 }
 
-void TemplateTable::patch_bytecode(Bytecodes::Code bytecode, Register bc,
-                                   Register scratch,
-                                   bool load_bc_into_scratch/*=true*/) {
-  if (!RewriteBytecodes) {
-    return;
+void TemplateTable::patch_bytecode(Bytecodes::Code bc, Register bc_reg,
+                                   Register temp_reg, bool load_bc_into_bc_reg/*=true*/,
+                                   int byte_no) {
+  if (!RewriteBytecodes)  return;
+  Label L_patch_done;
+
+  switch (bc) {
+  case Bytecodes::_fast_aputfield:
+  case Bytecodes::_fast_bputfield:
+  case Bytecodes::_fast_cputfield:
+  case Bytecodes::_fast_dputfield:
+  case Bytecodes::_fast_fputfield:
+  case Bytecodes::_fast_iputfield:
+  case Bytecodes::_fast_lputfield:
+  case Bytecodes::_fast_sputfield:
+    {
+      // We skip bytecode quickening for putfield instructions when
+      // the put_code written to the constant pool cache is zero.
+      // This is required so that every execution of this instruction
+      // calls out to InterpreterRuntime::resolve_get_put to do
+      // additional, required work.
+      assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
+      assert(load_bc_into_bc_reg, "we use bc_reg as temp");
+      __ get_cache_and_index_and_bytecode_at_bcp(temp_reg, bc_reg, temp_reg, byte_no, 1);
+      __ movl(bc_reg, bc);
+      __ cmpl(temp_reg, (int) 0);
+      __ jcc(Assembler::zero, L_patch_done);  // don't patch
+    }
+    break;
+  default:
+    assert(byte_no == -1, "sanity");
+    // the pair bytecodes have already done the load.
+    if (load_bc_into_bc_reg) {
+      __ movl(bc_reg, bc);
+    }
   }
-  // the pair bytecodes have already done the load.
-  if (load_bc_into_scratch) {
-    __ movl(bc, bytecode);
-  }
-  Label patch_done;
+
   if (JvmtiExport::can_post_breakpoint()) {
-    Label fast_patch;
+    Label L_fast_patch;
     // if a breakpoint is present we can't rewrite the stream directly
-    __ movzbl(scratch, at_bcp(0));
-    __ cmpl(scratch, Bytecodes::_breakpoint);
-    __ jcc(Assembler::notEqual, fast_patch);
-    __ get_method(scratch);
+    __ movzbl(temp_reg, at_bcp(0));
+    __ cmpl(temp_reg, Bytecodes::_breakpoint);
+    __ jcc(Assembler::notEqual, L_fast_patch);
+    __ get_method(temp_reg);
     // Let breakpoint table handling rewrite to quicker bytecode
-    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), scratch, r13, bc);
+    __ call_VM(noreg, CAST_FROM_FN_PTR(address, InterpreterRuntime::set_original_bytecode_at), temp_reg, r13, bc_reg);
 #ifndef ASSERT
-    __ jmpb(patch_done);
+    __ jmpb(L_patch_done);
 #else
-    __ jmp(patch_done);
+    __ jmp(L_patch_done);
 #endif
-    __ bind(fast_patch);
+    __ bind(L_fast_patch);
   }
+
 #ifdef ASSERT
-  Label okay;
-  __ load_unsigned_byte(scratch, at_bcp(0));
-  __ cmpl(scratch, (int) Bytecodes::java_code(bytecode));
-  __ jcc(Assembler::equal, okay);
-  __ cmpl(scratch, bc);
-  __ jcc(Assembler::equal, okay);
+  Label L_okay;
+  __ load_unsigned_byte(temp_reg, at_bcp(0));
+  __ cmpl(temp_reg, (int) Bytecodes::java_code(bc));
+  __ jcc(Assembler::equal, L_okay);
+  __ cmpl(temp_reg, bc_reg);
+  __ jcc(Assembler::equal, L_okay);
   __ stop("patching the wrong bytecode");
-  __ bind(okay);
+  __ bind(L_okay);
 #endif
+
   // patch bytecode
-  __ movb(at_bcp(0), bc);
-  __ bind(patch_done);
+  __ movb(at_bcp(0), bc_reg);
+  __ bind(L_patch_done);
 }
 
 
@@ -2098,24 +2126,20 @@
   assert_different_registers(result, Rcache, index, temp);
 
   Label resolved;
-  __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
   if (byte_no == f1_oop) {
     // We are resolved if the f1 field contains a non-null object (CallSite, etc.)
     // This kind of CP cache entry does not need to match the flags byte, because
     // there is a 1-1 relation between bytecode type and CP entry type.
     assert(result != noreg, ""); //else do cmpptr(Address(...), (int32_t) NULL_WORD)
+    __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
     __ movptr(result, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::f1_offset()));
     __ testptr(result, result);
     __ jcc(Assembler::notEqual, resolved);
   } else {
     assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
     assert(result == noreg, "");  //else change code for setting result
-    const int shift_count = (1 + byte_no) * BitsPerByte;
-    __ movl(temp, Address(Rcache, index, Address::times_ptr, constantPoolCacheOopDesc::base_offset() + ConstantPoolCacheEntry::indices_offset()));
-    __ shrl(temp, shift_count);
-    // have we resolved this bytecode?
-    __ andl(temp, 0xFF);
-    __ cmpl(temp, (int) bytecode());
+    __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
+    __ cmpl(temp, (int) bytecode());  // have we resolved this bytecode?
     __ jcc(Assembler::equal, resolved);
   }
 
@@ -2507,101 +2531,123 @@
   assert(btos == 0, "change code, btos != 0");
   __ andl(flags, 0x0f);
   __ jcc(Assembler::notZero, notByte);
+
   // btos
-  __ pop(btos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movb(field, rax);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx);
+  {
+    __ pop(btos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movb(field, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notByte);
   __ cmpl(flags, atos);
   __ jcc(Assembler::notEqual, notObj);
+
   // atos
-  __ pop(atos);
-  if (!is_static) pop_and_check_object(obj);
-
-  // Store into the field
-  do_oop_store(_masm, field, rax, _bs->kind(), false);
-
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx);
+  {
+    __ pop(atos);
+    if (!is_static) pop_and_check_object(obj);
+    // Store into the field
+    do_oop_store(_masm, field, rax, _bs->kind(), false);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notObj);
   __ cmpl(flags, itos);
   __ jcc(Assembler::notEqual, notInt);
+
   // itos
-  __ pop(itos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movl(field, rax);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx);
+  {
+    __ pop(itos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movl(field, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notInt);
   __ cmpl(flags, ctos);
   __ jcc(Assembler::notEqual, notChar);
+
   // ctos
-  __ pop(ctos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movw(field, rax);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx);
+  {
+    __ pop(ctos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movw(field, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notChar);
   __ cmpl(flags, stos);
   __ jcc(Assembler::notEqual, notShort);
+
   // stos
-  __ pop(stos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movw(field, rax);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx);
+  {
+    __ pop(stos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movw(field, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notShort);
   __ cmpl(flags, ltos);
   __ jcc(Assembler::notEqual, notLong);
+
   // ltos
-  __ pop(ltos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movq(field, rax);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx);
+  {
+    __ pop(ltos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movq(field, rax);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notLong);
   __ cmpl(flags, ftos);
   __ jcc(Assembler::notEqual, notFloat);
+
   // ftos
-  __ pop(ftos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movflt(field, xmm0);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx);
+  {
+    __ pop(ftos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movflt(field, xmm0);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no);
+    }
+    __ jmp(Done);
   }
-  __ jmp(Done);
 
   __ bind(notFloat);
 #ifdef ASSERT
   __ cmpl(flags, dtos);
   __ jcc(Assembler::notEqual, notDouble);
 #endif
+
   // dtos
-  __ pop(dtos);
-  if (!is_static) pop_and_check_object(obj);
-  __ movdbl(field, xmm0);
-  if (!is_static) {
-    patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx);
+  {
+    __ pop(dtos);
+    if (!is_static) pop_and_check_object(obj);
+    __ movdbl(field, xmm0);
+    if (!is_static) {
+      patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no);
+    }
   }
 
 #ifdef ASSERT
@@ -2612,12 +2658,12 @@
 #endif
 
   __ bind(Done);
+
   // Check for volatile store
   __ testl(rdx, rdx);
   __ jcc(Assembler::zero, notVolatile);
   volatile_barrier(Assembler::Membar_mask_bits(Assembler::StoreLoad |
                                                Assembler::StoreStore));
-
   __ bind(notVolatile);
 }
 
--- a/hotspot/src/share/vm/ci/ciCallSite.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/ci/ciCallSite.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -28,6 +28,16 @@
 
 // ciCallSite
 
+bool ciCallSite::is_constant_call_site() {
+  return klass()->is_subclass_of(CURRENT_ENV->ConstantCallSite_klass());
+}
+bool ciCallSite::is_mutable_call_site() {
+  return klass()->is_subclass_of(CURRENT_ENV->MutableCallSite_klass());
+}
+bool ciCallSite::is_volatile_call_site() {
+  return klass()->is_subclass_of(CURRENT_ENV->VolatileCallSite_klass());
+}
+
 // ------------------------------------------------------------------
 // ciCallSite::get_target
 //
--- a/hotspot/src/share/vm/ci/ciCallSite.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/ci/ciCallSite.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -37,6 +37,10 @@
   // What kind of ciObject is this?
   bool is_call_site() const { return true; }
 
+  bool is_constant_call_site();
+  bool is_mutable_call_site();
+  bool is_volatile_call_site();
+
   // Return the target MethodHandle of this CallSite.
   ciMethodHandle* get_target() const;
 
--- a/hotspot/src/share/vm/ci/ciField.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/ci/ciField.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1999, 2011, 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
@@ -178,6 +178,8 @@
   bool is_volatile    () { return flags().is_volatile(); }
   bool is_transient   () { return flags().is_transient(); }
 
+  bool is_call_site_target() { return ((holder() == CURRENT_ENV->CallSite_klass()) && (name() == ciSymbol::target_name())); }
+
   // Debugging output
   void print();
   void print_name_on(outputStream* st);
--- a/hotspot/src/share/vm/classfile/systemDictionary.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -1978,7 +1978,7 @@
 
   // JSR 292 classes
   WKID jsr292_group_start = WK_KLASS_ENUM_NAME(MethodHandle_klass);
-  WKID jsr292_group_end   = WK_KLASS_ENUM_NAME(CallSite_klass);
+  WKID jsr292_group_end   = WK_KLASS_ENUM_NAME(VolatileCallSite_klass);
   initialize_wk_klasses_until(jsr292_group_start, scan, CHECK);
   if (EnableInvokeDynamic) {
     initialize_wk_klasses_through(jsr292_group_end, scan, CHECK);
--- a/hotspot/src/share/vm/classfile/systemDictionary.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/classfile/systemDictionary.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -144,18 +144,21 @@
   template(reflect_UnsafeStaticFieldAccessorImpl_klass, sun_reflect_UnsafeStaticFieldAccessorImpl, Opt_Only_JDK15) \
                                                                               \
   /* support for dynamic typing; it's OK if these are NULL in earlier JDKs */ \
-  template(MethodHandle_klass,           java_lang_invoke_MethodHandle,     Pre_JSR292) \
-  template(MemberName_klass,             java_lang_invoke_MemberName,       Pre_JSR292) \
-  template(MethodHandleNatives_klass,    java_lang_invoke_MethodHandleNatives, Pre_JSR292) \
-  template(AdapterMethodHandle_klass,    java_lang_invoke_AdapterMethodHandle, Pre_JSR292) \
-  template(BoundMethodHandle_klass,      java_lang_invoke_BoundMethodHandle, Pre_JSR292) \
-  template(DirectMethodHandle_klass,     java_lang_invoke_DirectMethodHandle, Pre_JSR292) \
-  template(MethodType_klass,             java_lang_invoke_MethodType,       Pre_JSR292) \
-  template(MethodTypeForm_klass,         java_lang_invoke_MethodTypeForm,   Pre_JSR292) \
-  template(BootstrapMethodError_klass,   java_lang_BootstrapMethodError, Pre_JSR292) \
+  template(MethodHandle_klass,             java_lang_invoke_MethodHandle,             Pre_JSR292) \
+  template(MemberName_klass,               java_lang_invoke_MemberName,               Pre_JSR292) \
+  template(MethodHandleNatives_klass,      java_lang_invoke_MethodHandleNatives,      Pre_JSR292) \
+  template(AdapterMethodHandle_klass,      java_lang_invoke_AdapterMethodHandle,      Pre_JSR292) \
+  template(BoundMethodHandle_klass,        java_lang_invoke_BoundMethodHandle,        Pre_JSR292) \
+  template(DirectMethodHandle_klass,       java_lang_invoke_DirectMethodHandle,       Pre_JSR292) \
+  template(MethodType_klass,               java_lang_invoke_MethodType,               Pre_JSR292) \
+  template(MethodTypeForm_klass,           java_lang_invoke_MethodTypeForm,           Pre_JSR292) \
+  template(BootstrapMethodError_klass,     java_lang_BootstrapMethodError,            Pre_JSR292) \
   template(WrongMethodTypeException_klass, java_lang_invoke_WrongMethodTypeException, Pre_JSR292) \
-  template(CallSite_klass,               java_lang_invoke_CallSite,         Pre_JSR292) \
-  /* Note: MethodHandle must be first, and CallSite last in group */          \
+  template(CallSite_klass,                 java_lang_invoke_CallSite,                 Pre_JSR292) \
+  template(ConstantCallSite_klass,         java_lang_invoke_ConstantCallSite,         Pre_JSR292) \
+  template(MutableCallSite_klass,          java_lang_invoke_MutableCallSite,          Pre_JSR292) \
+  template(VolatileCallSite_klass,         java_lang_invoke_VolatileCallSite,         Pre_JSR292) \
+  /* Note: MethodHandle must be first, and VolatileCallSite last in group */  \
                                                                               \
   template(StringBuffer_klass,           java_lang_StringBuffer,         Pre) \
   template(StringBuilder_klass,          java_lang_StringBuilder,        Pre) \
--- a/hotspot/src/share/vm/classfile/vmSymbols.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/classfile/vmSymbols.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -233,6 +233,9 @@
   template(java_lang_invoke_InvokeDynamic,            "java/lang/invoke/InvokeDynamic")           \
   template(java_lang_invoke_Linkage,                  "java/lang/invoke/Linkage")                 \
   template(java_lang_invoke_CallSite,                 "java/lang/invoke/CallSite")                \
+  template(java_lang_invoke_ConstantCallSite,         "java/lang/invoke/ConstantCallSite")        \
+  template(java_lang_invoke_MutableCallSite,          "java/lang/invoke/MutableCallSite")         \
+  template(java_lang_invoke_VolatileCallSite,         "java/lang/invoke/VolatileCallSite")        \
   template(java_lang_invoke_MethodHandle,             "java/lang/invoke/MethodHandle")            \
   template(java_lang_invoke_MethodType,               "java/lang/invoke/MethodType")              \
   template(java_lang_invoke_WrongMethodTypeException, "java/lang/invoke/WrongMethodTypeException") \
--- a/hotspot/src/share/vm/code/dependencies.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/code/dependencies.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -113,6 +113,11 @@
   assert_common_1(no_finalizable_subclasses, ctxk);
 }
 
+void Dependencies::assert_call_site_target_value(ciKlass* ctxk, ciCallSite* call_site, ciMethodHandle* method_handle) {
+  check_ctxk(ctxk);
+  assert_common_3(call_site_target_value, ctxk, call_site, method_handle);
+}
+
 // Helper function.  If we are adding a new dep. under ctxk2,
 // try to find an old dep. under a broader* ctxk1.  If there is
 //
@@ -341,7 +346,8 @@
   "unique_concrete_method",
   "abstract_with_exclusive_concrete_subtypes_2",
   "exclusive_concrete_methods_2",
-  "no_finalizable_subclasses"
+  "no_finalizable_subclasses",
+  "call_site_target_value"
 };
 
 int Dependencies::_dep_args[TYPE_LIMIT] = {
@@ -354,7 +360,8 @@
   2, // unique_concrete_method ctxk, m
   3, // unique_concrete_subtypes_2 ctxk, k1, k2
   3, // unique_concrete_methods_2 ctxk, m1, m2
-  1  // no_finalizable_subclasses ctxk
+  1, // no_finalizable_subclasses ctxk
+  3  // call_site_target_value ctxk, call_site, method_handle
 };
 
 const char* Dependencies::dep_name(Dependencies::DepType dept) {
@@ -367,6 +374,13 @@
   return _dep_args[dept];
 }
 
+void Dependencies::check_valid_dependency_type(DepType dept) {
+  for (int deptv = (int) FIRST_TYPE; deptv < (int) TYPE_LIMIT; deptv++) {
+    if (dept == ((DepType) deptv))  return;
+  }
+  ShouldNotReachHere();
+}
+
 // for the sake of the compiler log, print out current dependencies:
 void Dependencies::log_all_dependencies() {
   if (log() == NULL)  return;
@@ -800,11 +814,11 @@
                                  bool participants_hide_witnesses,
                                  bool top_level_call = true);
   // the spot-checking version:
-  klassOop find_witness_in(DepChange& changes,
+  klassOop find_witness_in(KlassDepChange& changes,
                            klassOop context_type,
                            bool participants_hide_witnesses);
  public:
-  klassOop find_witness_subtype(klassOop context_type, DepChange* changes = NULL) {
+  klassOop find_witness_subtype(klassOop context_type, KlassDepChange* changes = NULL) {
     assert(doing_subtype_search(), "must set up a subtype search");
     // When looking for unexpected concrete types,
     // do not look beneath expected ones.
@@ -817,7 +831,7 @@
       return find_witness_anywhere(context_type, participants_hide_witnesses);
     }
   }
-  klassOop find_witness_definer(klassOop context_type, DepChange* changes = NULL) {
+  klassOop find_witness_definer(klassOop context_type, KlassDepChange* changes = NULL) {
     assert(!doing_subtype_search(), "must set up a method definer search");
     // When looking for unexpected concrete methods,
     // look beneath expected ones, to see if there are overrides.
@@ -878,7 +892,7 @@
 #endif //PRODUCT
 
 
-klassOop ClassHierarchyWalker::find_witness_in(DepChange& changes,
+klassOop ClassHierarchyWalker::find_witness_in(KlassDepChange& changes,
                                                klassOop context_type,
                                                bool participants_hide_witnesses) {
   assert(changes.involves_context(context_type), "irrelevant dependency");
@@ -1137,7 +1151,7 @@
 // when dealing with the types of actual instances.
 klassOop Dependencies::check_abstract_with_unique_concrete_subtype(klassOop ctxk,
                                                                    klassOop conck,
-                                                                   DepChange* changes) {
+                                                                   KlassDepChange* changes) {
   ClassHierarchyWalker wf(conck);
   return wf.find_witness_subtype(ctxk, changes);
 }
@@ -1146,7 +1160,7 @@
 // instantiatable.  This can allow the compiler to make some paths go
 // dead, if they are gated by a test of the type.
 klassOop Dependencies::check_abstract_with_no_concrete_subtype(klassOop ctxk,
-                                                               DepChange* changes) {
+                                                               KlassDepChange* changes) {
   // Find any concrete subtype, with no participants:
   ClassHierarchyWalker wf;
   return wf.find_witness_subtype(ctxk, changes);
@@ -1156,7 +1170,7 @@
 // If a concrete class has no concrete subtypes, it can always be
 // exactly typed.  This allows the use of a cheaper type test.
 klassOop Dependencies::check_concrete_with_no_concrete_subtype(klassOop ctxk,
-                                                               DepChange* changes) {
+                                                               KlassDepChange* changes) {
   // Find any concrete subtype, with only the ctxk as participant:
   ClassHierarchyWalker wf(ctxk);
   return wf.find_witness_subtype(ctxk, changes);
@@ -1217,7 +1231,7 @@
                                                 klassOop ctxk,
                                                 klassOop k1,
                                                 klassOop k2,
-                                                DepChange* changes) {
+                                                KlassDepChange* changes) {
   ClassHierarchyWalker wf;
   wf.add_participant(k1);
   wf.add_participant(k2);
@@ -1278,7 +1292,7 @@
 // If a class (or interface) has a unique concrete method uniqm, return NULL.
 // Otherwise, return a class that contains an interfering method.
 klassOop Dependencies::check_unique_concrete_method(klassOop ctxk, methodOop uniqm,
-                                                    DepChange* changes) {
+                                                    KlassDepChange* changes) {
   // Here is a missing optimization:  If uniqm->is_final(),
   // we don't really need to search beneath it for overrides.
   // This is probably not important, since we don't use dependencies
@@ -1321,7 +1335,7 @@
 klassOop Dependencies::check_exclusive_concrete_methods(klassOop ctxk,
                                                         methodOop m1,
                                                         methodOop m2,
-                                                        DepChange* changes) {
+                                                        KlassDepChange* changes) {
   ClassHierarchyWalker wf(m1);
   wf.add_participant(m1->method_holder());
   wf.add_participant(m2->method_holder());
@@ -1383,7 +1397,7 @@
 }
 
 
-klassOop Dependencies::check_has_no_finalizable_subclasses(klassOop ctxk, DepChange* changes) {
+klassOop Dependencies::check_has_no_finalizable_subclasses(klassOop ctxk, KlassDepChange* changes) {
   Klass* search_at = ctxk->klass_part();
   if (changes != NULL)
     search_at = changes->new_type()->klass_part(); // just look at the new bit
@@ -1395,8 +1409,39 @@
 }
 
 
-klassOop Dependencies::DepStream::check_dependency_impl(DepChange* changes) {
+klassOop Dependencies::check_call_site_target_value(klassOop ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes) {
+  assert(call_site    ->is_a(SystemDictionary::CallSite_klass()),     "sanity");
+  assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "sanity");
+  if (changes == NULL) {
+    // Validate all CallSites
+    if (java_lang_invoke_CallSite::target(call_site) != method_handle)
+      return ctxk;  // assertion failed
+  } else {
+    // Validate the given CallSite
+    if (call_site == changes->call_site() && java_lang_invoke_CallSite::target(call_site) != changes->method_handle()) {
+      assert(method_handle != changes->method_handle(), "must be");
+      return ctxk;  // assertion failed
+    }
+  }
+  assert(java_lang_invoke_CallSite::target(call_site) == method_handle, "should still be valid");
+  return NULL;  // assertion still valid
+}
+
+
+void Dependencies::DepStream::trace_and_log_witness(klassOop witness) {
+  if (witness != NULL) {
+    if (TraceDependencies) {
+      print_dependency(witness, /*verbose=*/ true);
+    }
+    // The following is a no-op unless logging is enabled:
+    log_dependency(witness);
+  }
+}
+
+
+klassOop Dependencies::DepStream::check_klass_dependency(KlassDepChange* changes) {
   assert_locked_or_safepoint(Compile_lock);
+  Dependencies::check_valid_dependency_type(type());
 
   klassOop witness = NULL;
   switch (type()) {
@@ -1407,95 +1452,103 @@
     witness = check_leaf_type(context_type());
     break;
   case abstract_with_unique_concrete_subtype:
-    witness = check_abstract_with_unique_concrete_subtype(context_type(),
-                                                          type_argument(1),
-                                                          changes);
+    witness = check_abstract_with_unique_concrete_subtype(context_type(), type_argument(1), changes);
     break;
   case abstract_with_no_concrete_subtype:
-    witness = check_abstract_with_no_concrete_subtype(context_type(),
-                                                      changes);
+    witness = check_abstract_with_no_concrete_subtype(context_type(), changes);
     break;
   case concrete_with_no_concrete_subtype:
-    witness = check_concrete_with_no_concrete_subtype(context_type(),
-                                                      changes);
+    witness = check_concrete_with_no_concrete_subtype(context_type(), changes);
     break;
   case unique_concrete_method:
-    witness = check_unique_concrete_method(context_type(),
-                                           method_argument(1),
-                                           changes);
+    witness = check_unique_concrete_method(context_type(), method_argument(1), changes);
     break;
   case abstract_with_exclusive_concrete_subtypes_2:
-    witness = check_abstract_with_exclusive_concrete_subtypes(context_type(),
-                                                              type_argument(1),
-                                                              type_argument(2),
-                                                              changes);
+    witness = check_abstract_with_exclusive_concrete_subtypes(context_type(), type_argument(1), type_argument(2), changes);
     break;
   case exclusive_concrete_methods_2:
-    witness = check_exclusive_concrete_methods(context_type(),
-                                               method_argument(1),
-                                               method_argument(2),
-                                               changes);
+    witness = check_exclusive_concrete_methods(context_type(), method_argument(1), method_argument(2), changes);
     break;
   case no_finalizable_subclasses:
-    witness = check_has_no_finalizable_subclasses(context_type(),
-                                                  changes);
+    witness = check_has_no_finalizable_subclasses(context_type(), changes);
     break;
-          default:
+  default:
     witness = NULL;
-    ShouldNotReachHere();
     break;
   }
-  if (witness != NULL) {
-    if (TraceDependencies) {
-      print_dependency(witness, /*verbose=*/ true);
-    }
-    // The following is a no-op unless logging is enabled:
-    log_dependency(witness);
+  trace_and_log_witness(witness);
+  return witness;
+}
+
+
+klassOop Dependencies::DepStream::check_call_site_dependency(CallSiteDepChange* changes) {
+  assert_locked_or_safepoint(Compile_lock);
+  Dependencies::check_valid_dependency_type(type());
+
+  klassOop witness = NULL;
+  switch (type()) {
+  case call_site_target_value:
+    witness = check_call_site_target_value(context_type(), argument(1), argument(2), changes);
+    break;
+  default:
+    witness = NULL;
+    break;
   }
+  trace_and_log_witness(witness);
   return witness;
 }
 
 
 klassOop Dependencies::DepStream::spot_check_dependency_at(DepChange& changes) {
-  if (!changes.involves_context(context_type()))
-    // irrelevant dependency; skip it
-    return NULL;
+  // Handle klass dependency
+  if (changes.is_klass_change() && changes.as_klass_change()->involves_context(context_type()))
+    return check_klass_dependency(changes.as_klass_change());
 
-  return check_dependency_impl(&changes);
+  // Handle CallSite dependency
+  if (changes.is_call_site_change())
+    return check_call_site_dependency(changes.as_call_site_change());
+
+  // irrelevant dependency; skip it
+  return NULL;
 }
 
 
-void DepChange::initialize() {
-  // entire transaction must be under this lock:
-  assert_lock_strong(Compile_lock);
-
-  // Mark all dependee and all its superclasses
-  // Mark transitive interfaces
+void DepChange::print() {
+  int nsup = 0, nint = 0;
   for (ContextStream str(*this); str.next(); ) {
-    klassOop d = str.klass();
-    assert(!instanceKlass::cast(d)->is_marked_dependent(), "checking");
-    instanceKlass::cast(d)->set_is_marked_dependent(true);
+    klassOop k = str.klass();
+    switch (str.change_type()) {
+    case Change_new_type:
+      tty->print_cr("  dependee = %s", instanceKlass::cast(k)->external_name());
+      break;
+    case Change_new_sub:
+      if (!WizardMode) {
+        ++nsup;
+      } else {
+        tty->print_cr("  context super = %s", instanceKlass::cast(k)->external_name());
+      }
+      break;
+    case Change_new_impl:
+      if (!WizardMode) {
+        ++nint;
+      } else {
+        tty->print_cr("  context interface = %s", instanceKlass::cast(k)->external_name());
+      }
+      break;
+    }
+  }
+  if (nsup + nint != 0) {
+    tty->print_cr("  context supers = %d, interfaces = %d", nsup, nint);
   }
 }
 
-DepChange::~DepChange() {
-  // Unmark all dependee and all its superclasses
-  // Unmark transitive interfaces
-  for (ContextStream str(*this); str.next(); ) {
-    klassOop d = str.klass();
-    instanceKlass::cast(d)->set_is_marked_dependent(false);
-  }
-}
-
-bool DepChange::involves_context(klassOop k) {
-  if (k == NULL || !Klass::cast(k)->oop_is_instance()) {
-    return false;
-  }
-  instanceKlass* ik = instanceKlass::cast(k);
-  bool is_contained = ik->is_marked_dependent();
-  assert(is_contained == Klass::cast(new_type())->is_subtype_of(k),
-         "correct marking of potential context types");
-  return is_contained;
+void DepChange::ContextStream::start() {
+  klassOop new_type = _changes.is_klass_change() ? _changes.as_klass_change()->new_type() : (klassOop) NULL;
+  _change_type = (new_type == NULL ? NO_CHANGE : Start_Klass);
+  _klass = new_type;
+  _ti_base = NULL;
+  _ti_index = 0;
+  _ti_limit = 0;
 }
 
 bool DepChange::ContextStream::next() {
@@ -1534,35 +1587,39 @@
   return false;
 }
 
-void DepChange::print() {
-  int nsup = 0, nint = 0;
+void KlassDepChange::initialize() {
+  // entire transaction must be under this lock:
+  assert_lock_strong(Compile_lock);
+
+  // Mark all dependee and all its superclasses
+  // Mark transitive interfaces
   for (ContextStream str(*this); str.next(); ) {
-    klassOop k = str.klass();
-    switch (str.change_type()) {
-    case Change_new_type:
-      tty->print_cr("  dependee = %s", instanceKlass::cast(k)->external_name());
-      break;
-    case Change_new_sub:
-      if (!WizardMode) {
-        ++nsup;
-      } else {
-        tty->print_cr("  context super = %s", instanceKlass::cast(k)->external_name());
-      }
-      break;
-    case Change_new_impl:
-      if (!WizardMode) {
-        ++nint;
-      } else {
-        tty->print_cr("  context interface = %s", instanceKlass::cast(k)->external_name());
-      }
-      break;
-    }
+    klassOop d = str.klass();
+    assert(!instanceKlass::cast(d)->is_marked_dependent(), "checking");
+    instanceKlass::cast(d)->set_is_marked_dependent(true);
   }
-  if (nsup + nint != 0) {
-    tty->print_cr("  context supers = %d, interfaces = %d", nsup, nint);
+}
+
+KlassDepChange::~KlassDepChange() {
+  // Unmark all dependee and all its superclasses
+  // Unmark transitive interfaces
+  for (ContextStream str(*this); str.next(); ) {
+    klassOop d = str.klass();
+    instanceKlass::cast(d)->set_is_marked_dependent(false);
   }
 }
 
+bool KlassDepChange::involves_context(klassOop k) {
+  if (k == NULL || !Klass::cast(k)->oop_is_instance()) {
+    return false;
+  }
+  instanceKlass* ik = instanceKlass::cast(k);
+  bool is_contained = ik->is_marked_dependent();
+  assert(is_contained == Klass::cast(new_type())->is_subtype_of(k),
+         "correct marking of potential context types");
+  return is_contained;
+}
+
 #ifndef PRODUCT
 void Dependencies::print_statistics() {
   if (deps_find_witness_print != 0) {
--- a/hotspot/src/share/vm/code/dependencies.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/code/dependencies.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2005, 2011, 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
@@ -25,18 +25,21 @@
 #ifndef SHARE_VM_CODE_DEPENDENCIES_HPP
 #define SHARE_VM_CODE_DEPENDENCIES_HPP
 
+#include "ci/ciCallSite.hpp"
 #include "ci/ciKlass.hpp"
+#include "ci/ciMethodHandle.hpp"
+#include "classfile/systemDictionary.hpp"
 #include "code/compressedStream.hpp"
 #include "code/nmethod.hpp"
 #include "utilities/growableArray.hpp"
 
 //** Dependencies represent assertions (approximate invariants) within
-// the class hierarchy.  An example is an assertion that a given
-// method is not overridden; another example is that a type has only
-// one concrete subtype.  Compiled code which relies on such
-// assertions must be discarded if they are overturned by changes in
-// the class hierarchy.  We can think of these assertions as
-// approximate invariants, because we expect them to be overturned
+// the runtime system, e.g. class hierarchy changes.  An example is an
+// assertion that a given method is not overridden; another example is
+// that a type has only one concrete subtype.  Compiled code which
+// relies on such assertions must be discarded if they are overturned
+// by changes in the runtime system.  We can think of these assertions
+// as approximate invariants, because we expect them to be overturned
 // very infrequently.  We are willing to perform expensive recovery
 // operations when they are overturned.  The benefit, of course, is
 // performing optimistic optimizations (!) on the object code.
@@ -52,6 +55,8 @@
 class xmlStream;
 class CompileLog;
 class DepChange;
+class   KlassDepChange;
+class   CallSiteDepChange;
 class No_Safepoint_Verifier;
 
 class Dependencies: public ResourceObj {
@@ -152,6 +157,9 @@
     // subclasses require finalization registration.
     no_finalizable_subclasses,
 
+    // This dependency asserts when the CallSite.target value changed.
+    call_site_target_value,
+
     TYPE_LIMIT
   };
   enum {
@@ -179,6 +187,7 @@
   static int  dep_context_arg(DepType dept) {
     return dept_in_mask(dept, ctxk_types)? 0: -1;
   }
+  static void check_valid_dependency_type(DepType dept);
 
  private:
   // State for writing a new set of dependencies:
@@ -255,6 +264,7 @@
   void assert_abstract_with_exclusive_concrete_subtypes(ciKlass* ctxk, ciKlass* k1, ciKlass* k2);
   void assert_exclusive_concrete_methods(ciKlass* ctxk, ciMethod* m1, ciMethod* m2);
   void assert_has_no_finalizable_subclasses(ciKlass* ctxk);
+  void assert_call_site_target_value(ciKlass* ctxk, ciCallSite* call_site, ciMethodHandle* method_handle);
 
   // Define whether a given method or type is concrete.
   // These methods define the term "concrete" as used in this module.
@@ -296,19 +306,19 @@
   static klassOop check_evol_method(methodOop m);
   static klassOop check_leaf_type(klassOop ctxk);
   static klassOop check_abstract_with_unique_concrete_subtype(klassOop ctxk, klassOop conck,
-                                                              DepChange* changes = NULL);
+                                                              KlassDepChange* changes = NULL);
   static klassOop check_abstract_with_no_concrete_subtype(klassOop ctxk,
-                                                          DepChange* changes = NULL);
+                                                          KlassDepChange* changes = NULL);
   static klassOop check_concrete_with_no_concrete_subtype(klassOop ctxk,
-                                                          DepChange* changes = NULL);
+                                                          KlassDepChange* changes = NULL);
   static klassOop check_unique_concrete_method(klassOop ctxk, methodOop uniqm,
-                                               DepChange* changes = NULL);
+                                               KlassDepChange* changes = NULL);
   static klassOop check_abstract_with_exclusive_concrete_subtypes(klassOop ctxk, klassOop k1, klassOop k2,
-                                                                  DepChange* changes = NULL);
+                                                                  KlassDepChange* changes = NULL);
   static klassOop check_exclusive_concrete_methods(klassOop ctxk, methodOop m1, methodOop m2,
-                                                   DepChange* changes = NULL);
-  static klassOop check_has_no_finalizable_subclasses(klassOop ctxk,
-                                                      DepChange* changes = NULL);
+                                                   KlassDepChange* changes = NULL);
+  static klassOop check_has_no_finalizable_subclasses(klassOop ctxk, KlassDepChange* changes = NULL);
+  static klassOop check_call_site_target_value(klassOop ctxk, oop call_site, oop method_handle, CallSiteDepChange* changes = NULL);
   // A returned klassOop is NULL if the dependency assertion is still
   // valid.  A non-NULL klassOop is a 'witness' to the assertion
   // failure, a point in the class hierarchy where the assertion has
@@ -415,7 +425,10 @@
     inline oop recorded_oop_at(int i);
         // => _code? _code->oop_at(i): *_deps->_oop_recorder->handle_at(i)
 
-    klassOop check_dependency_impl(DepChange* changes);
+    klassOop check_klass_dependency(KlassDepChange* changes);
+    klassOop check_call_site_dependency(CallSiteDepChange* changes);
+
+    void trace_and_log_witness(klassOop witness);
 
   public:
     DepStream(Dependencies* deps)
@@ -453,10 +466,13 @@
       return (klassOop) x;
     }
 
-    // The point of the whole exercise:  Is this dep is still OK?
+    // The point of the whole exercise:  Is this dep still OK?
     klassOop check_dependency() {
-      return check_dependency_impl(NULL);
+      klassOop result = check_klass_dependency(NULL);
+      if (result != NULL)  return result;
+      return check_call_site_dependency(NULL);
     }
+
     // A lighter version:  Checks only around recent changes in a class
     // hierarchy.  (See Universe::flush_dependents_on.)
     klassOop spot_check_dependency_at(DepChange& changes);
@@ -472,13 +488,27 @@
   static void print_statistics() PRODUCT_RETURN;
 };
 
-// A class hierarchy change coming through the VM (under the Compile_lock).
-// The change is structured as a single new type with any number of supers
-// and implemented interface types.  Other than the new type, any of the
-// super types can be context types for a relevant dependency, which the
-// new type could invalidate.
+
+// Every particular DepChange is a sub-class of this class.
 class DepChange : public StackObj {
  public:
+  // What kind of DepChange is this?
+  virtual bool is_klass_change()     const { return false; }
+  virtual bool is_call_site_change() const { return false; }
+
+  // Subclass casting with assertions.
+  KlassDepChange*    as_klass_change() {
+    assert(is_klass_change(), "bad cast");
+    return (KlassDepChange*) this;
+  }
+  CallSiteDepChange* as_call_site_change() {
+    assert(is_call_site_change(), "bad cast");
+    return (CallSiteDepChange*) this;
+  }
+
+  void print();
+
+ public:
   enum ChangeType {
     NO_CHANGE = 0,              // an uninvolved klass
     Change_new_type,            // a newly loaded type
@@ -488,28 +518,6 @@
     Start_Klass = CHANGE_LIMIT  // internal indicator for ContextStream
   };
 
- private:
-  // each change set is rooted in exactly one new type (at present):
-  KlassHandle _new_type;
-
-  void initialize();
-
- public:
-  // notes the new type, marks it and all its super-types
-  DepChange(KlassHandle new_type)
-    : _new_type(new_type)
-  {
-    initialize();
-  }
-
-  // cleans up the marks
-  ~DepChange();
-
-  klassOop new_type()                   { return _new_type(); }
-
-  // involves_context(k) is true if k is new_type or any of the super types
-  bool involves_context(klassOop k);
-
   // Usage:
   // for (DepChange::ContextStream str(changes); str.next(); ) {
   //   klassOop k = str.klass();
@@ -530,14 +538,7 @@
     int         _ti_limit;
 
     // start at the beginning:
-    void start() {
-      klassOop new_type = _changes.new_type();
-      _change_type = (new_type == NULL ? NO_CHANGE: Start_Klass);
-      _klass = new_type;
-      _ti_base = NULL;
-      _ti_index = 0;
-      _ti_limit = 0;
-    }
+    void start();
 
    public:
     ContextStream(DepChange& changes)
@@ -555,8 +556,62 @@
     klassOop   klass()           { return _klass; }
   };
   friend class DepChange::ContextStream;
+};
 
-  void print();
+
+// A class hierarchy change coming through the VM (under the Compile_lock).
+// The change is structured as a single new type with any number of supers
+// and implemented interface types.  Other than the new type, any of the
+// super types can be context types for a relevant dependency, which the
+// new type could invalidate.
+class KlassDepChange : public DepChange {
+ private:
+  // each change set is rooted in exactly one new type (at present):
+  KlassHandle _new_type;
+
+  void initialize();
+
+ public:
+  // notes the new type, marks it and all its super-types
+  KlassDepChange(KlassHandle new_type)
+    : _new_type(new_type)
+  {
+    initialize();
+  }
+
+  // cleans up the marks
+  ~KlassDepChange();
+
+  // What kind of DepChange is this?
+  virtual bool is_klass_change() const { return true; }
+
+  klassOop new_type() { return _new_type(); }
+
+  // involves_context(k) is true if k is new_type or any of the super types
+  bool involves_context(klassOop k);
+};
+
+
+// A CallSite has changed its target.
+class CallSiteDepChange : public DepChange {
+ private:
+  Handle _call_site;
+  Handle _method_handle;
+
+ public:
+  CallSiteDepChange(Handle call_site, Handle method_handle)
+    : _call_site(call_site),
+      _method_handle(method_handle)
+  {
+    assert(_call_site()    ->is_a(SystemDictionary::CallSite_klass()),     "must be");
+    assert(_method_handle()->is_a(SystemDictionary::MethodHandle_klass()), "must be");
+  }
+
+  // What kind of DepChange is this?
+  virtual bool is_call_site_change() const { return true; }
+
+  oop call_site()     const { return _call_site();     }
+  oop method_handle() const { return _method_handle(); }
 };
 
 #endif // SHARE_VM_CODE_DEPENDENCIES_HPP
--- a/hotspot/src/share/vm/code/nmethod.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/code/nmethod.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -25,6 +25,7 @@
 #include "precompiled.hpp"
 #include "code/codeCache.hpp"
 #include "code/compiledIC.hpp"
+#include "code/dependencies.hpp"
 #include "code/nmethod.hpp"
 #include "code/scopeDesc.hpp"
 #include "compiler/abstractCompiler.hpp"
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -509,6 +509,7 @@
   // resolve field
   FieldAccessInfo info;
   constantPoolHandle pool(thread, method(thread)->constants());
+  bool is_put    = (bytecode == Bytecodes::_putfield  || bytecode == Bytecodes::_putstatic);
   bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic);
 
   {
@@ -528,8 +529,6 @@
   // exceptions at the correct place. If we do not resolve completely
   // in the current pass, leaving the put_code set to zero will
   // cause the next put instruction to reresolve.
-  bool is_put = (bytecode == Bytecodes::_putfield ||
-                 bytecode == Bytecodes::_putstatic);
   Bytecodes::Code put_code = (Bytecodes::Code)0;
 
   // We also need to delay resolving getstatic instructions until the
@@ -541,7 +540,6 @@
                                !klass->is_initialized());
   Bytecodes::Code get_code = (Bytecodes::Code)0;
 
-
   if (!uninitialized_static) {
     get_code = ((is_static) ? Bytecodes::_getstatic : Bytecodes::_getfield);
     if (is_put || !info.access_flags().is_final()) {
@@ -549,6 +547,23 @@
     }
   }
 
+  if (is_put && !is_static && klass->is_subclass_of(SystemDictionary::CallSite_klass()) && (info.name() == vmSymbols::target_name())) {
+    const jint direction = frame::interpreter_frame_expression_stack_direction();
+    oop call_site     = *((oop*) thread->last_frame().interpreter_frame_tos_at(-1 * direction));
+    oop method_handle = *((oop*) thread->last_frame().interpreter_frame_tos_at( 0 * direction));
+    assert(call_site    ->is_a(SystemDictionary::CallSite_klass()),     "must be");
+    assert(method_handle->is_a(SystemDictionary::MethodHandle_klass()), "must be");
+
+    {
+      // Walk all nmethods depending on CallSite
+      MutexLocker mu(Compile_lock, thread);
+      Universe::flush_dependents_on(call_site, method_handle);
+    }
+
+    // Don't allow fast path for setting CallSite.target and sub-classes.
+    put_code = (Bytecodes::Code) 0;
+  }
+
   cache_entry(thread)->set_field(
     get_code,
     put_code,
--- a/hotspot/src/share/vm/interpreter/templateTable.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/interpreter/templateTable.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -120,8 +120,8 @@
 
   // helpers
   static void unimplemented_bc();
-  static void patch_bytecode(Bytecodes::Code bc, Register scratch1,
-                             Register scratch2, bool load_bc_in_scratch = true);
+  static void patch_bytecode(Bytecodes::Code bc, Register bc_reg,
+                             Register temp_reg, bool load_bc_into_bc_reg = true, int byte_no = -1);
 
   // C calls
   static void call_VM(Register oop_result, address entry_point);
--- a/hotspot/src/share/vm/memory/universe.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/memory/universe.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -1177,7 +1177,7 @@
   // stopped dring the safepoint so CodeCache will be safe to update without
   // holding the CodeCache_lock.
 
-  DepChange changes(dependee);
+  KlassDepChange changes(dependee);
 
   // Compute the dependent nmethods
   if (CodeCache::mark_for_deoptimization(changes) > 0) {
@@ -1187,6 +1187,37 @@
   }
 }
 
+// Flushes compiled methods dependent on a particular CallSite
+// instance when its target is different than the given MethodHandle.
+void Universe::flush_dependents_on(Handle call_site, Handle method_handle) {
+  assert_lock_strong(Compile_lock);
+
+  if (CodeCache::number_of_nmethods_with_dependencies() == 0) return;
+
+  // CodeCache can only be updated by a thread_in_VM and they will all be
+  // stopped dring the safepoint so CodeCache will be safe to update without
+  // holding the CodeCache_lock.
+
+  CallSiteDepChange changes(call_site(), method_handle());
+
+  // Compute the dependent nmethods that have a reference to a
+  // CallSite object.  We use instanceKlass::mark_dependent_nmethod
+  // directly instead of CodeCache::mark_for_deoptimization because we
+  // want dependents on the class CallSite only not all classes in the
+  // ContextStream.
+  int marked = 0;
+  {
+    MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag);
+    instanceKlass* call_site_klass = instanceKlass::cast(SystemDictionary::CallSite_klass());
+    marked = call_site_klass->mark_dependent_nmethods(changes);
+  }
+  if (marked > 0) {
+    // At least one nmethod has been marked for deoptimization
+    VM_Deoptimize op;
+    VMThread::execute(&op);
+  }
+}
+
 #ifdef HOTSWAP
 // Flushes compiled methods dependent on dependee in the evolutionary sense
 void Universe::flush_evol_dependents_on(instanceKlassHandle ev_k_h) {
--- a/hotspot/src/share/vm/memory/universe.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/memory/universe.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -439,6 +439,7 @@
 
   // Flushing and deoptimization
   static void flush_dependents_on(instanceKlassHandle dependee);
+  static void flush_dependents_on(Handle call_site, Handle method_handle);
 #ifdef HOTSWAP
   // Flushing and deoptimization in case of evolution
   static void flush_evol_dependents_on(instanceKlassHandle dependee);
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -1406,7 +1406,7 @@
 
 //
 // Walk the list of dependent nmethods searching for nmethods which
-// are dependent on the klassOop that was passed in and mark them for
+// are dependent on the changes that were passed in and mark them for
 // deoptimization.  Returns the number of nmethods found.
 //
 int instanceKlass::mark_dependent_nmethods(DepChange& changes) {
--- a/hotspot/src/share/vm/opto/callGenerator.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/opto/callGenerator.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -24,6 +24,7 @@
 
 #include "precompiled.hpp"
 #include "ci/bcEscapeAnalyzer.hpp"
+#include "ci/ciCallSite.hpp"
 #include "ci/ciCPCache.hpp"
 #include "ci/ciMethodHandle.hpp"
 #include "classfile/javaClasses.hpp"
@@ -738,6 +739,34 @@
 }
 
 
+CallGenerator* CallGenerator::for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms,
+                                                       ciMethod* caller, ciMethod* callee, ciCallProfile profile) {
+  assert(call_site->is_constant_call_site() || call_site->is_mutable_call_site(), "must be");
+  ciMethodHandle* method_handle = call_site->get_target();
+
+  // Set the callee to have access to the class and signature in the
+  // MethodHandleCompiler.
+  method_handle->set_callee(callee);
+  method_handle->set_caller(caller);
+  method_handle->set_call_profile(profile);
+
+  // Get an adapter for the MethodHandle.
+  ciMethod* target_method = method_handle->get_invokedynamic_adapter();
+  if (target_method != NULL) {
+    Compile *C = Compile::current();
+    CallGenerator* hit_cg = C->call_generator(target_method, -1, false, jvms, true, PROB_ALWAYS);
+    if (hit_cg != NULL && hit_cg->is_inline()) {
+      // Add a dependence for invalidation of the optimization.
+      if (call_site->is_mutable_call_site()) {
+        C->dependencies()->assert_call_site_target_value(C->env()->CallSite_klass(), call_site, method_handle);
+      }
+      return hit_cg;
+    }
+  }
+  return NULL;
+}
+
+
 JVMState* PredictedDynamicCallGenerator::generate(JVMState* jvms) {
   GraphKit kit(jvms);
   PhaseGVN& gvn = kit.gvn();
--- a/hotspot/src/share/vm/opto/callGenerator.hpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/opto/callGenerator.hpp	Tue Aug 16 04:14:05 2011 -0700
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2011, 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
@@ -111,7 +111,8 @@
   static CallGenerator* for_dynamic_call(ciMethod* m);   // invokedynamic
   static CallGenerator* for_virtual_call(ciMethod* m, int vtable_index);  // virtual, interface
 
-  static CallGenerator* for_method_handle_inline(Node* method_handle, JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile);
+  static CallGenerator* for_method_handle_inline(Node* method_handle,   JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile);
+  static CallGenerator* for_invokedynamic_inline(ciCallSite* call_site, JVMState* jvms, ciMethod* caller, ciMethod* callee, ciCallProfile profile);
 
   // How to generate a replace a direct call with an inline version
   static CallGenerator* for_late_inline(ciMethod* m, CallGenerator* inline_cg);
--- a/hotspot/src/share/vm/opto/doCall.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/opto/doCall.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -114,7 +114,7 @@
     if (cg != NULL)  return cg;
   }
 
-  // Do MethodHandle calls.
+  // Do method handle calls.
   // NOTE: This must happen before normal inlining logic below since
   // MethodHandle.invoke* are native methods which obviously don't
   // have bytecodes and so normal inlining fails.
@@ -127,33 +127,25 @@
       if (cg != NULL) {
         return cg;
       }
-
       return CallGenerator::for_direct_call(call_method);
     }
     else {
-      // Get the MethodHandle from the CallSite.
+      // Get the CallSite object.
       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();
+      ciCallSite* call_site = str.get_call_site();
 
-      // Set the callee to have access to the class and signature in
-      // the MethodHandleCompiler.
-      method_handle->set_callee(call_method);
-      method_handle->set_caller(caller);
-      method_handle->set_call_profile(profile);
-
-      // Get an adapter for the MethodHandle.
-      ciMethod* target_method = method_handle->get_invokedynamic_adapter();
-      if (target_method != NULL) {
-        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);
+      // Inline constant and mutable call sites.  We don't inline
+      // volatile call sites optimistically since they are specified
+      // to change their value often and that would result in a lot of
+      // deoptimizations and recompiles.
+      if (call_site->is_constant_call_site() || call_site->is_mutable_call_site()) {
+        CallGenerator* cg = CallGenerator::for_invokedynamic_inline(call_site, jvms, caller, call_method, profile);
+        if (cg != NULL) {
+          return cg;
         }
       }
-
       // If something failed, generate a normal dynamic call.
       return CallGenerator::for_dynamic_call(call_method);
     }
--- a/hotspot/src/share/vm/opto/parse3.cpp	Thu Aug 11 12:08:11 2011 -0700
+++ b/hotspot/src/share/vm/opto/parse3.cpp	Tue Aug 16 04:14:05 2011 -0700
@@ -100,6 +100,14 @@
     }
   }
 
+  // Deoptimize on putfield writes to CallSite.target
+  if (!is_get && field->is_call_site_target()) {
+    uncommon_trap(Deoptimization::Reason_unhandled,
+                  Deoptimization::Action_reinterpret,
+                  NULL, "put to CallSite.target field");
+    return;
+  }
+
   assert(field->will_link(method()->holder(), bc()), "getfield: typeflow responsibility");
 
   // Note:  We do not check for an unloaded field type here any more.