diff -r aa7b1ea52413 -r a57907813a83 src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp --- a/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp Fri Aug 30 20:39:38 2019 +0200 +++ b/src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp Mon Sep 02 19:42:46 2019 +0200 @@ -67,38 +67,7 @@ _class_unload = class_unload; } -traceid JfrSymbolId::mark_unsafe_anonymous_klass_name(const Klass* k) { - assert(k != NULL, "invariant"); - assert(k->is_instance_klass(), "invariant"); - assert(is_unsafe_anonymous_klass(k), "invariant"); - - uintptr_t anonymous_symbol_hash_code = 0; - const char* const anonymous_symbol = - create_unsafe_anonymous_klass_symbol((const InstanceKlass*)k, anonymous_symbol_hash_code); - - if (anonymous_symbol == NULL) { - return 0; - } - - assert(anonymous_symbol_hash_code != 0, "invariant"); - traceid symbol_id = mark(anonymous_symbol, anonymous_symbol_hash_code); - assert(mark(anonymous_symbol, anonymous_symbol_hash_code) == symbol_id, "invariant"); - return symbol_id; -} - -const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(const Symbol* symbol) const { - return _sym_table->lookup_only(symbol, (uintptr_t)symbol->identity_hash()); -} - -const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(uintptr_t hash) const { - return _sym_table->lookup_only(NULL, hash); -} - -const JfrSymbolId::CStringEntry* JfrSymbolId::map_cstring(uintptr_t hash) const { - return _cstring_table->lookup_only(NULL, hash); -} - -void JfrSymbolId::assign_id(const SymbolEntry* entry) { +void JfrSymbolId::link(const SymbolEntry* entry) { assert(entry != NULL, "invariant"); const_cast(entry->literal())->increment_refcount(); assert(entry->id() == 0, "invariant"); @@ -107,7 +76,7 @@ _sym_list = entry; } -bool JfrSymbolId::equals(const Symbol* query, uintptr_t hash, const SymbolEntry* entry) { +bool JfrSymbolId::equals(uintptr_t hash, const SymbolEntry* entry) { // query might be NULL assert(entry != NULL, "invariant"); assert(entry->hash() == hash, "invariant"); @@ -119,16 +88,26 @@ const_cast(entry->literal())->decrement_refcount(); } -void JfrSymbolId::assign_id(const CStringEntry* entry) { +static const char* resource_str_to_c_heap_str(const char* resource_str) { + assert(resource_str != NULL, "invariant"); + const size_t length = strlen(resource_str); + char* const c_string = JfrCHeapObj::new_array(length + 1); + assert(c_string != NULL, "invariant"); + strncpy(c_string, resource_str, length + 1); + return c_string; +} + +void JfrSymbolId::link(const CStringEntry* entry) { assert(entry != NULL, "invariant"); assert(entry->id() == 0, "invariant"); entry->set_id(++_symbol_id_counter); entry->set_list_next(_cstring_list); + const char* const resource_str = entry->literal(); + const_cast(entry)->set_literal(resource_str_to_c_heap_str(resource_str)); _cstring_list = entry; } -bool JfrSymbolId::equals(const char* query, uintptr_t hash, const CStringEntry* entry) { - // query might be NULL +bool JfrSymbolId::equals(uintptr_t hash, const CStringEntry* entry) { assert(entry != NULL, "invariant"); assert(entry->hash() == hash, "invariant"); return true; @@ -137,53 +116,57 @@ void JfrSymbolId::unlink(const CStringEntry* entry) { assert(entry != NULL, "invariant"); if (entry->id() != 1) { - FREE_C_HEAP_ARRAY(char, entry->literal()); + JfrCHeapObj::free(const_cast(entry->literal()), 0); } } -traceid JfrSymbolId::mark(const Klass* k) { - assert(k != NULL, "invariant"); - traceid symbol_id = 0; - if (is_unsafe_anonymous_klass(k)) { - symbol_id = mark_unsafe_anonymous_klass_name(k); - } - if (0 == symbol_id) { - Symbol* const sym = k->name(); - if (sym != NULL) { - symbol_id = mark(sym); - } - } - assert(symbol_id > 0, "a symbol handler must mark the symbol for writing"); - return symbol_id; +traceid JfrSymbolId::mark(const Symbol* symbol, bool leakp) { + assert(symbol != NULL, "invariant"); + return mark((uintptr_t)symbol->identity_hash(), symbol, leakp); } -traceid JfrSymbolId::mark(const Symbol* symbol) { - assert(symbol != NULL, "invariant"); - return mark(symbol, (uintptr_t)symbol->identity_hash()); -} +static unsigned int last_symbol_hash = 0; +static traceid last_symbol_id = 0; -traceid JfrSymbolId::mark(const Symbol* data, uintptr_t hash) { +traceid JfrSymbolId::mark(uintptr_t hash, const Symbol* data, bool leakp) { assert(data != NULL, "invariant"); assert(_sym_table != NULL, "invariant"); - const SymbolEntry& entry = _sym_table->lookup_put(data, hash); + if (hash == last_symbol_hash) { + assert(last_symbol_id != 0, "invariant"); + return last_symbol_id; + } + const SymbolEntry& entry = _sym_table->lookup_put(hash, data); if (_class_unload) { entry.set_unloading(); } - return entry.id(); + if (leakp) { + entry.set_leakp(); + } + last_symbol_hash = hash; + last_symbol_id = entry.id(); + return last_symbol_id; } -traceid JfrSymbolId::mark(const char* str, uintptr_t hash) { +static unsigned int last_cstring_hash = 0; +static traceid last_cstring_id = 0; + +traceid JfrSymbolId::mark(uintptr_t hash, const char* str, bool leakp) { assert(str != NULL, "invariant"); - const CStringEntry& entry = _cstring_table->lookup_put(str, hash); + assert(_cstring_table != NULL, "invariant"); + if (hash == last_cstring_hash) { + assert(last_cstring_id != 0, "invariant"); + return last_cstring_id; + } + const CStringEntry& entry = _cstring_table->lookup_put(hash, str); if (_class_unload) { entry.set_unloading(); } - return entry.id(); -} - -bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) { - assert(k != NULL, "invariant"); - return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous(); + if (leakp) { + entry.set_leakp(); + } + last_cstring_hash = hash; + last_cstring_id = entry.id(); + return last_cstring_id; } /* @@ -194,7 +177,7 @@ * caller needs ResourceMark */ -uintptr_t JfrSymbolId::unsafe_anonymous_klass_name_hash_code(const InstanceKlass* ik) { +uintptr_t JfrSymbolId::unsafe_anonymous_klass_name_hash(const InstanceKlass* ik) { assert(ik != NULL, "invariant"); assert(ik->is_unsafe_anonymous(), "invariant"); const oop mirror = ik->java_mirror_no_keepalive(); @@ -202,19 +185,18 @@ return (uintptr_t)mirror->identity_hash(); } -const char* JfrSymbolId::create_unsafe_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode) { +static const char* create_unsafe_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t hash) { assert(ik != NULL, "invariant"); assert(ik->is_unsafe_anonymous(), "invariant"); - assert(0 == hashcode, "invariant"); + assert(hash != 0, "invariant"); char* anonymous_symbol = NULL; const oop mirror = ik->java_mirror_no_keepalive(); assert(mirror != NULL, "invariant"); char hash_buf[40]; - hashcode = unsafe_anonymous_klass_name_hash_code(ik); - sprintf(hash_buf, "/" UINTX_FORMAT, hashcode); + sprintf(hash_buf, "/" UINTX_FORMAT, hash); const size_t hash_len = strlen(hash_buf); const size_t result_len = ik->name()->utf8_length(); - anonymous_symbol = NEW_C_HEAP_ARRAY(char, result_len + hash_len + 1, mtTracing); + anonymous_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1); assert(anonymous_symbol != NULL, "invariant"); ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1); assert(strlen(anonymous_symbol) == result_len, "invariant"); @@ -223,17 +205,54 @@ return anonymous_symbol; } -uintptr_t JfrSymbolId::regular_klass_name_hash_code(const Klass* k) { +bool JfrSymbolId::is_unsafe_anonymous_klass(const Klass* k) { assert(k != NULL, "invariant"); - const Symbol* const sym = k->name(); - assert(sym != NULL, "invariant"); - return (uintptr_t)const_cast(sym)->identity_hash(); + return k->is_instance_klass() && ((const InstanceKlass*)k)->is_unsafe_anonymous(); +} + +static unsigned int last_anonymous_hash = 0; +static traceid last_anonymous_id = 0; + +traceid JfrSymbolId::mark_unsafe_anonymous_klass_name(const InstanceKlass* ik, bool leakp) { + assert(ik != NULL, "invariant"); + assert(ik->is_unsafe_anonymous(), "invariant"); + const uintptr_t hash = unsafe_anonymous_klass_name_hash(ik); + if (hash == last_anonymous_hash) { + assert(last_anonymous_id != 0, "invariant"); + return last_anonymous_id; + } + last_anonymous_hash = hash; + last_anonymous_id = mark(hash, create_unsafe_anonymous_klass_symbol(ik, hash), leakp); + return last_anonymous_id; +} + +traceid JfrSymbolId::mark(const Klass* k, bool leakp) { + assert(k != NULL, "invariant"); + traceid symbol_id = 0; + if (is_unsafe_anonymous_klass(k)) { + assert(k->is_instance_klass(), "invariant"); + symbol_id = mark_unsafe_anonymous_klass_name((const InstanceKlass*)k, leakp); + } + if (0 == symbol_id) { + Symbol* const sym = k->name(); + if (sym != NULL) { + symbol_id = mark(sym, leakp); + } + } + assert(symbol_id > 0, "a symbol handler must mark the symbol for writing"); + return symbol_id; } static void preload_bootstrap_loader_name(JfrSymbolId* symbol_id) { assert(symbol_id != NULL, "invariant"); assert(!symbol_id->has_entries(), "invariant"); - symbol_id->mark((const char*)&BOOTSTRAP_LOADER_NAME, 0); // pre-load "bootstrap" into id 1 + symbol_id->mark(1, (const char*)&BOOTSTRAP_LOADER_NAME, false); // pre-load "bootstrap" into id 1 +} + +static void reset_symbol_caches() { + last_anonymous_hash = 0; + last_symbol_hash = 0; + last_cstring_hash = 0; } JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()), @@ -260,41 +279,31 @@ } void JfrArtifactSet::clear() { + reset_symbol_caches(); _symbol_id->clear(); preload_bootstrap_loader_name(_symbol_id); // _klass_list will be cleared by a ResourceMark } -traceid JfrArtifactSet::mark_unsafe_anonymous_klass_name(const Klass* klass) { - return _symbol_id->mark_unsafe_anonymous_klass_name(klass); +traceid JfrArtifactSet::mark_unsafe_anonymous_klass_name(const Klass* klass, bool leakp) { + assert(klass->is_instance_klass(), "invariant"); + return _symbol_id->mark_unsafe_anonymous_klass_name((const InstanceKlass*)klass, leakp); } -traceid JfrArtifactSet::mark(const Symbol* sym, uintptr_t hash) { - return _symbol_id->mark(sym, hash); -} - -traceid JfrArtifactSet::mark(const Klass* klass) { - return _symbol_id->mark(klass); +traceid JfrArtifactSet::mark(uintptr_t hash, const Symbol* sym, bool leakp) { + return _symbol_id->mark(hash, sym, leakp); } -traceid JfrArtifactSet::mark(const Symbol* symbol) { - return _symbol_id->mark(symbol); -} - -traceid JfrArtifactSet::mark(const char* const str, uintptr_t hash) { - return _symbol_id->mark(str, hash); +traceid JfrArtifactSet::mark(const Klass* klass, bool leakp) { + return _symbol_id->mark(klass, leakp); } -const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(const Symbol* symbol) const { - return _symbol_id->map_symbol(symbol); +traceid JfrArtifactSet::mark(const Symbol* symbol, bool leakp) { + return _symbol_id->mark(symbol, leakp); } -const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(uintptr_t hash) const { - return _symbol_id->map_symbol(hash); -} - -const JfrSymbolId::CStringEntry* JfrArtifactSet::map_cstring(uintptr_t hash) const { - return _symbol_id->map_cstring(hash); +traceid JfrArtifactSet::mark(uintptr_t hash, const char* const str, bool leakp) { + return _symbol_id->mark(hash, str, leakp); } bool JfrArtifactSet::has_klass_entries() const {