176 } 177 178 //---------------------------------------------------------------------------------------------------- 179 // Miscelaneous helper routines 180 181 // Store an oop (or NULL) at the address described by obj. 182 // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR). 183 // Also destroys new_val and obj.base(). 184 static void do_oop_store(InterpreterMacroAssembler* _masm, 185 Address obj, 186 Register new_val, 187 Register tmp1, 188 Register tmp2, 189 Register tmp3, 190 BarrierSet::Name barrier, 191 bool precise, 192 bool is_null) { 193 194 assert_different_registers(obj.base(), new_val, tmp1, tmp2, tmp3, noreg); 195 switch (barrier) { 196 #if INCLUDE_ALL_GCS 197 case BarrierSet::G1BarrierSet: 198 { 199 // flatten object address if needed 200 assert (obj.mode() == basic_offset, "pre- or post-indexing is not supported here"); 201 202 const Register store_addr = obj.base(); 203 if (obj.index() != noreg) { 204 assert (obj.disp() == 0, "index or displacement, not both"); 205 #ifdef AARCH64 206 __ add(store_addr, obj.base(), obj.index(), obj.extend(), obj.shift_imm()); 207 #else 208 assert(obj.offset_op() == add_offset, "addition is expected"); 209 __ add(store_addr, obj.base(), AsmOperand(obj.index(), obj.shift(), obj.shift_imm())); 210 #endif // AARCH64 211 } else if (obj.disp() != 0) { 212 __ add(store_addr, obj.base(), obj.disp()); 213 } 214 215 __ g1_write_barrier_pre(store_addr, new_val, tmp1, tmp2, tmp3); 216 if (is_null) { 217 __ store_heap_oop_null(new_val, Address(store_addr)); 218 } else { 219 // G1 barrier needs uncompressed oop for region cross check. 220 Register val_to_store = new_val; 221 if (UseCompressedOops) { 222 val_to_store = tmp1; 223 __ mov(val_to_store, new_val); 224 } 225 __ store_heap_oop(val_to_store, Address(store_addr)); // blows val_to_store: 226 val_to_store = noreg; 227 __ g1_write_barrier_post(store_addr, new_val, tmp1, tmp2, tmp3); 228 } 229 } 230 break; 231 #endif // INCLUDE_ALL_GCS 232 case BarrierSet::CardTableBarrierSet: 233 { 234 if (is_null) { 235 __ store_heap_oop_null(new_val, obj); 236 } else { 237 assert (!precise || (obj.index() == noreg && obj.disp() == 0), 238 "store check address should be calculated beforehand"); 239 240 __ store_check_part1(tmp1); 241 __ store_heap_oop(new_val, obj); // blows new_val: 242 new_val = noreg; 243 __ store_check_part2(obj.base(), tmp1, tmp2); 244 } 245 } 246 break; 247 case BarrierSet::ModRef: 248 ShouldNotReachHere(); 249 break; 250 default: 251 ShouldNotReachHere(); | 176 } 177 178 //---------------------------------------------------------------------------------------------------- 179 // Miscelaneous helper routines 180 181 // Store an oop (or NULL) at the address described by obj. 182 // Blows all volatile registers (R0-R3 on 32-bit ARM, R0-R18 on AArch64, Rtemp, LR). 183 // Also destroys new_val and obj.base(). 184 static void do_oop_store(InterpreterMacroAssembler* _masm, 185 Address obj, 186 Register new_val, 187 Register tmp1, 188 Register tmp2, 189 Register tmp3, 190 BarrierSet::Name barrier, 191 bool precise, 192 bool is_null) { 193 194 assert_different_registers(obj.base(), new_val, tmp1, tmp2, tmp3, noreg); 195 switch (barrier) { 196 #if INCLUDE_G1GC 197 case BarrierSet::G1BarrierSet: 198 { 199 // flatten object address if needed 200 assert (obj.mode() == basic_offset, "pre- or post-indexing is not supported here"); 201 202 const Register store_addr = obj.base(); 203 if (obj.index() != noreg) { 204 assert (obj.disp() == 0, "index or displacement, not both"); 205 #ifdef AARCH64 206 __ add(store_addr, obj.base(), obj.index(), obj.extend(), obj.shift_imm()); 207 #else 208 assert(obj.offset_op() == add_offset, "addition is expected"); 209 __ add(store_addr, obj.base(), AsmOperand(obj.index(), obj.shift(), obj.shift_imm())); 210 #endif // AARCH64 211 } else if (obj.disp() != 0) { 212 __ add(store_addr, obj.base(), obj.disp()); 213 } 214 215 __ g1_write_barrier_pre(store_addr, new_val, tmp1, tmp2, tmp3); 216 if (is_null) { 217 __ store_heap_oop_null(new_val, Address(store_addr)); 218 } else { 219 // G1 barrier needs uncompressed oop for region cross check. 220 Register val_to_store = new_val; 221 if (UseCompressedOops) { 222 val_to_store = tmp1; 223 __ mov(val_to_store, new_val); 224 } 225 __ store_heap_oop(val_to_store, Address(store_addr)); // blows val_to_store: 226 val_to_store = noreg; 227 __ g1_write_barrier_post(store_addr, new_val, tmp1, tmp2, tmp3); 228 } 229 } 230 break; 231 #endif // INCLUDE_G1GC 232 case BarrierSet::CardTableBarrierSet: 233 { 234 if (is_null) { 235 __ store_heap_oop_null(new_val, obj); 236 } else { 237 assert (!precise || (obj.index() == noreg && obj.disp() == 0), 238 "store check address should be calculated beforehand"); 239 240 __ store_check_part1(tmp1); 241 __ store_heap_oop(new_val, obj); // blows new_val: 242 new_val = noreg; 243 __ store_check_part2(obj.base(), tmp1, tmp2); 244 } 245 } 246 break; 247 case BarrierSet::ModRef: 248 ShouldNotReachHere(); 249 break; 250 default: 251 ShouldNotReachHere(); |