< prev index next >

src/hotspot/cpu/aarch64/gc/g1/g1BarrierSetAssembler_aarch64.cpp

Print this page
*** 1,7 ***
  /*
!  * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.
--- 1,7 ---
  /*
!  * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   *
   * This code is free software; you can redistribute it and/or modify it
   * under the terms of the GNU General Public License version 2 only, as
   * published by the Free Software Foundation.

*** 152,16 ***
--- 152,30 ---
    // Record the previous value
    __ str(pre_val, Address(tmp, 0));
    __ b(done);
  
    __ bind(runtime);
+ 
    // save the live input values
    RegSet saved = RegSet::of(pre_val);
+   FloatRegSet fsaved;
    if (tosca_live) saved += RegSet::of(r0);
    if (obj != noreg) saved += RegSet::of(obj);
  
+   // Barriers might be emitted when converting between (scalarized) calling
+   // conventions for inline types. Save all argument registers before calling
+   // into the runtime.
+   if (EnableValhalla && InlineTypePassFieldsAsArgs) {
+     saved += RegSet::of(j_rarg0, j_rarg1, j_rarg2, j_rarg3);
+     saved += RegSet::of(j_rarg4, j_rarg5, j_rarg6, j_rarg7);
+ 
+     fsaved += FloatRegSet::of(j_farg0, j_farg1, j_farg2, j_farg3);
+     fsaved += FloatRegSet::of(j_farg4, j_farg5, j_farg6, j_farg7);
+   }
+ 
    __ push(saved, sp);
+   __ push_fp(fsaved, sp);
  
    // Calling the runtime using the regular call_VM_leaf mechanism generates
    // code (generated by InterpreterMacroAssember::call_VM_leaf_base)
    // that checks that the *(rfp+frame::interpreter_frame_last_sp) == NULL.
    //

*** 178,10 ***
--- 192,11 ---
      __ super_call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
    } else {
      __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_pre_entry), pre_val, thread);
    }
  
+   __ pop_fp(fsaved, sp);
    __ pop(saved, sp);
  
    __ bind(done);
  
  }

*** 191,12 ***
                                                    Register new_val,
                                                    Register thread,
                                                    Register tmp,
                                                    Register tmp2) {
    assert(thread == rthread, "must be");
!   assert_different_registers(store_addr, new_val, thread, tmp, tmp2,
-                              rscratch1);
    assert(store_addr != noreg && new_val != noreg && tmp != noreg
           && tmp2 != noreg, "expecting a register");
  
    Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
    Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));
--- 206,11 ---
                                                    Register new_val,
                                                    Register thread,
                                                    Register tmp,
                                                    Register tmp2) {
    assert(thread == rthread, "must be");
!   assert_different_registers(store_addr, new_val, thread, tmp, rscratch1);
    assert(store_addr != noreg && new_val != noreg && tmp != noreg
           && tmp2 != noreg, "expecting a register");
  
    Address queue_index(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_index_offset()));
    Address buffer(thread, in_bytes(G1ThreadLocalData::dirty_card_queue_buffer_offset()));

*** 218,10 ***
--- 232,12 ---
  
    __ cbz(new_val, done);
  
    // storing region crossing non-NULL, is card already dirty?
  
+   assert_different_registers(store_addr, thread, tmp, tmp2, rscratch1);
+ 
    const Register card_addr = tmp;
  
    __ lsr(card_addr, store_addr, CardTable::card_shift);
  
    // get the address of the card

*** 251,14 ***
--- 267,30 ---
    __ ldr(tmp2, buffer);
    __ str(card_addr, Address(tmp2, rscratch1));
    __ b(done);
  
    __ bind(runtime);
+ 
    // save the live input values
    RegSet saved = RegSet::of(store_addr);
+   FloatRegSet fsaved;
+ 
+   // Barriers might be emitted when converting between (scalarized) calling
+   // conventions for inline types. Save all argument registers before calling
+   // into the runtime.
+   if (EnableValhalla && InlineTypePassFieldsAsArgs) {
+     saved += RegSet::of(j_rarg0, j_rarg1, j_rarg2, j_rarg3);
+     saved += RegSet::of(j_rarg4, j_rarg5, j_rarg6, j_rarg7);
+ 
+     fsaved += FloatRegSet::of(j_farg0, j_farg1, j_farg2, j_farg3);
+     fsaved += FloatRegSet::of(j_farg4, j_farg5, j_farg6, j_farg7);
+   }
+ 
    __ push(saved, sp);
+   __ push_fp(fsaved, sp);
    __ call_VM_leaf(CAST_FROM_FN_PTR(address, G1BarrierSetRuntime::write_ref_field_post_entry), card_addr, thread);
+   __ pop_fp(fsaved, sp);
    __ pop(saved, sp);
  
    __ bind(done);
  }
  

*** 284,44 ***
      __ leave();
    }
  }
  
  void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
!                                          Address dst, Register val, Register tmp1, Register tmp2) {
    // flatten object address if needed
    if (dst.index() == noreg && dst.offset() == 0) {
!     if (dst.base() != r3) {
!       __ mov(r3, dst.base());
      }
    } else {
!     __ lea(r3, dst);
    }
  
!   g1_write_barrier_pre(masm,
!                        r3 /* obj */,
!                        tmp2 /* pre_val */,
!                        rthread /* thread */,
!                        tmp1  /* tmp */,
!                        val != noreg /* tosca_live */,
!                        false /* expand_call */);
  
    if (val == noreg) {
!     BarrierSetAssembler::store_at(masm, decorators, type, Address(r3, 0), noreg, noreg, noreg);
    } else {
      // G1 barrier needs uncompressed oop for region cross check.
      Register new_val = val;
!     if (UseCompressedOops) {
!       new_val = rscratch2;
!       __ mov(new_val, val);
      }
-     BarrierSetAssembler::store_at(masm, decorators, type, Address(r3, 0), val, noreg, noreg);
-     g1_write_barrier_post(masm,
-                           r3 /* store_adr */,
-                           new_val /* new_val */,
-                           rthread /* thread */,
-                           tmp1 /* tmp */,
-                           tmp2 /* tmp2 */);
    }
  
  }
  
  #ifdef COMPILER1
--- 316,65 ---
      __ leave();
    }
  }
  
  void G1BarrierSetAssembler::oop_store_at(MacroAssembler* masm, DecoratorSet decorators, BasicType type,
!                                          Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) {
+ 
+   bool in_heap = (decorators & IN_HEAP) != 0;
+   bool as_normal = (decorators & AS_NORMAL) != 0;
+   bool dest_uninitialized = (decorators & IS_DEST_UNINITIALIZED) != 0;
+ 
+   bool needs_pre_barrier = as_normal && !dest_uninitialized;
+   bool needs_post_barrier = (val != noreg && in_heap);
+ 
+   if (tmp3 == noreg) {
+     tmp3 = rscratch2;
+   }
+   assert_different_registers(val, tmp1, tmp2, tmp3);
+ 
    // flatten object address if needed
    if (dst.index() == noreg && dst.offset() == 0) {
!     if (dst.base() != tmp1) {
!       __ mov(tmp1, dst.base());
      }
    } else {
!     __ lea(tmp1, dst);
    }
  
!   if (needs_pre_barrier) {
!     g1_write_barrier_pre(masm,
!                          tmp1 /* obj */,
!                          tmp2 /* pre_val */,
!                          rthread /* thread */,
!                          tmp3  /* tmp */,
!                          val != noreg /* tosca_live */,
+                          false /* expand_call */);
+   }
  
    if (val == noreg) {
!     BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), noreg, noreg, noreg, noreg);
    } else {
      // G1 barrier needs uncompressed oop for region cross check.
      Register new_val = val;
!     if (needs_post_barrier) {
!       if (UseCompressedOops) {
!         new_val = tmp3;
+         __ mov(new_val, val);
+       }
+     }
+ 
+     BarrierSetAssembler::store_at(masm, decorators, type, Address(tmp1, 0), val, noreg, noreg, noreg);
+ 
+     if (needs_post_barrier) {
+       g1_write_barrier_post(masm,
+                             tmp1 /* store_adr */,
+                             new_val /* new_val */,
+                             rthread /* thread */,
+                             tmp2 /* tmp */,
+                             tmp3 /* tmp2 */);
      }
    }
  
  }
  
  #ifdef COMPILER1
< prev index next >