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 #include "precompiled.hpp" 26 #include "classfile/classLoaderData.hpp" 27 #include "classfile/moduleEntry.hpp" 28 #include "classfile/packageEntry.hpp" 29 #include "jfr/periodic/jfrModuleEvent.hpp" 30 #include "jfr/utilities/jfrTraceTime.hpp" 31 #include "runtime/mutexLocker.hpp" 32 #include "trace/tracing.hpp" 33 34 // we want all requestable module events to have the same timestamp 35 static JfrTraceTime requestableTime = 0; 36 typedef void (*EventFunc)(const void* iterated_address, const JfrTraceTime& time, const ModuleEntry* module); 37 class ModuleEventCallbackClosure : public ModuleClosure { 38 protected: 39 const JfrTraceTime& _time; 40 const EventFunc _event_func; 41 ModuleEventCallbackClosure(const JfrTraceTime& time, EventFunc ef) : _time(time), _event_func(ef) {} 42 }; 43 44 class ModuleDependencyClosure : public ModuleEventCallbackClosure { 45 private: 46 const ModuleEntry* const _module; 47 public: 48 ModuleDependencyClosure(const ModuleEntry* module, const JfrTraceTime& time, EventFunc ef) : 49 ModuleEventCallbackClosure(time, ef), _module(module) {} 50 void do_module(ModuleEntry* const entry); 51 }; 52 53 class ModuleExportClosure : public ModuleEventCallbackClosure { 54 private: 55 const PackageEntry* const _package; 56 public: 57 ModuleExportClosure(const PackageEntry* pkg, const JfrTraceTime& time, EventFunc ef) : 58 ModuleEventCallbackClosure(time, ef), _package(pkg) {} 59 void do_module(ModuleEntry* const entry); 60 }; 61 62 static void write_module_dependency_event(const void* from_module, const JfrTraceTime& time, const ModuleEntry* to_module) { 63 EventModuleRequire event(UNTIMED); 64 event.set_endtime(time); 65 event.set_source((const ModuleEntry* const)from_module); 66 event.set_requiredModule(to_module); 67 event.commit(); 68 } 69 70 static void write_module_export_event(const void* package, const JfrTraceTime& time, const ModuleEntry* qualified_export) { 71 EventModuleExport event(UNTIMED); 72 event.set_endtime(time); 73 event.set_exportedPackage((const PackageEntry*)package); 74 event.set_targetModule(qualified_export); 75 event.commit(); 76 } 77 78 void ModuleDependencyClosure::do_module(ModuleEntry* to_module) { 79 assert_locked_or_safepoint(Module_lock); 80 assert(to_module != NULL, "invariant"); 81 assert(_module != NULL, "invariant"); 82 assert(_event_func != NULL, "invariant"); 83 _event_func(_module, _time, to_module); 84 } 85 86 void ModuleExportClosure::do_module(ModuleEntry* qualified_export) { 87 assert_locked_or_safepoint(Module_lock); 88 assert(qualified_export != NULL, "invariant"); 89 assert(_package != NULL, "invariant"); 90 assert(_event_func != NULL, "invariant"); 91 _event_func(_package, _time, qualified_export); 92 } 93 94 static void module_dependency_event_callback(ModuleEntry* module) { 95 assert_locked_or_safepoint(Module_lock); 96 assert(module != NULL, "invariant"); 97 if (module->has_reads_list()) { 98 // create an individual event for each directed edge 99 ModuleDependencyClosure directed_edges(module, requestableTime, &write_module_dependency_event); 100 module->module_reads_do(&directed_edges); 101 } 102 } 103 104 static void module_export_event_callback(PackageEntry* package) { 105 assert_locked_or_safepoint(Module_lock); 106 assert(package != NULL, "invariant"); 107 if (package->is_exported()) { 108 if (package->has_qual_exports_list()) { 109 // package is qualifiedly exported to a set of modules, 110 // create an event for each module in the qualified exported list 111 ModuleExportClosure qexports(package, requestableTime, &write_module_export_event); 112 package->package_exports_do(&qexports); 113 return; 114 } 115 116 assert(!package->is_qual_exported() || package->is_exported_allUnnamed(), "invariant"); 117 // no qualified exports 118 // only create a single event with NULL 119 // for the qualified_exports module 120 write_module_export_event(package, requestableTime, NULL); 121 } 122 } 123 124 void JfrModuleEvent::generate_module_dependency_events() { 125 assert(0 == requestableTime, "invariant"); 126 requestableTime = JfrTraceTime::now(); 127 { 128 MutexLockerEx module_lock(Module_lock); 129 ClassLoaderDataGraph::modules_do(&module_dependency_event_callback); 130 } 131 requestableTime = 0; 132 } 133 134 void JfrModuleEvent::generate_module_export_events() { 135 assert(0 == requestableTime, "invariant"); 136 requestableTime = JfrTraceTime::now(); 137 { 138 MutexLockerEx module_lock(Module_lock); 139 ClassLoaderDataGraph::packages_do(&module_export_event_callback); 140 } 141 requestableTime = 0; 142 }