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

Mon, 12 Aug 2019 18:30:40 +0300

author
apetushkov
date
Mon, 12 Aug 2019 18:30:40 +0300
changeset 9858
b985cbb00e68
child 9926
d20a5f399218
permissions
-rw-r--r--

8223147: JFR Backport
8199712: Flight Recorder
8203346: JFR: Inconsistent signature of jfr_add_string_constant
8195817: JFR.stop should require name of recording
8195818: JFR.start should increase autogenerated name by one
8195819: Remove recording=x from jcmd JFR.check output
8203921: JFR thread sampling is missing fixes from JDK-8194552
8203929: Limit amount of data for JFR.dump
8203664: JFR start failure after AppCDS archive created with JFR StartFlightRecording
8003209: JFR events for network utilization
8207392: [PPC64] Implement JFR profiling
8202835: jfr/event/os/TestSystemProcess.java fails on missing events
Summary: Backport JFR from JDK11. Initial integration
Reviewed-by: neugens

     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)), _cstring_table(new CStringTable(this)) {
    32   assert(_sym_table != NULL, "invariant");
    33   assert(_cstring_table != NULL, "invariant");
    34   initialize();
    35 }
    37 void JfrSymbolId::initialize() {
    38   clear();
    39   assert(_symbol_id_counter == 0, "invariant");
    40 }
    42 void JfrSymbolId::clear() {
    43   assert(_sym_table != NULL, "invariant");
    44   if (_sym_table->has_entries()) {
    45     _sym_table->clear_entries();
    46   }
    47   assert(!_sym_table->has_entries(), "invariant");
    49   assert(_cstring_table != NULL, "invariant");
    50   if (_cstring_table->has_entries()) {
    51     _cstring_table->clear_entries();
    52   }
    53   assert(!_cstring_table->has_entries(), "invariant");
    54   _symbol_id_counter = 0;
    55 }
    57 JfrSymbolId::~JfrSymbolId() {
    58   delete _sym_table;
    59   delete _cstring_table;
    60 }
    62 traceid JfrSymbolId::mark_anonymous_klass_name(const Klass* k) {
    63   assert(k != NULL, "invariant");
    64   assert(k->oop_is_instance(), "invariant");
    65   assert(is_anonymous_klass(k), "invariant");
    67   uintptr_t anonymous_symbol_hash_code = 0;
    68   const char* const anonymous_symbol =
    69     create_anonymous_klass_symbol((const InstanceKlass*)k, anonymous_symbol_hash_code);
    71   if (anonymous_symbol == NULL) {
    72     return 0;
    73   }
    75   assert(anonymous_symbol_hash_code != 0, "invariant");
    76   traceid symbol_id = mark(anonymous_symbol, anonymous_symbol_hash_code);
    77   assert(mark(anonymous_symbol, anonymous_symbol_hash_code) == symbol_id, "invariant");
    78   return symbol_id;
    79 }
    81 const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(const Symbol* symbol) const {
    82   return _sym_table->lookup_only(symbol, (uintptr_t)const_cast<Symbol*>(symbol)->identity_hash());
    83 }
    85 const JfrSymbolId::SymbolEntry* JfrSymbolId::map_symbol(uintptr_t hash) const {
    86   return _sym_table->lookup_only(NULL, hash);
    87 }
    89 const JfrSymbolId::CStringEntry* JfrSymbolId::map_cstring(uintptr_t hash) const {
    90   return _cstring_table->lookup_only(NULL, hash);
    91 }
    93 void JfrSymbolId::assign_id(SymbolEntry* entry) {
    94   assert(entry != NULL, "invariant");
    95   assert(entry->id() == 0, "invariant");
    96   entry->set_id(++_symbol_id_counter);
    97 }
    99 bool JfrSymbolId::equals(const Symbol* query, uintptr_t hash, const SymbolEntry* entry) {
   100   // query might be NULL
   101   assert(entry != NULL, "invariant");
   102   assert(entry->hash() == hash, "invariant");
   103   return true;
   104 }
   106 void JfrSymbolId::assign_id(CStringEntry* entry) {
   107   assert(entry != NULL, "invariant");
   108   assert(entry->id() == 0, "invariant");
   109   entry->set_id(++_symbol_id_counter);
   110 }
   112 bool JfrSymbolId::equals(const char* query, uintptr_t hash, const CStringEntry* entry) {
   113   // query might be NULL
   114   assert(entry != NULL, "invariant");
   115   assert(entry->hash() == hash, "invariant");
   116   return true;
   117 }
   119 traceid JfrSymbolId::mark(const Klass* k) {
   120   assert(k != NULL, "invariant");
   121   traceid symbol_id = 0;
   122   if (is_anonymous_klass(k)) {
   123     symbol_id = mark_anonymous_klass_name(k);
   124   }
   125   if (0 == symbol_id) {
   126     const Symbol* const sym = k->name();
   127     if (sym != NULL) {
   128       symbol_id = mark(sym);
   129     }
   130   }
   131   assert(symbol_id > 0, "a symbol handler must mark the symbol for writing");
   132   return symbol_id;
   133 }
   135 traceid JfrSymbolId::mark(const Symbol* symbol) {
   136   assert(symbol != NULL, "invariant");
   137   return mark(symbol, (uintptr_t)const_cast<Symbol*>(symbol)->identity_hash());
   138 }
   140 traceid JfrSymbolId::mark(const Symbol* data, uintptr_t hash) {
   141   assert(data != NULL, "invariant");
   142   assert(_sym_table != NULL, "invariant");
   143   return _sym_table->id(data, hash);
   144 }
   146 traceid JfrSymbolId::mark(const char* str, uintptr_t hash) {
   147   assert(str != NULL, "invariant");
   148   return _cstring_table->id(str, hash);
   149 }
   151 bool JfrSymbolId::is_anonymous_klass(const Klass* k) {
   152   assert(k != NULL, "invariant");
   153   return k->oop_is_instance() && ((const InstanceKlass*)k)->is_anonymous();
   154 }
   156 /*
   157 * jsr292 anonymous classes symbol is the external name +
   158 * the identity_hashcode slash appended:
   159 *   java.lang.invoke.LambdaForm$BMH/22626602
   160 *
   161 * caller needs ResourceMark
   162 */
   164 uintptr_t JfrSymbolId::anonymous_klass_name_hash_code(const InstanceKlass* ik) {
   165   assert(ik != NULL, "invariant");
   166   assert(ik->is_anonymous(), "invariant");
   167   const oop mirror = ik->java_mirror();
   168   assert(mirror != NULL, "invariant");
   169   return (uintptr_t)mirror->identity_hash();
   170 }
   172 const char* JfrSymbolId::create_anonymous_klass_symbol(const InstanceKlass* ik, uintptr_t& hashcode) {
   173   assert(ik != NULL, "invariant");
   174   assert(ik->is_anonymous(), "invariant");
   175   assert(0 == hashcode, "invariant");
   176   char* anonymous_symbol = NULL;
   177   const oop mirror = ik->java_mirror();
   178   assert(mirror != NULL, "invariant");
   179   char hash_buf[40];
   180   hashcode = anonymous_klass_name_hash_code(ik);
   181   sprintf(hash_buf, "/" UINTX_FORMAT, hashcode);
   182   const size_t hash_len = strlen(hash_buf);
   183   const size_t result_len = ik->name()->utf8_length();
   184   anonymous_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
   185   ik->name()->as_klass_external_name(anonymous_symbol, (int)result_len + 1);
   186   assert(strlen(anonymous_symbol) == result_len, "invariant");
   187   strcpy(anonymous_symbol + result_len, hash_buf);
   188   assert(strlen(anonymous_symbol) == result_len + hash_len, "invariant");
   189   return anonymous_symbol;
   190 }
   192 uintptr_t JfrSymbolId::regular_klass_name_hash_code(const Klass* k) {
   193   assert(k != NULL, "invariant");
   194   const Symbol* const sym = k->name();
   195   assert(sym != NULL, "invariant");
   196   return (uintptr_t)const_cast<Symbol*>(sym)->identity_hash();
   197 }
   199 JfrArtifactSet::JfrArtifactSet(bool class_unload) : _symbol_id(new JfrSymbolId()),
   200                                                     _klass_list(NULL),
   201                                                     _class_unload(class_unload) {
   202   initialize(class_unload);
   203   assert(_klass_list != NULL, "invariant");
   204 }
   206 static const size_t initial_class_list_size = 200;
   207 void JfrArtifactSet::initialize(bool class_unload) {
   208   assert(_symbol_id != NULL, "invariant");
   209   _symbol_id->initialize();
   210   assert(!_symbol_id->has_entries(), "invariant");
   211   _symbol_id->mark(BOOTSTRAP_LOADER_NAME, 0); // pre-load "bootstrap"
   212   _class_unload = class_unload;
   213   // resource allocation
   214   _klass_list = new GrowableArray<const Klass*>(initial_class_list_size, false, mtTracing);
   215 }
   217 JfrArtifactSet::~JfrArtifactSet() {
   218   clear();
   219 }
   221 void JfrArtifactSet::clear() {
   222   _symbol_id->clear();
   223   // _klass_list will be cleared by a ResourceMark
   224 }
   226 traceid JfrArtifactSet::mark_anonymous_klass_name(const Klass* klass) {
   227   return _symbol_id->mark_anonymous_klass_name(klass);
   228 }
   230 traceid JfrArtifactSet::mark(const Symbol* sym, uintptr_t hash) {
   231   return _symbol_id->mark(sym, hash);
   232 }
   234 traceid JfrArtifactSet::mark(const Klass* klass) {
   235   return _symbol_id->mark(klass);
   236 }
   238 traceid JfrArtifactSet::mark(const Symbol* symbol) {
   239   return _symbol_id->mark(symbol);
   240 }
   242 traceid JfrArtifactSet::mark(const char* const str, uintptr_t hash) {
   243   return _symbol_id->mark(str, hash);
   244 }
   246 const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(const Symbol* symbol) const {
   247   return _symbol_id->map_symbol(symbol);
   248 }
   250 const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(uintptr_t hash) const {
   251   return _symbol_id->map_symbol(hash);
   252 }
   254 const JfrSymbolId::CStringEntry* JfrArtifactSet::map_cstring(uintptr_t hash) const {
   255   return _symbol_id->map_cstring(hash);
   256 }
   258 bool JfrArtifactSet::has_klass_entries() const {
   259   return _klass_list->is_nonempty();
   260 }
   262 int JfrArtifactSet::entries() const {
   263   return _klass_list->length();
   264 }
   266 void JfrArtifactSet::register_klass(const Klass* k) {
   267   assert(k != NULL, "invariant");
   268   assert(_klass_list != NULL, "invariant");
   269   assert(_klass_list->find(k) == -1, "invariant");
   270   _klass_list->append(k);
   271 }

mercurial