6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "asm/macroAssembler.inline.hpp"
26 #include "gc/g1/g1BarrierSet.hpp"
27 #include "gc/g1/g1BarrierSetAssembler.hpp"
28 #include "gc/g1/g1BarrierSetRuntime.hpp"
29 #include "gc/g1/g1CardTable.hpp"
30 #include "gc/g1/g1HeapRegion.hpp"
31 #include "gc/g1/g1ThreadLocalData.hpp"
32 #include "interpreter/interp_masm.hpp"
33 #include "runtime/sharedRuntime.hpp"
34 #include "utilities/debug.hpp"
35 #include "utilities/macros.hpp"
36 #ifdef COMPILER1
37 #include "c1/c1_LIRAssembler.hpp"
38 #include "c1/c1_MacroAssembler.hpp"
39 #include "gc/g1/c1/g1BarrierSetC1.hpp"
40 #endif // COMPILER1
41 #ifdef COMPILER2
42 #include "gc/g1/c2/g1BarrierSetC2.hpp"
43 #endif // COMPILER2
44
45 #define __ masm->
251 // expand_call should be passed true.
252
253 if (expand_call) {
254 assert(pre_val != c_rarg1, "smashed arg");
255 if (c_rarg1 != thread) {
256 __ mov(c_rarg1, thread);
257 }
258 if (c_rarg0 != pre_val) {
259 __ mov(c_rarg0, pre_val);
260 }
261 __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2);
262 } else {
263 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
264 }
265
266 __ pop_call_clobbered_registers();
267
268 __ bind(done);
269 }
270
271 static void generate_post_barrier_fast_path(MacroAssembler* masm,
272 const Register store_addr,
273 const Register new_val,
274 const Register tmp1,
275 Label& done,
276 bool new_val_may_be_null) {
277
278 assert_different_registers(store_addr, new_val, tmp1, noreg);
279
280 Register thread = r15_thread;
281
282 // Does store cross heap regions?
283 __ movptr(tmp1, store_addr); // tmp1 := store address
284 __ xorptr(tmp1, new_val); // tmp1 := store address ^ new value
285 __ shrptr(tmp1, G1HeapRegion::LogOfHRGrainBytes); // ((store address ^ new value) >> LogOfHRGrainBytes) == 0?
286 __ jcc(Assembler::equal, done);
287
288 // Crosses regions, storing null?
289 if (new_val_may_be_null) {
290 __ cmpptr(new_val, NULL_WORD); // new value == null?
291 __ jcc(Assembler::equal, done);
292 }
293
294 __ movptr(tmp1, store_addr); // tmp1 := store address
295 __ shrptr(tmp1, CardTable::card_shift()); // tmp1 := card address relative to card table base
296
297 Address card_table_addr(thread, in_bytes(G1ThreadLocalData::card_table_base_offset()));
298 __ addptr(tmp1, card_table_addr); // tmp1 := card address
299 if (UseCondCardMark) {
300 __ cmpb(Address(tmp1, 0), G1CardTable::clean_card_val()); // *(card address) == clean_card_val?
301 __ jcc(Assembler::notEqual, done);
302 }
303 // Storing a region crossing, non-null oop, card is clean.
304 // Dirty card.
305 __ movb(Address(tmp1, 0), G1CardTable::dirty_card_val()); // *(card address) := dirty_card_val
306 }
|
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25 #include "asm/macroAssembler.inline.hpp"
26 #include "code/aotCodeCache.hpp"
27 #include "gc/g1/g1BarrierSet.hpp"
28 #include "gc/g1/g1BarrierSetAssembler.hpp"
29 #include "gc/g1/g1BarrierSetRuntime.hpp"
30 #include "gc/g1/g1CardTable.hpp"
31 #include "gc/g1/g1HeapRegion.hpp"
32 #include "gc/g1/g1ThreadLocalData.hpp"
33 #include "interpreter/interp_masm.hpp"
34 #include "runtime/sharedRuntime.hpp"
35 #include "utilities/debug.hpp"
36 #include "utilities/macros.hpp"
37 #ifdef COMPILER1
38 #include "c1/c1_LIRAssembler.hpp"
39 #include "c1/c1_MacroAssembler.hpp"
40 #include "gc/g1/c1/g1BarrierSetC1.hpp"
41 #endif // COMPILER1
42 #ifdef COMPILER2
43 #include "gc/g1/c2/g1BarrierSetC2.hpp"
44 #endif // COMPILER2
45
46 #define __ masm->
252 // expand_call should be passed true.
253
254 if (expand_call) {
255 assert(pre_val != c_rarg1, "smashed arg");
256 if (c_rarg1 != thread) {
257 __ mov(c_rarg1, thread);
258 }
259 if (c_rarg0 != pre_val) {
260 __ mov(c_rarg0, pre_val);
261 }
262 __ MacroAssembler::call_VM_leaf_base(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), 2);
263 } else {
264 __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
265 }
266
267 __ pop_call_clobbered_registers();
268
269 __ bind(done);
270 }
271
272 // return a register that differs from reg1, reg2, reg3 and is not rcx
273
274 static Register pick_different_reg(Register reg1, Register reg2 = noreg, Register reg3= noreg, Register reg4 = noreg) {
275 RegSet available = (RegSet::of(rscratch1, rscratch2, rax, rbx) + rdx -
276 RegSet::of(reg1, reg2, reg3, reg4));
277 return *(available.begin());
278 }
279
280 static void generate_post_barrier_fast_path(MacroAssembler* masm,
281 const Register store_addr,
282 const Register new_val,
283 const Register tmp1,
284 Label& done,
285 bool new_val_may_be_null) {
286
287 assert_different_registers(store_addr, new_val, tmp1, noreg);
288
289 Register thread = r15_thread;
290
291 // Does store cross heap regions?
292 #if INCLUDE_CDS
293 // AOT code needs to load the barrier grain shift from the aot
294 // runtime constants area in the code cache otherwise we can compile
295 // it as an immediate operand
296
297 if (AOTCodeCache::is_on_for_dump()) {
298 address grain_shift_addr = AOTRuntimeConstants::grain_shift_address();
299 Register save = pick_different_reg(rcx, tmp1, new_val, store_addr);
300 __ push(save);
301 __ movptr(save, store_addr);
302 __ xorptr(save, new_val);
303 __ push(rcx);
304 __ lea(rcx, ExternalAddress(grain_shift_addr));
305 __ movptr(rcx, Address(rcx, 0));
306 __ shrptr(save);
307 __ pop(rcx);
308 __ mov(tmp1, save);
309 __ pop(save);
310 __ jcc(Assembler::equal, done);
311 } else
312 #endif // INCLUDE_CDS
313 {
314 __ movptr(tmp1, store_addr); // tmp1 := store address
315 __ xorptr(tmp1, new_val); // tmp1 := store address ^ new value
316 __ shrptr(tmp1, G1HeapRegion::LogOfHRGrainBytes); // ((store address ^ new value) >> LogOfHRGrainBytes) == 0?
317 __ jcc(Assembler::equal, done);
318 }
319
320 // Crosses regions, storing null?
321 if (new_val_may_be_null) {
322 __ cmpptr(new_val, NULL_WORD); // new value == null?
323 __ jcc(Assembler::equal, done);
324 }
325
326 __ movptr(tmp1, store_addr); // tmp1 := store address
327 __ shrptr(tmp1, CardTable::card_shift()); // tmp1 := card address relative to card table base
328
329 Address card_table_addr(thread, in_bytes(G1ThreadLocalData::card_table_base_offset()));
330 __ addptr(tmp1, card_table_addr); // tmp1 := card address
331 if (UseCondCardMark) {
332 __ cmpb(Address(tmp1, 0), G1CardTable::clean_card_val()); // *(card address) == clean_card_val?
333 __ jcc(Assembler::notEqual, done);
334 }
335 // Storing a region crossing, non-null oop, card is clean.
336 // Dirty card.
337 __ movb(Address(tmp1, 0), G1CardTable::dirty_card_val()); // *(card address) := dirty_card_val
338 }
|