Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/Java/Openjdk/src/hotspot/share/jfr/support/   (Sun/Oracle ©)  Datei vom 13.11.2022 mit Größe 9 kB image not shown  

Quelle  jfrSymbolTable.cpp   Sprache: C

 
/*
 * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */


#include "precompiled.hpp"
#include "classfile/javaClasses.inline.hpp"
#include "classfile/classLoaderData.hpp"
#include "jfr/support/jfrSymbolTable.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "runtime/mutexLocker.hpp"

// incremented on each rotation
static u8 checkpoint_id = 1;

// creates a unique id by combining a checkpoint relative symbol id (2^24)
// with the current checkpoint id (2^40)
#define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id)))

static traceid create_symbol_id(traceid artifact_id) {
  return artifact_id != 0 ? CREATE_SYMBOL_ID(artifact_id) : 0;
}

static uintptr_t string_hash(const char* str) {
  return java_lang_String::hash_code(reinterpret_cast<const jbyte*>(str), static_cast<int>(strlen(str)));
}

static JfrSymbolTable::StringEntry* bootstrap = NULL;

static JfrSymbolTable* _instance = NULL;

static JfrSymbolTable& instance() {
  assert(_instance != NULL, "invariant");
  return *_instance;
}

JfrSymbolTable* JfrSymbolTable::create() {
  assert(_instance == NULL, "invariant");
  assert_lock_strong(ClassLoaderDataGraph_lock);
  _instance = new JfrSymbolTable();
  return _instance;
}

void JfrSymbolTable::destroy() {
  assert_lock_strong(ClassLoaderDataGraph_lock);
  if (_instance != NULL) {
    delete _instance;
    _instance = NULL;
  }
  assert(_instance == NULL, "invariant");
}

JfrSymbolTable::JfrSymbolTable() :
  _symbols(new Symbols(this)),
  _strings(new Strings(this)),
  _symbol_list(NULL),
  _string_list(NULL),
  _symbol_query(NULL),
  _string_query(NULL),
  _id_counter(1),
  _class_unload(false) {
  assert(_symbols != NULL, "invariant");
  assert(_strings != NULL, "invariant");
  bootstrap = new StringEntry(0, (const char*)&BOOTSTRAP_LOADER_NAME);
  assert(bootstrap != NULL, "invariant");
  bootstrap->set_id(create_symbol_id(1));
  _string_list = bootstrap;
}

JfrSymbolTable::~JfrSymbolTable() {
  clear();
  delete _symbols;
  delete _strings;
  delete bootstrap;
}

void JfrSymbolTable::clear() {
  assert(_symbols != NULL, "invariant");
  if (_symbols->has_entries()) {
    _symbols->clear_entries();
  }
  assert(!_symbols->has_entries(), "invariant");

  assert(_strings != NULL, "invariant");
  if (_strings->has_entries()) {
    _strings->clear_entries();
  }
  assert(!_strings->has_entries(), "invariant");

  _symbol_list = NULL;
  _id_counter = 1;

  _symbol_query = NULL;
  _string_query = NULL;

  assert(bootstrap != NULL, "invariant");
  bootstrap->reset();
  _string_list = bootstrap;
}

void JfrSymbolTable::set_class_unload(bool class_unload) {
  _class_unload = class_unload;
}

void JfrSymbolTable::increment_checkpoint_id() {
  assert_lock_strong(ClassLoaderDataGraph_lock);
  clear();
  ++checkpoint_id;
}

template <typename T>
inline void JfrSymbolTable::assign_id(T* entry) {
  assert(entry != NULL, "invariant");
  assert(entry->id() == 0, "invariant");
  entry->set_id(create_symbol_id(++_id_counter));
}

void JfrSymbolTable::on_link(const SymbolEntry* entry) {
  assign_id(entry);
  const_cast<Symbol*>(entry->literal())->increment_refcount();
  entry->set_list_next(_symbol_list);
  _symbol_list = entry;
}

bool JfrSymbolTable::on_equals(uintptr_t hash, const SymbolEntry* entry) {
  assert(entry != NULL, "invariant");
  assert(entry->hash() == hash, "invariant");
  assert(_symbol_query != NULL, "invariant");
  return _symbol_query == entry->literal();
}

void JfrSymbolTable::on_unlink(const SymbolEntry* entry) {
  assert(entry != NULL, "invariant");
  const_cast<Symbol*>(entry->literal())->decrement_refcount();
}

static const char* resource_to_c_heap_string(const char* resource_str) {
  assert(resource_str != NULL, "invariant");
  const size_t length = strlen(resource_str);
  charconst c_string = JfrCHeapObj::new_array<char>(length + 1);
  assert(c_string != NULL, "invariant");
  strncpy(c_string, resource_str, length + 1);
  return c_string;
}

void JfrSymbolTable::on_link(const StringEntry* entry) {
  assign_id(entry);
  const_cast<StringEntry*>(entry)->set_literal(resource_to_c_heap_string(entry->literal()));
  entry->set_list_next(_string_list);
  _string_list = entry;
}

static bool string_compare(const char* query, const char* candidate) {
  assert(query != NULL, "invariant");
  assert(candidate != NULL, "invariant");
  const size_t length = strlen(query);
  return strncmp(query, candidate, length) == 0;
}

bool JfrSymbolTable::on_equals(uintptr_t hash, const StringEntry* entry) {
  assert(entry != NULL, "invariant");
  assert(entry->hash() == hash, "invariant");
  assert(_string_query != NULL, "invariant");
  return string_compare(_string_query, entry->literal());
}

void JfrSymbolTable::on_unlink(const StringEntry* entry) {
  assert(entry != NULL, "invariant");
  JfrCHeapObj::free(const_cast<char*>(entry->literal()), strlen(entry->literal() + 1));
}

traceid JfrSymbolTable::bootstrap_name(bool leakp) {
  assert(bootstrap != NULL, "invariant");
  if (leakp) {
    bootstrap->set_leakp();
  }
  return bootstrap->id();
}

traceid JfrSymbolTable::mark(const Symbol* sym, bool leakp /* false */) {
  assert(sym != NULL, "invariant");
  return mark((uintptr_t)sym->identity_hash(), sym, leakp);
}

traceid JfrSymbolTable::mark(uintptr_t hash, const Symbol* sym, bool leakp) {
  assert(sym != NULL, "invariant");
  assert(_symbols != NULL, "invariant");
  _symbol_query = sym;
  const SymbolEntry& entry = _symbols->lookup_put(hash, sym);
  if (_class_unload) {
    entry.set_unloading();
  }
  if (leakp) {
    entry.set_leakp();
  }
  return entry.id();
}

traceid JfrSymbolTable::mark(const char* str, bool leakp /* false*/) {
  return mark(string_hash(str), str, leakp);
}

traceid JfrSymbolTable::mark(uintptr_t hash, const char* str, bool leakp) {
  assert(str != NULL, "invariant");
  assert(_strings != NULL, "invariant");
  _string_query = str;
  const StringEntry& entry = _strings->lookup_put(hash, str);
  if (_class_unload) {
    entry.set_unloading();
  }
  if (leakp) {
    entry.set_leakp();
  }
  return entry.id();
}

/*
* hidden classes symbol is the external name +
* the address of its InstanceKlass slash appended:
*   java.lang.invoke.LambdaForm$BMH/22626602
*
* caller needs ResourceMark
*/


uintptr_t JfrSymbolTable::hidden_klass_name_hash(const InstanceKlass* ik) {
  assert(ik != NULL, "invariant");
  assert(ik->is_hidden(), "invariant");
  const oop mirror = ik->java_mirror_no_keepalive();
  assert(mirror != NULL, "invariant");
  return (uintptr_t)mirror->identity_hash();
}

static const char* create_hidden_klass_symbol(const InstanceKlass* ik, uintptr_t hash) {
  assert(ik != NULL, "invariant");
  assert(ik->is_hidden(), "invariant");
  assert(hash != 0, "invariant");
  char* hidden_symbol = NULL;
  const oop mirror = ik->java_mirror_no_keepalive();
  assert(mirror != NULL, "invariant");
  char hash_buf[40];
  sprintf(hash_buf, "/" UINTX_FORMAT, hash);
  const size_t hash_len = strlen(hash_buf);
  const size_t result_len = ik->name()->utf8_length();
  hidden_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1);
  ik->name()->as_klass_external_name(hidden_symbol, (int)result_len + 1);
  assert(strlen(hidden_symbol) == result_len, "invariant");
  strcpy(hidden_symbol + result_len, hash_buf);
  assert(strlen(hidden_symbol) == result_len + hash_len, "invariant");
  return hidden_symbol;
}

bool JfrSymbolTable::is_hidden_klass(const Klass* k) {
  assert(k != NULL, "invariant");
  return k->is_instance_klass() && ((const InstanceKlass*)k)->is_hidden();
}

traceid JfrSymbolTable::mark_hidden_klass_name(const InstanceKlass* ik, bool leakp) {
  assert(ik != NULL, "invariant");
  assert(ik->is_hidden(), "invariant");
  const uintptr_t hash = hidden_klass_name_hash(ik);
  const charconst hidden_symbol = create_hidden_klass_symbol(ik, hash);
  return mark(hash, hidden_symbol, leakp);
}

traceid JfrSymbolTable::mark(const Klass* k, bool leakp) {
  assert(k != NULL, "invariant");
  traceid symbol_id = 0;
  if (is_hidden_klass(k)) {
    assert(k->is_instance_klass(), "invariant");
    symbol_id = mark_hidden_klass_name((const InstanceKlass*)k, leakp);
  } else {
    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;
}

template <typename T>
traceid JfrSymbolTable::add_impl(const T* sym) {
  assert(sym != NULL, "invariant");
  assert(_instance != NULL, "invariant");
  assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
  return instance().mark(sym);
}

traceid JfrSymbolTable::add(const Symbol* sym) {
  return add_impl(sym);
}

traceid JfrSymbolTable::add(const char* str) {
  return add_impl(str);
}

Messung V0.5
C=94 H=90 G=91

¤ Dauer der Verarbeitung: 0.9 Sekunden  (vorverarbeitet)  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.