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