src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp

Mon, 15 Jun 2020 14:08:11 +0300

author
apetushkov
date
Mon, 15 Jun 2020 14:08:11 +0300
changeset 9926
d20a5f399218
parent 9858
b985cbb00e68
permissions
-rw-r--r--

8245167: Top package in method profiling shows null in JMC
Reviewed-by: neugens
Contributed-by: asemenov@azul.com

     1 /*
     2  * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    20  * or visit www.oracle.com if you need additional information or have any
    21  * questions.
    22  *
    23  */
    25 #include "precompiled.hpp"
    26 #include "jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp"
    27 #include "oops/instanceKlass.hpp"
    28 #include "oops/oop.inline.hpp"
    29 #include "oops/symbol.hpp"
    31 JfrSymbolId::JfrSymbolId() : _symbol_id_counter(0), _sym_table(new SymbolTable(this)),
    32         _cstring_table(new CStringTable(this)), _pkg_table(new CStringTable(this)) {
    33   assert(_sym_table != NULL, "invariant");
    34   assert(_cstring_table != NULL, "invariant");
    35   assert(_pkg_table != NULL, "invariant");
    36   initialize();
    37 }
    39 void JfrSymbolId::initialize() {
    40   clear();
    41   assert(_symbol_id_counter == 0, "invariant");
    42 }
    44 void JfrSymbolId::clear() {
    45   assert(_sym_table != NULL, "invariant");
    46   if (_sym_table->has_entries()) {
    47     _sym_table->clear_entries();
    48   }
    49   assert(!_sym_table->has_entries(), "invariant");
    51   assert(_cstring_table != NULL, "invariant");
    52   if (_cstring_table->has_entries()) {
    53     _cstring_table->clear_entries();
    54   }
    55   assert(!_cstring_table->has_entries(), "invariant");
    56   _symbol_id_counter = 0;
    57   assert(_pkg_table != NULL, "invariant");
    58   if (_pkg_table->has_entries()) {
    59     _pkg_table->clear_entries();
    60   }
    61   assert(!_pkg_table->has_entries(), "invariant");
    62 }
    64 JfrSymbolId::~JfrSymbolId() {
    65   delete _sym_table;
    66   delete _cstring_table;
    67 }
    69 traceid JfrSymbolId::mark_anonymous_klass_name(const Klass* k) {
    70   assert(k != NULL, "invariant");
    71   assert(k->oop_is_instance(), "invariant");
    72   assert(is_anonymous_klass(k), "invariant");
    74   uintptr_t anonymous_symbol_hash_code = 0;
    75   const char* const anonymous_symbol =
    76     create_anonymous_klass_symbol((const InstanceKlass*)k, anonymous_symbol_hash_code);
    78   if (anonymous_symbol == NULL) {
    79     return 0;
    80   }
    82   assert(anonymous_symbol_hash_code != 0, "invariant");
    83   traceid symbol_id = mark(anonymous_symbol, anonymous_symbol_hash_code);
    84   assert(mark(anonymous_symbol, anonymous_symbol_hash_code) == symbol_id, "invariant");
    85   return symbol_id;
    86 }
    88 const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(const Symbol* symbol) const {
    89   return _sym_table->lookup_only(symbol, (uintptr_t)const_cast<Symbol*>(symbol)->identity_hash());
    90 }
    92 const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(uintptr_t hash) const {
    93   return _sym_table->lookup_only(NULL, hash);
    94 }
    96 const JfrSymbolId::CStringEntry* JfrSymbolId::map_cstring(uintptr_t hash) const {
    97   return _cstring_table->lookup_only(NULL, hash);
    98 }
   100 void JfrSymbolId::assign_id(SymbolEntry* entry) {
   101   assert(entry != NULL, "invariant");
   102   assert(entry->id() == 0, "invariant");
   103   entry->set_id(++_symbol_id_counter);
   104 }
   106 bool JfrSymbolId::equals(const Symbol* query, uintptr_t hash, const SymbolEntry* entry) {
   107   // query might be NULL
   108   assert(entry != NULL, "invariant");
   109   assert(entry->hash() == hash, "invariant");
   110   return true;
   111 }
   113 void JfrSymbolId::assign_id(CStringEntry* entry) {
   114   assert(entry != NULL, "invariant");
   115   assert(entry->id() == 0, "invariant");
   116   entry->set_id(++_symbol_id_counter);
   117 }
   119 bool JfrSymbolId::equals(const char* query, uintptr_t hash, const CStringEntry* entry) {
   120   // query might be NULL
   121   assert(entry != NULL, "invariant");
   122   assert(entry->hash() == hash, "invariant");
   123   return true;
   124 }
   126 traceid JfrSymbolId::mark(const Klass* k) {
   127   assert(k != NULL, "invariant");
   128   traceid symbol_id = 0;
   129   if (is_anonymous_klass(k)) {
   130     symbol_id = mark_anonymous_klass_name(k);
   131   }
   132   if (0 == symbol_id) {
   133     const Symbol* const sym = k->name();
   134     if (sym != NULL) {
   135       symbol_id = mark(sym);
   136     }
   137   }
   138   assert(symbol_id > 0, "a symbol handler must mark the symbol for writing");
   139   return symbol_id;
   140 }
   142 traceid JfrSymbolId::mark(const Symbol* symbol) {
   143   assert(symbol != NULL, "invariant");
   144   return mark(symbol, (uintptr_t)const_cast<Symbol*>(symbol)->identity_hash());
   145 }
   147 traceid JfrSymbolId::mark(const Symbol* data, uintptr_t hash) {
   148   assert(data != NULL, "invariant");
   149   assert(_sym_table != NULL, "invariant");
   150   return _sym_table->id(data, hash);
   151 }
   153 traceid JfrSymbolId::mark(const char* str, uintptr_t hash) {
   154   assert(str != NULL, "invariant");
   155   return _cstring_table->id(str, hash);
   156 }
   158 traceid JfrSymbolId::markPackage(const char* name, uintptr_t hash) {
   159   assert(name != NULL, "invariant");
   160   assert(_pkg_table != NULL, "invariant");
   161   return _pkg_table->id(name, hash);
   162 }
   164 bool JfrSymbolId::is_anonymous_klass(const Klass* k) {
   165   assert(k != NULL, "invariant");
   166   return k->oop_is_instance() && ((const InstanceKlass*)k)->is_anonymous();
   167 }
   169 /*
   170 * jsr292 anonymous classes symbol is the external name +
   171 * the identity_hashcode slash appended:
   172 *   java.lang.invoke.LambdaForm$BMH/22626602
   173 *
   174 * caller needs ResourceMark
   175 */
   177 uintptr_t JfrSymbolId::anonymous_klass_name_hash_code(const InstanceKlass* ik) {
   178   assert(ik != NULL, "invariant");
   179   assert(ik->is_anonymous(), "invariant");
   180   const oop mirror = ik->java_mirror();
   181   assert(mirror != NULL, "invariant");
   182   return (uintptr_t)mirror->identity_hash();
   183 }
   185 const char* JfrSymbolId::create_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode) {
   186   assert(ik != NULL, "invariant");
   187   assert(ik->is_anonymous(), "invariant");
   188   assert(0 == hashcode, "invariant");
   189   char* anonymous_symbol = NULL;
   190   const oop mirror = ik->java_mirror();
   191   assert(mirror != NULL, "invariant");
   192   char hash_buf[40];
   193   hashcode = anonymous_klass_name_hash_code(ik);
   194   sprintf(hash_buf, "/" UINTX_FORMAT, hashcode);
   195   const size_t hash_len = strlen(hash_buf);
   196   const size_t result_len = ik->name()->utf8_length();
   197   anonymous_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
   198   ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1);
   199   assert(strlen(anonymous_symbol) == result_len, "invariant");
   200   strcpy(anonymous_symbol + result_len, hash_buf);
   201   assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant");
   202   return anonymous_symbol;
   203 }
   205 uintptr_t JfrSymbolId::regular_klass_name_hash_code(const Klass* k) {
   206   assert(k != NULL, "invariant");
   207   const Symbol* const sym = k->name();
   208   assert(sym != NULL, "invariant");
   209   return (uintptr_t)const_cast<Symbol*>(sym)->identity_hash();
   210 }
   212 JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()),
   213                                                     _klass_list(NULL),
   214                                                     _class_unload(class_unload) {
   215   initialize(class_unload);
   216   assert(_klass_list != NULL, "invariant");
   217 }
   219 static const size_t initial_class_list_size = 200;
   220 void JfrArtifactSet::initialize(bool class_unload) {
   221   assert(_symbol_id != NULL, "invariant");
   222   _symbol_id->initialize();
   223   assert(!_symbol_id->has_entries(), "invariant");
   224   _symbol_id->mark(BOOTSTRAP_LOADER_NAME, 0); // pre-load "bootstrap"
   225   _class_unload = class_unload;
   226   // resource allocation
   227   _klass_list = new GrowableArray<const Klass*>(initial_class_list_size, false, mtTracing);
   228 }
   230 JfrArtifactSet::~JfrArtifactSet() {
   231   clear();
   232 }
   234 void JfrArtifactSet::clear() {
   235   _symbol_id->clear();
   236   // _klass_list will be cleared by a ResourceMark
   237 }
   239 traceid JfrArtifactSet::mark_anonymous_klass_name(const Klass* klass) {
   240   return _symbol_id->mark_anonymous_klass_name(klass);
   241 }
   243 traceid JfrArtifactSet::mark(const Symbol* sym, uintptr_t hash) {
   244   return _symbol_id->mark(sym, hash);
   245 }
   247 traceid JfrArtifactSet::mark(const Klass* klass) {
   248   return _symbol_id->mark(klass);
   249 }
   251 traceid JfrArtifactSet::mark(const Symbol* symbol) {
   252   return _symbol_id->mark(symbol);
   253 }
   255 traceid JfrArtifactSet::mark(const char* const str, uintptr_t hash) {
   256   return _symbol_id->mark(str, hash);
   257 }
   259 traceid JfrArtifactSet::markPackage(const char* const name, uintptr_t hash) {
   260   return _symbol_id->markPackage(name, hash);
   261 }
   263 const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(const Symbol* symbol) const {
   264   return _symbol_id->map_symbol(symbol);
   265 }
   267 const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(uintptr_t hash) const {
   268   return _symbol_id->map_symbol(hash);
   269 }
   271 const JfrSymbolId::CStringEntry* JfrArtifactSet::map_cstring(uintptr_t hash) const {
   272   return _symbol_id->map_cstring(hash);
   273 }
   275 bool JfrArtifactSet::has_klass_entries() const {
   276   return _klass_list->is_nonempty();
   277 }
   279 int JfrArtifactSet::entries() const {
   280   return _klass_list->length();
   281 }
   283 void JfrArtifactSet::register_klass(const Klass* k) {
   284   assert(k != NULL, "invariant");
   285   assert(_klass_list != NULL, "invariant");
   286   assert(_klass_list->find(k) == -1, "invariant");
   287   _klass_list->append(k);
   288 }

mercurial