6627983: G1: Bad oop deference during marking

Tue, 01 Mar 2011 14:56:48 -0800

author
iveresov
date
Tue, 01 Mar 2011 14:56:48 -0800
changeset 2606
0ac769a57c64
parent 2605
bc6b27fb3568
child 2607
8c9c9ee30d71

6627983: G1: Bad oop deference during marking
Summary: Bulk zeroing reduction didn't work with G1, because arraycopy would call pre-barriers on uninitialized oops. The solution is to have version of arraycopy stubs that don't have pre-barriers. Also refactored arraycopy stubs generation on SPARC to be more readable and reduced the number of stubs necessary in some cases.
Reviewed-by: jrose, kvn, never

src/cpu/sparc/vm/stubGenerator_sparc.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/stubGenerator_x86_32.cpp file | annotate | diff | comparison | revisions
src/cpu/x86/vm/stubGenerator_x86_64.cpp file | annotate | diff | comparison | revisions
src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp file | annotate | diff | comparison | revisions
src/share/vm/memory/barrierSet.cpp file | annotate | diff | comparison | revisions
src/share/vm/memory/barrierSet.hpp file | annotate | diff | comparison | revisions
src/share/vm/opto/library_call.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/arguments.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/stubRoutines.cpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/stubRoutines.hpp file | annotate | diff | comparison | revisions
     1.1 --- a/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Tue Mar 01 10:27:15 2011 -0800
     1.2 +++ b/src/cpu/sparc/vm/stubGenerator_sparc.cpp	Tue Mar 01 14:56:48 2011 -0800
     1.3 @@ -1033,31 +1033,40 @@
     1.4    //
     1.5    //  The input registers are overwritten.
     1.6    //
     1.7 -  void gen_write_ref_array_pre_barrier(Register addr, Register count) {
     1.8 +  void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
     1.9      BarrierSet* bs = Universe::heap()->barrier_set();
    1.10 -    if (bs->has_write_ref_pre_barrier()) {
    1.11 -      assert(bs->has_write_ref_array_pre_opt(),
    1.12 -             "Else unsupported barrier set.");
    1.13 -
    1.14 -      __ save_frame(0);
    1.15 -      // Save the necessary global regs... will be used after.
    1.16 -      if (addr->is_global()) {
    1.17 -        __ mov(addr, L0);
    1.18 -      }
    1.19 -      if (count->is_global()) {
    1.20 -        __ mov(count, L1);
    1.21 -      }
    1.22 -      __ mov(addr->after_save(), O0);
    1.23 -      // Get the count into O1
    1.24 -      __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre));
    1.25 -      __ delayed()->mov(count->after_save(), O1);
    1.26 -      if (addr->is_global()) {
    1.27 -        __ mov(L0, addr);
    1.28 -      }
    1.29 -      if (count->is_global()) {
    1.30 -        __ mov(L1, count);
    1.31 -      }
    1.32 -      __ restore();
    1.33 +    switch (bs->kind()) {
    1.34 +      case BarrierSet::G1SATBCT:
    1.35 +      case BarrierSet::G1SATBCTLogging:
    1.36 +        // With G1, don't generate the call if we statically know that the target in uninitialized
    1.37 +        if (!dest_uninitialized) {
    1.38 +          __ save_frame(0);
    1.39 +          // Save the necessary global regs... will be used after.
    1.40 +          if (addr->is_global()) {
    1.41 +            __ mov(addr, L0);
    1.42 +          }
    1.43 +          if (count->is_global()) {
    1.44 +            __ mov(count, L1);
    1.45 +          }
    1.46 +          __ mov(addr->after_save(), O0);
    1.47 +          // Get the count into O1
    1.48 +          __ call(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre));
    1.49 +          __ delayed()->mov(count->after_save(), O1);
    1.50 +          if (addr->is_global()) {
    1.51 +            __ mov(L0, addr);
    1.52 +          }
    1.53 +          if (count->is_global()) {
    1.54 +            __ mov(L1, count);
    1.55 +          }
    1.56 +          __ restore();
    1.57 +        }
    1.58 +        break;
    1.59 +      case BarrierSet::CardTableModRef:
    1.60 +      case BarrierSet::CardTableExtension:
    1.61 +      case BarrierSet::ModRef:
    1.62 +        break;
    1.63 +      default:
    1.64 +        ShouldNotReachHere();
    1.65      }
    1.66    }
    1.67    //
    1.68 @@ -1071,7 +1080,7 @@
    1.69    //  The input registers are overwritten.
    1.70    //
    1.71    void gen_write_ref_array_post_barrier(Register addr, Register count,
    1.72 -                                   Register tmp) {
    1.73 +                                        Register tmp) {
    1.74      BarrierSet* bs = Universe::heap()->barrier_set();
    1.75  
    1.76      switch (bs->kind()) {
    1.77 @@ -2406,7 +2415,7 @@
    1.78      StubCodeMark mark(this, "StubRoutines", name);
    1.79      address start = __ pc();
    1.80  
    1.81 -    assert(!aligned, "usage");
    1.82 +    assert(aligned, "Should always be aligned");
    1.83  
    1.84      assert_clean_int(O2, O3);     // Make sure 'count' is clean int.
    1.85  
    1.86 @@ -2435,7 +2444,8 @@
    1.87    //      to:    O1
    1.88    //      count: O2 treated as signed
    1.89    //
    1.90 -  address generate_disjoint_oop_copy(bool aligned, address *entry, const char *name) {
    1.91 +  address generate_disjoint_oop_copy(bool aligned, address *entry, const char *name,
    1.92 +                                     bool dest_uninitialized = false) {
    1.93  
    1.94      const Register from  = O0;  // source array address
    1.95      const Register to    = O1;  // destination array address
    1.96 @@ -2456,7 +2466,7 @@
    1.97      // save arguments for barrier generation
    1.98      __ mov(to, G1);
    1.99      __ mov(count, G5);
   1.100 -    gen_write_ref_array_pre_barrier(G1, G5);
   1.101 +    gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized);
   1.102    #ifdef _LP64
   1.103      assert_clean_int(count, O3);     // Make sure 'count' is clean int.
   1.104      if (UseCompressedOops) {
   1.105 @@ -2486,7 +2496,8 @@
   1.106    //      count: O2 treated as signed
   1.107    //
   1.108    address generate_conjoint_oop_copy(bool aligned, address nooverlap_target,
   1.109 -                                     address *entry, const char *name) {
   1.110 +                                     address *entry, const char *name,
   1.111 +                                     bool dest_uninitialized = false) {
   1.112  
   1.113      const Register from  = O0;  // source array address
   1.114      const Register to    = O1;  // destination array address
   1.115 @@ -2509,7 +2520,7 @@
   1.116      // save arguments for barrier generation
   1.117      __ mov(to, G1);
   1.118      __ mov(count, G5);
   1.119 -    gen_write_ref_array_pre_barrier(G1, G5);
   1.120 +    gen_write_ref_array_pre_barrier(G1, G5, dest_uninitialized);
   1.121  
   1.122    #ifdef _LP64
   1.123      if (UseCompressedOops) {
   1.124 @@ -2578,7 +2589,7 @@
   1.125    //      ckval: O4 (super_klass)
   1.126    //      ret:   O0 zero for success; (-1^K) where K is partial transfer count
   1.127    //
   1.128 -  address generate_checkcast_copy(const char *name, address *entry) {
   1.129 +  address generate_checkcast_copy(const char *name, address *entry, bool dest_uninitialized = false) {
   1.130  
   1.131      const Register O0_from   = O0;      // source array address
   1.132      const Register O1_to     = O1;      // destination array address
   1.133 @@ -2624,8 +2635,7 @@
   1.134        // caller can pass a 64-bit byte count here (from generic stub)
   1.135        BLOCK_COMMENT("Entry:");
   1.136      }
   1.137 -
   1.138 -    gen_write_ref_array_pre_barrier(O1_to, O2_count);
   1.139 +    gen_write_ref_array_pre_barrier(O1_to, O2_count, dest_uninitialized);
   1.140  
   1.141      Label load_element, store_element, do_card_marks, fail, done;
   1.142      __ addcc(O2_count, 0, G1_remain);   // initialize loop index, and test it
   1.143 @@ -3083,56 +3093,104 @@
   1.144      address entry_jlong_arraycopy;
   1.145      address entry_checkcast_arraycopy;
   1.146  
   1.147 -    StubRoutines::_jbyte_disjoint_arraycopy  = generate_disjoint_byte_copy(false, &entry,
   1.148 -                                                                           "jbyte_disjoint_arraycopy");
   1.149 -    StubRoutines::_jbyte_arraycopy           = generate_conjoint_byte_copy(false, entry, &entry_jbyte_arraycopy,
   1.150 -                                                                           "jbyte_arraycopy");
   1.151 -    StubRoutines::_jshort_disjoint_arraycopy = generate_disjoint_short_copy(false, &entry,
   1.152 -                                                                            "jshort_disjoint_arraycopy");
   1.153 -    StubRoutines::_jshort_arraycopy          = generate_conjoint_short_copy(false, entry, &entry_jshort_arraycopy,
   1.154 -                                                                            "jshort_arraycopy");
   1.155 -    StubRoutines::_jint_disjoint_arraycopy   = generate_disjoint_int_copy(false, &entry,
   1.156 -                                                                          "jint_disjoint_arraycopy");
   1.157 -    StubRoutines::_jint_arraycopy            = generate_conjoint_int_copy(false, entry, &entry_jint_arraycopy,
   1.158 -                                                                          "jint_arraycopy");
   1.159 -    StubRoutines::_jlong_disjoint_arraycopy  = generate_disjoint_long_copy(false, &entry,
   1.160 -                                                                           "jlong_disjoint_arraycopy");
   1.161 -    StubRoutines::_jlong_arraycopy           = generate_conjoint_long_copy(false, entry, &entry_jlong_arraycopy,
   1.162 -                                                                           "jlong_arraycopy");
   1.163 -    StubRoutines::_oop_disjoint_arraycopy    = generate_disjoint_oop_copy(false, &entry,
   1.164 -                                                                          "oop_disjoint_arraycopy");
   1.165 -    StubRoutines::_oop_arraycopy             = generate_conjoint_oop_copy(false, entry, &entry_oop_arraycopy,
   1.166 -                                                                          "oop_arraycopy");
   1.167 -
   1.168 -
   1.169 -    StubRoutines::_arrayof_jbyte_disjoint_arraycopy  = generate_disjoint_byte_copy(true, &entry,
   1.170 -                                                                                   "arrayof_jbyte_disjoint_arraycopy");
   1.171 -    StubRoutines::_arrayof_jbyte_arraycopy           = generate_conjoint_byte_copy(true, entry, NULL,
   1.172 -                                                                                   "arrayof_jbyte_arraycopy");
   1.173 -
   1.174 +    //*** jbyte
   1.175 +    // Always need aligned and unaligned versions
   1.176 +    StubRoutines::_jbyte_disjoint_arraycopy         = generate_disjoint_byte_copy(false, &entry,
   1.177 +                                                                                  "jbyte_disjoint_arraycopy");
   1.178 +    StubRoutines::_jbyte_arraycopy                  = generate_conjoint_byte_copy(false, entry,
   1.179 +                                                                                  &entry_jbyte_arraycopy,
   1.180 +                                                                                  "jbyte_arraycopy");
   1.181 +    StubRoutines::_arrayof_jbyte_disjoint_arraycopy = generate_disjoint_byte_copy(true, &entry,
   1.182 +                                                                                  "arrayof_jbyte_disjoint_arraycopy");
   1.183 +    StubRoutines::_arrayof_jbyte_arraycopy          = generate_conjoint_byte_copy(true, entry, NULL,
   1.184 +                                                                                  "arrayof_jbyte_arraycopy");
   1.185 +
   1.186 +    //*** jshort
   1.187 +    // Always need aligned and unaligned versions
   1.188 +    StubRoutines::_jshort_disjoint_arraycopy         = generate_disjoint_short_copy(false, &entry,
   1.189 +                                                                                    "jshort_disjoint_arraycopy");
   1.190 +    StubRoutines::_jshort_arraycopy                  = generate_conjoint_short_copy(false, entry,
   1.191 +                                                                                    &entry_jshort_arraycopy,
   1.192 +                                                                                    "jshort_arraycopy");
   1.193      StubRoutines::_arrayof_jshort_disjoint_arraycopy = generate_disjoint_short_copy(true, &entry,
   1.194                                                                                      "arrayof_jshort_disjoint_arraycopy");
   1.195      StubRoutines::_arrayof_jshort_arraycopy          = generate_conjoint_short_copy(true, entry, NULL,
   1.196                                                                                      "arrayof_jshort_arraycopy");
   1.197  
   1.198 -    StubRoutines::_arrayof_jint_disjoint_arraycopy   = generate_disjoint_int_copy(true, &entry,
   1.199 -                                                                                  "arrayof_jint_disjoint_arraycopy");
   1.200 +    //*** jint
   1.201 +    // Aligned versions
   1.202 +    StubRoutines::_arrayof_jint_disjoint_arraycopy = generate_disjoint_int_copy(true, &entry,
   1.203 +                                                                                "arrayof_jint_disjoint_arraycopy");
   1.204 +    StubRoutines::_arrayof_jint_arraycopy          = generate_conjoint_int_copy(true, entry, &entry_jint_arraycopy,
   1.205 +                                                                                "arrayof_jint_arraycopy");
   1.206  #ifdef _LP64
   1.207 -    // since sizeof(jint) < sizeof(HeapWord), there's a different flavor:
   1.208 -    StubRoutines::_arrayof_jint_arraycopy     = generate_conjoint_int_copy(true, entry, NULL, "arrayof_jint_arraycopy");
   1.209 -  #else
   1.210 -    StubRoutines::_arrayof_jint_arraycopy     = StubRoutines::_jint_arraycopy;
   1.211 +    // In 64 bit we need both aligned and unaligned versions of jint arraycopy.
   1.212 +    // entry_jint_arraycopy always points to the unaligned version (notice that we overwrite it).
   1.213 +    StubRoutines::_jint_disjoint_arraycopy         = generate_disjoint_int_copy(false, &entry,
   1.214 +                                                                                "jint_disjoint_arraycopy");
   1.215 +    StubRoutines::_jint_arraycopy                  = generate_conjoint_int_copy(false, entry,
   1.216 +                                                                                &entry_jint_arraycopy,
   1.217 +                                                                                "jint_arraycopy");
   1.218 +#else
   1.219 +    // In 32 bit jints are always HeapWordSize aligned, so always use the aligned version
   1.220 +    // (in fact in 32bit we always have a pre-loop part even in the aligned version,
   1.221 +    //  because it uses 64-bit loads/stores, so the aligned flag is actually ignored).
   1.222 +    StubRoutines::_jint_disjoint_arraycopy = StubRoutines::_arrayof_jint_disjoint_arraycopy;
   1.223 +    StubRoutines::_jint_arraycopy          = StubRoutines::_arrayof_jint_arraycopy;
   1.224  #endif
   1.225  
   1.226 -    StubRoutines::_arrayof_jlong_disjoint_arraycopy  = generate_disjoint_long_copy(true, NULL,
   1.227 -                                                                                   "arrayof_jlong_disjoint_arraycopy");
   1.228 -    StubRoutines::_arrayof_oop_disjoint_arraycopy    =  generate_disjoint_oop_copy(true, NULL,
   1.229 -                                                                                   "arrayof_oop_disjoint_arraycopy");
   1.230 -
   1.231 -    StubRoutines::_arrayof_jlong_arraycopy    = StubRoutines::_jlong_arraycopy;
   1.232 -    StubRoutines::_arrayof_oop_arraycopy      = StubRoutines::_oop_arraycopy;
   1.233 -
   1.234 -    StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy);
   1.235 +
   1.236 +    //*** jlong
   1.237 +    // It is always aligned
   1.238 +    StubRoutines::_arrayof_jlong_disjoint_arraycopy = generate_disjoint_long_copy(true, &entry,
   1.239 +                                                                                  "arrayof_jlong_disjoint_arraycopy");
   1.240 +    StubRoutines::_arrayof_jlong_arraycopy          = generate_conjoint_long_copy(true, entry, &entry_jlong_arraycopy,
   1.241 +                                                                                  "arrayof_jlong_arraycopy");
   1.242 +    StubRoutines::_jlong_disjoint_arraycopy         = StubRoutines::_arrayof_jlong_disjoint_arraycopy;
   1.243 +    StubRoutines::_jlong_arraycopy                  = StubRoutines::_arrayof_jlong_arraycopy;
   1.244 +
   1.245 +
   1.246 +    //*** oops
   1.247 +    // Aligned versions
   1.248 +    StubRoutines::_arrayof_oop_disjoint_arraycopy        = generate_disjoint_oop_copy(true, &entry,
   1.249 +                                                                                      "arrayof_oop_disjoint_arraycopy");
   1.250 +    StubRoutines::_arrayof_oop_arraycopy                 = generate_conjoint_oop_copy(true, entry, &entry_oop_arraycopy,
   1.251 +                                                                                      "arrayof_oop_arraycopy");
   1.252 +    // Aligned versions without pre-barriers
   1.253 +    StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = generate_disjoint_oop_copy(true, &entry,
   1.254 +                                                                                      "arrayof_oop_disjoint_arraycopy_uninit",
   1.255 +                                                                                      /*dest_uninitialized*/true);
   1.256 +    StubRoutines::_arrayof_oop_arraycopy_uninit          = generate_conjoint_oop_copy(true, entry, NULL,
   1.257 +                                                                                      "arrayof_oop_arraycopy_uninit",
   1.258 +                                                                                      /*dest_uninitialized*/true);
   1.259 +#ifdef _LP64
   1.260 +    if (UseCompressedOops) {
   1.261 +      // With compressed oops we need unaligned versions, notice that we overwrite entry_oop_arraycopy.
   1.262 +      StubRoutines::_oop_disjoint_arraycopy            = generate_disjoint_oop_copy(false, &entry,
   1.263 +                                                                                    "oop_disjoint_arraycopy");
   1.264 +      StubRoutines::_oop_arraycopy                     = generate_conjoint_oop_copy(false, entry, &entry_oop_arraycopy,
   1.265 +                                                                                    "oop_arraycopy");
   1.266 +      // Unaligned versions without pre-barriers
   1.267 +      StubRoutines::_oop_disjoint_arraycopy_uninit     = generate_disjoint_oop_copy(false, &entry,
   1.268 +                                                                                    "oop_disjoint_arraycopy_uninit",
   1.269 +                                                                                    /*dest_uninitialized*/true);
   1.270 +      StubRoutines::_oop_arraycopy_uninit              = generate_conjoint_oop_copy(false, entry, NULL,
   1.271 +                                                                                    "oop_arraycopy_uninit",
   1.272 +                                                                                    /*dest_uninitialized*/true);
   1.273 +    } else
   1.274 +#endif
   1.275 +    {
   1.276 +      // oop arraycopy is always aligned on 32bit and 64bit without compressed oops
   1.277 +      StubRoutines::_oop_disjoint_arraycopy            = StubRoutines::_arrayof_oop_disjoint_arraycopy;
   1.278 +      StubRoutines::_oop_arraycopy                     = StubRoutines::_arrayof_oop_arraycopy;
   1.279 +      StubRoutines::_oop_disjoint_arraycopy_uninit     = StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit;
   1.280 +      StubRoutines::_oop_arraycopy_uninit              = StubRoutines::_arrayof_oop_arraycopy_uninit;
   1.281 +    }
   1.282 +
   1.283 +    StubRoutines::_checkcast_arraycopy        = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy);
   1.284 +    StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy("checkcast_arraycopy_uninit", NULL,
   1.285 +                                                                        /*dest_uninitialized*/true);
   1.286 +
   1.287      StubRoutines::_unsafe_arraycopy    = generate_unsafe_copy("unsafe_arraycopy",
   1.288                                                                entry_jbyte_arraycopy,
   1.289                                                                entry_jshort_arraycopy,
     2.1 --- a/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Tue Mar 01 10:27:15 2011 -0800
     2.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_32.cpp	Tue Mar 01 14:56:48 2011 -0800
     2.3 @@ -729,18 +729,19 @@
     2.4    //  Input:
     2.5    //     start   -  starting address
     2.6    //     count   -  element count
     2.7 -  void  gen_write_ref_array_pre_barrier(Register start, Register count) {
     2.8 +  void  gen_write_ref_array_pre_barrier(Register start, Register count, bool uninitialized_target) {
     2.9      assert_different_registers(start, count);
    2.10      BarrierSet* bs = Universe::heap()->barrier_set();
    2.11      switch (bs->kind()) {
    2.12        case BarrierSet::G1SATBCT:
    2.13        case BarrierSet::G1SATBCTLogging:
    2.14 -        {
    2.15 -          __ pusha();                      // push registers
    2.16 -          __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre),
    2.17 -                          start, count);
    2.18 -          __ popa();
    2.19 -        }
    2.20 +        // With G1, don't generate the call if we statically know that the target in uninitialized
    2.21 +        if (!uninitialized_target) {
    2.22 +           __ pusha();                      // push registers
    2.23 +           __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre),
    2.24 +                           start, count);
    2.25 +           __ popa();
    2.26 +         }
    2.27          break;
    2.28        case BarrierSet::CardTableModRef:
    2.29        case BarrierSet::CardTableExtension:
    2.30 @@ -919,7 +920,8 @@
    2.31  
    2.32    address generate_disjoint_copy(BasicType t, bool aligned,
    2.33                                   Address::ScaleFactor sf,
    2.34 -                                 address* entry, const char *name) {
    2.35 +                                 address* entry, const char *name,
    2.36 +                                 bool dest_uninitialized = false) {
    2.37      __ align(CodeEntryAlignment);
    2.38      StubCodeMark mark(this, "StubRoutines", name);
    2.39      address start = __ pc();
    2.40 @@ -950,7 +952,7 @@
    2.41      if (t == T_OBJECT) {
    2.42        __ testl(count, count);
    2.43        __ jcc(Assembler::zero, L_0_count);
    2.44 -      gen_write_ref_array_pre_barrier(to, count);
    2.45 +      gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
    2.46        __ mov(saved_to, to);          // save 'to'
    2.47      }
    2.48  
    2.49 @@ -1084,7 +1086,8 @@
    2.50    address generate_conjoint_copy(BasicType t, bool aligned,
    2.51                                   Address::ScaleFactor sf,
    2.52                                   address nooverlap_target,
    2.53 -                                 address* entry, const char *name) {
    2.54 +                                 address* entry, const char *name,
    2.55 +                                 bool dest_uninitialized = false) {
    2.56      __ align(CodeEntryAlignment);
    2.57      StubCodeMark mark(this, "StubRoutines", name);
    2.58      address start = __ pc();
    2.59 @@ -1128,7 +1131,7 @@
    2.60      if (t == T_OBJECT) {
    2.61        __ testl(count, count);
    2.62        __ jcc(Assembler::zero, L_0_count);
    2.63 -       gen_write_ref_array_pre_barrier(dst, count);
    2.64 +      gen_write_ref_array_pre_barrier(dst, count, dest_uninitialized);
    2.65      }
    2.66  
    2.67      // copy from high to low
    2.68 @@ -1415,7 +1418,7 @@
    2.69    //    rax, ==  0  -  success
    2.70    //    rax, == -1^K - failure, where K is partial transfer count
    2.71    //
    2.72 -  address generate_checkcast_copy(const char *name, address* entry) {
    2.73 +  address generate_checkcast_copy(const char *name, address* entry, bool dest_uninitialized = false) {
    2.74      __ align(CodeEntryAlignment);
    2.75      StubCodeMark mark(this, "StubRoutines", name);
    2.76      address start = __ pc();
    2.77 @@ -1476,7 +1479,7 @@
    2.78      Address elem_klass_addr(elem, oopDesc::klass_offset_in_bytes());
    2.79  
    2.80      // Copy from low to high addresses, indexed from the end of each array.
    2.81 -    gen_write_ref_array_pre_barrier(to, count);
    2.82 +    gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
    2.83      __ lea(end_from, end_from_addr);
    2.84      __ lea(end_to,   end_to_addr);
    2.85      assert(length == count, "");        // else fix next line:
    2.86 @@ -2039,6 +2042,15 @@
    2.87          generate_conjoint_copy(T_OBJECT, true, Address::times_ptr,  entry,
    2.88                                 &entry_oop_arraycopy, "oop_arraycopy");
    2.89  
    2.90 +    StubRoutines::_oop_disjoint_arraycopy_uninit =
    2.91 +        generate_disjoint_copy(T_OBJECT, true, Address::times_ptr, &entry,
    2.92 +                               "oop_disjoint_arraycopy_uninit",
    2.93 +                               /*dest_uninitialized*/true);
    2.94 +    StubRoutines::_oop_arraycopy_uninit =
    2.95 +        generate_conjoint_copy(T_OBJECT, true, Address::times_ptr,  entry,
    2.96 +                               NULL, "oop_arraycopy_uninit",
    2.97 +                               /*dest_uninitialized*/true);
    2.98 +
    2.99      StubRoutines::_jlong_disjoint_arraycopy =
   2.100          generate_disjoint_long_copy(&entry, "jlong_disjoint_arraycopy");
   2.101      StubRoutines::_jlong_arraycopy =
   2.102 @@ -2052,20 +2064,20 @@
   2.103      StubRoutines::_arrayof_jshort_fill = generate_fill(T_SHORT, true, "arrayof_jshort_fill");
   2.104      StubRoutines::_arrayof_jint_fill = generate_fill(T_INT, true, "arrayof_jint_fill");
   2.105  
   2.106 -    StubRoutines::_arrayof_jint_disjoint_arraycopy  =
   2.107 -        StubRoutines::_jint_disjoint_arraycopy;
   2.108 -    StubRoutines::_arrayof_oop_disjoint_arraycopy   =
   2.109 -        StubRoutines::_oop_disjoint_arraycopy;
   2.110 -    StubRoutines::_arrayof_jlong_disjoint_arraycopy =
   2.111 -        StubRoutines::_jlong_disjoint_arraycopy;
   2.112 +    StubRoutines::_arrayof_jint_disjoint_arraycopy       = StubRoutines::_jint_disjoint_arraycopy;
   2.113 +    StubRoutines::_arrayof_oop_disjoint_arraycopy        = StubRoutines::_oop_disjoint_arraycopy;
   2.114 +    StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = StubRoutines::_oop_disjoint_arraycopy_uninit;
   2.115 +    StubRoutines::_arrayof_jlong_disjoint_arraycopy      = StubRoutines::_jlong_disjoint_arraycopy;
   2.116  
   2.117 -    StubRoutines::_arrayof_jint_arraycopy  = StubRoutines::_jint_arraycopy;
   2.118 -    StubRoutines::_arrayof_oop_arraycopy   = StubRoutines::_oop_arraycopy;
   2.119 -    StubRoutines::_arrayof_jlong_arraycopy = StubRoutines::_jlong_arraycopy;
   2.120 +    StubRoutines::_arrayof_jint_arraycopy       = StubRoutines::_jint_arraycopy;
   2.121 +    StubRoutines::_arrayof_oop_arraycopy        = StubRoutines::_oop_arraycopy;
   2.122 +    StubRoutines::_arrayof_oop_arraycopy_uninit = StubRoutines::_oop_arraycopy_uninit;
   2.123 +    StubRoutines::_arrayof_jlong_arraycopy      = StubRoutines::_jlong_arraycopy;
   2.124  
   2.125      StubRoutines::_checkcast_arraycopy =
   2.126 -        generate_checkcast_copy("checkcast_arraycopy",
   2.127 -                                  &entry_checkcast_arraycopy);
   2.128 +        generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy);
   2.129 +    StubRoutines::_checkcast_arraycopy_uninit =
   2.130 +        generate_checkcast_copy("checkcast_arraycopy_uninit", NULL, /*dest_uninitialized*/true);
   2.131  
   2.132      StubRoutines::_unsafe_arraycopy =
   2.133          generate_unsafe_copy("unsafe_arraycopy",
     3.1 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Tue Mar 01 10:27:15 2011 -0800
     3.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp	Tue Mar 01 14:56:48 2011 -0800
     3.3 @@ -1159,34 +1159,35 @@
     3.4    // Generate code for an array write pre barrier
     3.5    //
     3.6    //     addr    -  starting address
     3.7 -  //     count    -  element count
     3.8 +  //     count   -  element count
     3.9 +  //     tmp     - scratch register
    3.10    //
    3.11    //     Destroy no registers!
    3.12    //
    3.13 -  void  gen_write_ref_array_pre_barrier(Register addr, Register count) {
    3.14 +  void  gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) {
    3.15      BarrierSet* bs = Universe::heap()->barrier_set();
    3.16      switch (bs->kind()) {
    3.17        case BarrierSet::G1SATBCT:
    3.18        case BarrierSet::G1SATBCTLogging:
    3.19 -        {
    3.20 -          __ pusha();                      // push registers
    3.21 -          if (count == c_rarg0) {
    3.22 -            if (addr == c_rarg1) {
    3.23 -              // exactly backwards!!
    3.24 -              __ xchgptr(c_rarg1, c_rarg0);
    3.25 -            } else {
    3.26 -              __ movptr(c_rarg1, count);
    3.27 -              __ movptr(c_rarg0, addr);
    3.28 -            }
    3.29 -
    3.30 -          } else {
    3.31 -            __ movptr(c_rarg0, addr);
    3.32 -            __ movptr(c_rarg1, count);
    3.33 -          }
    3.34 -          __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2);
    3.35 -          __ popa();
    3.36 +        // With G1, don't generate the call if we statically know that the target in uninitialized
    3.37 +        if (!dest_uninitialized) {
    3.38 +           __ pusha();                      // push registers
    3.39 +           if (count == c_rarg0) {
    3.40 +             if (addr == c_rarg1) {
    3.41 +               // exactly backwards!!
    3.42 +               __ xchgptr(c_rarg1, c_rarg0);
    3.43 +             } else {
    3.44 +               __ movptr(c_rarg1, count);
    3.45 +               __ movptr(c_rarg0, addr);
    3.46 +             }
    3.47 +           } else {
    3.48 +             __ movptr(c_rarg0, addr);
    3.49 +             __ movptr(c_rarg1, count);
    3.50 +           }
    3.51 +           __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2);
    3.52 +           __ popa();
    3.53          }
    3.54 -        break;
    3.55 +         break;
    3.56        case BarrierSet::CardTableModRef:
    3.57        case BarrierSet::CardTableExtension:
    3.58        case BarrierSet::ModRef:
    3.59 @@ -1769,7 +1770,8 @@
    3.60    //   disjoint_int_copy_entry is set to the no-overlap entry point
    3.61    //   used by generate_conjoint_int_oop_copy().
    3.62    //
    3.63 -  address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, address* entry, const char *name) {
    3.64 +  address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, address* entry,
    3.65 +                                         const char *name, bool dest_uninitialized = false) {
    3.66      __ align(CodeEntryAlignment);
    3.67      StubCodeMark mark(this, "StubRoutines", name);
    3.68      address start = __ pc();
    3.69 @@ -1799,7 +1801,7 @@
    3.70                        // r9 and r10 may be used to save non-volatile registers
    3.71      if (is_oop) {
    3.72        __ movq(saved_to, to);
    3.73 -      gen_write_ref_array_pre_barrier(to, count);
    3.74 +      gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
    3.75      }
    3.76  
    3.77      // 'from', 'to' and 'count' are now valid
    3.78 @@ -1860,7 +1862,8 @@
    3.79    // cache line boundaries will still be loaded and stored atomicly.
    3.80    //
    3.81    address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, address nooverlap_target,
    3.82 -                                         address *entry, const char *name) {
    3.83 +                                         address *entry, const char *name,
    3.84 +                                         bool dest_uninitialized = false) {
    3.85      __ align(CodeEntryAlignment);
    3.86      StubCodeMark mark(this, "StubRoutines", name);
    3.87      address start = __ pc();
    3.88 @@ -1887,7 +1890,7 @@
    3.89  
    3.90      if (is_oop) {
    3.91        // no registers are destroyed by this call
    3.92 -      gen_write_ref_array_pre_barrier(to, count);
    3.93 +      gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
    3.94      }
    3.95  
    3.96      assert_clean_int(count, rax); // Make sure 'count' is clean int.
    3.97 @@ -1953,7 +1956,8 @@
    3.98    //   disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the
    3.99    //   no-overlap entry point used by generate_conjoint_long_oop_copy().
   3.100    //
   3.101 -  address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, address *entry, const char *name) {
   3.102 +  address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, address *entry,
   3.103 +                                          const char *name, bool dest_uninitialized = false) {
   3.104      __ align(CodeEntryAlignment);
   3.105      StubCodeMark mark(this, "StubRoutines", name);
   3.106      address start = __ pc();
   3.107 @@ -1983,7 +1987,7 @@
   3.108      // 'from', 'to' and 'qword_count' are now valid
   3.109      if (is_oop) {
   3.110        // no registers are destroyed by this call
   3.111 -      gen_write_ref_array_pre_barrier(to, qword_count);
   3.112 +      gen_write_ref_array_pre_barrier(to, qword_count, dest_uninitialized);
   3.113      }
   3.114  
   3.115      // Copy from low to high addresses.  Use 'to' as scratch.
   3.116 @@ -2038,8 +2042,9 @@
   3.117    //   c_rarg1   - destination array address
   3.118    //   c_rarg2   - element count, treated as ssize_t, can be zero
   3.119    //
   3.120 -  address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, address nooverlap_target,
   3.121 -                                          address *entry, const char *name) {
   3.122 +  address generate_conjoint_long_oop_copy(bool aligned, bool is_oop,
   3.123 +                                          address nooverlap_target, address *entry,
   3.124 +                                          const char *name, bool dest_uninitialized = false) {
   3.125      __ align(CodeEntryAlignment);
   3.126      StubCodeMark mark(this, "StubRoutines", name);
   3.127      address start = __ pc();
   3.128 @@ -2067,7 +2072,7 @@
   3.129        // Save to and count for store barrier
   3.130        __ movptr(saved_count, qword_count);
   3.131        // No registers are destroyed by this call
   3.132 -      gen_write_ref_array_pre_barrier(to, saved_count);
   3.133 +      gen_write_ref_array_pre_barrier(to, saved_count, dest_uninitialized);
   3.134      }
   3.135  
   3.136      __ jmp(L_copy_32_bytes);
   3.137 @@ -2146,7 +2151,8 @@
   3.138    //    rax ==  0  -  success
   3.139    //    rax == -1^K - failure, where K is partial transfer count
   3.140    //
   3.141 -  address generate_checkcast_copy(const char *name, address *entry) {
   3.142 +  address generate_checkcast_copy(const char *name, address *entry,
   3.143 +                                  bool dest_uninitialized = false) {
   3.144  
   3.145      Label L_load_element, L_store_element, L_do_card_marks, L_done;
   3.146  
   3.147 @@ -2240,7 +2246,7 @@
   3.148      Address from_element_addr(end_from, count, TIMES_OOP, 0);
   3.149      Address   to_element_addr(end_to,   count, TIMES_OOP, 0);
   3.150  
   3.151 -    gen_write_ref_array_pre_barrier(to, count);
   3.152 +    gen_write_ref_array_pre_barrier(to, count, dest_uninitialized);
   3.153  
   3.154      // Copy from low to high addresses, indexed from the end of each array.
   3.155      __ lea(end_from, end_from_addr);
   3.156 @@ -2750,14 +2756,29 @@
   3.157                                                                                "oop_disjoint_arraycopy");
   3.158        StubRoutines::_oop_arraycopy           = generate_conjoint_int_oop_copy(false, true, entry,
   3.159                                                                                &entry_oop_arraycopy, "oop_arraycopy");
   3.160 +      StubRoutines::_oop_disjoint_arraycopy_uninit  = generate_disjoint_int_oop_copy(false, true, &entry,
   3.161 +                                                                                     "oop_disjoint_arraycopy_uninit",
   3.162 +                                                                                     /*dest_uninitialized*/true);
   3.163 +      StubRoutines::_oop_arraycopy_uninit           = generate_conjoint_int_oop_copy(false, true, entry,
   3.164 +                                                                                     NULL, "oop_arraycopy_uninit",
   3.165 +                                                                                     /*dest_uninitialized*/true);
   3.166      } else {
   3.167        StubRoutines::_oop_disjoint_arraycopy  = generate_disjoint_long_oop_copy(false, true, &entry,
   3.168                                                                                 "oop_disjoint_arraycopy");
   3.169        StubRoutines::_oop_arraycopy           = generate_conjoint_long_oop_copy(false, true, entry,
   3.170                                                                                 &entry_oop_arraycopy, "oop_arraycopy");
   3.171 +      StubRoutines::_oop_disjoint_arraycopy_uninit  = generate_disjoint_long_oop_copy(false, true, &entry,
   3.172 +                                                                                      "oop_disjoint_arraycopy_uninit",
   3.173 +                                                                                      /*dest_uninitialized*/true);
   3.174 +      StubRoutines::_oop_arraycopy_uninit           = generate_conjoint_long_oop_copy(false, true, entry,
   3.175 +                                                                                      NULL, "oop_arraycopy_uninit",
   3.176 +                                                                                      /*dest_uninitialized*/true);
   3.177      }
   3.178  
   3.179 -    StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy);
   3.180 +    StubRoutines::_checkcast_arraycopy        = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy);
   3.181 +    StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy("checkcast_arraycopy_uninit", NULL,
   3.182 +                                                                        /*dest_uninitialized*/true);
   3.183 +
   3.184      StubRoutines::_unsafe_arraycopy    = generate_unsafe_copy("unsafe_arraycopy",
   3.185                                                                entry_jbyte_arraycopy,
   3.186                                                                entry_jshort_arraycopy,
   3.187 @@ -2794,6 +2815,9 @@
   3.188  
   3.189      StubRoutines::_arrayof_oop_disjoint_arraycopy    = StubRoutines::_oop_disjoint_arraycopy;
   3.190      StubRoutines::_arrayof_oop_arraycopy             = StubRoutines::_oop_arraycopy;
   3.191 +
   3.192 +    StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit    = StubRoutines::_oop_disjoint_arraycopy_uninit;
   3.193 +    StubRoutines::_arrayof_oop_arraycopy_uninit             = StubRoutines::_oop_arraycopy_uninit;
   3.194    }
   3.195  
   3.196    void generate_math_stubs() {
     4.1 --- a/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Tue Mar 01 10:27:15 2011 -0800
     4.2 +++ b/src/share/vm/gc_implementation/g1/g1SATBCardTableModRefBS.hpp	Tue Mar 01 14:56:48 2011 -0800
     4.3 @@ -83,11 +83,15 @@
     4.4    }
     4.5  
     4.6    template <class T> void write_ref_array_pre_work(T* dst, int count);
     4.7 -  virtual void write_ref_array_pre(oop* dst, int count) {
     4.8 -    write_ref_array_pre_work(dst, count);
     4.9 +  virtual void write_ref_array_pre(oop* dst, int count, bool dest_uninitialized) {
    4.10 +    if (!dest_uninitialized) {
    4.11 +      write_ref_array_pre_work(dst, count);
    4.12 +    }
    4.13    }
    4.14 -  virtual void write_ref_array_pre(narrowOop* dst, int count) {
    4.15 -    write_ref_array_pre_work(dst, count);
    4.16 +  virtual void write_ref_array_pre(narrowOop* dst, int count, bool dest_uninitialized) {
    4.17 +    if (!dest_uninitialized) {
    4.18 +      write_ref_array_pre_work(dst, count);
    4.19 +    }
    4.20    }
    4.21  };
    4.22  
     5.1 --- a/src/share/vm/memory/barrierSet.cpp	Tue Mar 01 10:27:15 2011 -0800
     5.2 +++ b/src/share/vm/memory/barrierSet.cpp	Tue Mar 01 14:56:48 2011 -0800
     5.3 @@ -35,9 +35,9 @@
     5.4                     start,            count);
     5.5  #endif
     5.6    if (UseCompressedOops) {
     5.7 -    Universe::heap()->barrier_set()->write_ref_array_pre((narrowOop*)start, (int)count);
     5.8 +    Universe::heap()->barrier_set()->write_ref_array_pre((narrowOop*)start, (int)count, false);
     5.9    } else {
    5.10 -    Universe::heap()->barrier_set()->write_ref_array_pre(      (oop*)start, (int)count);
    5.11 +    Universe::heap()->barrier_set()->write_ref_array_pre(      (oop*)start, (int)count, false);
    5.12    }
    5.13  }
    5.14  
     6.1 --- a/src/share/vm/memory/barrierSet.hpp	Tue Mar 01 10:27:15 2011 -0800
     6.2 +++ b/src/share/vm/memory/barrierSet.hpp	Tue Mar 01 14:56:48 2011 -0800
     6.3 @@ -1,5 +1,5 @@
     6.4  /*
     6.5 - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
     6.6 + * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
     6.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     6.8   *
     6.9   * This code is free software; you can redistribute it and/or modify it
    6.10 @@ -44,6 +44,10 @@
    6.11      Uninit
    6.12    };
    6.13  
    6.14 +  enum Flags {
    6.15 +    None                = 0,
    6.16 +    TargetUninitialized = 1
    6.17 +  };
    6.18  protected:
    6.19    int _max_covered_regions;
    6.20    Name _kind;
    6.21 @@ -128,8 +132,10 @@
    6.22    virtual void read_prim_array(MemRegion mr) = 0;
    6.23  
    6.24    // Below length is the # array elements being written
    6.25 -  virtual void write_ref_array_pre(      oop* dst, int length) {}
    6.26 -  virtual void write_ref_array_pre(narrowOop* dst, int length) {}
    6.27 +  virtual void write_ref_array_pre(oop* dst, int length,
    6.28 +                                   bool dest_uninitialized = false) {}
    6.29 +  virtual void write_ref_array_pre(narrowOop* dst, int length,
    6.30 +                                   bool dest_uninitialized = false) {}
    6.31    // Below count is the # array elements being written, starting
    6.32    // at the address "start", which may not necessarily be HeapWord-aligned
    6.33    inline void write_ref_array(HeapWord* start, size_t count);
     7.1 --- a/src/share/vm/opto/library_call.cpp	Tue Mar 01 10:27:15 2011 -0800
     7.2 +++ b/src/share/vm/opto/library_call.cpp	Tue Mar 01 14:56:48 2011 -0800
     7.3 @@ -97,7 +97,7 @@
     7.4                               RegionNode* region);
     7.5    Node* generate_current_thread(Node* &tls_output);
     7.6    address basictype2arraycopy(BasicType t, Node *src_offset, Node *dest_offset,
     7.7 -                              bool disjoint_bases, const char* &name);
     7.8 +                              bool disjoint_bases, const char* &name, bool dest_uninitialized);
     7.9    Node* load_mirror_from_klass(Node* klass);
    7.10    Node* load_klass_from_mirror_common(Node* mirror, bool never_see_null,
    7.11                                        int nargs,
    7.12 @@ -212,26 +212,26 @@
    7.13                                  AllocateNode* alloc,
    7.14                                  Node* src,  Node* src_offset,
    7.15                                  Node* dest, Node* dest_offset,
    7.16 -                                Node* dest_size);
    7.17 +                                Node* dest_size, bool dest_uninitialized);
    7.18    void generate_slow_arraycopy(const TypePtr* adr_type,
    7.19                                 Node* src,  Node* src_offset,
    7.20                                 Node* dest, Node* dest_offset,
    7.21 -                               Node* copy_length);
    7.22 +                               Node* copy_length, bool dest_uninitialized);
    7.23    Node* generate_checkcast_arraycopy(const TypePtr* adr_type,
    7.24                                       Node* dest_elem_klass,
    7.25                                       Node* src,  Node* src_offset,
    7.26                                       Node* dest, Node* dest_offset,
    7.27 -                                     Node* copy_length);
    7.28 +                                     Node* copy_length, bool dest_uninitialized);
    7.29    Node* generate_generic_arraycopy(const TypePtr* adr_type,
    7.30                                     Node* src,  Node* src_offset,
    7.31                                     Node* dest, Node* dest_offset,
    7.32 -                                   Node* copy_length);
    7.33 +                                   Node* copy_length, bool dest_uninitialized);
    7.34    void generate_unchecked_arraycopy(const TypePtr* adr_type,
    7.35                                      BasicType basic_elem_type,
    7.36                                      bool disjoint_bases,
    7.37                                      Node* src,  Node* src_offset,
    7.38                                      Node* dest, Node* dest_offset,
    7.39 -                                    Node* copy_length);
    7.40 +                                    Node* copy_length, bool dest_uninitialized);
    7.41    bool inline_unsafe_CAS(BasicType type);
    7.42    bool inline_unsafe_ordered_store(BasicType type);
    7.43    bool inline_fp_conversions(vmIntrinsics::ID id);
    7.44 @@ -4092,7 +4092,8 @@
    7.45    const TypePtr* raw_adr_type = TypeRawPtr::BOTTOM;
    7.46    bool disjoint_bases = true;
    7.47    generate_unchecked_arraycopy(raw_adr_type, T_LONG, disjoint_bases,
    7.48 -                               src, NULL, dest, NULL, countx);
    7.49 +                               src, NULL, dest, NULL, countx,
    7.50 +                               /*dest_uninitialized*/true);
    7.51  
    7.52    // If necessary, emit some card marks afterwards.  (Non-arrays only.)
    7.53    if (card_mark) {
    7.54 @@ -4306,7 +4307,7 @@
    7.55  // Note:  The condition "disjoint" applies also for overlapping copies
    7.56  // where an descending copy is permitted (i.e., dest_offset <= src_offset).
    7.57  static address
    7.58 -select_arraycopy_function(BasicType t, bool aligned, bool disjoint, const char* &name) {
    7.59 +select_arraycopy_function(BasicType t, bool aligned, bool disjoint, const char* &name, bool dest_uninitialized) {
    7.60    int selector =
    7.61      (aligned  ? COPYFUNC_ALIGNED  : COPYFUNC_UNALIGNED) +
    7.62      (disjoint ? COPYFUNC_DISJOINT : COPYFUNC_CONJOINT);
    7.63 @@ -4315,6 +4316,10 @@
    7.64    name = #xxx_arraycopy; \
    7.65    return StubRoutines::xxx_arraycopy(); }
    7.66  
    7.67 +#define RETURN_STUB_PARM(xxx_arraycopy, parm) {           \
    7.68 +  name = #xxx_arraycopy; \
    7.69 +  return StubRoutines::xxx_arraycopy(parm); }
    7.70 +
    7.71    switch (t) {
    7.72    case T_BYTE:
    7.73    case T_BOOLEAN:
    7.74 @@ -4351,10 +4356,10 @@
    7.75    case T_ARRAY:
    7.76    case T_OBJECT:
    7.77      switch (selector) {
    7.78 -    case COPYFUNC_CONJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(oop_arraycopy);
    7.79 -    case COPYFUNC_CONJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_oop_arraycopy);
    7.80 -    case COPYFUNC_DISJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB(oop_disjoint_arraycopy);
    7.81 -    case COPYFUNC_DISJOINT | COPYFUNC_ALIGNED:    RETURN_STUB(arrayof_oop_disjoint_arraycopy);
    7.82 +    case COPYFUNC_CONJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB_PARM(oop_arraycopy, dest_uninitialized);
    7.83 +    case COPYFUNC_CONJOINT | COPYFUNC_ALIGNED:    RETURN_STUB_PARM(arrayof_oop_arraycopy, dest_uninitialized);
    7.84 +    case COPYFUNC_DISJOINT | COPYFUNC_UNALIGNED:  RETURN_STUB_PARM(oop_disjoint_arraycopy, dest_uninitialized);
    7.85 +    case COPYFUNC_DISJOINT | COPYFUNC_ALIGNED:    RETURN_STUB_PARM(arrayof_oop_disjoint_arraycopy, dest_uninitialized);
    7.86      }
    7.87    default:
    7.88      ShouldNotReachHere();
    7.89 @@ -4362,6 +4367,7 @@
    7.90    }
    7.91  
    7.92  #undef RETURN_STUB
    7.93 +#undef RETURN_STUB_PARM
    7.94  }
    7.95  
    7.96  //------------------------------basictype2arraycopy----------------------------
    7.97 @@ -4369,7 +4375,8 @@
    7.98                                              Node* src_offset,
    7.99                                              Node* dest_offset,
   7.100                                              bool disjoint_bases,
   7.101 -                                            const char* &name) {
   7.102 +                                            const char* &name,
   7.103 +                                            bool dest_uninitialized) {
   7.104    const TypeInt* src_offset_inttype  = gvn().find_int_type(src_offset);;
   7.105    const TypeInt* dest_offset_inttype = gvn().find_int_type(dest_offset);;
   7.106  
   7.107 @@ -4395,7 +4402,7 @@
   7.108      disjoint = true;
   7.109    }
   7.110  
   7.111 -  return select_arraycopy_function(t, aligned, disjoint, name);
   7.112 +  return select_arraycopy_function(t, aligned, disjoint, name, dest_uninitialized);
   7.113  }
   7.114  
   7.115  
   7.116 @@ -4451,7 +4458,8 @@
   7.117      // The component types are not the same or are not recognized.  Punt.
   7.118      // (But, avoid the native method wrapper to JVM_ArrayCopy.)
   7.119      generate_slow_arraycopy(TypePtr::BOTTOM,
   7.120 -                            src, src_offset, dest, dest_offset, length);
   7.121 +                            src, src_offset, dest, dest_offset, length,
   7.122 +                            /*dest_uninitialized*/false);
   7.123      return true;
   7.124    }
   7.125  
   7.126 @@ -4564,7 +4572,7 @@
   7.127  
   7.128    Node* original_dest      = dest;
   7.129    AllocateArrayNode* alloc = NULL;  // used for zeroing, if needed
   7.130 -  bool  must_clear_dest    = false;
   7.131 +  bool  dest_uninitialized = false;
   7.132  
   7.133    // See if this is the initialization of a newly-allocated array.
   7.134    // If so, we will take responsibility here for initializing it to zero.
   7.135 @@ -4587,12 +4595,14 @@
   7.136      adr_type = TypeRawPtr::BOTTOM;  // all initializations are into raw memory
   7.137      // From this point on, every exit path is responsible for
   7.138      // initializing any non-copied parts of the object to zero.
   7.139 -    must_clear_dest = true;
   7.140 +    // Also, if this flag is set we make sure that arraycopy interacts properly
   7.141 +    // with G1, eliding pre-barriers. See CR 6627983.
   7.142 +    dest_uninitialized = true;
   7.143    } else {
   7.144      // No zeroing elimination here.
   7.145      alloc             = NULL;
   7.146      //original_dest   = dest;
   7.147 -    //must_clear_dest = false;
   7.148 +    //dest_uninitialized = false;
   7.149    }
   7.150  
   7.151    // Results are placed here:
   7.152 @@ -4624,10 +4634,10 @@
   7.153    Node* checked_value   = NULL;
   7.154  
   7.155    if (basic_elem_type == T_CONFLICT) {
   7.156 -    assert(!must_clear_dest, "");
   7.157 +    assert(!dest_uninitialized, "");
   7.158      Node* cv = generate_generic_arraycopy(adr_type,
   7.159                                            src, src_offset, dest, dest_offset,
   7.160 -                                          copy_length);
   7.161 +                                          copy_length, dest_uninitialized);
   7.162      if (cv == NULL)  cv = intcon(-1);  // failure (no stub available)
   7.163      checked_control = control();
   7.164      checked_i_o     = i_o();
   7.165 @@ -4647,7 +4657,7 @@
   7.166      }
   7.167  
   7.168      // copy_length is 0.
   7.169 -    if (!stopped() && must_clear_dest) {
   7.170 +    if (!stopped() && dest_uninitialized) {
   7.171        Node* dest_length = alloc->in(AllocateNode::ALength);
   7.172        if (_gvn.eqv_uncast(copy_length, dest_length)
   7.173            || _gvn.find_int_con(dest_length, 1) <= 0) {
   7.174 @@ -4673,7 +4683,7 @@
   7.175      result_memory->init_req(zero_path, memory(adr_type));
   7.176    }
   7.177  
   7.178 -  if (!stopped() && must_clear_dest) {
   7.179 +  if (!stopped() && dest_uninitialized) {
   7.180      // We have to initialize the *uncopied* part of the array to zero.
   7.181      // The copy destination is the slice dest[off..off+len].  The other slices
   7.182      // are dest_head = dest[0..off] and dest_tail = dest[off+len..dest.length].
   7.183 @@ -4709,7 +4719,7 @@
   7.184        { PreserveJVMState pjvms(this);
   7.185          didit = generate_block_arraycopy(adr_type, basic_elem_type, alloc,
   7.186                                           src, src_offset, dest, dest_offset,
   7.187 -                                         dest_size);
   7.188 +                                         dest_size, dest_uninitialized);
   7.189          if (didit) {
   7.190            // Present the results of the block-copying fast call.
   7.191            result_region->init_req(bcopy_path, control());
   7.192 @@ -4785,7 +4795,7 @@
   7.193        Node* cv = generate_checkcast_arraycopy(adr_type,
   7.194                                                dest_elem_klass,
   7.195                                                src, src_offset, dest, dest_offset,
   7.196 -                                              ConvI2X(copy_length));
   7.197 +                                              ConvI2X(copy_length), dest_uninitialized);
   7.198        if (cv == NULL)  cv = intcon(-1);  // failure (no stub available)
   7.199        checked_control = control();
   7.200        checked_i_o     = i_o();
   7.201 @@ -4808,7 +4818,7 @@
   7.202      PreserveJVMState pjvms(this);
   7.203      generate_unchecked_arraycopy(adr_type, copy_type, disjoint_bases,
   7.204                                   src, src_offset, dest, dest_offset,
   7.205 -                                 ConvI2X(copy_length));
   7.206 +                                 ConvI2X(copy_length), dest_uninitialized);
   7.207  
   7.208      // Present the results of the fast call.
   7.209      result_region->init_req(fast_path, control());
   7.210 @@ -4887,7 +4897,7 @@
   7.211      set_memory(slow_mem, adr_type);
   7.212      set_i_o(slow_i_o);
   7.213  
   7.214 -    if (must_clear_dest) {
   7.215 +    if (dest_uninitialized) {
   7.216        generate_clear_array(adr_type, dest, basic_elem_type,
   7.217                             intcon(0), NULL,
   7.218                             alloc->in(AllocateNode::AllocSize));
   7.219 @@ -4895,7 +4905,7 @@
   7.220  
   7.221      generate_slow_arraycopy(adr_type,
   7.222                              src, src_offset, dest, dest_offset,
   7.223 -                            copy_length);
   7.224 +                            copy_length, /*dest_uninitialized*/false);
   7.225  
   7.226      result_region->init_req(slow_call_path, control());
   7.227      result_i_o   ->init_req(slow_call_path, i_o());
   7.228 @@ -5139,7 +5149,7 @@
   7.229                                           AllocateNode* alloc,
   7.230                                           Node* src,  Node* src_offset,
   7.231                                           Node* dest, Node* dest_offset,
   7.232 -                                         Node* dest_size) {
   7.233 +                                         Node* dest_size, bool dest_uninitialized) {
   7.234    // See if there is an advantage from block transfer.
   7.235    int scale = exact_log2(type2aelembytes(basic_elem_type));
   7.236    if (scale >= LogBytesPerLong)
   7.237 @@ -5184,7 +5194,7 @@
   7.238  
   7.239    bool disjoint_bases = true;   // since alloc != NULL
   7.240    generate_unchecked_arraycopy(adr_type, T_LONG, disjoint_bases,
   7.241 -                               sptr, NULL, dptr, NULL, countx);
   7.242 +                               sptr, NULL, dptr, NULL, countx, dest_uninitialized);
   7.243  
   7.244    return true;
   7.245  }
   7.246 @@ -5197,7 +5207,8 @@
   7.247  LibraryCallKit::generate_slow_arraycopy(const TypePtr* adr_type,
   7.248                                          Node* src,  Node* src_offset,
   7.249                                          Node* dest, Node* dest_offset,
   7.250 -                                        Node* copy_length) {
   7.251 +                                        Node* copy_length, bool dest_uninitialized) {
   7.252 +  assert(!dest_uninitialized, "Invariant");
   7.253    Node* call = make_runtime_call(RC_NO_LEAF | RC_UNCOMMON,
   7.254                                   OptoRuntime::slow_arraycopy_Type(),
   7.255                                   OptoRuntime::slow_arraycopy_Java(),
   7.256 @@ -5215,10 +5226,10 @@
   7.257                                               Node* dest_elem_klass,
   7.258                                               Node* src,  Node* src_offset,
   7.259                                               Node* dest, Node* dest_offset,
   7.260 -                                             Node* copy_length) {
   7.261 +                                             Node* copy_length, bool dest_uninitialized) {
   7.262    if (stopped())  return NULL;
   7.263  
   7.264 -  address copyfunc_addr = StubRoutines::checkcast_arraycopy();
   7.265 +  address copyfunc_addr = StubRoutines::checkcast_arraycopy(dest_uninitialized);
   7.266    if (copyfunc_addr == NULL) { // Stub was not generated, go slow path.
   7.267      return NULL;
   7.268    }
   7.269 @@ -5256,9 +5267,9 @@
   7.270  LibraryCallKit::generate_generic_arraycopy(const TypePtr* adr_type,
   7.271                                             Node* src,  Node* src_offset,
   7.272                                             Node* dest, Node* dest_offset,
   7.273 -                                           Node* copy_length) {
   7.274 +                                           Node* copy_length, bool dest_uninitialized) {
   7.275 +  assert(!dest_uninitialized, "Invariant");
   7.276    if (stopped())  return NULL;
   7.277 -
   7.278    address copyfunc_addr = StubRoutines::generic_arraycopy();
   7.279    if (copyfunc_addr == NULL) { // Stub was not generated, go slow path.
   7.280      return NULL;
   7.281 @@ -5279,7 +5290,7 @@
   7.282                                               bool disjoint_bases,
   7.283                                               Node* src,  Node* src_offset,
   7.284                                               Node* dest, Node* dest_offset,
   7.285 -                                             Node* copy_length) {
   7.286 +                                             Node* copy_length, bool dest_uninitialized) {
   7.287    if (stopped())  return;               // nothing to do
   7.288  
   7.289    Node* src_start  = src;
   7.290 @@ -5294,7 +5305,7 @@
   7.291    const char* copyfunc_name = "arraycopy";
   7.292    address     copyfunc_addr =
   7.293        basictype2arraycopy(basic_elem_type, src_offset, dest_offset,
   7.294 -                          disjoint_bases, copyfunc_name);
   7.295 +                          disjoint_bases, copyfunc_name, dest_uninitialized);
   7.296  
   7.297    // Call it.  Note that the count_ix value is not scaled to a byte-size.
   7.298    make_runtime_call(RC_LEAF|RC_NO_FP,
     8.1 --- a/src/share/vm/runtime/arguments.cpp	Tue Mar 01 10:27:15 2011 -0800
     8.2 +++ b/src/share/vm/runtime/arguments.cpp	Tue Mar 01 14:56:48 2011 -0800
     8.3 @@ -2790,10 +2790,6 @@
     8.4    if (!FLAG_IS_DEFAULT(OptoLoopAlignment) && FLAG_IS_DEFAULT(MaxLoopPad)) {
     8.5      FLAG_SET_DEFAULT(MaxLoopPad, OptoLoopAlignment-1);
     8.6    }
     8.7 -  // Temporary disable bulk zeroing reduction with G1. See CR 6627983.
     8.8 -  if (UseG1GC) {
     8.9 -    FLAG_SET_DEFAULT(ReduceBulkZeroing, false);
    8.10 -  }
    8.11  #endif
    8.12  
    8.13    // If we are running in a headless jre, force java.awt.headless property
     9.1 --- a/src/share/vm/runtime/stubRoutines.cpp	Tue Mar 01 10:27:15 2011 -0800
     9.2 +++ b/src/share/vm/runtime/stubRoutines.cpp	Tue Mar 01 14:56:48 2011 -0800
     9.3 @@ -1,5 +1,5 @@
     9.4  /*
     9.5 - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
     9.6 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
     9.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.8   *
     9.9   * This code is free software; you can redistribute it and/or modify it
    9.10 @@ -80,30 +80,36 @@
    9.11  jint    StubRoutines::_fpu_subnormal_bias2[3]                   = { 0, 0, 0 };
    9.12  
    9.13  // Compiled code entry points default values
    9.14 -// The dafault functions don't have separate disjoint versions.
    9.15 +// The default functions don't have separate disjoint versions.
    9.16  address StubRoutines::_jbyte_arraycopy          = CAST_FROM_FN_PTR(address, StubRoutines::jbyte_copy);
    9.17  address StubRoutines::_jshort_arraycopy         = CAST_FROM_FN_PTR(address, StubRoutines::jshort_copy);
    9.18  address StubRoutines::_jint_arraycopy           = CAST_FROM_FN_PTR(address, StubRoutines::jint_copy);
    9.19  address StubRoutines::_jlong_arraycopy          = CAST_FROM_FN_PTR(address, StubRoutines::jlong_copy);
    9.20  address StubRoutines::_oop_arraycopy            = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy);
    9.21 +address StubRoutines::_oop_arraycopy_uninit     = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy_uninit);
    9.22  address StubRoutines::_jbyte_disjoint_arraycopy          = CAST_FROM_FN_PTR(address, StubRoutines::jbyte_copy);
    9.23  address StubRoutines::_jshort_disjoint_arraycopy         = CAST_FROM_FN_PTR(address, StubRoutines::jshort_copy);
    9.24  address StubRoutines::_jint_disjoint_arraycopy           = CAST_FROM_FN_PTR(address, StubRoutines::jint_copy);
    9.25  address StubRoutines::_jlong_disjoint_arraycopy          = CAST_FROM_FN_PTR(address, StubRoutines::jlong_copy);
    9.26  address StubRoutines::_oop_disjoint_arraycopy            = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy);
    9.27 +address StubRoutines::_oop_disjoint_arraycopy_uninit     = CAST_FROM_FN_PTR(address, StubRoutines::oop_copy_uninit);
    9.28  
    9.29  address StubRoutines::_arrayof_jbyte_arraycopy  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jbyte_copy);
    9.30  address StubRoutines::_arrayof_jshort_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jshort_copy);
    9.31  address StubRoutines::_arrayof_jint_arraycopy   = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jint_copy);
    9.32  address StubRoutines::_arrayof_jlong_arraycopy  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jlong_copy);
    9.33  address StubRoutines::_arrayof_oop_arraycopy    = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy);
    9.34 +address StubRoutines::_arrayof_oop_arraycopy_uninit      = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy_uninit);
    9.35  address StubRoutines::_arrayof_jbyte_disjoint_arraycopy  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jbyte_copy);
    9.36  address StubRoutines::_arrayof_jshort_disjoint_arraycopy = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jshort_copy);
    9.37  address StubRoutines::_arrayof_jint_disjoint_arraycopy   = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jint_copy);
    9.38  address StubRoutines::_arrayof_jlong_disjoint_arraycopy  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_jlong_copy);
    9.39 -address StubRoutines::_arrayof_oop_disjoint_arraycopy  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy);
    9.40 +address StubRoutines::_arrayof_oop_disjoint_arraycopy    = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy);
    9.41 +address StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit  = CAST_FROM_FN_PTR(address, StubRoutines::arrayof_oop_copy_uninit);
    9.42 +
    9.43  
    9.44  address StubRoutines::_checkcast_arraycopy               = NULL;
    9.45 +address StubRoutines::_checkcast_arraycopy_uninit        = NULL;
    9.46  address StubRoutines::_unsafe_arraycopy                  = NULL;
    9.47  address StubRoutines::_generic_arraycopy                 = NULL;
    9.48  
    9.49 @@ -282,12 +288,12 @@
    9.50  // Default versions of arraycopy functions
    9.51  //
    9.52  
    9.53 -static void gen_arraycopy_barrier_pre(oop* dest, size_t count) {
    9.54 +static void gen_arraycopy_barrier_pre(oop* dest, size_t count, bool dest_uninitialized) {
    9.55      assert(count != 0, "count should be non-zero");
    9.56      assert(count <= (size_t)max_intx, "count too large");
    9.57      BarrierSet* bs = Universe::heap()->barrier_set();
    9.58      assert(bs->has_write_ref_array_pre_opt(), "Must have pre-barrier opt");
    9.59 -    bs->write_ref_array_pre(dest, (int)count);
    9.60 +    bs->write_ref_array_pre(dest, (int)count, dest_uninitialized);
    9.61  }
    9.62  
    9.63  static void gen_arraycopy_barrier(oop* dest, size_t count) {
    9.64 @@ -330,7 +336,17 @@
    9.65    SharedRuntime::_oop_array_copy_ctr++;        // Slow-path oop array copy
    9.66  #endif // !PRODUCT
    9.67    assert(count != 0, "count should be non-zero");
    9.68 -  gen_arraycopy_barrier_pre(dest, count);
    9.69 +  gen_arraycopy_barrier_pre(dest, count, /*dest_uninitialized*/false);
    9.70 +  Copy::conjoint_oops_atomic(src, dest, count);
    9.71 +  gen_arraycopy_barrier(dest, count);
    9.72 +JRT_END
    9.73 +
    9.74 +JRT_LEAF(void, StubRoutines::oop_copy_uninit(oop* src, oop* dest, size_t count))
    9.75 +#ifndef PRODUCT
    9.76 +  SharedRuntime::_oop_array_copy_ctr++;        // Slow-path oop array copy
    9.77 +#endif // !PRODUCT
    9.78 +  assert(count != 0, "count should be non-zero");
    9.79 +  gen_arraycopy_barrier_pre(dest, count, /*dest_uninitialized*/true);
    9.80    Copy::conjoint_oops_atomic(src, dest, count);
    9.81    gen_arraycopy_barrier(dest, count);
    9.82  JRT_END
    9.83 @@ -368,11 +384,20 @@
    9.84    SharedRuntime::_oop_array_copy_ctr++;        // Slow-path oop array copy
    9.85  #endif // !PRODUCT
    9.86    assert(count != 0, "count should be non-zero");
    9.87 -  gen_arraycopy_barrier_pre((oop *) dest, count);
    9.88 +  gen_arraycopy_barrier_pre((oop *) dest, count, /*dest_uninitialized*/false);
    9.89    Copy::arrayof_conjoint_oops(src, dest, count);
    9.90    gen_arraycopy_barrier((oop *) dest, count);
    9.91  JRT_END
    9.92  
    9.93 +JRT_LEAF(void, StubRoutines::arrayof_oop_copy_uninit(HeapWord* src, HeapWord* dest, size_t count))
    9.94 +#ifndef PRODUCT
    9.95 +  SharedRuntime::_oop_array_copy_ctr++;        // Slow-path oop array copy
    9.96 +#endif // !PRODUCT
    9.97 +  assert(count != 0, "count should be non-zero");
    9.98 +  gen_arraycopy_barrier_pre((oop *) dest, count, /*dest_uninitialized*/true);
    9.99 +  Copy::arrayof_conjoint_oops(src, dest, count);
   9.100 +  gen_arraycopy_barrier((oop *) dest, count);
   9.101 +JRT_END
   9.102  
   9.103  address StubRoutines::select_fill_function(BasicType t, bool aligned, const char* &name) {
   9.104  #define RETURN_STUB(xxx_fill) { \
    10.1 --- a/src/share/vm/runtime/stubRoutines.hpp	Tue Mar 01 10:27:15 2011 -0800
    10.2 +++ b/src/share/vm/runtime/stubRoutines.hpp	Tue Mar 01 14:56:48 2011 -0800
    10.3 @@ -1,5 +1,5 @@
    10.4  /*
    10.5 - * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
    10.6 + * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved.
    10.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    10.8   *
    10.9   * This code is free software; you can redistribute it and/or modify it
   10.10 @@ -164,12 +164,12 @@
   10.11    static address _jshort_arraycopy;
   10.12    static address _jint_arraycopy;
   10.13    static address _jlong_arraycopy;
   10.14 -  static address _oop_arraycopy;
   10.15 +  static address _oop_arraycopy, _oop_arraycopy_uninit;
   10.16    static address _jbyte_disjoint_arraycopy;
   10.17    static address _jshort_disjoint_arraycopy;
   10.18    static address _jint_disjoint_arraycopy;
   10.19    static address _jlong_disjoint_arraycopy;
   10.20 -  static address _oop_disjoint_arraycopy;
   10.21 +  static address _oop_disjoint_arraycopy, _oop_disjoint_arraycopy_uninit;
   10.22  
   10.23    // arraycopy operands aligned on zero'th element boundary
   10.24    // These are identical to the ones aligned aligned on an
   10.25 @@ -179,15 +179,15 @@
   10.26    static address _arrayof_jshort_arraycopy;
   10.27    static address _arrayof_jint_arraycopy;
   10.28    static address _arrayof_jlong_arraycopy;
   10.29 -  static address _arrayof_oop_arraycopy;
   10.30 +  static address _arrayof_oop_arraycopy, _arrayof_oop_arraycopy_uninit;
   10.31    static address _arrayof_jbyte_disjoint_arraycopy;
   10.32    static address _arrayof_jshort_disjoint_arraycopy;
   10.33    static address _arrayof_jint_disjoint_arraycopy;
   10.34    static address _arrayof_jlong_disjoint_arraycopy;
   10.35 -  static address _arrayof_oop_disjoint_arraycopy;
   10.36 +  static address _arrayof_oop_disjoint_arraycopy, _arrayof_oop_disjoint_arraycopy_uninit;
   10.37  
   10.38    // these are recommended but optional:
   10.39 -  static address _checkcast_arraycopy;
   10.40 +  static address _checkcast_arraycopy, _checkcast_arraycopy_uninit;
   10.41    static address _unsafe_arraycopy;
   10.42    static address _generic_arraycopy;
   10.43  
   10.44 @@ -286,26 +286,36 @@
   10.45    static address jshort_arraycopy() { return _jshort_arraycopy; }
   10.46    static address jint_arraycopy()   { return _jint_arraycopy; }
   10.47    static address jlong_arraycopy()  { return _jlong_arraycopy; }
   10.48 -  static address oop_arraycopy()    { return _oop_arraycopy; }
   10.49 +  static address oop_arraycopy(bool dest_uninitialized = false) {
   10.50 +    return dest_uninitialized ? _oop_arraycopy_uninit : _oop_arraycopy;
   10.51 +  }
   10.52    static address jbyte_disjoint_arraycopy()  { return _jbyte_disjoint_arraycopy; }
   10.53    static address jshort_disjoint_arraycopy() { return _jshort_disjoint_arraycopy; }
   10.54    static address jint_disjoint_arraycopy()   { return _jint_disjoint_arraycopy; }
   10.55    static address jlong_disjoint_arraycopy()  { return _jlong_disjoint_arraycopy; }
   10.56 -  static address oop_disjoint_arraycopy()    { return _oop_disjoint_arraycopy; }
   10.57 +  static address oop_disjoint_arraycopy(bool dest_uninitialized = false) {
   10.58 +    return dest_uninitialized ?  _oop_disjoint_arraycopy_uninit : _oop_disjoint_arraycopy;
   10.59 +  }
   10.60  
   10.61    static address arrayof_jbyte_arraycopy()  { return _arrayof_jbyte_arraycopy; }
   10.62    static address arrayof_jshort_arraycopy() { return _arrayof_jshort_arraycopy; }
   10.63    static address arrayof_jint_arraycopy()   { return _arrayof_jint_arraycopy; }
   10.64    static address arrayof_jlong_arraycopy()  { return _arrayof_jlong_arraycopy; }
   10.65 -  static address arrayof_oop_arraycopy()    { return _arrayof_oop_arraycopy; }
   10.66 +  static address arrayof_oop_arraycopy(bool dest_uninitialized = false) {
   10.67 +    return dest_uninitialized ? _arrayof_oop_arraycopy_uninit : _arrayof_oop_arraycopy;
   10.68 +  }
   10.69  
   10.70    static address arrayof_jbyte_disjoint_arraycopy()  { return _arrayof_jbyte_disjoint_arraycopy; }
   10.71    static address arrayof_jshort_disjoint_arraycopy() { return _arrayof_jshort_disjoint_arraycopy; }
   10.72    static address arrayof_jint_disjoint_arraycopy()   { return _arrayof_jint_disjoint_arraycopy; }
   10.73    static address arrayof_jlong_disjoint_arraycopy()  { return _arrayof_jlong_disjoint_arraycopy; }
   10.74 -  static address arrayof_oop_disjoint_arraycopy()    { return _arrayof_oop_disjoint_arraycopy; }
   10.75 +  static address arrayof_oop_disjoint_arraycopy(bool dest_uninitialized = false) {
   10.76 +    return dest_uninitialized ? _arrayof_oop_disjoint_arraycopy_uninit : _arrayof_oop_disjoint_arraycopy;
   10.77 +  }
   10.78  
   10.79 -  static address checkcast_arraycopy()     { return _checkcast_arraycopy; }
   10.80 +  static address checkcast_arraycopy(bool dest_uninitialized = false) {
   10.81 +    return dest_uninitialized ? _checkcast_arraycopy_uninit : _checkcast_arraycopy;
   10.82 +  }
   10.83    static address unsafe_arraycopy()        { return _unsafe_arraycopy; }
   10.84    static address generic_arraycopy()       { return _generic_arraycopy; }
   10.85  
   10.86 @@ -352,17 +362,19 @@
   10.87    // Default versions of the above arraycopy functions for platforms which do
   10.88    // not have specialized versions
   10.89    //
   10.90 -  static void jbyte_copy (jbyte*  src, jbyte*  dest, size_t count);
   10.91 -  static void jshort_copy(jshort* src, jshort* dest, size_t count);
   10.92 -  static void jint_copy  (jint*   src, jint*   dest, size_t count);
   10.93 -  static void jlong_copy (jlong*  src, jlong*  dest, size_t count);
   10.94 -  static void oop_copy   (oop*    src, oop*    dest, size_t count);
   10.95 +  static void jbyte_copy     (jbyte*  src, jbyte*  dest, size_t count);
   10.96 +  static void jshort_copy    (jshort* src, jshort* dest, size_t count);
   10.97 +  static void jint_copy      (jint*   src, jint*   dest, size_t count);
   10.98 +  static void jlong_copy     (jlong*  src, jlong*  dest, size_t count);
   10.99 +  static void oop_copy       (oop*    src, oop*    dest, size_t count);
  10.100 +  static void oop_copy_uninit(oop*    src, oop*    dest, size_t count);
  10.101  
  10.102 -  static void arrayof_jbyte_copy (HeapWord* src, HeapWord* dest, size_t count);
  10.103 -  static void arrayof_jshort_copy(HeapWord* src, HeapWord* dest, size_t count);
  10.104 -  static void arrayof_jint_copy  (HeapWord* src, HeapWord* dest, size_t count);
  10.105 -  static void arrayof_jlong_copy (HeapWord* src, HeapWord* dest, size_t count);
  10.106 -  static void arrayof_oop_copy   (HeapWord* src, HeapWord* dest, size_t count);
  10.107 +  static void arrayof_jbyte_copy     (HeapWord* src, HeapWord* dest, size_t count);
  10.108 +  static void arrayof_jshort_copy    (HeapWord* src, HeapWord* dest, size_t count);
  10.109 +  static void arrayof_jint_copy      (HeapWord* src, HeapWord* dest, size_t count);
  10.110 +  static void arrayof_jlong_copy     (HeapWord* src, HeapWord* dest, size_t count);
  10.111 +  static void arrayof_oop_copy       (HeapWord* src, HeapWord* dest, size_t count);
  10.112 +  static void arrayof_oop_copy_uninit(HeapWord* src, HeapWord* dest, size_t count);
  10.113  };
  10.114  
  10.115  #endif // SHARE_VM_RUNTIME_STUBROUTINES_HPP

mercurial