Mon, 12 Aug 2019 18:30:40 +0300
8223147: JFR Backport
8199712: Flight Recorder
8203346: JFR: Inconsistent signature of jfr_add_string_constant
8195817: JFR.stop should require name of recording
8195818: JFR.start should increase autogenerated name by one
8195819: Remove recording=x from jcmd JFR.check output
8203921: JFR thread sampling is missing fixes from JDK-8194552
8203929: Limit amount of data for JFR.dump
8203664: JFR start failure after AppCDS archive created with JFR StartFlightRecording
8003209: JFR events for network utilization
8207392: [PPC64] Implement JFR profiling
8202835: jfr/event/os/TestSystemProcess.java fails on missing events
Summary: Backport JFR from JDK11. Initial integration
Reviewed-by: neugens
1 /*
2 * Copyright (c) 2017, 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 */
25 #include "precompiled.hpp"
26 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp"
27 #include "oops/instanceKlass.hpp"
28 #include "oops/oop.inline.hpp"
29 #include "oops/symbol.hpp"
31 JfrSymbolId::JfrSymbolId() : _symbol_id_counter(0), _sym_table(new SymbolTable(this)), _cstring_table(new CStringTable(this)) {
32 assert(_sym_table != NULL, "invariant");
33 assert(_cstring_table != NULL, "invariant");
34 initialize();
35 }
37 void JfrSymbolId::initialize() {
38 clear();
39 assert(_symbol_id_counter == 0, "invariant");
40 }
42 void JfrSymbolId::clear() {
43 assert(_sym_table != NULL, "invariant");
44 if (_sym_table->has_entries()) {
45 _sym_table->clear_entries();
46 }
47 assert(!_sym_table->has_entries(), "invariant");
49 assert(_cstring_table != NULL, "invariant");
50 if (_cstring_table->has_entries()) {
51 _cstring_table->clear_entries();
52 }
53 assert(!_cstring_table->has_entries(), "invariant");
54 _symbol_id_counter = 0;
55 }
57 JfrSymbolId::~JfrSymbolId() {
58 delete _sym_table;
59 delete _cstring_table;
60 }
62 traceid JfrSymbolId::mark_anonymous_klass_name(const Klass* k) {
63 assert(k != NULL, "invariant");
64 assert(k->oop_is_instance(), "invariant");
65 assert(is_anonymous_klass(k), "invariant");
67 uintptr_t anonymous_symbol_hash_code = 0;
68 const char* const anonymous_symbol =
69 create_anonymous_klass_symbol((const InstanceKlass*)k, anonymous_symbol_hash_code);
71 if (anonymous_symbol == NULL) {
72 return 0;
73 }
75 assert(anonymous_symbol_hash_code != 0, "invariant");
76 traceid symbol_id = mark(anonymous_symbol, anonymous_symbol_hash_code);
77 assert(mark(anonymous_symbol, anonymous_symbol_hash_code) == symbol_id, "invariant");
78 return symbol_id;
79 }
81 const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(const Symbol* symbol) const {
82 return _sym_table->lookup_only(symbol, (uintptr_t)const_cast<Symbol*>(symbol)->identity_hash());
83 }
85 const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(uintptr_t hash) const {
86 return _sym_table->lookup_only(NULL, hash);
87 }
89 const JfrSymbolId::CStringEntry* JfrSymbolId::map_cstring(uintptr_t hash) const {
90 return _cstring_table->lookup_only(NULL, hash);
91 }
93 void JfrSymbolId::assign_id(SymbolEntry* entry) {
94 assert(entry != NULL, "invariant");
95 assert(entry->id() == 0, "invariant");
96 entry->set_id(++_symbol_id_counter);
97 }
99 bool JfrSymbolId::equals(const Symbol* query, uintptr_t hash, const SymbolEntry* entry) {
100 // query might be NULL
101 assert(entry != NULL, "invariant");
102 assert(entry->hash() == hash, "invariant");
103 return true;
104 }
106 void JfrSymbolId::assign_id(CStringEntry* entry) {
107 assert(entry != NULL, "invariant");
108 assert(entry->id() == 0, "invariant");
109 entry->set_id(++_symbol_id_counter);
110 }
112 bool JfrSymbolId::equals(const char* query, uintptr_t hash, const CStringEntry* entry) {
113 // query might be NULL
114 assert(entry != NULL, "invariant");
115 assert(entry->hash() == hash, "invariant");
116 return true;
117 }
119 traceid JfrSymbolId::mark(const Klass* k) {
120 assert(k != NULL, "invariant");
121 traceid symbol_id = 0;
122 if (is_anonymous_klass(k)) {
123 symbol_id = mark_anonymous_klass_name(k);
124 }
125 if (0 == symbol_id) {
126 const Symbol* const sym = k->name();
127 if (sym != NULL) {
128 symbol_id = mark(sym);
129 }
130 }
131 assert(symbol_id > 0, "a symbol handler must mark the symbol for writing");
132 return symbol_id;
133 }
135 traceid JfrSymbolId::mark(const Symbol* symbol) {
136 assert(symbol != NULL, "invariant");
137 return mark(symbol, (uintptr_t)const_cast<Symbol*>(symbol)->identity_hash());
138 }
140 traceid JfrSymbolId::mark(const Symbol* data, uintptr_t hash) {
141 assert(data != NULL, "invariant");
142 assert(_sym_table != NULL, "invariant");
143 return _sym_table->id(data, hash);
144 }
146 traceid JfrSymbolId::mark(const char* str, uintptr_t hash) {
147 assert(str != NULL, "invariant");
148 return _cstring_table->id(str, hash);
149 }
151 bool JfrSymbolId::is_anonymous_klass(const Klass* k) {
152 assert(k != NULL, "invariant");
153 return k->oop_is_instance() && ((const InstanceKlass*)k)->is_anonymous();
154 }
156 /*
157 * jsr292 anonymous classes symbol is the external name +
158 * the identity_hashcode slash appended:
159 * java.lang.invoke.LambdaForm$BMH/22626602
160 *
161 * caller needs ResourceMark
162 */
164 uintptr_t JfrSymbolId::anonymous_klass_name_hash_code(const InstanceKlass* ik) {
165 assert(ik != NULL, "invariant");
166 assert(ik->is_anonymous(), "invariant");
167 const oop mirror = ik->java_mirror();
168 assert(mirror != NULL, "invariant");
169 return (uintptr_t)mirror->identity_hash();
170 }
172 const char* JfrSymbolId::create_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode) {
173 assert(ik != NULL, "invariant");
174 assert(ik->is_anonymous(), "invariant");
175 assert(0 == hashcode, "invariant");
176 char* anonymous_symbol = NULL;
177 const oop mirror = ik->java_mirror();
178 assert(mirror != NULL, "invariant");
179 char hash_buf[40];
180 hashcode = anonymous_klass_name_hash_code(ik);
181 sprintf(hash_buf, "/" UINTX_FORMAT, hashcode);
182 const size_t hash_len = strlen(hash_buf);
183 const size_t result_len = ik->name()->utf8_length();
184 anonymous_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
185 ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1);
186 assert(strlen(anonymous_symbol) == result_len, "invariant");
187 strcpy(anonymous_symbol + result_len, hash_buf);
188 assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant");
189 return anonymous_symbol;
190 }
192 uintptr_t JfrSymbolId::regular_klass_name_hash_code(const Klass* k) {
193 assert(k != NULL, "invariant");
194 const Symbol* const sym = k->name();
195 assert(sym != NULL, "invariant");
196 return (uintptr_t)const_cast<Symbol*>(sym)->identity_hash();
197 }
199 JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()),
200 _klass_list(NULL),
201 _class_unload(class_unload) {
202 initialize(class_unload);
203 assert(_klass_list != NULL, "invariant");
204 }
206 static const size_t initial_class_list_size = 200;
207 void JfrArtifactSet::initialize(bool class_unload) {
208 assert(_symbol_id != NULL, "invariant");
209 _symbol_id->initialize();
210 assert(!_symbol_id->has_entries(), "invariant");
211 _symbol_id->mark(BOOTSTRAP_LOADER_NAME, 0); // pre-load "bootstrap"
212 _class_unload = class_unload;
213 // resource allocation
214 _klass_list = new GrowableArray<const Klass*>(initial_class_list_size, false, mtTracing);
215 }
217 JfrArtifactSet::~JfrArtifactSet() {
218 clear();
219 }
221 void JfrArtifactSet::clear() {
222 _symbol_id->clear();
223 // _klass_list will be cleared by a ResourceMark
224 }
226 traceid JfrArtifactSet::mark_anonymous_klass_name(const Klass* klass) {
227 return _symbol_id->mark_anonymous_klass_name(klass);
228 }
230 traceid JfrArtifactSet::mark(const Symbol* sym, uintptr_t hash) {
231 return _symbol_id->mark(sym, hash);
232 }
234 traceid JfrArtifactSet::mark(const Klass* klass) {
235 return _symbol_id->mark(klass);
236 }
238 traceid JfrArtifactSet::mark(const Symbol* symbol) {
239 return _symbol_id->mark(symbol);
240 }
242 traceid JfrArtifactSet::mark(const char* const str, uintptr_t hash) {
243 return _symbol_id->mark(str, hash);
244 }
246 const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(const Symbol* symbol) const {
247 return _symbol_id->map_symbol(symbol);
248 }
250 const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(uintptr_t hash) const {
251 return _symbol_id->map_symbol(hash);
252 }
254 const JfrSymbolId::CStringEntry* JfrArtifactSet::map_cstring(uintptr_t hash) const {
255 return _symbol_id->map_cstring(hash);
256 }
258 bool JfrArtifactSet::has_klass_entries() const {
259 return _klass_list->is_nonempty();
260 }
262 int JfrArtifactSet::entries() const {
263 return _klass_list->length();
264 }
266 void JfrArtifactSet::register_klass(const Klass* k) {
267 assert(k != NULL, "invariant");
268 assert(_klass_list != NULL, "invariant");
269 assert(_klass_list->find(k) == -1, "invariant");
270 _klass_list->append(k);
271 }