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