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 #ifndef SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP 26 #define SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP 27 28 #include "gc/shared/oopStorageParState.hpp" 29 #include "gc/shared/stringdedup/stringDedup.hpp" 30 #include "gc/shared/workgroup.hpp" 31 32 class ParallelCleaningTask; 33 34 class StringCleaningTask : public AbstractGangTask { 35 private: 36 BoolObjectClosure* _is_alive; 37 StringDedupUnlinkOrOopsDoClosure * const _dedup_closure; 38 39 OopStorage::ParState<false /* concurrent */, false /* const */> _par_state_string; 40 41 int _initial_string_table_size; 42 43 bool _process_strings; 44 volatile size_t _strings_processed; 45 volatile size_t _strings_removed; 46 47 public: 48 StringCleaningTask(BoolObjectClosure* is_alive, StringDedupUnlinkOrOopsDoClosure* dedup_closure, bool process_strings); 49 ~StringCleaningTask(); 50 51 void work(uint worker_id); 52 53 size_t strings_processed() const { return _strings_processed; } 54 size_t strings_removed() const { return _strings_removed; } 55 }; 56 57 class CodeCacheUnloadingTask { 58 private: 59 static Monitor* _lock; 60 61 BoolObjectClosure* const _is_alive; 62 const bool _unloading_occurred; 63 const uint _num_workers; 64 65 // Variables used to claim nmethods. 66 CompiledMethod* _first_nmethod; 67 CompiledMethod* volatile _claimed_nmethod; 68 69 // The list of nmethods that need to be processed by the second pass. 70 CompiledMethod* volatile _postponed_list; 71 volatile uint _num_entered_barrier; 72 73 public: 74 CodeCacheUnloadingTask(uint num_workers, BoolObjectClosure* is_alive, bool unloading_occurred); 75 ~CodeCacheUnloadingTask(); 76 77 private: 78 void add_to_postponed_list(CompiledMethod* nm); 79 void clean_nmethod(CompiledMethod* nm); 80 void clean_nmethod_postponed(CompiledMethod* nm); 81 82 static const int MaxClaimNmethods = 16; 83 84 void claim_nmethods(CompiledMethod** claimed_nmethods, int *num_claimed_nmethods); 85 CompiledMethod* claim_postponed_nmethod(); 86 public: 87 // Mark that we're done with the first pass of nmethod cleaning. 88 void barrier_mark(uint worker_id); 89 90 // See if we have to wait for the other workers to 91 // finish their first-pass nmethod cleaning work. 92 void barrier_wait(uint worker_id); 93 94 // Cleaning and unloading of nmethods. Some work has to be postponed 95 // to the second pass, when we know which nmethods survive. 96 void work_first_pass(uint worker_id); 97 void work_second_pass(uint worker_id); 98 }; 99 100 101 class KlassCleaningTask : public StackObj { 102 volatile int _clean_klass_tree_claimed; 103 ClassLoaderDataGraphKlassIteratorAtomic _klass_iterator; 104 105 public: 106 KlassCleaningTask(); 107 108 private: 109 bool claim_clean_klass_tree_task(); 110 InstanceKlass* claim_next_klass(); 111 112 public: 113 114 void clean_klass(InstanceKlass* ik) { 115 ik->clean_weak_instanceklass_links(); 116 } 117 118 void work(); 119 }; 120 121 // To minimize the remark pause times, the tasks below are done in parallel. 122 class ParallelCleaningTask : public AbstractGangTask { 123 private: 124 bool _unloading_occurred; 125 StringCleaningTask _string_task; 126 CodeCacheUnloadingTask _code_cache_task; 127 KlassCleaningTask _klass_cleaning_task; 128 129 public: 130 // The constructor is run in the VMThread. 131 ParallelCleaningTask(BoolObjectClosure* is_alive, StringDedupUnlinkOrOopsDoClosure* dedup_closure, 132 uint num_workers, bool unloading_occurred); 133 134 void work(uint worker_id); 135 }; 136 137 #endif // SHARE_VM_GC_SHARED_PARALLELCLEANING_HPP