< prev index next >

src/hotspot/share/gc/shenandoah/c1/shenandoahBarrierSetC1.cpp

Print this page
@@ -1,7 +1,8 @@
  /*
   * Copyright (c) 2018, 2024, Red Hat, Inc. All rights reserved.
+  * Copyright Amazon.com Inc. 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.

@@ -23,10 +24,11 @@
   */
  
  #include "precompiled.hpp"
  #include "c1/c1_IR.hpp"
  #include "gc/shared/satbMarkQueue.hpp"
+ #include "gc/shenandoah/mode/shenandoahMode.hpp"
  #include "gc/shenandoah/shenandoahBarrierSet.hpp"
  #include "gc/shenandoah/shenandoahBarrierSetAssembler.hpp"
  #include "gc/shenandoah/shenandoahHeap.inline.hpp"
  #include "gc/shenandoah/shenandoahHeapRegion.hpp"
  #include "gc/shenandoah/shenandoahRuntime.hpp"

@@ -70,11 +72,10 @@
    // Read the gc_state flag.
    LIR_Opr flag_val = gen->new_register(T_INT);
    __ load(gc_state_addr, flag_val);
  
    // Create a mask to test if the marking bit is set.
-   // TODO: can we directly test if bit is set?
    LIR_Opr mask = LIR_OprFact::intConst(ShenandoahHeap::MARKING);
    LIR_Opr mask_reg = gen->new_register(T_INT);
    __ move(mask, mask_reg);
  
    if (two_operand_lir_form) {

@@ -188,10 +189,20 @@
      if (ShenandoahSATBBarrier) {
        pre_barrier(access.gen(), access.access_emit_info(), access.decorators(), access.resolved_addr(), LIR_OprFact::illegalOpr /* pre_val */);
      }
    }
    BarrierSetC1::store_at_resolved(access, value);
+ 
+   if (ShenandoahCardBarrier && access.is_oop()) {
+     DecoratorSet decorators = access.decorators();
+     bool is_array = (decorators & IS_ARRAY) != 0;
+     bool on_anonymous = (decorators & ON_UNKNOWN_OOP_REF) != 0;
+ 
+     bool precise = is_array || on_anonymous;
+     LIR_Opr post_addr = precise ? access.resolved_addr() : access.base().opr();
+     post_barrier(access, post_addr, value);
+   }
  }
  
  LIR_Opr ShenandoahBarrierSetC1::resolve_address(LIRAccess& access, bool resolve_in_register) {
    // We must resolve in register when patching. This is to avoid
    // having a patch area in the load barrier stub, since the call

@@ -286,5 +297,64 @@
      _load_reference_barrier_phantom_rt_code_blob = Runtime1::generate_blob(buffer_blob, C1StubId::NO_STUBID,
                                                                             "shenandoah_load_reference_barrier_phantom_slow",
                                                                             false, &lrb_phantom_code_gen_cl);
    }
  }
+ 
+ void ShenandoahBarrierSetC1::post_barrier(LIRAccess& access, LIR_Opr addr, LIR_Opr new_val) {
+   assert(ShenandoahCardBarrier, "Should have been checked by caller");
+ 
+   DecoratorSet decorators = access.decorators();
+   LIRGenerator* gen = access.gen();
+   bool in_heap = (decorators & IN_HEAP) != 0;
+   if (!in_heap) {
+     return;
+   }
+ 
+   BarrierSet* bs = BarrierSet::barrier_set();
+   ShenandoahBarrierSet* ctbs = barrier_set_cast<ShenandoahBarrierSet>(bs);
+   CardTable* ct = ctbs->card_table();
+   LIR_Const* card_table_base = new LIR_Const(ct->byte_map_base());
+   if (addr->is_address()) {
+     LIR_Address* address = addr->as_address_ptr();
+     // ptr cannot be an object because we use this barrier for array card marks
+     // and addr can point in the middle of an array.
+     LIR_Opr ptr = gen->new_pointer_register();
+     if (!address->index()->is_valid() && address->disp() == 0) {
+       __ move(address->base(), ptr);
+     } else {
+       assert(address->disp() != max_jint, "lea doesn't support patched addresses!");
+       __ leal(addr, ptr);
+     }
+     addr = ptr;
+   }
+   assert(addr->is_register(), "must be a register at this point");
+ 
+   LIR_Opr tmp = gen->new_pointer_register();
+   if (two_operand_lir_form) {
+     __ move(addr, tmp);
+     __ unsigned_shift_right(tmp, CardTable::card_shift(), tmp);
+   } else {
+     __ unsigned_shift_right(addr, CardTable::card_shift(), tmp);
+   }
+ 
+   LIR_Address* card_addr;
+   if (gen->can_inline_as_constant(card_table_base)) {
+     card_addr = new LIR_Address(tmp, card_table_base->as_jint(), T_BYTE);
+   } else {
+     card_addr = new LIR_Address(tmp, gen->load_constant(card_table_base), T_BYTE);
+   }
+ 
+   LIR_Opr dirty = LIR_OprFact::intConst(CardTable::dirty_card_val());
+   if (UseCondCardMark) {
+     LIR_Opr cur_value = gen->new_register(T_INT);
+     __ move(card_addr, cur_value);
+ 
+     LabelObj* L_already_dirty = new LabelObj();
+     __ cmp(lir_cond_equal, cur_value, dirty);
+     __ branch(lir_cond_equal, L_already_dirty->label());
+     __ move(dirty, card_addr);
+     __ branch_destination(L_already_dirty->label());
+   } else {
+     __ move(dirty, card_addr);
+   }
+ }
< prev index next >