1 /* 2 * Copyright (c) 2017, 2019, 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 #include "precompiled.hpp" 25 #include "classfile/classLoaderData.hpp" 26 #include "classfile/classLoaderDataGraph.hpp" 27 #include "gc/z/zBarrier.inline.hpp" 28 #include "gc/z/zGlobals.hpp" 29 #include "gc/z/zGranuleMap.inline.hpp" 30 #include "gc/z/zHeapIterator.hpp" 31 #include "gc/z/zOop.inline.hpp" 32 #include "gc/z/zRootsIterator.hpp" 33 #include "gc/z/zStat.hpp" 34 #include "memory/iterator.inline.hpp" 35 #include "utilities/bitMap.inline.hpp" 36 #include "utilities/stack.inline.hpp" 37 38 class ZHeapIteratorBitMap : public CHeapObj<mtGC> { 39 private: 40 CHeapBitMap _map; 41 42 public: 43 ZHeapIteratorBitMap(size_t size_in_bits) : 44 _map(size_in_bits) {} 45 46 bool try_set_bit(size_t index) { 47 if (_map.at(index)) { 48 return false; 49 } 50 51 _map.set_bit(index); 52 return true; 53 } 54 }; 55 56 template <bool Concurrent, bool Weak> 57 class ZHeapIteratorRootOopClosure : public ZRootsIteratorClosure { 58 private: 59 ZHeapIterator* const _iter; 60 61 oop load_oop(oop* p) { 62 if (Weak) { 63 return NativeAccess<AS_NO_KEEPALIVE | ON_PHANTOM_OOP_REF>::oop_load(p); 64 } 65 66 if (Concurrent) { 67 return NativeAccess<AS_NO_KEEPALIVE>::oop_load(p); 68 } 69 70 return RawAccess<>::oop_load(p); 71 } 72 73 public: 74 ZHeapIteratorRootOopClosure(ZHeapIterator* iter) : 75 _iter(iter) {} 76 77 virtual void do_oop(oop* p) { 78 const oop obj = load_oop(p); 79 _iter->push(obj); 80 } 81 82 virtual void do_oop(narrowOop* p) { 83 ShouldNotReachHere(); 84 } 85 }; 86 87 template <bool VisitReferents> 88 class ZHeapIteratorOopClosure : public ClaimMetadataVisitingOopIterateClosure { 89 private: 90 ZHeapIterator* const _iter; 91 const oop _base; 92 93 oop load_oop(oop* p) { 94 if (VisitReferents) { 95 return HeapAccess<AS_NO_KEEPALIVE | ON_UNKNOWN_OOP_REF>::oop_load_at(_base, _base->field_offset(p)); 96 } 97 98 return HeapAccess<AS_NO_KEEPALIVE>::oop_load(p); 99 } 100 101 public: 102 ZHeapIteratorOopClosure(ZHeapIterator* iter, oop base) : 103 ClaimMetadataVisitingOopIterateClosure(ClassLoaderData::_claim_other), 104 _iter(iter), 105 _base(base) {} 106 107 virtual ReferenceIterationMode reference_iteration_mode() { 108 return VisitReferents ? DO_FIELDS : DO_FIELDS_EXCEPT_REFERENT; 109 } 110 111 virtual void do_oop(oop* p) { 112 const oop obj = load_oop(p); 113 _iter->push(obj); 114 } 115 116 virtual void do_oop(narrowOop* p) { 117 ShouldNotReachHere(); 118 } 119 120 #ifdef ASSERT 121 virtual bool should_verify_oops() { 122 return false; 123 } 124 #endif 125 }; 126 127 ZHeapIterator::ZHeapIterator() : 128 _visit_stack(), 129 _visit_map() {} 130 131 ZHeapIterator::~ZHeapIterator() { 132 ZVisitMapIterator iter(&_visit_map); 133 for (ZHeapIteratorBitMap* map; iter.next(&map);) { 134 delete map; 135 } 136 ClassLoaderDataGraph::clear_claimed_marks(ClassLoaderData::_claim_other); 137 } 138 139 static size_t object_index_max() { 140 return ZGranuleSize >> ZObjectAlignmentSmallShift; 141 } 142 143 static size_t object_index(oop obj) { 144 const uintptr_t addr = ZOop::to_address(obj); 145 const uintptr_t offset = ZAddress::offset(addr); 146 const uintptr_t mask = ZGranuleSize - 1; 147 return (offset & mask) >> ZObjectAlignmentSmallShift; 148 } 149 150 ZHeapIteratorBitMap* ZHeapIterator::object_map(oop obj) { 151 const uintptr_t addr = ZOop::to_address(obj); 152 ZHeapIteratorBitMap* map = _visit_map.get(addr); 153 if (map == NULL) { 154 map = new ZHeapIteratorBitMap(object_index_max()); 155 _visit_map.put(addr, map); 156 } 157 158 return map; 159 } 160 161 void ZHeapIterator::push(oop obj) { 162 if (obj == NULL) { 163 // Ignore 164 return; 165 } 166 167 ZHeapIteratorBitMap* const map = object_map(obj); 168 const size_t index = object_index(obj); 169 if (!map->try_set_bit(index)) { 170 // Already pushed 171 return; 172 } 173 174 // Push 175 _visit_stack.push(obj); 176 } 177 178 template <typename RootsIterator, bool Concurrent, bool Weak> 179 void ZHeapIterator::push_roots() { 180 ZHeapIteratorRootOopClosure<Concurrent, Weak> cl(this); 181 RootsIterator roots; 182 roots.oops_do(&cl); 183 } 184 185 template <bool VisitReferents> 186 void ZHeapIterator::push_fields(oop obj) { 187 ZHeapIteratorOopClosure<VisitReferents> cl(this, obj); 188 obj->oop_iterate(&cl); 189 } 190 191 template <bool VisitWeaks> 192 void ZHeapIterator::objects_do(ObjectClosure* cl) { 193 ZStatTimerDisable disable; 194 195 // Push roots to visit 196 push_roots<ZRootsIterator, false /* Concurrent */, false /* Weak */>(); 197 push_roots<ZConcurrentRootsIteratorClaimOther, true /* Concurrent */, false /* Weak */>(); 198 if (VisitWeaks) { 199 push_roots<ZWeakRootsIterator, false /* Concurrent */, true /* Weak */>(); 200 push_roots<ZConcurrentWeakRootsIterator, true /* Concurrent */, true /* Weak */>(); 201 } 202 203 // Drain stack 204 while (!_visit_stack.is_empty()) { 205 const oop obj = _visit_stack.pop(); 206 207 // Visit object 208 cl->do_object(obj); 209 210 // Push fields to visit 211 push_fields<VisitWeaks>(obj); 212 } 213 } 214 215 void ZHeapIterator::objects_do(ObjectClosure* cl, bool visit_weaks) { 216 if (visit_weaks) { 217 objects_do<true /* VisitWeaks */>(cl); 218 } else { 219 objects_do<false /* VisitWeaks */>(cl); 220 } 221 }