1.1 --- a/src/cpu/x86/vm/stubGenerator_x86_64.cpp Tue Mar 01 10:27:15 2011 -0800 1.2 +++ b/src/cpu/x86/vm/stubGenerator_x86_64.cpp Tue Mar 01 14:56:48 2011 -0800 1.3 @@ -1159,34 +1159,35 @@ 1.4 // Generate code for an array write pre barrier 1.5 // 1.6 // addr - starting address 1.7 - // count - element count 1.8 + // count - element count 1.9 + // tmp - scratch register 1.10 // 1.11 // Destroy no registers! 1.12 // 1.13 - void gen_write_ref_array_pre_barrier(Register addr, Register count) { 1.14 + void gen_write_ref_array_pre_barrier(Register addr, Register count, bool dest_uninitialized) { 1.15 BarrierSet* bs = Universe::heap()->barrier_set(); 1.16 switch (bs->kind()) { 1.17 case BarrierSet::G1SATBCT: 1.18 case BarrierSet::G1SATBCTLogging: 1.19 - { 1.20 - __ pusha(); // push registers 1.21 - if (count == c_rarg0) { 1.22 - if (addr == c_rarg1) { 1.23 - // exactly backwards!! 1.24 - __ xchgptr(c_rarg1, c_rarg0); 1.25 - } else { 1.26 - __ movptr(c_rarg1, count); 1.27 - __ movptr(c_rarg0, addr); 1.28 - } 1.29 - 1.30 - } else { 1.31 - __ movptr(c_rarg0, addr); 1.32 - __ movptr(c_rarg1, count); 1.33 - } 1.34 - __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2); 1.35 - __ popa(); 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 + __ pusha(); // push registers 1.39 + if (count == c_rarg0) { 1.40 + if (addr == c_rarg1) { 1.41 + // exactly backwards!! 1.42 + __ xchgptr(c_rarg1, c_rarg0); 1.43 + } else { 1.44 + __ movptr(c_rarg1, count); 1.45 + __ movptr(c_rarg0, addr); 1.46 + } 1.47 + } else { 1.48 + __ movptr(c_rarg0, addr); 1.49 + __ movptr(c_rarg1, count); 1.50 + } 1.51 + __ call_VM_leaf(CAST_FROM_FN_PTR(address, BarrierSet::static_write_ref_array_pre), 2); 1.52 + __ popa(); 1.53 } 1.54 - break; 1.55 + break; 1.56 case BarrierSet::CardTableModRef: 1.57 case BarrierSet::CardTableExtension: 1.58 case BarrierSet::ModRef: 1.59 @@ -1769,7 +1770,8 @@ 1.60 // disjoint_int_copy_entry is set to the no-overlap entry point 1.61 // used by generate_conjoint_int_oop_copy(). 1.62 // 1.63 - address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, address* entry, const char *name) { 1.64 + address generate_disjoint_int_oop_copy(bool aligned, bool is_oop, address* entry, 1.65 + const char *name, bool dest_uninitialized = false) { 1.66 __ align(CodeEntryAlignment); 1.67 StubCodeMark mark(this, "StubRoutines", name); 1.68 address start = __ pc(); 1.69 @@ -1799,7 +1801,7 @@ 1.70 // r9 and r10 may be used to save non-volatile registers 1.71 if (is_oop) { 1.72 __ movq(saved_to, to); 1.73 - gen_write_ref_array_pre_barrier(to, count); 1.74 + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); 1.75 } 1.76 1.77 // 'from', 'to' and 'count' are now valid 1.78 @@ -1860,7 +1862,8 @@ 1.79 // cache line boundaries will still be loaded and stored atomicly. 1.80 // 1.81 address generate_conjoint_int_oop_copy(bool aligned, bool is_oop, address nooverlap_target, 1.82 - address *entry, const char *name) { 1.83 + address *entry, const char *name, 1.84 + bool dest_uninitialized = false) { 1.85 __ align(CodeEntryAlignment); 1.86 StubCodeMark mark(this, "StubRoutines", name); 1.87 address start = __ pc(); 1.88 @@ -1887,7 +1890,7 @@ 1.89 1.90 if (is_oop) { 1.91 // no registers are destroyed by this call 1.92 - gen_write_ref_array_pre_barrier(to, count); 1.93 + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); 1.94 } 1.95 1.96 assert_clean_int(count, rax); // Make sure 'count' is clean int. 1.97 @@ -1953,7 +1956,8 @@ 1.98 // disjoint_oop_copy_entry or disjoint_long_copy_entry is set to the 1.99 // no-overlap entry point used by generate_conjoint_long_oop_copy(). 1.100 // 1.101 - address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, address *entry, const char *name) { 1.102 + address generate_disjoint_long_oop_copy(bool aligned, bool is_oop, address *entry, 1.103 + const char *name, bool dest_uninitialized = false) { 1.104 __ align(CodeEntryAlignment); 1.105 StubCodeMark mark(this, "StubRoutines", name); 1.106 address start = __ pc(); 1.107 @@ -1983,7 +1987,7 @@ 1.108 // 'from', 'to' and 'qword_count' are now valid 1.109 if (is_oop) { 1.110 // no registers are destroyed by this call 1.111 - gen_write_ref_array_pre_barrier(to, qword_count); 1.112 + gen_write_ref_array_pre_barrier(to, qword_count, dest_uninitialized); 1.113 } 1.114 1.115 // Copy from low to high addresses. Use 'to' as scratch. 1.116 @@ -2038,8 +2042,9 @@ 1.117 // c_rarg1 - destination array address 1.118 // c_rarg2 - element count, treated as ssize_t, can be zero 1.119 // 1.120 - address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, address nooverlap_target, 1.121 - address *entry, const char *name) { 1.122 + address generate_conjoint_long_oop_copy(bool aligned, bool is_oop, 1.123 + address nooverlap_target, address *entry, 1.124 + const char *name, bool dest_uninitialized = false) { 1.125 __ align(CodeEntryAlignment); 1.126 StubCodeMark mark(this, "StubRoutines", name); 1.127 address start = __ pc(); 1.128 @@ -2067,7 +2072,7 @@ 1.129 // Save to and count for store barrier 1.130 __ movptr(saved_count, qword_count); 1.131 // No registers are destroyed by this call 1.132 - gen_write_ref_array_pre_barrier(to, saved_count); 1.133 + gen_write_ref_array_pre_barrier(to, saved_count, dest_uninitialized); 1.134 } 1.135 1.136 __ jmp(L_copy_32_bytes); 1.137 @@ -2146,7 +2151,8 @@ 1.138 // rax == 0 - success 1.139 // rax == -1^K - failure, where K is partial transfer count 1.140 // 1.141 - address generate_checkcast_copy(const char *name, address *entry) { 1.142 + address generate_checkcast_copy(const char *name, address *entry, 1.143 + bool dest_uninitialized = false) { 1.144 1.145 Label L_load_element, L_store_element, L_do_card_marks, L_done; 1.146 1.147 @@ -2240,7 +2246,7 @@ 1.148 Address from_element_addr(end_from, count, TIMES_OOP, 0); 1.149 Address to_element_addr(end_to, count, TIMES_OOP, 0); 1.150 1.151 - gen_write_ref_array_pre_barrier(to, count); 1.152 + gen_write_ref_array_pre_barrier(to, count, dest_uninitialized); 1.153 1.154 // Copy from low to high addresses, indexed from the end of each array. 1.155 __ lea(end_from, end_from_addr); 1.156 @@ -2750,14 +2756,29 @@ 1.157 "oop_disjoint_arraycopy"); 1.158 StubRoutines::_oop_arraycopy = generate_conjoint_int_oop_copy(false, true, entry, 1.159 &entry_oop_arraycopy, "oop_arraycopy"); 1.160 + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_int_oop_copy(false, true, &entry, 1.161 + "oop_disjoint_arraycopy_uninit", 1.162 + /*dest_uninitialized*/true); 1.163 + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_int_oop_copy(false, true, entry, 1.164 + NULL, "oop_arraycopy_uninit", 1.165 + /*dest_uninitialized*/true); 1.166 } else { 1.167 StubRoutines::_oop_disjoint_arraycopy = generate_disjoint_long_oop_copy(false, true, &entry, 1.168 "oop_disjoint_arraycopy"); 1.169 StubRoutines::_oop_arraycopy = generate_conjoint_long_oop_copy(false, true, entry, 1.170 &entry_oop_arraycopy, "oop_arraycopy"); 1.171 + StubRoutines::_oop_disjoint_arraycopy_uninit = generate_disjoint_long_oop_copy(false, true, &entry, 1.172 + "oop_disjoint_arraycopy_uninit", 1.173 + /*dest_uninitialized*/true); 1.174 + StubRoutines::_oop_arraycopy_uninit = generate_conjoint_long_oop_copy(false, true, entry, 1.175 + NULL, "oop_arraycopy_uninit", 1.176 + /*dest_uninitialized*/true); 1.177 } 1.178 1.179 - StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); 1.180 + StubRoutines::_checkcast_arraycopy = generate_checkcast_copy("checkcast_arraycopy", &entry_checkcast_arraycopy); 1.181 + StubRoutines::_checkcast_arraycopy_uninit = generate_checkcast_copy("checkcast_arraycopy_uninit", NULL, 1.182 + /*dest_uninitialized*/true); 1.183 + 1.184 StubRoutines::_unsafe_arraycopy = generate_unsafe_copy("unsafe_arraycopy", 1.185 entry_jbyte_arraycopy, 1.186 entry_jshort_arraycopy, 1.187 @@ -2794,6 +2815,9 @@ 1.188 1.189 StubRoutines::_arrayof_oop_disjoint_arraycopy = StubRoutines::_oop_disjoint_arraycopy; 1.190 StubRoutines::_arrayof_oop_arraycopy = StubRoutines::_oop_arraycopy; 1.191 + 1.192 + StubRoutines::_arrayof_oop_disjoint_arraycopy_uninit = StubRoutines::_oop_disjoint_arraycopy_uninit; 1.193 + StubRoutines::_arrayof_oop_arraycopy_uninit = StubRoutines::_oop_arraycopy_uninit; 1.194 } 1.195 1.196 void generate_math_stubs() {