src/hotspot/share/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp
branchJEP-349-branch
changeset 58171 c16b748a224e
parent 58158 369ebc2a11c2
child 58251 c4067538a0f2
equal deleted inserted replaced
58170:2bcc33884590 58171:c16b748a224e
    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);
    67 
    69 
    68   _sym_list = NULL;
    70   _sym_list = NULL;
    69   _cstring_list = NULL;
    71   _cstring_list = NULL;
    70   _symbol_id_counter = 1;
    72   _symbol_id_counter = 1;
    71 
    73 
       
    74   _sym_query = NULL;
       
    75   _cstring_query = NULL;
       
    76 
    72   assert(bootstrap != NULL, "invariant");
    77   assert(bootstrap != NULL, "invariant");
    73   bootstrap->reset();
    78   bootstrap->reset();
    74   _cstring_list = bootstrap;
    79   _cstring_list = bootstrap;
    75 }
    80 }
    76 
    81 
    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");
   276   clear();
   268   clear();
   277   delete _symbol_id;
   269   delete _symbol_id;
   278 }
   270 }
   279 
   271 
   280 void JfrArtifactSet::clear() {
   272 void JfrArtifactSet::clear() {
   281   reset_symbol_caches();
       
   282   _symbol_id->clear();
   273   _symbol_id->clear();
   283   // _klass_list will be cleared by a ResourceMark
   274   // _klass_list will be cleared by a ResourceMark
   284 }
   275 }
   285 
   276 
   286 traceid JfrArtifactSet::bootstrap_name(bool leakp) {
   277 traceid JfrArtifactSet::bootstrap_name(bool leakp) {