8074345: Enable RewriteBytecodes when VM runs with CDS
authorminqi
Wed, 25 Mar 2015 15:18:37 -0700
changeset 30117 cce2cdac56dc
parent 30116 f5a6b1ebdbe3
child 30118 dadad0daaab4
8074345: Enable RewriteBytecodes when VM runs with CDS Summary: Enable bytecode rewriting when CDS turned on. Reviewed-by: coleenp, iklam Contributed-by: yumin.qi@oracle.com, ioi.lam@oracle.com
hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp
hotspot/src/cpu/x86/vm/templateTable_x86.cpp
hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp
hotspot/src/share/vm/interpreter/bytecodes.cpp
hotspot/src/share/vm/interpreter/bytecodes.hpp
hotspot/src/share/vm/interpreter/interpreterRuntime.cpp
hotspot/src/share/vm/interpreter/linkResolver.cpp
hotspot/src/share/vm/interpreter/rewriter.cpp
hotspot/src/share/vm/interpreter/templateTable.cpp
hotspot/src/share/vm/interpreter/templateTable.hpp
hotspot/src/share/vm/memory/metaspaceShared.cpp
hotspot/src/share/vm/oops/constMethod.hpp
hotspot/src/share/vm/runtime/arguments.cpp
--- a/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/cpu/sparc/vm/templateTable_sparc.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -386,7 +386,6 @@
   __ verify_oop(Otos_i);
 }
 
-
 void TemplateTable::ldc2_w() {
   transition(vtos, vtos);
   Label Long, exit;
@@ -431,22 +430,28 @@
   __ bind(exit);
 }
 
-
 void TemplateTable::locals_index(Register reg, int offset) {
   __ ldub( at_bcp(offset), reg );
 }
 
-
 void TemplateTable::locals_index_wide(Register reg) {
   // offset is 2, not 1, because Lbcp points to wide prefix code
   __ get_2_byte_integer_at_bcp(2, G4_scratch, reg, InterpreterMacroAssembler::Unsigned);
 }
 
 void TemplateTable::iload() {
+  iload_internal();
+}
+
+void TemplateTable::nofast_iload() {
+  iload_internal(may_not_rewrite);
+}
+
+void TemplateTable::iload_internal(RewriteControl rc) {
   transition(vtos, itos);
   // Rewrite iload,iload  pair into fast_iload2
   //         iload,caload pair into fast_icaload
-  if (RewriteFrequentPairs) {
+  if (RewriteFrequentPairs && rc == may_rewrite) {
     Label rewrite, done;
 
     // get next byte
@@ -673,8 +678,15 @@
   __ ld_ptr( Llocals, Interpreter::local_offset_in_bytes(n), Otos_i );
 }
 
-
 void TemplateTable::aload_0() {
+  aload_0_internal();
+}
+
+void TemplateTable::nofast_aload_0() {
+  aload_0_internal(may_not_rewrite);
+}
+
+void TemplateTable::aload_0_internal(RewriteControl rc) {
   transition(vtos, atos);
 
   // According to bytecode histograms, the pairs:
@@ -688,7 +700,7 @@
   // bytecode into a pair bytecode; otherwise it rewrites the current
   // bytecode into _fast_aload_0 that doesn't do the pair check anymore.
   //
-  if (RewriteFrequentPairs) {
+  if (RewriteFrequentPairs && rc == may_rewrite) {
     Label rewrite, done;
 
     // get next byte
@@ -732,7 +744,6 @@
   }
 }
 
-
 void TemplateTable::istore() {
   transition(itos, vtos);
   locals_index(G3_scratch);
@@ -2046,16 +2057,23 @@
                                             Register index,
                                             size_t index_size) {
   // Depends on cpCacheOop layout!
+
   Label resolved;
-
-    assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
-    __ 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);
+  Bytecodes::Code code = bytecode();
+  switch (code) {
+  case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
+  case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
+  }
+
+  assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
+  __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, Lbyte_code, byte_no, 1, index_size);
+  __ cmp(Lbyte_code, code);  // have we resolved this bytecode?
+  __ br(Assembler::equal, false, Assembler::pt, resolved);
+  __ delayed()->set(code, O1);
 
   address entry;
-  switch (bytecode()) {
+
+  switch (code) {
     case Bytecodes::_getstatic      : // fall through
     case Bytecodes::_putstatic      : // fall through
     case Bytecodes::_getfield       : // fall through
@@ -2067,7 +2085,7 @@
     case Bytecodes::_invokehandle   : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle);  break;
     case Bytecodes::_invokedynamic  : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);  break;
     default:
-      fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
+      fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(code)));
       break;
   }
   // first time invocation - must resolve first
@@ -2184,7 +2202,7 @@
   }
 }
 
-void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
+void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
   transition(vtos, vtos);
 
   Register Rcache = G3_scratch;
@@ -2232,7 +2250,7 @@
   __ load_heap_oop(Rclass, Roffset, Otos_i);
   __ verify_oop(Otos_i);
   __ push(atos);
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_agetfield, G3_scratch, G4_scratch);
   }
   __ ba(checkVolatile);
@@ -2247,7 +2265,7 @@
   // itos
   __ ld(Rclass, Roffset, Otos_i);
   __ push(itos);
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_igetfield, G3_scratch, G4_scratch);
   }
   __ ba(checkVolatile);
@@ -2263,7 +2281,7 @@
   // load must be atomic
   __ ld_long(Rclass, Roffset, Otos_l);
   __ push(ltos);
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_lgetfield, G3_scratch, G4_scratch);
   }
   __ ba(checkVolatile);
@@ -2278,7 +2296,7 @@
   // btos
   __ ldsb(Rclass, Roffset, Otos_i);
   __ push(itos);
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_bgetfield, G3_scratch, G4_scratch);
   }
   __ ba(checkVolatile);
@@ -2293,7 +2311,7 @@
   // ctos
   __ lduh(Rclass, Roffset, Otos_i);
   __ push(itos);
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_cgetfield, G3_scratch, G4_scratch);
   }
   __ ba(checkVolatile);
@@ -2308,7 +2326,7 @@
   // stos
   __ ldsh(Rclass, Roffset, Otos_i);
   __ push(itos);
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_sgetfield, G3_scratch, G4_scratch);
   }
   __ ba(checkVolatile);
@@ -2324,7 +2342,7 @@
   // ftos
   __ ldf(FloatRegisterImpl::S, Rclass, Roffset, Ftos_f);
   __ push(ftos);
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_fgetfield, G3_scratch, G4_scratch);
   }
   __ ba(checkVolatile);
@@ -2336,7 +2354,7 @@
   // dtos
   __ ldf(FloatRegisterImpl::D, Rclass, Roffset, Ftos_d);
   __ push(dtos);
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_dgetfield, G3_scratch, G4_scratch);
   }
 
@@ -2351,16 +2369,18 @@
   __ bind(exit);
 }
 
-
 void TemplateTable::getfield(int byte_no) {
   getfield_or_static(byte_no, false);
 }
 
+void TemplateTable::nofast_getfield(int byte_no) {
+  getfield_or_static(byte_no, false, may_not_rewrite);
+}
+
 void TemplateTable::getstatic(int byte_no) {
   getfield_or_static(byte_no, true);
 }
 
-
 void TemplateTable::fast_accessfield(TosState state) {
   transition(atos, state);
   Register Rcache  = G3_scratch;
@@ -2545,7 +2565,7 @@
   __ verify_oop(r);
 }
 
-void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
+void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
   transition(vtos, vtos);
   Register Rcache = G3_scratch;
   Register index  = G4_scratch;
@@ -2621,7 +2641,7 @@
       __ pop_i();
       pop_and_check_object(Rclass);
       __ st(Otos_i, Rclass, Roffset);
-      patch_bytecode(Bytecodes::_fast_iputfield, G3_scratch, G4_scratch, true, byte_no);
+      if (rc == may_rewrite) patch_bytecode(Bytecodes::_fast_iputfield, G3_scratch, G4_scratch, true, byte_no);
       __ ba(checkVolatile);
       __ delayed()->tst(Lscratch);
     }
@@ -2637,7 +2657,7 @@
       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);
+      if (rc == may_rewrite) patch_bytecode(Bytecodes::_fast_aputfield, G3_scratch, G4_scratch, true, byte_no);
       __ ba(checkVolatile);
       __ delayed()->tst(Lscratch);
     }
@@ -2654,7 +2674,7 @@
     __ pop_i();
     if (!is_static) pop_and_check_object(Rclass);
     __ stb(Otos_i, Rclass, Roffset);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_bputfield, G3_scratch, G4_scratch, true, byte_no);
     }
     __ ba(checkVolatile);
@@ -2671,7 +2691,7 @@
     __ pop_l();
     if (!is_static) pop_and_check_object(Rclass);
     __ st_long(Otos_l, Rclass, Roffset);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_lputfield, G3_scratch, G4_scratch, true, byte_no);
     }
     __ ba(checkVolatile);
@@ -2688,7 +2708,7 @@
     __ pop_i();
     if (!is_static) pop_and_check_object(Rclass);
     __ sth(Otos_i, Rclass, Roffset);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_cputfield, G3_scratch, G4_scratch, true, byte_no);
     }
     __ ba(checkVolatile);
@@ -2705,7 +2725,7 @@
     __ pop_i();
     if (!is_static) pop_and_check_object(Rclass);
     __ sth(Otos_i, Rclass, Roffset);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_sputfield, G3_scratch, G4_scratch, true, byte_no);
     }
     __ ba(checkVolatile);
@@ -2722,7 +2742,7 @@
     __ pop_f();
     if (!is_static) pop_and_check_object(Rclass);
     __ stf(FloatRegisterImpl::S, Ftos_f, Rclass, Roffset);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_fputfield, G3_scratch, G4_scratch, true, byte_no);
     }
     __ ba(checkVolatile);
@@ -2736,7 +2756,7 @@
     __ pop_d();
     if (!is_static) pop_and_check_object(Rclass);
     __ stf(FloatRegisterImpl::D, Ftos_d, Rclass, Roffset);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_dputfield, G3_scratch, G4_scratch, true, byte_no);
     }
   }
@@ -2810,16 +2830,18 @@
   }
 }
 
-
 void TemplateTable::putfield(int byte_no) {
   putfield_or_static(byte_no, false);
 }
 
+void TemplateTable::nofast_putfield(int byte_no) {
+  putfield_or_static(byte_no, false, may_not_rewrite);
+}
+
 void TemplateTable::putstatic(int byte_no) {
   putfield_or_static(byte_no, true);
 }
 
-
 void TemplateTable::fast_xaccess(TosState state) {
   transition(vtos, state);
   Register Rcache = G3_scratch;
@@ -2972,7 +2994,9 @@
   __ br(Assembler::zero, false, Assembler::pt, notFinal);
   __ delayed()->and3(Rret, 0xFF, G4_scratch);      // gets number of parameters
 
-  patch_bytecode(Bytecodes::_fast_invokevfinal, Rscratch, Rtemp);
+  if (RewriteBytecodes && !UseSharedSpaces) {
+    patch_bytecode(Bytecodes::_fast_invokevfinal, Rscratch, Rtemp);
+  }
 
   invokevfinal_helper(Rscratch, Rret);
 
--- a/hotspot/src/cpu/x86/vm/templateTable_x86.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/cpu/x86/vm/templateTable_x86.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -544,8 +544,16 @@
 }
 
 void TemplateTable::iload() {
+  iload_internal();
+}
+
+void TemplateTable::nofast_iload() {
+  iload_internal(may_not_rewrite);
+}
+
+void TemplateTable::iload_internal(RewriteControl rc) {
   transition(vtos, itos);
-  if (RewriteFrequentPairs) {
+  if (RewriteFrequentPairs && rc == may_rewrite) {
     Label rewrite, done;
     const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx);
     LP64_ONLY(assert(rbx != bc, "register damaged"));
@@ -816,6 +824,14 @@
 }
 
 void TemplateTable::aload_0() {
+  aload_0_internal();
+}
+
+void TemplateTable::nofast_aload_0() {
+  aload_0_internal(may_not_rewrite);
+}
+
+void TemplateTable::aload_0_internal(RewriteControl rc) {
   transition(vtos, atos);
   // According to bytecode histograms, the pairs:
   //
@@ -838,7 +854,7 @@
   //   aload_0, iload_1
   // These bytecodes with a small amount of code are most profitable
   // to rewrite
-  if (RewriteFrequentPairs) {
+  if (RewriteFrequentPairs && rc == may_rewrite) {
     Label rewrite, done;
 
     const Register bc = LP64_ONLY(c_rarg3) NOT_LP64(rcx);
@@ -2492,14 +2508,21 @@
   assert_different_registers(Rcache, index, temp);
 
   Label resolved;
-    assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
-    __ 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);
+
+  Bytecodes::Code code = bytecode();
+  switch (code) {
+  case Bytecodes::_nofast_getfield: code = Bytecodes::_getfield; break;
+  case Bytecodes::_nofast_putfield: code = Bytecodes::_putfield; break;
+  }
+
+  assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
+  __ get_cache_and_index_and_bytecode_at_bcp(Rcache, index, temp, byte_no, 1, index_size);
+  __ cmpl(temp, code);  // have we resolved this bytecode?
+  __ jcc(Assembler::equal, resolved);
 
   // resolve first time through
   address entry;
-  switch (bytecode()) {
+  switch (code) {
     case Bytecodes::_getstatic      : // fall through
     case Bytecodes::_putstatic      : // fall through
     case Bytecodes::_getfield       : // fall through
@@ -2511,10 +2534,10 @@
     case Bytecodes::_invokehandle   : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokehandle);   break;
     case Bytecodes::_invokedynamic  : entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_invokedynamic);  break;
     default:
-      fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(bytecode())));
+      fatal(err_msg("unexpected bytecode: %s", Bytecodes::name(code)));
       break;
   }
-  __ movl(temp, (int)bytecode());
+  __ movl(temp, code);
   __ call_VM(noreg, entry, temp);
   // Update registers with resolved info
   __ get_cache_and_index_at_bcp(Rcache, index, 1, index_size);
@@ -2629,7 +2652,7 @@
   __ verify_oop(r);
 }
 
-void TemplateTable::getfield_or_static(int byte_no, bool is_static) {
+void TemplateTable::getfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
   transition(vtos, vtos);
 
   const Register cache = rcx;
@@ -2661,7 +2684,7 @@
   __ load_signed_byte(rax, field);
   __ push(btos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_bgetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2672,7 +2695,7 @@
   // atos
   __ load_heap_oop(rax, field);
   __ push(atos);
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_agetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2684,7 +2707,7 @@
   __ movl(rax, field);
   __ push(itos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_igetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2696,7 +2719,7 @@
   __ load_unsigned_short(rax, field);
   __ push(ctos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_cgetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2708,7 +2731,7 @@
   __ load_signed_short(rax, field);
   __ push(stos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_sgetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2732,7 +2755,7 @@
 
   __ push(ltos);
   // Rewrite bytecode to be faster
-  LP64_ONLY(if (!is_static) patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx));
+  LP64_ONLY(if (!is_static && rc == may_rewrite) patch_bytecode(Bytecodes::_fast_lgetfield, bc, rbx));
   __ jmp(Done);
 
   __ bind(notLong);
@@ -2744,7 +2767,7 @@
   NOT_LP64(__ fld_s(field));
   __ push(ftos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_fgetfield, bc, rbx);
   }
   __ jmp(Done);
@@ -2759,7 +2782,7 @@
   NOT_LP64(__ fld_d(field));
   __ push(dtos);
   // Rewrite bytecode to be faster
-  if (!is_static) {
+  if (!is_static && rc == may_rewrite) {
     patch_bytecode(Bytecodes::_fast_dgetfield, bc, rbx);
   }
 #ifdef ASSERT
@@ -2780,6 +2803,10 @@
   getfield_or_static(byte_no, false);
 }
 
+void TemplateTable::nofast_getfield(int byte_no) {
+  getfield_or_static(byte_no, false, may_not_rewrite);
+}
+
 void TemplateTable::getstatic(int byte_no) {
   getfield_or_static(byte_no, true);
 }
@@ -2871,7 +2898,7 @@
   }
 }
 
-void TemplateTable::putfield_or_static(int byte_no, bool is_static) {
+void TemplateTable::putfield_or_static(int byte_no, bool is_static, RewriteControl rc) {
   transition(vtos, vtos);
 
   const Register cache = rcx;
@@ -2912,7 +2939,7 @@
     __ pop(btos);
     if (!is_static) pop_and_check_object(obj);
     __ movb(field, rax);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_bputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -2928,7 +2955,7 @@
     if (!is_static) pop_and_check_object(obj);
     // Store into the field
     do_oop_store(_masm, field, rax, _bs->kind(), false);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_aputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -2943,7 +2970,7 @@
     __ pop(itos);
     if (!is_static) pop_and_check_object(obj);
     __ movl(field, rax);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_iputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -2958,7 +2985,7 @@
     __ pop(ctos);
     if (!is_static) pop_and_check_object(obj);
     __ movw(field, rax);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_cputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -2973,7 +3000,7 @@
     __ pop(stos);
     if (!is_static) pop_and_check_object(obj);
     __ movw(field, rax);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_sputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -2989,7 +3016,7 @@
     __ pop(ltos);
     if (!is_static) pop_and_check_object(obj);
     __ movq(field, rax);
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_lputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -3036,7 +3063,7 @@
     if (!is_static) pop_and_check_object(obj);
     NOT_LP64( __ fstp_s(field);)
     LP64_ONLY( __ movflt(field, xmm0);)
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_fputfield, bc, rbx, true, byte_no);
     }
     __ jmp(Done);
@@ -3054,7 +3081,7 @@
     if (!is_static) pop_and_check_object(obj);
     NOT_LP64( __ fstp_d(field);)
     LP64_ONLY( __ movdbl(field, xmm0);)
-    if (!is_static) {
+    if (!is_static && rc == may_rewrite) {
       patch_bytecode(Bytecodes::_fast_dputfield, bc, rbx, true, byte_no);
     }
   }
@@ -3080,6 +3107,10 @@
   putfield_or_static(byte_no, false);
 }
 
+void TemplateTable::nofast_putfield(int byte_no) {
+  putfield_or_static(byte_no, false, may_not_rewrite);
+}
+
 void TemplateTable::putstatic(int byte_no) {
   putfield_or_static(byte_no, true);
 }
--- a/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/bytecodeInterpreter.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -576,10 +576,10 @@
 /* 0xD8 */ &&opc_default,     &&opc_default,        &&opc_default,      &&opc_default,
 /* 0xDC */ &&opc_default,     &&opc_default,        &&opc_default,      &&opc_default,
 
-/* 0xE0 */ &&opc_default,     &&opc_default,        &&opc_default,      &&opc_default,
-/* 0xE4 */ &&opc_default,     &&opc_fast_aldc,      &&opc_fast_aldc_w,  &&opc_return_register_finalizer,
-/* 0xE8 */ &&opc_invokehandle,&&opc_default,        &&opc_default,      &&opc_default,
-/* 0xEC */ &&opc_default,     &&opc_default,        &&opc_default,      &&opc_default,
+/* 0xE0 */ &&opc_default,     &&opc_default,        &&opc_default,         &&opc_default,
+/* 0xE4 */ &&opc_default,     &&opc_fast_aldc,      &&opc_fast_aldc_w,     &&opc_return_register_finalizer,
+/* 0xE8 */ &&opc_invokehandle,&&opc_nofast_getfield,&&opc_nofast_putfield, &&opc_nofast_aload_0,
+/* 0xEC */ &&opc_nofast_iload,&&opc_default,        &&opc_default,         &&opc_default,
 
 /* 0xF0 */ &&opc_default,     &&opc_default,        &&opc_default,      &&opc_default,
 /* 0xF4 */ &&opc_default,     &&opc_default,        &&opc_default,      &&opc_default,
--- a/hotspot/src/share/vm/interpreter/bytecodes.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/bytecodes.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -525,6 +525,12 @@
   def(_fast_aldc           , "fast_aldc"           , "bj"   , NULL    , T_OBJECT,   1, true,  _ldc   );
   def(_fast_aldc_w         , "fast_aldc_w"         , "bJJ"  , NULL    , T_OBJECT,   1, true,  _ldc_w );
 
+  def(_nofast_getfield     , "nofast_getfield"     , "bJJ"  , NULL    , T_ILLEGAL,  0, true,  _getfield       );
+  def(_nofast_putfield     , "nofast_putfield"     , "bJJ"  , NULL    , T_ILLEGAL, -2, true , _putfield       );
+
+  def(_nofast_aload_0      , "nofast_aload_0"      , "b"    , NULL    , T_ILLEGAL,  1, true , _aload_0        );
+  def(_nofast_iload        , "nofast_iload"        , "bi"   , NULL    , T_ILLEGAL,  1, false, _iload          );
+
   def(_shouldnotreachhere  , "_shouldnotreachhere" , "b"    , NULL    , T_VOID   ,  0, false);
 
   // compare can_trap information for each bytecode with the
--- a/hotspot/src/share/vm/interpreter/bytecodes.hpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/bytecodes.hpp	Wed Mar 25 15:18:37 2015 -0700
@@ -285,7 +285,20 @@
     // special handling of signature-polymorphic methods:
     _invokehandle         ,
 
-    _shouldnotreachhere,      // For debugging
+    // These bytecodes are rewritten at CDS dump time, so that we can prevent them from being
+    // rewritten at run time. This way, the ConstMethods can be placed in the CDS ReadOnly
+    // section, and RewriteByteCodes/RewriteFrequentPairs can rewrite non-CDS bytecodes
+    // at run time.
+    //
+    // Rewritten at CDS dump time to | Original bytecode
+    // _invoke_virtual rewritten on sparc, will be disabled if UseSharedSpaces turned on.
+    // ------------------------------+------------------
+    _nofast_getfield      ,          //  <- _getfield
+    _nofast_putfield      ,          //  <- _putfield
+    _nofast_aload_0       ,          //  <- _aload_0
+    _nofast_iload         ,          //  <- _iload
+
+    _shouldnotreachhere   ,          // For debugging
 
 
     number_of_codes
--- a/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/interpreterRuntime.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -541,7 +541,8 @@
   // resolve field
   fieldDescriptor info;
   constantPoolHandle pool(thread, method(thread)->constants());
-  bool is_put    = (bytecode == Bytecodes::_putfield  || bytecode == Bytecodes::_putstatic);
+  bool is_put    = (bytecode == Bytecodes::_putfield  || bytecode == Bytecodes::_nofast_putfield ||
+                    bytecode == Bytecodes::_putstatic);
   bool is_static = (bytecode == Bytecodes::_getstatic || bytecode == Bytecodes::_putstatic);
 
   {
--- a/hotspot/src/share/vm/interpreter/linkResolver.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/linkResolver.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -777,11 +777,11 @@
                                  TRAPS) {
   assert(byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic ||
          byte == Bytecodes::_getfield  || byte == Bytecodes::_putfield  ||
+         byte == Bytecodes::_nofast_getfield  || byte == Bytecodes::_nofast_putfield  ||
          (byte == Bytecodes::_nop && !check_access), "bad field access bytecode");
 
   bool is_static = (byte == Bytecodes::_getstatic || byte == Bytecodes::_putstatic);
-  bool is_put    = (byte == Bytecodes::_putfield  || byte == Bytecodes::_putstatic);
-
+  bool is_put    = (byte == Bytecodes::_putfield  || byte == Bytecodes::_putstatic || byte == Bytecodes::_nofast_putfield);
   // Check if there's a resolved klass containing the field
   if (resolved_klass.is_null()) {
     ResourceMark rm(THREAD);
--- a/hotspot/src/share/vm/interpreter/rewriter.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/rewriter.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -26,6 +26,7 @@
 #include "interpreter/bytecodes.hpp"
 #include "interpreter/interpreter.hpp"
 #include "interpreter/rewriter.hpp"
+#include "memory/metaspaceShared.hpp"
 #include "memory/gcLocker.hpp"
 #include "memory/resourceArea.hpp"
 #include "oops/generateOopMap.hpp"
@@ -167,12 +168,12 @@
   if (!reverse) {
     int cp_index = Bytes::get_Java_u2(p);
     if (_pool->tag_at(cp_index).is_interface_method()) {
-    int cache_index = add_invokespecial_cp_cache_entry(cp_index);
-    if (cache_index != (int)(jushort) cache_index) {
-      *invokespecial_error = true;
-    }
-    Bytes::put_native_u2(p, cache_index);
-  } else {
+      int cache_index = add_invokespecial_cp_cache_entry(cp_index);
+      if (cache_index != (int)(jushort) cache_index) {
+        *invokespecial_error = true;
+      }
+      Bytes::put_native_u2(p, cache_index);
+    } else {
       rewrite_member_reference(bcp, offset, reverse);
     }
   } else {
@@ -500,12 +501,14 @@
 }
 
 void Rewriter::rewrite(instanceKlassHandle klass, TRAPS) {
+  if (!DumpSharedSpaces) {
+    assert(!MetaspaceShared::is_in_shared_space(klass()), "archive methods must not be rewritten at run time");
+  }
   ResourceMark rm(THREAD);
   Rewriter     rw(klass, klass->constants(), klass->methods(), CHECK);
   // (That's all, folks.)
 }
 
-
 Rewriter::Rewriter(instanceKlassHandle klass, constantPoolHandle cpool, Array<Method*>* methods, TRAPS)
   : _klass(klass),
     _pool(cpool),
--- a/hotspot/src/share/vm/interpreter/templateTable.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/templateTable.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -517,6 +517,12 @@
 
   def(Bytecodes::_invokehandle        , ubcp|disp|clvm|____, vtos, vtos, invokehandle        , f1_byte      );
 
+  def(Bytecodes::_nofast_getfield     , ubcp|____|clvm|____, vtos, vtos, nofast_getfield     , f1_byte      );
+  def(Bytecodes::_nofast_putfield     , ubcp|____|clvm|____, vtos, vtos, nofast_putfield     , f2_byte      );
+
+  def(Bytecodes::_nofast_aload_0      , ____|____|clvm|____, vtos, atos, nofast_aload_0      ,  _           );
+  def(Bytecodes::_nofast_iload        , ubcp|____|clvm|____, vtos, itos, nofast_iload        ,  _           );
+
   def(Bytecodes::_shouldnotreachhere   , ____|____|____|____, vtos, vtos, shouldnotreachhere ,  _           );
   // platform specific bytecodes
   pd_initialize();
--- a/hotspot/src/share/vm/interpreter/templateTable.hpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/interpreter/templateTable.hpp	Wed Mar 25 15:18:37 2015 -0700
@@ -82,6 +82,7 @@
   enum Operation { add, sub, mul, div, rem, _and, _or, _xor, shl, shr, ushr };
   enum Condition { equal, not_equal, less, less_equal, greater, greater_equal };
   enum CacheByte { f1_byte = 1, f2_byte = 2 };  // byte_no codes
+  enum RewriteControl { may_rewrite, may_not_rewrite };  // control for fast code under CDS
 
  private:
   static bool            _is_initialized;        // true if TemplateTable has been initialized
@@ -165,6 +166,10 @@
   static void dload(int n);
   static void aload(int n);
   static void aload_0();
+  static void nofast_aload_0();
+  static void nofast_iload();
+  static void iload_internal(RewriteControl rc = may_rewrite);
+  static void aload_0_internal(RewriteControl rc = may_rewrite);
 
   static void istore();
   static void lstore();
@@ -279,10 +284,13 @@
   static void invokehandle(int byte_no);
   static void fast_invokevfinal(int byte_no);
 
-  static void getfield_or_static(int byte_no, bool is_static);
-  static void putfield_or_static(int byte_no, bool is_static);
+  static void getfield_or_static(int byte_no, bool is_static, RewriteControl rc = may_rewrite);
+  static void putfield_or_static(int byte_no, bool is_static, RewriteControl rc = may_rewrite);
+
   static void getfield(int byte_no);
   static void putfield(int byte_no);
+  static void nofast_getfield(int byte_no);
+  static void nofast_putfield(int byte_no);
   static void getstatic(int byte_no);
   static void putstatic(int byte_no);
   static void pop_and_check_object(Register obj);
--- a/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/memory/metaspaceShared.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -30,6 +30,8 @@
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
 #include "code/codeCache.hpp"
+#include "interpreter/bytecodes.hpp"
+#include "interpreter/bytecodeStream.hpp"
 #include "memory/filemap.hpp"
 #include "memory/gcLocker.hpp"
 #include "memory/metaspace.hpp"
@@ -104,15 +106,33 @@
   }
 }
 
-// Walk all methods in the class list and assign a fingerprint.
-// so that this part of the ConstMethod* is read only.
-static void calculate_fingerprints() {
+static void rewrite_nofast_bytecode(Method* method) {
+  RawBytecodeStream bcs(method);
+  while (!bcs.is_last_bytecode()) {
+    Bytecodes::Code opcode = bcs.raw_next();
+    switch (opcode) {
+    case Bytecodes::_getfield:      *bcs.bcp() = Bytecodes::_nofast_getfield;      break;
+    case Bytecodes::_putfield:      *bcs.bcp() = Bytecodes::_nofast_putfield;      break;
+    case Bytecodes::_aload_0:       *bcs.bcp() = Bytecodes::_nofast_aload_0;       break;
+    case Bytecodes::_iload:         *bcs.bcp() = Bytecodes::_nofast_iload;         break;
+    default: break;
+    }
+  }
+}
+
+// Walk all methods in the class list to ensure that they won't be modified at
+// run time. This includes:
+// [1] Rewrite all bytecodes as needed, so that the ConstMethod* will not be modified
+//     at run time by RewriteBytecodes/RewriteFrequentPairs
+// [2] Assign a fingerprint, so one doesn't need to be assigned at run-time.
+static void rewrite_nofast_bytecodes_and_calculate_fingerprints() {
   for (int i = 0; i < _global_klass_objects->length(); i++) {
     Klass* k = _global_klass_objects->at(i);
     if (k->oop_is_instance()) {
       InstanceKlass* ik = InstanceKlass::cast(k);
       for (int i = 0; i < ik->methods()->length(); i++) {
         Method* m = ik->methods()->at(i);
+        rewrite_nofast_bytecode(m);
         Fingerprinter fp(m);
         // The side effect of this call sets method's fingerprint field.
         fp.fingerprint();
@@ -476,9 +496,10 @@
     tty->print_cr("    type array classes = %5d", num_type_array);
   }
 
-  // Update all the fingerprints in the shared methods.
-  tty->print("Calculating fingerprints ... ");
-  calculate_fingerprints();
+
+  // Ensure the ConstMethods won't be modified at run-time
+  tty->print("Updating ConstMethods ... ");
+  rewrite_nofast_bytecodes_and_calculate_fingerprints();
   tty->print_cr("done. ");
 
   // Remove all references outside the metadata
--- a/hotspot/src/share/vm/oops/constMethod.hpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/oops/constMethod.hpp	Wed Mar 25 15:18:37 2015 -0700
@@ -32,7 +32,6 @@
 // processes in a read-only section with Class Data Sharing (CDS).  It's important
 // that this class doesn't have virtual functions because the vptr cannot be shared
 // with CDS.
-//   (*)RewriteByteCodes and RewriteFrequentPairs is an exception but turned off in CDS
 //
 // Note that most applications load thousands of methods, so keeping the size of this
 // structure small has a big impact on footprint.
--- a/hotspot/src/share/vm/runtime/arguments.cpp	Wed Mar 25 15:22:44 2015 +0000
+++ b/hotspot/src/share/vm/runtime/arguments.cpp	Wed Mar 25 15:18:37 2015 -0700
@@ -1848,15 +1848,8 @@
   }
 }
 
-// This must be called after ergonomics because we want bytecode rewriting
-// if the server compiler is used, or if UseSharedSpaces is disabled.
+// This must be called after ergonomics.
 void Arguments::set_bytecode_flags() {
-  // Better not attempt to store into a read-only space.
-  if (UseSharedSpaces) {
-    FLAG_SET_DEFAULT(RewriteBytecodes, false);
-    FLAG_SET_DEFAULT(RewriteFrequentPairs, false);
-  }
-
   if (!RewriteBytecodes) {
     FLAG_SET_DEFAULT(RewriteFrequentPairs, false);
   }