1 /*
2 * Copyright (c) 2017, 2019, 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 *
172 assert(_cstring_table != NULL, "invariant");
173 _cstring_query = str;
174 const CStringEntry& entry = _cstring_table->lookup_put(hash, str);
175 if (_class_unload) {
176 entry.set_unloading();
177 }
178 if (leakp) {
179 entry.set_leakp();
180 }
181 return entry.id();
182 }
183
184 /*
185 * jsr292 anonymous classes symbol is the external name +
186 * the identity_hashcode slash appended:
187 * java.lang.invoke.LambdaForm$BMH/22626602
188 *
189 * caller needs ResourceMark
190 */
191
192 uintptr_t JfrSymbolId::unsafe_anonymous_klass_name_hash(const InstanceKlass* ik) {
193 assert(ik != NULL, "invariant");
194 assert(ik->is_unsafe_anonymous(), "invariant");
195 const oop mirror = ik->java_mirror_no_keepalive();
196 assert(mirror != NULL, "invariant");
197 return (uintptr_t)mirror->identity_hash();
198 }
199
200 static const char* create_unsafe_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t hash) {
201 assert(ik != NULL, "invariant");
202 assert(ik->is_unsafe_anonymous(), "invariant");
203 assert(hash != 0, "invariant");
204 char* anonymous_symbol = NULL;
205 const oop mirror = ik->java_mirror_no_keepalive();
206 assert(mirror != NULL, "invariant");
207 char hash_buf[40];
208 sprintf(hash_buf, "/" UINTX_FORMAT, hash);
209 const size_t hash_len = strlen(hash_buf);
210 const size_t result_len = ik->name()->utf8_length();
211 anonymous_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
212 ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1);
213 assert(strlen(anonymous_symbol) == result_len, "invariant");
214 strcpy(anonymous_symbol + result_len, hash_buf);
215 assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant");
216 return anonymous_symbol;
217 }
218
219 bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) {
220 assert(k != NULL, "invariant");
221 return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous();
222 }
223
224 traceid JfrSymbolId::mark_unsafe_anonymous_klass_name(const InstanceKlass* ik, bool leakp) {
225 assert(ik != NULL, "invariant");
226 assert(ik->is_unsafe_anonymous(), "invariant");
227 const uintptr_t hash = unsafe_anonymous_klass_name_hash(ik);
228 const char* const anonymous_klass_symbol = create_unsafe_anonymous_klass_symbol(ik, hash);
229 return mark(hash, anonymous_klass_symbol, leakp);
230 }
231
232 traceid JfrSymbolId::mark(const Klass* k, bool leakp) {
233 assert(k != NULL, "invariant");
234 traceid symbol_id = 0;
235 if (is_unsafe_anonymous_klass(k)) {
236 assert(k->is_instance_klass(), "invariant");
237 symbol_id = mark_unsafe_anonymous_klass_name((const InstanceKlass*)k, leakp);
238 }
239 if (0 == symbol_id) {
240 Symbol* const sym = k->name();
241 if (sym != NULL) {
242 symbol_id = mark(sym, leakp);
243 }
244 }
245 assert(symbol_id > 0, "a symbol handler must mark the symbol for writing");
246 return symbol_id;
247 }
248
249 JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()),
250 _klass_list(NULL),
251 _total_count(0) {
252 initialize(class_unload);
253 assert(_klass_list != NULL, "invariant");
254 }
255
256 static const size_t initial_class_list_size = 200;
257
259 assert(_symbol_id != NULL, "invariant");
260 if (clear) {
261 _symbol_id->clear();
262 }
263 _symbol_id->set_class_unload(class_unload);
264 _total_count = 0;
265 // resource allocation
266 _klass_list = new GrowableArray<const Klass*>(initial_class_list_size, false, mtTracing);
267 }
268
269 JfrArtifactSet::~JfrArtifactSet() {
270 _symbol_id->clear();
271 delete _symbol_id;
272 // _klass_list will be cleared by a ResourceMark
273 }
274
275 traceid JfrArtifactSet::bootstrap_name(bool leakp) {
276 return _symbol_id->bootstrap_name(leakp);
277 }
278
279 traceid JfrArtifactSet::mark_unsafe_anonymous_klass_name(const Klass* klass, bool leakp) {
280 assert(klass->is_instance_klass(), "invariant");
281 return _symbol_id->mark_unsafe_anonymous_klass_name((const InstanceKlass*)klass, leakp);
282 }
283
284 traceid JfrArtifactSet::mark(uintptr_t hash, const Symbol* sym, bool leakp) {
285 return _symbol_id->mark(hash, sym, leakp);
286 }
287
288 traceid JfrArtifactSet::mark(const Klass* klass, bool leakp) {
289 return _symbol_id->mark(klass, leakp);
290 }
291
292 traceid JfrArtifactSet::mark(const Symbol* symbol, bool leakp) {
293 return _symbol_id->mark(symbol, leakp);
294 }
295
296 traceid JfrArtifactSet::mark(uintptr_t hash, const char* const str, bool leakp) {
297 return _symbol_id->mark(hash, str, leakp);
298 }
299
300 bool JfrArtifactSet::has_klass_entries() const {
301 return _klass_list->is_nonempty();
|
1 /*
2 * Copyright (c) 2017, 2020, 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 *
172 assert(_cstring_table != NULL, "invariant");
173 _cstring_query = str;
174 const CStringEntry& entry = _cstring_table->lookup_put(hash, str);
175 if (_class_unload) {
176 entry.set_unloading();
177 }
178 if (leakp) {
179 entry.set_leakp();
180 }
181 return entry.id();
182 }
183
184 /*
185 * jsr292 anonymous classes symbol is the external name +
186 * the identity_hashcode slash appended:
187 * java.lang.invoke.LambdaForm$BMH/22626602
188 *
189 * caller needs ResourceMark
190 */
191
192 uintptr_t JfrSymbolId::hidden_or_anon_klass_name_hash(const InstanceKlass* ik) {
193 assert(ik != NULL, "invariant");
194 assert(ik->is_unsafe_anonymous() || ik->is_hidden(), "invariant");
195 const oop mirror = ik->java_mirror_no_keepalive();
196 assert(mirror != NULL, "invariant");
197 return (uintptr_t)mirror->identity_hash();
198 }
199
200 static const char* create_hidden_or_anon_klass_symbol(const InstanceKlass* ik, uintptr_t hash) {
201 assert(ik != NULL, "invariant");
202 assert(ik->is_unsafe_anonymous() || ik->is_hidden(), "invariant");
203 assert(hash != 0, "invariant");
204 char* hidden_or_anon_symbol = NULL;
205 const oop mirror = ik->java_mirror_no_keepalive();
206 assert(mirror != NULL, "invariant");
207 char hash_buf[40];
208 sprintf(hash_buf, "/" UINTX_FORMAT, hash);
209 const size_t hash_len = strlen(hash_buf);
210 const size_t result_len = ik->name()->utf8_length();
211 hidden_or_anon_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
212 ik->name()->as_klass_external_name(hidden_or_anon_symbol, (int)result_len + 1);
213 assert(strlen(hidden_or_anon_symbol) == result_len, "invariant");
214 strcpy(hidden_or_anon_symbol + result_len, hash_buf);
215 assert(strlen(hidden_or_anon_symbol) == result_len + hash_len, "invariant");
216 return hidden_or_anon_symbol;
217 }
218
219 bool JfrSymbolId::is_hidden_or_anon_klass(const Klass* k) {
220 assert(k != NULL, "invariant");
221 return k->is_instance_klass() &&
222 (((const InstanceKlass*)k)->is_unsafe_anonymous() ||
223 ((const InstanceKlass*)k)->is_hidden());
224 }
225
226 traceid JfrSymbolId::mark_hidden_or_anon_klass_name(const InstanceKlass* ik, bool leakp) {
227 assert(ik != NULL, "invariant");
228 assert(ik->is_unsafe_anonymous() || ik->is_hidden(), "invariant");
229 const uintptr_t hash = hidden_or_anon_klass_name_hash(ik);
230 const char* const hidden_or_anon_symbol = create_hidden_or_anon_klass_symbol(ik, hash);
231 return mark(hash, hidden_or_anon_symbol, leakp);
232 }
233
234 traceid JfrSymbolId::mark(const Klass* k, bool leakp) {
235 assert(k != NULL, "invariant");
236 traceid symbol_id = 0;
237 if (is_hidden_or_anon_klass(k)) {
238 assert(k->is_instance_klass(), "invariant");
239 symbol_id = mark_hidden_or_anon_klass_name((const InstanceKlass*)k, leakp);
240 }
241 if (0 == symbol_id) {
242 Symbol* const sym = k->name();
243 if (sym != NULL) {
244 symbol_id = mark(sym, leakp);
245 }
246 }
247 assert(symbol_id > 0, "a symbol handler must mark the symbol for writing");
248 return symbol_id;
249 }
250
251 JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()),
252 _klass_list(NULL),
253 _total_count(0) {
254 initialize(class_unload);
255 assert(_klass_list != NULL, "invariant");
256 }
257
258 static const size_t initial_class_list_size = 200;
259
261 assert(_symbol_id != NULL, "invariant");
262 if (clear) {
263 _symbol_id->clear();
264 }
265 _symbol_id->set_class_unload(class_unload);
266 _total_count = 0;
267 // resource allocation
268 _klass_list = new GrowableArray<const Klass*>(initial_class_list_size, false, mtTracing);
269 }
270
271 JfrArtifactSet::~JfrArtifactSet() {
272 _symbol_id->clear();
273 delete _symbol_id;
274 // _klass_list will be cleared by a ResourceMark
275 }
276
277 traceid JfrArtifactSet::bootstrap_name(bool leakp) {
278 return _symbol_id->bootstrap_name(leakp);
279 }
280
281 traceid JfrArtifactSet::mark_hidden_or_anon_klass_name(const Klass* klass, bool leakp) {
282 assert(klass->is_instance_klass(), "invariant");
283 return _symbol_id->mark_hidden_or_anon_klass_name((const InstanceKlass*)klass, leakp);
284 }
285
286 traceid JfrArtifactSet::mark(uintptr_t hash, const Symbol* sym, bool leakp) {
287 return _symbol_id->mark(hash, sym, leakp);
288 }
289
290 traceid JfrArtifactSet::mark(const Klass* klass, bool leakp) {
291 return _symbol_id->mark(klass, leakp);
292 }
293
294 traceid JfrArtifactSet::mark(const Symbol* symbol, bool leakp) {
295 return _symbol_id->mark(symbol, leakp);
296 }
297
298 traceid JfrArtifactSet::mark(uintptr_t hash, const char* const str, bool leakp) {
299 return _symbol_id->mark(hash, str, leakp);
300 }
301
302 bool JfrArtifactSet::has_klass_entries() const {
303 return _klass_list->is_nonempty();
|