1 /* 2 * Copyright (c) 2017, Red Hat, Inc. and/or its affiliates. 3 * 4 * This code is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License version 2 only, as 6 * published by the Free Software Foundation. 7 * 8 * This code is distributed in the hope that it will be useful, but WITHOUT 9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 11 * version 2 for more details (a copy is included in the LICENSE file that 12 * accompanied this code). 13 * 14 * You should have received a copy of the GNU General Public License version 15 * 2 along with this work; if not, write to the Free Software Foundation, 16 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 19 * or visit www.oracle.com if you need additional information or have any 20 * questions. 21 * 22 */ 23 24 #include "precompiled.hpp" 25 26 #include "classfile/javaClasses.inline.hpp" 27 #include "gc/g1/g1StringDedup.hpp" 28 #include "gc/g1/g1StringDedupQueue.hpp" 29 #include "gc/g1/g1StringDedupTable.hpp" 30 #include "gc/g1/g1StringDedupThread.hpp" 31 #include "gc/shared/workgroup.hpp" 32 #include "gc/shenandoah/brooksPointer.hpp" 33 #include "gc/shenandoah/shenandoahCollectionSet.hpp" 34 #include "gc/shenandoah/shenandoahCollectionSet.inline.hpp" 35 #include "gc/shenandoah/shenandoahHeap.hpp" 36 #include "gc/shenandoah/shenandoahStringDedup.hpp" 37 #include "logging/log.hpp" 38 #include "runtime/safepoint.hpp" 39 40 41 // This closure is only used during full gc, after references are adjusted, 42 // and before heap compaction. No oop verification can be performed. 43 class ShenandoahIsAliveCompleteClosure: public BoolObjectClosure { 44 private: 45 ShenandoahHeap* _heap; 46 public: 47 ShenandoahIsAliveCompleteClosure() : _heap(ShenandoahHeap::heap()) { 48 } 49 50 bool do_object_b(oop obj) { 51 assert(!oopDesc::is_null(obj), "null"); 52 return _heap->is_marked_complete(obj); 53 } 54 }; 55 56 // Same as above 57 class ShenandoahUpdateLiveRefsClosure: public OopClosure { 58 private: 59 ShenandoahHeap* _heap; 60 61 template <class T> 62 inline void do_oop_work(T* p) { 63 T o = oopDesc::load_heap_oop(p); 64 if (! oopDesc::is_null(o)) { 65 oop obj = oopDesc::decode_heap_oop_not_null(o); 66 assert(_heap->is_in(obj), "Must be in the heap"); 67 HeapWord* ptr = BrooksPointer::get_raw(obj); 68 oop forw = oop(ptr); 69 70 assert(_heap->is_in(forw), "Must be in the heap"); 71 assert(!oopDesc::is_null(forw), "Can not be null"); 72 if (!oopDesc::unsafe_equals(forw, obj)) { 73 oopDesc::encode_store_heap_oop(p, forw); 74 } 75 } else { 76 assert(false, "NULL oop"); 77 } 78 } 79 80 public: 81 ShenandoahUpdateLiveRefsClosure() : _heap(ShenandoahHeap::heap()) { 82 } 83 84 inline void do_oop(oop* p) { do_oop_work(p); } 85 inline void do_oop(narrowOop* p) { do_oop_work(p); } 86 }; 87 88 89 // Perform String Dedup update and/or cleanup task 90 class ShenandoahStringDedupTableUpdateOrUnlinkTask : public AbstractGangTask { 91 private: 92 G1StringDedupUnlinkOrOopsDoClosure _dedup_closure; 93 public: 94 ShenandoahStringDedupTableUpdateOrUnlinkTask(BoolObjectClosure* is_alive_closure, OopClosure* keep_alive_closure) 95 : AbstractGangTask("Shenandoah Dedup unlink task"), 96 _dedup_closure(is_alive_closure, keep_alive_closure, true) { 97 } 98 99 void work(uint worker_id) { 100 G1StringDedup::parallel_unlink(&_dedup_closure, worker_id); 101 } 102 }; 103 104 105 void ShenandoahStringDedup::initialize() { 106 assert(UseShenandoahGC, "String deduplication available with ShenandoahGC"); 107 if (UseStringDeduplication) { 108 _enabled = true; 109 G1StringDedupQueue::create(ShenandoahHeap::heap()->max_workers()); 110 G1StringDedupTable::create(); 111 G1StringDedupThread::create("Shenandoah StrDedup"); 112 } 113 } 114 115 116 void ShenandoahStringDedup::try_dedup(oop java_string) { 117 if (is_candidate(java_string)) { 118 G1StringDedup::deduplicate(java_string); 119 } 120 } 121 122 void ShenandoahStringDedup::enqueue_from_safepoint(oop java_string, uint worker_id) { 123 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 124 assert(Thread::current()->is_Worker_thread(), "Must be a worker thread"); 125 assert(worker_id < ShenandoahHeap::heap()->max_workers(), "Sanity"); 126 127 G1StringDedupQueue::push(worker_id, java_string); 128 } 129 130 131 void ShenandoahStringDedup::parallel_full_gc_update_or_unlink() { 132 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 133 assert(ShenandoahHeap::heap()->is_full_gc_in_progress(), "Must be during full gc"); 134 135 ShenandoahUpdateLiveRefsClosure update_refs_closure; 136 ShenandoahIsAliveCompleteClosure is_alive_closure; 137 ShenandoahStringDedupTableUpdateOrUnlinkTask task(&is_alive_closure, &update_refs_closure); 138 ShenandoahHeap::heap()->workers()->run_task(&task); 139 } 140 141 142 void ShenandoahStringDedup::parallel_update_refs() { 143 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 144 ShenandoahUpdateRefsClosure update_refs_closure; 145 ShenandoahAlwaysTrueClosure is_alive_closure; 146 ShenandoahStringDedupTableUpdateOrUnlinkTask task(&is_alive_closure, &update_refs_closure); 147 ShenandoahHeap::heap()->workers()->run_task(&task); 148 } 149 150 151 void ShenandoahStringDedup::parallel_cleanup() { 152 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 153 ShenandoahForwardedIsAliveClosure is_alive_closure; 154 ShenandoahStringDedupTableUpdateOrUnlinkTask task(&is_alive_closure, NULL); 155 ShenandoahHeap::heap()->workers()->run_task(&task); 156 } 157 158 159 // Only used during partial GC after evacuation. 160 // We don't have accurate bitmap during partial GC to determine liveness of 161 // an object. So after evacuation, if the object is in collection set but not 162 // evacuated, it is dead. 163 class ShenandoahPartialIsAliveClosure: public BoolObjectClosure { 164 private: 165 ShenandoahHeap* _heap; 166 public: 167 ShenandoahPartialIsAliveClosure() : _heap(ShenandoahHeap::heap()) { 168 } 169 170 bool do_object_b(oop obj); 171 }; 172 173 bool ShenandoahPartialIsAliveClosure::do_object_b(oop obj) { 174 if (_heap->in_collection_set(obj)) { 175 oop forw = ShenandoahBarrierSet::resolve_oop_static_not_null(obj); 176 return !oopDesc::unsafe_equals(forw, obj); 177 } 178 179 return true; 180 } 181 182 183 void ShenandoahStringDedup::parallel_partial_update_or_unlink() { 184 assert(SafepointSynchronize::is_at_safepoint(), "Must be at a safepoint"); 185 ShenandoahUpdateLiveRefsClosure update_refs_closure; 186 ShenandoahPartialIsAliveClosure is_alive_closure; 187 ShenandoahStringDedupTableUpdateOrUnlinkTask task(&is_alive_closure, &update_refs_closure); 188 ShenandoahHeap::heap()->workers()->run_task(&task); 189 }