26 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp" |
26 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp" |
27 #include "oops/instanceKlass.hpp" |
27 #include "oops/instanceKlass.hpp" |
28 #include "oops/oop.inline.hpp" |
28 #include "oops/oop.inline.hpp" |
29 #include "oops/symbol.hpp" |
29 #include "oops/symbol.hpp" |
30 |
30 |
31 JfrSymbolId::JfrSymbolId() : _sym_table(new SymbolTable(this)), _cstring_table(new CStringTable(this)), _symbol_id_counter(0) { |
31 JfrSymbolId::JfrSymbolId() : |
|
32 _sym_table(new SymbolTable(this)), |
|
33 _cstring_table(new CStringTable(this)), |
|
34 _sym_list(NULL), |
|
35 _cstring_list(NULL), |
|
36 _symbol_id_counter(0), |
|
37 _class_unload(false) { |
32 assert(_sym_table != NULL, "invariant"); |
38 assert(_sym_table != NULL, "invariant"); |
33 assert(_cstring_table != NULL, "invariant"); |
39 assert(_cstring_table != NULL, "invariant"); |
34 initialize(); |
40 } |
35 } |
41 |
36 |
42 JfrSymbolId::~JfrSymbolId() { |
37 void JfrSymbolId::initialize() { |
|
38 clear(); |
43 clear(); |
39 assert(_symbol_id_counter == 0, "invariant"); |
44 delete _sym_table; |
|
45 delete _cstring_table; |
40 } |
46 } |
41 |
47 |
42 void JfrSymbolId::clear() { |
48 void JfrSymbolId::clear() { |
43 assert(_sym_table != NULL, "invariant"); |
49 assert(_sym_table != NULL, "invariant"); |
44 if (_sym_table->has_entries()) { |
50 if (_sym_table->has_entries()) { |
77 assert(mark(anonymous_symbol, anonymous_symbol_hash_code) == symbol_id, "invariant"); |
85 assert(mark(anonymous_symbol, anonymous_symbol_hash_code) == symbol_id, "invariant"); |
78 return symbol_id; |
86 return symbol_id; |
79 } |
87 } |
80 |
88 |
81 const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(const Symbol* symbol) const { |
89 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()); |
90 return _sym_table->lookup_only(symbol, (uintptr_t)symbol->identity_hash()); |
83 } |
91 } |
84 |
92 |
85 const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(uintptr_t hash) const { |
93 const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(uintptr_t hash) const { |
86 return _sym_table->lookup_only(NULL, hash); |
94 return _sym_table->lookup_only(NULL, hash); |
87 } |
95 } |
88 |
96 |
89 const JfrSymbolId::CStringEntry* JfrSymbolId::map_cstring(uintptr_t hash) const { |
97 const JfrSymbolId::CStringEntry* JfrSymbolId::map_cstring(uintptr_t hash) const { |
90 return _cstring_table->lookup_only(NULL, hash); |
98 return _cstring_table->lookup_only(NULL, hash); |
91 } |
99 } |
92 |
100 |
93 void JfrSymbolId::assign_id(SymbolEntry* entry) { |
101 void JfrSymbolId::assign_id(const SymbolEntry* entry) { |
94 assert(entry != NULL, "invariant"); |
102 assert(entry != NULL, "invariant"); |
|
103 const_cast<Symbol*>(entry->literal())->increment_refcount(); |
95 assert(entry->id() == 0, "invariant"); |
104 assert(entry->id() == 0, "invariant"); |
96 entry->set_id(++_symbol_id_counter); |
105 entry->set_id(++_symbol_id_counter); |
|
106 entry->set_list_next(_sym_list); |
|
107 _sym_list = entry; |
97 } |
108 } |
98 |
109 |
99 bool JfrSymbolId::equals(const Symbol* query, uintptr_t hash, const SymbolEntry* entry) { |
110 bool JfrSymbolId::equals(const Symbol* query, uintptr_t hash, const SymbolEntry* entry) { |
100 // query might be NULL |
111 // query might be NULL |
101 assert(entry != NULL, "invariant"); |
112 assert(entry != NULL, "invariant"); |
102 assert(entry->hash() == hash, "invariant"); |
113 assert(entry->hash() == hash, "invariant"); |
103 return true; |
114 return true; |
104 } |
115 } |
105 |
116 |
106 void JfrSymbolId::assign_id(CStringEntry* entry) { |
117 void JfrSymbolId::unlink(const SymbolEntry* entry) { |
|
118 assert(entry != NULL, "invariant"); |
|
119 const_cast<Symbol*>(entry->literal())->decrement_refcount(); |
|
120 } |
|
121 |
|
122 void JfrSymbolId::assign_id(const CStringEntry* entry) { |
107 assert(entry != NULL, "invariant"); |
123 assert(entry != NULL, "invariant"); |
108 assert(entry->id() == 0, "invariant"); |
124 assert(entry->id() == 0, "invariant"); |
109 entry->set_id(++_symbol_id_counter); |
125 entry->set_id(++_symbol_id_counter); |
|
126 entry->set_list_next(_cstring_list); |
|
127 _cstring_list = entry; |
110 } |
128 } |
111 |
129 |
112 bool JfrSymbolId::equals(const char* query, uintptr_t hash, const CStringEntry* entry) { |
130 bool JfrSymbolId::equals(const char* query, uintptr_t hash, const CStringEntry* entry) { |
113 // query might be NULL |
131 // query might be NULL |
114 assert(entry != NULL, "invariant"); |
132 assert(entry != NULL, "invariant"); |
115 assert(entry->hash() == hash, "invariant"); |
133 assert(entry->hash() == hash, "invariant"); |
116 return true; |
134 return true; |
|
135 } |
|
136 |
|
137 void JfrSymbolId::unlink(const CStringEntry* entry) { |
|
138 assert(entry != NULL, "invariant"); |
|
139 if (entry->id() != 1) { |
|
140 FREE_C_HEAP_ARRAY(char, entry->literal()); |
|
141 } |
117 } |
142 } |
118 |
143 |
119 traceid JfrSymbolId::mark(const Klass* k) { |
144 traceid JfrSymbolId::mark(const Klass* k) { |
120 assert(k != NULL, "invariant"); |
145 assert(k != NULL, "invariant"); |
121 traceid symbol_id = 0; |
146 traceid symbol_id = 0; |
122 if (is_unsafe_anonymous_klass(k)) { |
147 if (is_unsafe_anonymous_klass(k)) { |
123 symbol_id = mark_unsafe_anonymous_klass_name(k); |
148 symbol_id = mark_unsafe_anonymous_klass_name(k); |
124 } |
149 } |
125 if (0 == symbol_id) { |
150 if (0 == symbol_id) { |
126 const Symbol* const sym = k->name(); |
151 Symbol* const sym = k->name(); |
127 if (sym != NULL) { |
152 if (sym != NULL) { |
128 symbol_id = mark(sym); |
153 symbol_id = mark(sym); |
129 } |
154 } |
130 } |
155 } |
131 assert(symbol_id > 0, "a symbol handler must mark the symbol for writing"); |
156 assert(symbol_id > 0, "a symbol handler must mark the symbol for writing"); |
132 return symbol_id; |
157 return symbol_id; |
133 } |
158 } |
134 |
159 |
135 traceid JfrSymbolId::mark(const Symbol* symbol) { |
160 traceid JfrSymbolId::mark(const Symbol* symbol) { |
136 assert(symbol != NULL, "invariant"); |
161 assert(symbol != NULL, "invariant"); |
137 return mark(symbol, (uintptr_t)const_cast<Symbol*>(symbol)->identity_hash()); |
162 return mark(symbol, (uintptr_t)symbol->identity_hash()); |
138 } |
163 } |
139 |
164 |
140 traceid JfrSymbolId::mark(const Symbol* data, uintptr_t hash) { |
165 traceid JfrSymbolId::mark(const Symbol* data, uintptr_t hash) { |
141 assert(data != NULL, "invariant"); |
166 assert(data != NULL, "invariant"); |
142 assert(_sym_table != NULL, "invariant"); |
167 assert(_sym_table != NULL, "invariant"); |
143 return _sym_table->id(data, hash); |
168 const SymbolEntry& entry = _sym_table->lookup_put(data, hash); |
|
169 if (_class_unload) { |
|
170 entry.set_unloading(); |
|
171 } |
|
172 return entry.id(); |
144 } |
173 } |
145 |
174 |
146 traceid JfrSymbolId::mark(const char* str, uintptr_t hash) { |
175 traceid JfrSymbolId::mark(const char* str, uintptr_t hash) { |
147 assert(str != NULL, "invariant"); |
176 assert(str != NULL, "invariant"); |
148 return _cstring_table->id(str, hash); |
177 const CStringEntry& entry = _cstring_table->lookup_put(str, hash); |
|
178 if (_class_unload) { |
|
179 entry.set_unloading(); |
|
180 } |
|
181 return entry.id(); |
149 } |
182 } |
150 |
183 |
151 bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) { |
184 bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) { |
152 assert(k != NULL, "invariant"); |
185 assert(k != NULL, "invariant"); |
153 return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous(); |
186 return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous(); |
179 char hash_buf[40]; |
212 char hash_buf[40]; |
180 hashcode = unsafe_anonymous_klass_name_hash_code(ik); |
213 hashcode = unsafe_anonymous_klass_name_hash_code(ik); |
181 sprintf(hash_buf, "/" UINTX_FORMAT, hashcode); |
214 sprintf(hash_buf, "/" UINTX_FORMAT, hashcode); |
182 const size_t hash_len = strlen(hash_buf); |
215 const size_t hash_len = strlen(hash_buf); |
183 const size_t result_len = ik->name()->utf8_length(); |
216 const size_t result_len = ik->name()->utf8_length(); |
184 anonymous_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1); |
217 anonymous_symbol = NEW_C_HEAP_ARRAY(char, result_len + hash_len + 1, mtTracing); |
|
218 assert(anonymous_symbol != NULL, "invariant"); |
185 ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1); |
219 ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1); |
186 assert(strlen(anonymous_symbol) == result_len, "invariant"); |
220 assert(strlen(anonymous_symbol) == result_len, "invariant"); |
187 strcpy(anonymous_symbol + result_len, hash_buf); |
221 strcpy(anonymous_symbol + result_len, hash_buf); |
188 assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant"); |
222 assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant"); |
189 return anonymous_symbol; |
223 return anonymous_symbol; |
194 const Symbol* const sym = k->name(); |
228 const Symbol* const sym = k->name(); |
195 assert(sym != NULL, "invariant"); |
229 assert(sym != NULL, "invariant"); |
196 return (uintptr_t)const_cast<Symbol*>(sym)->identity_hash(); |
230 return (uintptr_t)const_cast<Symbol*>(sym)->identity_hash(); |
197 } |
231 } |
198 |
232 |
199 JfrArtifactSet::JfrArtifactSet(bool current_epoch) : _symbol_id(new JfrSymbolId()), |
233 static void preload_bootstrap_loader_name(JfrSymbolId* symbol_id) { |
|
234 assert(symbol_id != NULL, "invariant"); |
|
235 assert(!symbol_id->has_entries(), "invariant"); |
|
236 symbol_id->mark((const char*)&BOOTSTRAP_LOADER_NAME, 0); // pre-load "bootstrap" into id 1 |
|
237 } |
|
238 |
|
239 JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()), |
200 _klass_list(NULL), |
240 _klass_list(NULL), |
201 _total_count(0), |
241 _total_count(0) { |
202 _current_epoch(current_epoch) { |
242 preload_bootstrap_loader_name(_symbol_id); |
203 initialize(current_epoch); |
243 initialize(class_unload); |
204 assert(_klass_list != NULL, "invariant"); |
244 assert(_klass_list != NULL, "invariant"); |
205 } |
245 } |
206 |
246 |
207 static const size_t initial_class_list_size = 200; |
247 static const size_t initial_class_list_size = 200; |
208 void JfrArtifactSet::initialize(bool current_epoch) { |
248 |
|
249 void JfrArtifactSet::initialize(bool class_unload) { |
209 assert(_symbol_id != NULL, "invariant"); |
250 assert(_symbol_id != NULL, "invariant"); |
210 _symbol_id->initialize(); |
251 _symbol_id->set_class_unload(class_unload); |
211 assert(!_symbol_id->has_entries(), "invariant"); |
|
212 _symbol_id->mark(BOOTSTRAP_LOADER_NAME, 0); // pre-load "bootstrap" |
|
213 _total_count = 0; |
252 _total_count = 0; |
214 _current_epoch = current_epoch; |
|
215 // resource allocation |
253 // resource allocation |
216 _klass_list = new GrowableArray<const Klass*>(initial_class_list_size, false, mtTracing); |
254 _klass_list = new GrowableArray<const Klass*>(initial_class_list_size, false, mtTracing); |
217 } |
255 } |
218 |
256 |
219 JfrArtifactSet::~JfrArtifactSet() { |
257 JfrArtifactSet::~JfrArtifactSet() { |
220 clear(); |
258 clear(); |
|
259 delete _symbol_id; |
221 } |
260 } |
222 |
261 |
223 void JfrArtifactSet::clear() { |
262 void JfrArtifactSet::clear() { |
224 _symbol_id->clear(); |
263 _symbol_id->clear(); |
|
264 preload_bootstrap_loader_name(_symbol_id); |
225 // _klass_list will be cleared by a ResourceMark |
265 // _klass_list will be cleared by a ResourceMark |
226 } |
266 } |
227 |
267 |
228 traceid JfrArtifactSet::mark_unsafe_anonymous_klass_name(const Klass* klass) { |
268 traceid JfrArtifactSet::mark_unsafe_anonymous_klass_name(const Klass* klass) { |
229 return _symbol_id->mark_unsafe_anonymous_klass_name(klass); |
269 return _symbol_id->mark_unsafe_anonymous_klass_name(klass); |