33 JfrSymbolId::JfrSymbolId() : |
33 JfrSymbolId::JfrSymbolId() : |
34 _sym_table(new SymbolTable(this)), |
34 _sym_table(new SymbolTable(this)), |
35 _cstring_table(new CStringTable(this)), |
35 _cstring_table(new CStringTable(this)), |
36 _sym_list(NULL), |
36 _sym_list(NULL), |
37 _cstring_list(NULL), |
37 _cstring_list(NULL), |
|
38 _sym_query(NULL), |
|
39 _cstring_query(NULL), |
38 _symbol_id_counter(1), |
40 _symbol_id_counter(1), |
39 _class_unload(false) { |
41 _class_unload(false) { |
40 assert(_sym_table != NULL, "invariant"); |
42 assert(_sym_table != NULL, "invariant"); |
41 assert(_cstring_table != NULL, "invariant"); |
43 assert(_cstring_table != NULL, "invariant"); |
42 bootstrap = new CStringEntry(0, (const char*)&BOOTSTRAP_LOADER_NAME); |
44 bootstrap = new CStringEntry(0, (const char*)&BOOTSTRAP_LOADER_NAME); |
86 entry->set_list_next(_sym_list); |
90 entry->set_list_next(_sym_list); |
87 _sym_list = entry; |
91 _sym_list = entry; |
88 } |
92 } |
89 |
93 |
90 bool JfrSymbolId::on_equals(uintptr_t hash, const SymbolEntry* entry) { |
94 bool JfrSymbolId::on_equals(uintptr_t hash, const SymbolEntry* entry) { |
91 // query might be NULL |
|
92 assert(entry != NULL, "invariant"); |
95 assert(entry != NULL, "invariant"); |
93 assert(entry->hash() == hash, "invariant"); |
96 assert(entry->hash() == hash, "invariant"); |
94 return true; |
97 assert(_sym_query != NULL, "invariant"); |
|
98 return _sym_query == entry->literal(); |
95 } |
99 } |
96 |
100 |
97 void JfrSymbolId::on_unlink(const SymbolEntry* entry) { |
101 void JfrSymbolId::on_unlink(const SymbolEntry* entry) { |
98 assert(entry != NULL, "invariant"); |
102 assert(entry != NULL, "invariant"); |
99 const_cast<Symbol*>(entry->literal())->decrement_refcount(); |
103 const_cast<Symbol*>(entry->literal())->decrement_refcount(); |
|
104 } |
|
105 |
|
106 static const char* resource_to_cstring(const char* resource_str) { |
|
107 assert(resource_str != NULL, "invariant"); |
|
108 const size_t length = strlen(resource_str); |
|
109 char* const c_string = JfrCHeapObj::new_array<char>(length + 1); |
|
110 assert(c_string != NULL, "invariant"); |
|
111 strncpy(c_string, resource_str, length + 1); |
|
112 return c_string; |
100 } |
113 } |
101 |
114 |
102 void JfrSymbolId::on_link(const CStringEntry* entry) { |
115 void JfrSymbolId::on_link(const CStringEntry* entry) { |
103 assert(entry != NULL, "invariant"); |
116 assert(entry != NULL, "invariant"); |
104 assert(entry->id() == 0, "invariant"); |
117 assert(entry->id() == 0, "invariant"); |
105 entry->set_id(++_symbol_id_counter); |
118 entry->set_id(++_symbol_id_counter); |
|
119 const_cast<CStringEntry*>(entry)->set_literal(resource_to_cstring(entry->literal())); |
106 entry->set_list_next(_cstring_list); |
120 entry->set_list_next(_cstring_list); |
107 _cstring_list = entry; |
121 _cstring_list = entry; |
108 } |
122 } |
109 |
123 |
|
124 static bool string_compare(const char* query, const char* candidate) { |
|
125 assert(query != NULL, "invariant"); |
|
126 assert(candidate != NULL, "invariant"); |
|
127 const size_t length = strlen(query); |
|
128 return strncmp(query, candidate, length) == 0; |
|
129 } |
|
130 |
110 bool JfrSymbolId::on_equals(uintptr_t hash, const CStringEntry* entry) { |
131 bool JfrSymbolId::on_equals(uintptr_t hash, const CStringEntry* entry) { |
111 assert(entry != NULL, "invariant"); |
132 assert(entry != NULL, "invariant"); |
112 assert(entry->hash() == hash, "invariant"); |
133 assert(entry->hash() == hash, "invariant"); |
113 return true; |
134 assert(_cstring_query != NULL, "invariant"); |
|
135 return string_compare(_cstring_query, entry->literal()); |
114 } |
136 } |
115 |
137 |
116 void JfrSymbolId::on_unlink(const CStringEntry* entry) { |
138 void JfrSymbolId::on_unlink(const CStringEntry* entry) { |
117 assert(entry != NULL, "invariant"); |
139 assert(entry != NULL, "invariant"); |
118 JfrCHeapObj::free(const_cast<char*>(entry->literal()), strlen(entry->literal() + 1)); |
140 JfrCHeapObj::free(const_cast<char*>(entry->literal()), strlen(entry->literal() + 1)); |
129 traceid JfrSymbolId::mark(const Symbol* symbol, bool leakp) { |
151 traceid JfrSymbolId::mark(const Symbol* symbol, bool leakp) { |
130 assert(symbol != NULL, "invariant"); |
152 assert(symbol != NULL, "invariant"); |
131 return mark((uintptr_t)symbol->identity_hash(), symbol, leakp); |
153 return mark((uintptr_t)symbol->identity_hash(), symbol, leakp); |
132 } |
154 } |
133 |
155 |
134 static unsigned int last_symbol_hash = 0; |
|
135 static traceid last_symbol_id = 0; |
|
136 |
|
137 traceid JfrSymbolId::mark(uintptr_t hash, const Symbol* data, bool leakp) { |
156 traceid JfrSymbolId::mark(uintptr_t hash, const Symbol* data, bool leakp) { |
138 assert(data != NULL, "invariant"); |
157 assert(data != NULL, "invariant"); |
139 assert(_sym_table != NULL, "invariant"); |
158 assert(_sym_table != NULL, "invariant"); |
140 if (hash == last_symbol_hash) { |
159 _sym_query = data; |
141 assert(last_symbol_id != 0, "invariant"); |
|
142 return last_symbol_id; |
|
143 } |
|
144 const SymbolEntry& entry = _sym_table->lookup_put(hash, data); |
160 const SymbolEntry& entry = _sym_table->lookup_put(hash, data); |
145 if (_class_unload) { |
161 if (_class_unload) { |
146 entry.set_unloading(); |
162 entry.set_unloading(); |
147 } |
163 } |
148 if (leakp) { |
164 if (leakp) { |
149 entry.set_leakp(); |
165 entry.set_leakp(); |
150 } |
166 } |
151 last_symbol_hash = hash; |
167 return entry.id(); |
152 last_symbol_id = entry.id(); |
168 } |
153 return last_symbol_id; |
|
154 } |
|
155 |
|
156 static unsigned int last_cstring_hash = 0; |
|
157 static traceid last_cstring_id = 0; |
|
158 |
169 |
159 traceid JfrSymbolId::mark(uintptr_t hash, const char* str, bool leakp) { |
170 traceid JfrSymbolId::mark(uintptr_t hash, const char* str, bool leakp) { |
160 assert(str != NULL, "invariant"); |
171 assert(str != NULL, "invariant"); |
161 assert(_cstring_table != NULL, "invariant"); |
172 assert(_cstring_table != NULL, "invariant"); |
162 if (hash == last_cstring_hash) { |
173 _cstring_query = str; |
163 assert(last_cstring_id != 0, "invariant"); |
|
164 return last_cstring_id; |
|
165 } |
|
166 const CStringEntry& entry = _cstring_table->lookup_put(hash, str); |
174 const CStringEntry& entry = _cstring_table->lookup_put(hash, str); |
167 if (_class_unload) { |
175 if (_class_unload) { |
168 entry.set_unloading(); |
176 entry.set_unloading(); |
169 } |
177 } |
170 if (leakp) { |
178 if (leakp) { |
171 entry.set_leakp(); |
179 entry.set_leakp(); |
172 } |
180 } |
173 last_cstring_hash = hash; |
181 return entry.id(); |
174 last_cstring_id = entry.id(); |
|
175 return last_cstring_id; |
|
176 } |
182 } |
177 |
183 |
178 /* |
184 /* |
179 * jsr292 anonymous classes symbol is the external name + |
185 * jsr292 anonymous classes symbol is the external name + |
180 * the identity_hashcode slash appended: |
186 * the identity_hashcode slash appended: |
200 assert(mirror != NULL, "invariant"); |
206 assert(mirror != NULL, "invariant"); |
201 char hash_buf[40]; |
207 char hash_buf[40]; |
202 sprintf(hash_buf, "/" UINTX_FORMAT, hash); |
208 sprintf(hash_buf, "/" UINTX_FORMAT, hash); |
203 const size_t hash_len = strlen(hash_buf); |
209 const size_t hash_len = strlen(hash_buf); |
204 const size_t result_len = ik->name()->utf8_length(); |
210 const size_t result_len = ik->name()->utf8_length(); |
205 anonymous_symbol = JfrCHeapObj::new_array<char>(result_len + hash_len + 1); |
211 anonymous_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1); |
206 ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1); |
212 ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1); |
207 assert(strlen(anonymous_symbol) == result_len, "invariant"); |
213 assert(strlen(anonymous_symbol) == result_len, "invariant"); |
208 strcpy(anonymous_symbol + result_len, hash_buf); |
214 strcpy(anonymous_symbol + result_len, hash_buf); |
209 assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant"); |
215 assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant"); |
210 return anonymous_symbol; |
216 return anonymous_symbol; |
213 bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) { |
219 bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) { |
214 assert(k != NULL, "invariant"); |
220 assert(k != NULL, "invariant"); |
215 return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous(); |
221 return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous(); |
216 } |
222 } |
217 |
223 |
218 static unsigned int last_anonymous_hash = 0; |
|
219 static traceid last_anonymous_id = 0; |
|
220 |
|
221 traceid JfrSymbolId::mark_unsafe_anonymous_klass_name(const InstanceKlass* ik, bool leakp) { |
224 traceid JfrSymbolId::mark_unsafe_anonymous_klass_name(const InstanceKlass* ik, bool leakp) { |
222 assert(ik != NULL, "invariant"); |
225 assert(ik != NULL, "invariant"); |
223 assert(ik->is_unsafe_anonymous(), "invariant"); |
226 assert(ik->is_unsafe_anonymous(), "invariant"); |
224 const uintptr_t hash = unsafe_anonymous_klass_name_hash(ik); |
227 const uintptr_t hash = unsafe_anonymous_klass_name_hash(ik); |
225 if (hash == last_anonymous_hash) { |
228 const char* const anonymous_klass_symbol = create_unsafe_anonymous_klass_symbol(ik, hash); |
226 assert(last_anonymous_id != 0, "invariant"); |
229 return mark(hash, anonymous_klass_symbol, leakp); |
227 return last_anonymous_id; |
|
228 } |
|
229 last_anonymous_hash = hash; |
|
230 const CStringEntry* const entry = _cstring_table->lookup_only(hash); |
|
231 last_anonymous_id = entry != NULL ? entry->id() : mark(hash, create_unsafe_anonymous_klass_symbol(ik, hash), leakp); |
|
232 return last_anonymous_id; |
|
233 } |
230 } |
234 |
231 |
235 traceid JfrSymbolId::mark(const Klass* k, bool leakp) { |
232 traceid JfrSymbolId::mark(const Klass* k, bool leakp) { |
236 assert(k != NULL, "invariant"); |
233 assert(k != NULL, "invariant"); |
237 traceid symbol_id = 0; |
234 traceid symbol_id = 0; |
247 } |
244 } |
248 assert(symbol_id > 0, "a symbol handler must mark the symbol for writing"); |
245 assert(symbol_id > 0, "a symbol handler must mark the symbol for writing"); |
249 return symbol_id; |
246 return symbol_id; |
250 } |
247 } |
251 |
248 |
252 static void reset_symbol_caches() { |
|
253 last_anonymous_hash = 0; |
|
254 last_symbol_hash = 0; |
|
255 last_cstring_hash = 0; |
|
256 } |
|
257 |
|
258 JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()), |
249 JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()), |
259 _klass_list(NULL), |
250 _klass_list(NULL), |
260 _total_count(0) { |
251 _total_count(0) { |
261 initialize(class_unload); |
252 initialize(class_unload); |
262 assert(_klass_list != NULL, "invariant"); |
253 assert(_klass_list != NULL, "invariant"); |
263 } |
254 } |
264 |
255 |
265 static const size_t initial_class_list_size = 200; |
256 static const size_t initial_class_list_size = 200; |
266 |
257 |
267 void JfrArtifactSet::initialize(bool class_unload) { |
258 void JfrArtifactSet::initialize(bool class_unload, bool clear /* false */) { |
268 assert(_symbol_id != NULL, "invariant"); |
259 assert(_symbol_id != NULL, "invariant"); |
|
260 if (clear) { |
|
261 _symbol_id->clear(); |
|
262 } |
269 _symbol_id->set_class_unload(class_unload); |
263 _symbol_id->set_class_unload(class_unload); |
270 _total_count = 0; |
264 _total_count = 0; |
271 // resource allocation |
265 // resource allocation |
272 _klass_list = new GrowableArray<const Klass*>(initial_class_list_size, false, mtTracing); |
266 _klass_list = new GrowableArray<const Klass*>(initial_class_list_size, false, mtTracing); |
273 } |
267 } |
274 |
268 |
275 JfrArtifactSet::~JfrArtifactSet() { |
269 JfrArtifactSet::~JfrArtifactSet() { |
276 clear(); |
270 _symbol_id->clear(); |
277 delete _symbol_id; |
271 delete _symbol_id; |
278 } |
|
279 |
|
280 void JfrArtifactSet::clear() { |
|
281 reset_symbol_caches(); |
|
282 _symbol_id->clear(); |
|
283 // _klass_list will be cleared by a ResourceMark |
272 // _klass_list will be cleared by a ResourceMark |
284 } |
273 } |
285 |
274 |
286 traceid JfrArtifactSet::bootstrap_name(bool leakp) { |
275 traceid JfrArtifactSet::bootstrap_name(bool leakp) { |
287 return _symbol_id->bootstrap_name(leakp); |
276 return _symbol_id->bootstrap_name(leakp); |