-
Notifications
You must be signed in to change notification settings - Fork 5.4k
/
jfrTraceId.cpp
243 lines (215 loc) · 8.08 KB
/
jfrTraceId.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
/*
* Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
#include "precompiled.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/symbolTable.hpp"
#include "jfr/recorder/checkpoint/types/traceid/jfrTraceId.inline.hpp"
#include "jfr/utilities/jfrTypes.hpp"
#include "oops/arrayKlass.inline.hpp"
#include "oops/klass.inline.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/method.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/atomic.hpp"
#include "runtime/vm_version.hpp"
#include "runtime/jniHandles.inline.hpp"
#include "runtime/thread.inline.hpp"
#include "utilities/debug.hpp"
// returns updated value
static traceid atomic_inc(traceid volatile* const dest) {
assert(VM_Version::supports_cx8(), "invariant");
traceid compare_value;
traceid exchange_value;
do {
compare_value = *dest;
exchange_value = compare_value + 1;
} while (Atomic::cmpxchg(dest, compare_value, exchange_value) != compare_value);
return exchange_value;
}
static traceid next_class_id() {
static volatile traceid class_id_counter = LAST_TYPE_ID;
return atomic_inc(&class_id_counter) << TRACE_ID_SHIFT;
}
static traceid next_thread_id() {
static volatile traceid thread_id_counter = 0;
return atomic_inc(&thread_id_counter);
}
static traceid next_module_id() {
static volatile traceid module_id_counter = 0;
return atomic_inc(&module_id_counter) << TRACE_ID_SHIFT;
}
static traceid next_package_id() {
static volatile traceid package_id_counter = 0;
return atomic_inc(&package_id_counter) << TRACE_ID_SHIFT;
}
static traceid next_class_loader_data_id() {
static volatile traceid cld_id_counter = 0;
return atomic_inc(&cld_id_counter) << TRACE_ID_SHIFT;
}
static bool found_jdk_internal_event_klass = false;
static bool found_jdk_jfr_event_klass = false;
static void check_klass(const Klass* klass) {
assert(klass != NULL, "invariant");
if (found_jdk_internal_event_klass && found_jdk_jfr_event_klass) {
return;
}
static const Symbol* jdk_internal_event_sym = NULL;
if (jdk_internal_event_sym == NULL) {
// setup when loading the first TypeArrayKlass (Universe::genesis) hence single threaded invariant
jdk_internal_event_sym = SymbolTable::new_permanent_symbol("jdk/internal/event/Event");
}
assert(jdk_internal_event_sym != NULL, "invariant");
static const Symbol* jdk_jfr_event_sym = NULL;
if (jdk_jfr_event_sym == NULL) {
// setup when loading the first TypeArrayKlass (Universe::genesis) hence single threaded invariant
jdk_jfr_event_sym = SymbolTable::new_permanent_symbol("jdk/jfr/Event");
}
assert(jdk_jfr_event_sym != NULL, "invariant");
const Symbol* const klass_name = klass->name();
if (!found_jdk_internal_event_klass) {
if (jdk_internal_event_sym == klass_name && klass->class_loader() == NULL) {
found_jdk_internal_event_klass = true;
JfrTraceId::tag_as_jdk_jfr_event(klass);
return;
}
}
if (!found_jdk_jfr_event_klass) {
if (jdk_jfr_event_sym == klass_name && klass->class_loader() == NULL) {
found_jdk_jfr_event_klass = true;
JfrTraceId::tag_as_jdk_jfr_event(klass);
return;
}
}
}
void JfrTraceId::assign(const Klass* klass) {
assert(klass != NULL, "invariant");
klass->set_trace_id(next_class_id());
check_klass(klass);
const Klass* const super = klass->super();
if (super == NULL) {
return;
}
if (IS_EVENT_KLASS(super)) {
tag_as_jdk_jfr_event_sub(klass);
}
}
void JfrTraceId::assign(const ModuleEntry* module) {
assert(module != NULL, "invariant");
module->set_trace_id(next_module_id());
}
void JfrTraceId::assign(const PackageEntry* package) {
assert(package != NULL, "invariant");
package->set_trace_id(next_package_id());
}
void JfrTraceId::assign(const ClassLoaderData* cld) {
assert(cld != NULL, "invariant");
if (cld->has_class_mirror_holder()) {
cld->set_trace_id(0);
return;
}
cld->set_trace_id(next_class_loader_data_id());
}
traceid JfrTraceId::assign_thread_id() {
return next_thread_id();
}
traceid JfrTraceId::load_raw(jclass jc) {
assert(jc != NULL, "invariant");
assert(JavaThread::current()->thread_state() == _thread_in_vm, "invariant");
const oop my_oop = JNIHandles::resolve(jc);
assert(my_oop != NULL, "invariant");
return load_raw(java_lang_Class::as_Klass(my_oop));
}
// used by CDS / APPCDS as part of "remove_unshareable_info"
void JfrTraceId::remove(const Klass* k) {
assert(k != NULL, "invariant");
// Mask off and store the event flags.
// This mechanism will retain the event specific flags
// in the archive, allowing for event flag restoration
// when renewing the traceid on klass revival.
k->set_trace_id(EVENT_KLASS_MASK(k));
}
// used by CDS / APPCDS as part of "remove_unshareable_info"
void JfrTraceId::remove(const Method* method) {
assert(method != NULL, "invariant");
// Clear all bits.
method->set_trace_flags(0);
}
// used by CDS / APPCDS as part of "restore_unshareable_info"
void JfrTraceId::restore(const Klass* k) {
assert(k != NULL, "invariant");
if (IS_JDK_JFR_EVENT_KLASS(k)) {
found_jdk_jfr_event_klass = true;
}
const traceid event_flags = k->trace_id();
// get a fresh traceid and restore the original event flags
k->set_trace_id(next_class_id() | event_flags);
}
bool JfrTraceId::in_visible_set(const jclass jc) {
assert(jc != NULL, "invariant");
assert(JavaThread::current()->thread_state() == _thread_in_vm, "invariant");
const oop mirror = JNIHandles::resolve(jc);
assert(mirror != NULL, "invariant");
return in_visible_set(java_lang_Class::as_Klass(mirror));
}
bool JfrTraceId::in_jdk_jfr_event_hierarchy(const jclass jc) {
assert(jc != NULL, "invariant");
const oop mirror = JNIHandles::resolve(jc);
assert(mirror != NULL, "invariant");
return in_jdk_jfr_event_hierarchy(java_lang_Class::as_Klass(mirror));
}
bool JfrTraceId::is_jdk_jfr_event_sub(const jclass jc) {
assert(jc != NULL, "invariant");
const oop mirror = JNIHandles::resolve(jc);
assert(mirror != NULL, "invariant");
return is_jdk_jfr_event_sub(java_lang_Class::as_Klass(mirror));
}
bool JfrTraceId::is_jdk_jfr_event(const jclass jc) {
assert(jc != NULL, "invariant");
const oop mirror = JNIHandles::resolve(jc);
assert(mirror != NULL, "invariant");
return is_jdk_jfr_event(java_lang_Class::as_Klass(mirror));
}
bool JfrTraceId::is_event_host(const jclass jc) {
assert(jc != NULL, "invariant");
const oop mirror = JNIHandles::resolve(jc);
assert(mirror != NULL, "invariant");
return is_event_host(java_lang_Class::as_Klass(mirror));
}
void JfrTraceId::tag_as_jdk_jfr_event_sub(const jclass jc) {
assert(jc != NULL, "invariant");
const oop mirror = JNIHandles::resolve(jc);
assert(mirror != NULL, "invariant");
const Klass* const k = java_lang_Class::as_Klass(mirror);
tag_as_jdk_jfr_event_sub(k);
assert(IS_JDK_JFR_EVENT_SUBKLASS(k), "invariant");
}
void JfrTraceId::tag_as_event_host(const jclass jc) {
assert(jc != NULL, "invariant");
const oop mirror = JNIHandles::resolve(jc);
assert(mirror != NULL, "invariant");
const Klass* const k = java_lang_Class::as_Klass(mirror);
tag_as_event_host(k);
assert(IS_EVENT_HOST_KLASS(k), "invariant");
}