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); |
91 entry->set_list_next(_sym_list); |
87 _sym_list = entry; |
92 _sym_list = entry; |
88 } |
93 } |
89 |
94 |
90 bool JfrSymbolId::on_equals(uintptr_t hash, const SymbolEntry* entry) { |
95 bool JfrSymbolId::on_equals(uintptr_t hash, const SymbolEntry* entry) { |
91 // query might be NULL |
|
92 assert(entry != NULL, "invariant"); |
96 assert(entry != NULL, "invariant"); |
93 assert(entry->hash() == hash, "invariant"); |
97 assert(entry->hash() == hash, "invariant"); |
94 return true; |
98 assert(_sym_query != NULL, "invariant"); |
|
99 return _sym_query == entry->literal(); |
95 } |
100 } |
96 |
101 |
97 void JfrSymbolId::on_unlink(const SymbolEntry* entry) { |
102 void JfrSymbolId::on_unlink(const SymbolEntry* entry) { |
98 assert(entry != NULL, "invariant"); |
103 assert(entry != NULL, "invariant"); |
99 const_cast<Symbol*>(entry->literal())->decrement_refcount(); |
104 const_cast<Symbol*>(entry->literal())->decrement_refcount(); |
|
105 } |
|
106 |
|
107 static const char* resource_to_cstring(const char* resource_str) { |
|
108 assert(resource_str != NULL, "invariant"); |
|
109 const size_t length = strlen(resource_str); |
|
110 char* const c_string = JfrCHeapObj::new_array<char>(length + 1); |
|
111 assert(c_string != NULL, "invariant"); |
|
112 strncpy(c_string, resource_str, length + 1); |
|
113 return c_string; |
100 } |
114 } |
101 |
115 |
102 void JfrSymbolId::on_link(const CStringEntry* entry) { |
116 void JfrSymbolId::on_link(const CStringEntry* entry) { |
103 assert(entry != NULL, "invariant"); |
117 assert(entry != NULL, "invariant"); |
104 assert(entry->id() == 0, "invariant"); |
118 assert(entry->id() == 0, "invariant"); |
105 entry->set_id(++_symbol_id_counter); |
119 entry->set_id(++_symbol_id_counter); |
|
120 const_cast<CStringEntry*>(entry)->set_literal(resource_to_cstring(entry->literal())); |
106 entry->set_list_next(_cstring_list); |
121 entry->set_list_next(_cstring_list); |
107 _cstring_list = entry; |
122 _cstring_list = entry; |
108 } |
123 } |
109 |
124 |
|
125 static bool string_compare(const char* query, const char* candidate) { |
|
126 assert(query != NULL, "invariant"); |
|
127 assert(candidate != NULL, "invariant"); |
|
128 const size_t length = strlen(query); |
|
129 return strncmp(query, candidate, length) == 0; |
|
130 } |
|
131 |
110 bool JfrSymbolId::on_equals(uintptr_t hash, const CStringEntry* entry) { |
132 bool JfrSymbolId::on_equals(uintptr_t hash, const CStringEntry* entry) { |
111 assert(entry != NULL, "invariant"); |
133 assert(entry != NULL, "invariant"); |
112 assert(entry->hash() == hash, "invariant"); |
134 assert(entry->hash() == hash, "invariant"); |
113 return true; |
135 assert(_cstring_query != NULL, "invariant"); |
|
136 return string_compare(_cstring_query, entry->literal()); |
114 } |
137 } |
115 |
138 |
116 void JfrSymbolId::on_unlink(const CStringEntry* entry) { |
139 void JfrSymbolId::on_unlink(const CStringEntry* entry) { |
117 assert(entry != NULL, "invariant"); |
140 assert(entry != NULL, "invariant"); |
118 JfrCHeapObj::free(const_cast<char*>(entry->literal()), strlen(entry->literal() + 1)); |
141 JfrCHeapObj::free(const_cast<char*>(entry->literal()), strlen(entry->literal() + 1)); |
129 traceid JfrSymbolId::mark(const Symbol* symbol, bool leakp) { |
152 traceid JfrSymbolId::mark(const Symbol* symbol, bool leakp) { |
130 assert(symbol != NULL, "invariant"); |
153 assert(symbol != NULL, "invariant"); |
131 return mark((uintptr_t)symbol->identity_hash(), symbol, leakp); |
154 return mark((uintptr_t)symbol->identity_hash(), symbol, leakp); |
132 } |
155 } |
133 |
156 |
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) { |
157 traceid JfrSymbolId::mark(uintptr_t hash, const Symbol* data, bool leakp) { |
138 assert(data != NULL, "invariant"); |
158 assert(data != NULL, "invariant"); |
139 assert(_sym_table != NULL, "invariant"); |
159 assert(_sym_table != NULL, "invariant"); |
140 if (hash == last_symbol_hash) { |
160 _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); |
161 const SymbolEntry& entry = _sym_table->lookup_put(hash, data); |
145 if (_class_unload) { |
162 if (_class_unload) { |
146 entry.set_unloading(); |
163 entry.set_unloading(); |
147 } |
164 } |
148 if (leakp) { |
165 if (leakp) { |
149 entry.set_leakp(); |
166 entry.set_leakp(); |
150 } |
167 } |
151 last_symbol_hash = hash; |
168 return entry.id(); |
152 last_symbol_id = entry.id(); |
169 } |
153 return last_symbol_id; |
|
154 } |
|
155 |
|
156 static unsigned int last_cstring_hash = 0; |
|
157 static traceid last_cstring_id = 0; |
|
158 |
170 |
159 traceid JfrSymbolId::mark(uintptr_t hash, const char* str, bool leakp) { |
171 traceid JfrSymbolId::mark(uintptr_t hash, const char* str, bool leakp) { |
160 assert(str != NULL, "invariant"); |
172 assert(str != NULL, "invariant"); |
161 assert(_cstring_table != NULL, "invariant"); |
173 assert(_cstring_table != NULL, "invariant"); |
162 if (hash == last_cstring_hash) { |
174 _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); |
175 const CStringEntry& entry = _cstring_table->lookup_put(hash, str); |
167 if (_class_unload) { |
176 if (_class_unload) { |
168 entry.set_unloading(); |
177 entry.set_unloading(); |
169 } |
178 } |
170 if (leakp) { |
179 if (leakp) { |
171 entry.set_leakp(); |
180 entry.set_leakp(); |
172 } |
181 } |
173 last_cstring_hash = hash; |
182 return entry.id(); |
174 last_cstring_id = entry.id(); |
|
175 return last_cstring_id; |
|
176 } |
183 } |
177 |
184 |
178 /* |
185 /* |
179 * jsr292 anonymous classes symbol is the external name + |
186 * jsr292 anonymous classes symbol is the external name + |
180 * the identity_hashcode slash appended: |
187 * the identity_hashcode slash appended: |
200 assert(mirror != NULL, "invariant"); |
207 assert(mirror != NULL, "invariant"); |
201 char hash_buf[40]; |
208 char hash_buf[40]; |
202 sprintf(hash_buf, "/" UINTX_FORMAT, hash); |
209 sprintf(hash_buf, "/" UINTX_FORMAT, hash); |
203 const size_t hash_len = strlen(hash_buf); |
210 const size_t hash_len = strlen(hash_buf); |
204 const size_t result_len = ik->name()->utf8_length(); |
211 const size_t result_len = ik->name()->utf8_length(); |
205 anonymous_symbol = JfrCHeapObj::new_array<char>(result_len + hash_len + 1); |
212 anonymous_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1); |
206 ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1); |
213 ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1); |
207 assert(strlen(anonymous_symbol) == result_len, "invariant"); |
214 assert(strlen(anonymous_symbol) == result_len, "invariant"); |
208 strcpy(anonymous_symbol + result_len, hash_buf); |
215 strcpy(anonymous_symbol + result_len, hash_buf); |
209 assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant"); |
216 assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant"); |
210 return anonymous_symbol; |
217 return anonymous_symbol; |
213 bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) { |
220 bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) { |
214 assert(k != NULL, "invariant"); |
221 assert(k != NULL, "invariant"); |
215 return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous(); |
222 return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous(); |
216 } |
223 } |
217 |
224 |
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) { |
225 traceid JfrSymbolId::mark_unsafe_anonymous_klass_name(const InstanceKlass* ik, bool leakp) { |
222 assert(ik != NULL, "invariant"); |
226 assert(ik != NULL, "invariant"); |
223 assert(ik->is_unsafe_anonymous(), "invariant"); |
227 assert(ik->is_unsafe_anonymous(), "invariant"); |
224 const uintptr_t hash = unsafe_anonymous_klass_name_hash(ik); |
228 const uintptr_t hash = unsafe_anonymous_klass_name_hash(ik); |
225 if (hash == last_anonymous_hash) { |
229 const char* const anonymous_klass_symbol = create_unsafe_anonymous_klass_symbol(ik, hash); |
226 assert(last_anonymous_id != 0, "invariant"); |
230 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 } |
231 } |
234 |
232 |
235 traceid JfrSymbolId::mark(const Klass* k, bool leakp) { |
233 traceid JfrSymbolId::mark(const Klass* k, bool leakp) { |
236 assert(k != NULL, "invariant"); |
234 assert(k != NULL, "invariant"); |
237 traceid symbol_id = 0; |
235 traceid symbol_id = 0; |
247 } |
245 } |
248 assert(symbol_id > 0, "a symbol handler must mark the symbol for writing"); |
246 assert(symbol_id > 0, "a symbol handler must mark the symbol for writing"); |
249 return symbol_id; |
247 return symbol_id; |
250 } |
248 } |
251 |
249 |
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()), |
250 JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()), |
259 _klass_list(NULL), |
251 _klass_list(NULL), |
260 _total_count(0) { |
252 _total_count(0) { |
261 initialize(class_unload); |
253 initialize(class_unload); |
262 assert(_klass_list != NULL, "invariant"); |
254 assert(_klass_list != NULL, "invariant"); |