1 /* 2 * Copyright (c) 2015, 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/stringTable.hpp" 27 #include "classfile/systemDictionary.hpp" 28 #include "code/codeCache.hpp" 29 #include "gc/shenandoah/shenandoahRootProcessor.hpp" 30 #include "memory/allocation.inline.hpp" 31 #include "runtime/fprofiler.hpp" 32 #include "runtime/mutex.hpp" 33 #include "services/management.hpp" 34 35 ShenandoahRootProcessor::ShenandoahRootProcessor(ShenandoahHeap* heap, uint n_workers) : 36 _process_strong_tasks(new SubTasksDone(SHENANDOAH_RP_PS_NumElements)), 37 _srs(n_workers) 38 { 39 } 40 41 void ShenandoahRootProcessor::process_roots(OopClosure* strong_oops, 42 OopClosure* weak_oops, 43 CLDClosure* strong_clds, 44 CLDClosure* weak_clds, 45 CLDClosure* thread_stack_clds, 46 CodeBlobClosure* strong_code) { 47 process_java_roots(strong_oops, thread_stack_clds, strong_clds, weak_clds, strong_code, 0); 48 process_vm_roots(strong_oops, weak_oops, 0); 49 50 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_CodeCache_oops_do)) { 51 CodeCache::blobs_do(strong_code); 52 } 53 54 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_JNIHandles_weak_oops_do)) { 55 ShenandoahAlwaysTrueClosure always_true; 56 JNIHandles::weak_oops_do(&always_true, weak_oops); 57 } 58 59 _process_strong_tasks->all_tasks_completed(n_workers()); 60 } 61 62 void ShenandoahRootProcessor::process_strong_roots(OopClosure* oops, 63 CLDClosure* clds, 64 CodeBlobClosure* blobs) { 65 66 process_java_roots(oops, clds, clds, NULL, blobs, 0); 67 process_vm_roots(oops, NULL, 0); 68 69 _process_strong_tasks->all_tasks_completed(n_workers()); 70 } 71 72 void ShenandoahRootProcessor::process_all_roots(OopClosure* oops, 73 CLDClosure* clds, 74 CodeBlobClosure* blobs) { 75 76 process_java_roots(oops, NULL, clds, clds, NULL, 0); 77 process_vm_roots(oops, oops, 0); 78 79 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_CodeCache_oops_do)) { 80 CodeCache::blobs_do(blobs); 81 } 82 83 _process_strong_tasks->all_tasks_completed(n_workers()); 84 } 85 86 void ShenandoahRootProcessor::process_java_roots(OopClosure* strong_roots, 87 CLDClosure* thread_stack_clds, 88 CLDClosure* strong_clds, 89 CLDClosure* weak_clds, 90 CodeBlobClosure* strong_code, 91 uint worker_i) 92 { 93 //assert(thread_stack_clds == NULL || weak_clds == NULL, "There is overlap between those, only one may be set"); 94 // Iterating over the CLDG and the Threads are done early to allow us to 95 // first process the strong CLDs and nmethods and then, after a barrier, 96 // let the thread process the weak CLDs and nmethods. 97 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_ClassLoaderDataGraph_oops_do)) { 98 ClassLoaderDataGraph::roots_cld_do(strong_clds, weak_clds); 99 } 100 101 bool is_par = n_workers() > 1; 102 ResourceMark rm; 103 Threads::possibly_parallel_oops_do(is_par, strong_roots, thread_stack_clds, strong_code); 104 } 105 106 void ShenandoahRootProcessor::process_vm_roots(OopClosure* strong_roots, 107 OopClosure* weak_roots, 108 uint worker_i) 109 { 110 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Universe_oops_do)) { 111 Universe::oops_do(strong_roots); 112 } 113 114 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_JNIHandles_oops_do)) { 115 JNIHandles::oops_do(strong_roots); 116 } 117 if (!_process_strong_tasks-> is_task_claimed(SHENANDOAH_RP_PS_ObjectSynchronizer_oops_do)) { 118 ObjectSynchronizer::oops_do(strong_roots); 119 } 120 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_FlatProfiler_oops_do)) { 121 FlatProfiler::oops_do(strong_roots); 122 } 123 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_Management_oops_do)) { 124 Management::oops_do(strong_roots); 125 } 126 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_jvmti_oops_do)) { 127 JvmtiExport::oops_do(strong_roots); 128 } 129 if (!_process_strong_tasks->is_task_claimed(SHENANDOAH_RP_PS_SystemDictionary_oops_do)) { 130 SystemDictionary::roots_oops_do(strong_roots, weak_roots); 131 } 132 // All threads execute the following. A specific chunk of buckets 133 // from the StringTable are the individual tasks. 134 if (weak_roots != NULL) { 135 StringTable::possibly_parallel_oops_do(weak_roots); 136 } 137 } 138 139 uint ShenandoahRootProcessor::n_workers() const { 140 return _srs.n_threads(); 141 }