1 /* 2 * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 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 "precompiled.hpp" 26 #include "gc/g1/heapRegion.hpp" 27 #include "gc/g1/g1BarrierSet.inline.hpp" 28 #include "gc/g1/g1BarrierSetRuntime.hpp" 29 #include "gc/g1/g1ThreadLocalData.hpp" 30 #include "runtime/interfaceSupport.inline.hpp" 31 #include "utilities/macros.hpp" 32 33 PerfCounter* G1BarrierSetRuntime::_total_write_barriers = NULL; 34 PerfCounter* G1BarrierSetRuntime::_young_ref_writes = NULL; 35 PerfCounter* G1BarrierSetRuntime::_cross_region_ref_writes = NULL; 36 PerfCounter* G1BarrierSetRuntime::_young_cross_region_ref_writes = NULL; 37 PerfCounter* G1BarrierSetRuntime::_old_cross_region_ref_writes = NULL; 38 PerfCounter* G1BarrierSetRuntime::_old_dirty_cross_ref_writes = NULL; 39 PerfCounter* G1BarrierSetRuntime::_ref_array_writes = NULL; 40 41 void G1BarrierSetRuntime::write_ref_array_pre_oop_entry(oop* dst, size_t length) { 42 G1BarrierSet *bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set()); 43 bs->write_ref_array_pre(dst, length, false); 44 } 45 46 void G1BarrierSetRuntime::write_ref_array_pre_narrow_oop_entry(narrowOop* dst, size_t length) { 47 G1BarrierSet *bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set()); 48 bs->write_ref_array_pre(dst, length, false); 49 } 50 51 void G1BarrierSetRuntime::write_ref_array_post_entry(HeapWord* dst, size_t length) { 52 if (UsePerfData && G1WriteBarrierStats) { 53 _ref_array_writes->atomic_add((jlong)length); 54 } 55 G1BarrierSet *bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set()); 56 bs->G1BarrierSet::write_ref_array(dst, length); 57 } 58 59 // G1 pre write barrier slowpath 60 JRT_LEAF(void, G1BarrierSetRuntime::write_ref_field_pre_entry(oopDesc* orig, JavaThread *thread)) 61 if (orig == NULL) { 62 assert(false, "should be optimized out"); 63 return; 64 } 65 assert(oopDesc::is_oop(orig, true /* ignore mark word */), "Error"); 66 // store the original value that was in the field reference 67 G1ThreadLocalData::satb_mark_queue(thread).enqueue(orig); 68 JRT_END 69 70 // G1 post write barrier slowpath 71 JRT_LEAF(void, G1BarrierSetRuntime::write_ref_field_post_entry(void* card_addr, JavaThread* thread)) 72 G1ThreadLocalData::dirty_card_queue(thread).enqueue(card_addr); 73 JRT_END 74 75 JRT_LEAF(void, G1BarrierSetRuntime::write_ref_stats(HeapWord* dst, oopDesc* val)) 76 _total_write_barriers->atomic_inc(); 77 G1BarrierSet* bs = barrier_set_cast<G1BarrierSet>(BarrierSet::barrier_set()); 78 CardTable* ct = bs->card_table(); 79 bool is_young = ct->is_in_young(oop(dst)); 80 uint64_t xor_result = 81 reinterpret_cast<uint64_t>(dst) ^ reinterpret_cast<uint64_t>(val); 82 bool is_cross_region = (xor_result >> HeapRegion::LogOfHRGrainBytes) != 0; 83 if (is_young) { 84 _young_ref_writes->atomic_inc(); 85 } 86 if (is_cross_region) { 87 _cross_region_ref_writes->atomic_inc(); 88 } 89 if (is_young && is_cross_region) { 90 _young_cross_region_ref_writes->atomic_inc(); 91 } 92 if (!is_young && is_cross_region) { 93 _old_cross_region_ref_writes->atomic_inc(); 94 if (*ct->byte_for(dst) == CardTable::dirty_card_val()) { 95 _old_dirty_cross_ref_writes->atomic_inc(); 96 } 97 } 98 JRT_END 99 100 void G1BarrierSetRuntime::initialize() { 101 if (UsePerfData && G1WriteBarrierStats) { 102 EXCEPTION_MARK; 103 104 _total_write_barriers = 105 PerfDataManager::create_counter(NULL_NS, "total_write_barriers", 106 PerfData::U_Ticks, CHECK); 107 _young_ref_writes = 108 PerfDataManager::create_counter(NULL_NS, "young_ref_writes", 109 PerfData::U_Ticks, CHECK); 110 _cross_region_ref_writes = 111 PerfDataManager::create_counter(NULL_NS, "cross_region_ref_writes", 112 PerfData::U_Ticks, CHECK); 113 _young_cross_region_ref_writes = 114 PerfDataManager::create_counter(NULL_NS, "young_cross_region_ref_writes", 115 PerfData::U_Ticks, CHECK); 116 _old_cross_region_ref_writes = 117 PerfDataManager::create_counter(NULL_NS, "old_cross_region_ref_writes", 118 PerfData::U_Ticks, CHECK); 119 _old_dirty_cross_ref_writes = 120 PerfDataManager::create_counter(NULL_NS, "old_dirty_cross_ref_writes", 121 PerfData::U_Ticks, CHECK); 122 _ref_array_writes = 123 PerfDataManager::create_counter(NULL_NS, "ref_array_writes", 124 PerfData::U_Ticks, CHECK); 125 } 126 }