src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
changeset 58786 7909763ad193
parent 58132 caa25ab47aca
child 58823 6a21dba79b81
equal deleted inserted replaced
58785:c6cbcc673cd3 58786:7909763ad193
    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);
    64     _cstring_table->clear_entries();
    66     _cstring_table->clear_entries();
    65   }
    67   }
    66   assert(!_cstring_table->has_entries(), "invariant");
    68   assert(!_cstring_table->has_entries(), "invariant");
    67 
    69 
    68   _sym_list = NULL;
    70   _sym_list = NULL;
    69   _cstring_list = NULL;
       
    70   _symbol_id_counter = 1;
    71   _symbol_id_counter = 1;
       
    72 
       
    73   _sym_query = NULL;
       
    74   _cstring_query = NULL;
    71 
    75 
    72   assert(bootstrap != NULL, "invariant");
    76   assert(bootstrap != NULL, "invariant");
    73   bootstrap->reset();
    77   bootstrap->reset();
    74   _cstring_list = bootstrap;
    78   _cstring_list = bootstrap;
    75 }
    79 }
    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);