Tue, 01 Mar 2011 14:56:48 -0800
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
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