Merge

Mon, 29 Jun 2020 21:30:26 +0100

author
andrew
date
Mon, 29 Jun 2020 21:30:26 +0100
changeset 9949
fb74ae591209
parent 9948
ae4fc0906f45
parent 9930
1c6e1f187fdc
child 9950
f3ceb2e8bd21

Merge

.hgtags file | annotate | diff | comparison | revisions
src/share/vm/jfr/jni/jfrJavaSupport.cpp file | annotate | diff | comparison | revisions
src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.cpp file | annotate | diff | comparison | revisions
src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.hpp file | annotate | diff | comparison | revisions
src/share/vm/runtime/thread.cpp file | annotate | diff | comparison | revisions
     1.1 --- a/.hgtags	Mon Apr 11 08:51:53 2016 +0200
     1.2 +++ b/.hgtags	Mon Jun 29 21:30:26 2020 +0100
     1.3 @@ -1313,3 +1313,6 @@
     1.4  f7691a80458c365b5dd754b1e117818144ed30f1 jdk8u262-b05
     1.5  f7691a80458c365b5dd754b1e117818144ed30f1 jdk8u272-b00
     1.6  de6565b66f9458fb97eb66483e48f159b3f39d36 jdk8u262-b06
     1.7 +d20a5f399218f58f82f4f4503d24957ce7e48e60 jdk8u262-b07
     1.8 +d2c2cd90513e48822648ff16016aa76577eb7ab1 jdk8u262-b08
     1.9 +cf6e3496e19a2957f7d8b28bd0a033cefbf6509f jdk8u262-b09
     2.1 --- a/src/share/vm/classfile/classLoader.cpp	Mon Apr 11 08:51:53 2016 +0200
     2.2 +++ b/src/share/vm/classfile/classLoader.cpp	Mon Jun 29 21:30:26 2020 +0100
     2.3 @@ -162,6 +162,64 @@
     2.4    return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0);
     2.5  }
     2.6  
     2.7 +// Used to obtain the package name from a fully qualified class name.
     2.8 +// It is the responsibility of the caller to establish a ResourceMark.
     2.9 +const char* ClassLoader::package_from_name(const char* const class_name, bool* bad_class_name) {
    2.10 +  if (class_name == NULL) {
    2.11 +    if (bad_class_name != NULL) {
    2.12 +      *bad_class_name = true;
    2.13 +    }
    2.14 +    return NULL;
    2.15 +  }
    2.16 +
    2.17 +  if (bad_class_name != NULL) {
    2.18 +    *bad_class_name = false;
    2.19 +  }
    2.20 +
    2.21 +  const char* const last_slash = strrchr(class_name, '/');
    2.22 +  if (last_slash == NULL) {
    2.23 +    // No package name
    2.24 +    return NULL;
    2.25 +  }
    2.26 +
    2.27 +  char* class_name_ptr = (char*) class_name;
    2.28 +  // Skip over '['s
    2.29 +  if (*class_name_ptr == '[') {
    2.30 +    do {
    2.31 +      class_name_ptr++;
    2.32 +    } while (*class_name_ptr == '[');
    2.33 +
    2.34 +    // Fully qualified class names should not contain a 'L'.
    2.35 +    // Set bad_class_name to true to indicate that the package name
    2.36 +    // could not be obtained due to an error condition.
    2.37 +    // In this situation, is_same_class_package returns false.
    2.38 +    if (*class_name_ptr == 'L') {
    2.39 +      if (bad_class_name != NULL) {
    2.40 +        *bad_class_name = true;
    2.41 +      }
    2.42 +      return NULL;
    2.43 +    }
    2.44 +  }
    2.45 +
    2.46 +  int length = last_slash - class_name_ptr;
    2.47 +
    2.48 +  // A class name could have just the slash character in the name.
    2.49 +  if (length <= 0) {
    2.50 +    // No package name
    2.51 +    if (bad_class_name != NULL) {
    2.52 +      *bad_class_name = true;
    2.53 +    }
    2.54 +    return NULL;
    2.55 +  }
    2.56 +
    2.57 +  // drop name after last slash (including slash)
    2.58 +  // Ex., "java/lang/String.class" => "java/lang"
    2.59 +  char* pkg_name = NEW_RESOURCE_ARRAY(char, length + 1);
    2.60 +  strncpy(pkg_name, class_name_ptr, length);
    2.61 +  *(pkg_name+length) = '\0';
    2.62 +
    2.63 +  return (const char *)pkg_name;
    2.64 +}
    2.65  
    2.66  MetaIndex::MetaIndex(char** meta_package_names, int num_meta_package_names) {
    2.67    if (num_meta_package_names == 0) {
     3.1 --- a/src/share/vm/classfile/classLoader.hpp	Mon Apr 11 08:51:53 2016 +0200
     3.2 +++ b/src/share/vm/classfile/classLoader.hpp	Mon Jun 29 21:30:26 2020 +0100
     3.3 @@ -366,6 +366,11 @@
     3.4    // creates a class path zip entry (returns NULL if JAR file cannot be opened)
     3.5    static ClassPathZipEntry* create_class_path_zip_entry(const char *apath);
     3.6  
     3.7 +  // obtain package name from a fully qualified class name
     3.8 +  // *bad_class_name is set to true if there's a problem with parsing class_name, to
     3.9 +  // distinguish from a class_name with no package name, as both cases have a NULL return value
    3.10 +  static const char* package_from_name(const char* const class_name, bool* bad_class_name = NULL);
    3.11 +
    3.12    // Debugging
    3.13    static void verify()              PRODUCT_RETURN;
    3.14  
     4.1 --- a/src/share/vm/jfr/recorder/checkpoint/jfrCheckpointManager.cpp	Mon Apr 11 08:51:53 2016 +0200
     4.2 +++ b/src/share/vm/jfr/recorder/checkpoint/jfrCheckpointManager.cpp	Mon Jun 29 21:30:26 2020 +0100
     4.3 @@ -1,5 +1,5 @@
     4.4  /*
     4.5 - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
     4.6 + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
     4.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4.8   *
     4.9   * This code is free software; you can redistribute it and/or modify it
    4.10 @@ -135,6 +135,8 @@
    4.11  
    4.12  void JfrCheckpointManager::register_full(BufferPtr t, Thread* thread) {
    4.13    // nothing here at the moment
    4.14 +  assert(t != NULL, "invariant");
    4.15 +  assert(t->acquired_by(thread), "invariant");
    4.16    assert(t->retired(), "invariant");
    4.17  }
    4.18  
     5.1 --- a/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.cpp	Mon Apr 11 08:51:53 2016 +0200
     5.2 +++ b/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.cpp	Mon Jun 29 21:30:26 2020 +0100
     5.3 @@ -51,6 +51,7 @@
     5.4  // creates a unique id by combining a checkpoint relative symbol id (2^24)
     5.5  // with the current checkpoint id (2^40)
     5.6  #define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id)))
     5.7 +#define CREATE_PACKAGE_ID(pkg_id) (((u8)((checkpoint_id << 24) | pkg_id)))
     5.8  
     5.9  typedef const Klass* KlassPtr;
    5.10  typedef const ClassLoaderData* CldPtr;
    5.11 @@ -59,6 +60,24 @@
    5.12  typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr;
    5.13  typedef const JfrSymbolId::CStringEntry* CStringEntryPtr;
    5.14  
    5.15 +inline uintptr_t package_name_hash(const char *s) {
    5.16 +  uintptr_t val = 0;
    5.17 +  while (*s != 0) {
    5.18 +    val = *s++ + 31 * val;
    5.19 +  }
    5.20 +  return val;
    5.21 +}
    5.22 +
    5.23 +static traceid package_id(KlassPtr klass, JfrArtifactSet* artifacts) {
    5.24 +  assert(klass != NULL, "invariant");
    5.25 +  char* klass_name = klass->name()->as_C_string(); // uses ResourceMark declared in JfrTypeSet::serialize()
    5.26 +  const char* pkg_name = ClassLoader::package_from_name(klass_name, NULL);
    5.27 +  if (pkg_name == NULL) {
    5.28 +    return 0;
    5.29 +  }
    5.30 +  return CREATE_PACKAGE_ID(artifacts->markPackage(pkg_name, package_name_hash(pkg_name)));
    5.31 +}
    5.32 +
    5.33  static traceid cld_id(CldPtr cld) {
    5.34    assert(cld != NULL, "invariant");
    5.35    return cld->is_anonymous() ? 0 : TRACE_ID(cld);
    5.36 @@ -111,7 +130,7 @@
    5.37      theklass = obj_arr_klass->bottom_klass();
    5.38    }
    5.39    if (theklass->oop_is_instance()) {
    5.40 -    pkg_id = 0;
    5.41 +    pkg_id = package_id(theklass, artifacts);
    5.42    } else {
    5.43      assert(theklass->oop_is_typeArray(), "invariant");
    5.44    }
    5.45 @@ -155,6 +174,20 @@
    5.46  typedef JfrArtifactWriterImplHost<MethodPtr, write__artifact__method> MethodWriterImplTarget;
    5.47  typedef JfrArtifactWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl;
    5.48  
    5.49 +int write__artifact__package(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* p) {
    5.50 +  assert(writer != NULL, "invariant");
    5.51 +  assert(artifacts != NULL, "invariant");
    5.52 +  assert(p != NULL, "invariant");
    5.53 +
    5.54 +  CStringEntryPtr entry = (CStringEntryPtr)p;
    5.55 +  const traceid package_name_symbol_id = artifacts->mark(entry->value(), package_name_hash(entry->value()));
    5.56 +  assert(package_name_symbol_id > 0, "invariant");
    5.57 +  writer->write((traceid)CREATE_PACKAGE_ID(entry->id()));
    5.58 +  writer->write((traceid)CREATE_SYMBOL_ID(package_name_symbol_id));
    5.59 +  writer->write((bool)true); // exported
    5.60 +  return 1;
    5.61 +}
    5.62 +
    5.63  int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) {
    5.64    assert(c != NULL, "invariant");
    5.65    CldPtr cld = (CldPtr)c;
    5.66 @@ -436,6 +469,18 @@
    5.67    do_klasses();
    5.68  }
    5.69  
    5.70 +typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__package> PackageEntryWriterImpl;
    5.71 +typedef JfrArtifactWriterHost<PackageEntryWriterImpl, TYPE_PACKAGE> PackageEntryWriter;
    5.72 +
    5.73 +void JfrTypeSet::write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) {
    5.74 +  assert(_artifacts->has_klass_entries(), "invariant");
    5.75 +  assert(writer != NULL, "invariant");
    5.76 +  // below jdk9 there is no oop for packages, so nothing to do with leakp_writer
    5.77 +  // just write packages
    5.78 +  PackageEntryWriter pw(writer, _artifacts, _class_unload);
    5.79 +  _artifacts->iterate_packages(pw);
    5.80 +}
    5.81 +
    5.82  typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear;
    5.83  typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter;
    5.84  typedef CompositeFunctor<CldPtr, CompositeCldWriter, ClearArtifact<CldPtr> > CompositeCldWriterWithClear;
    5.85 @@ -685,6 +730,7 @@
    5.86    // might tag an artifact to be written in a subsequent step
    5.87    write_klass_constants(writer, leakp_writer);
    5.88    if (_artifacts->has_klass_entries()) {
    5.89 +    write_package_constants(writer, leakp_writer);
    5.90      write_class_loader_constants(writer, leakp_writer);
    5.91      write_method_constants(writer, leakp_writer);
    5.92      write_symbol_constants(writer, leakp_writer);
     6.1 --- a/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.hpp	Mon Apr 11 08:51:53 2016 +0200
     6.2 +++ b/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.hpp	Mon Jun 29 21:30:26 2020 +0100
     6.3 @@ -51,6 +51,7 @@
     6.4    static void do_class_loaders();
     6.5  
     6.6    static void write_klass_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer);
     6.7 +  static void write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer);
     6.8    static void write_class_loader_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer);
     6.9    static void write_method_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer);
    6.10    static void write_symbol_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer);
     7.1 --- a/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp	Mon Apr 11 08:51:53 2016 +0200
     7.2 +++ b/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp	Mon Jun 29 21:30:26 2020 +0100
     7.3 @@ -28,9 +28,11 @@
     7.4  #include "oops/oop.inline.hpp"
     7.5  #include "oops/symbol.hpp"
     7.6  
     7.7 -JfrSymbolId::JfrSymbolId() : _symbol_id_counter(0), _sym_table(new SymbolTable(this)), _cstring_table(new CStringTable(this)) {
     7.8 +JfrSymbolId::JfrSymbolId() : _symbol_id_counter(0), _sym_table(new SymbolTable(this)),
     7.9 +        _cstring_table(new CStringTable(this)), _pkg_table(new CStringTable(this)) {
    7.10    assert(_sym_table != NULL, "invariant");
    7.11    assert(_cstring_table != NULL, "invariant");
    7.12 +  assert(_pkg_table != NULL, "invariant");
    7.13    initialize();
    7.14  }
    7.15  
    7.16 @@ -52,6 +54,11 @@
    7.17    }
    7.18    assert(!_cstring_table->has_entries(), "invariant");
    7.19    _symbol_id_counter = 0;
    7.20 +  assert(_pkg_table != NULL, "invariant");
    7.21 +  if (_pkg_table->has_entries()) {
    7.22 +    _pkg_table->clear_entries();
    7.23 +  }
    7.24 +  assert(!_pkg_table->has_entries(), "invariant");
    7.25  }
    7.26  
    7.27  JfrSymbolId::~JfrSymbolId() {
    7.28 @@ -148,6 +155,12 @@
    7.29    return _cstring_table->id(str, hash);
    7.30  }
    7.31  
    7.32 +traceid JfrSymbolId::markPackage(const char* name, uintptr_t hash) {
    7.33 +  assert(name != NULL, "invariant");
    7.34 +  assert(_pkg_table != NULL, "invariant");
    7.35 +  return _pkg_table->id(name, hash);
    7.36 +}
    7.37 +
    7.38  bool JfrSymbolId::is_anonymous_klass(const Klass* k) {
    7.39    assert(k != NULL, "invariant");
    7.40    return k->oop_is_instance() && ((const InstanceKlass*)k)->is_anonymous();
    7.41 @@ -243,6 +256,10 @@
    7.42    return _symbol_id->mark(str, hash);
    7.43  }
    7.44  
    7.45 +traceid JfrArtifactSet::markPackage(const char* const name, uintptr_t hash) {
    7.46 +  return _symbol_id->markPackage(name, hash);
    7.47 +}
    7.48 +
    7.49  const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(const Symbol* symbol) const {
    7.50    return _symbol_id->map_symbol(symbol);
    7.51  }
     8.1 --- a/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp	Mon Apr 11 08:51:53 2016 +0200
     8.2 +++ b/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp	Mon Jun 29 21:30:26 2020 +0100
     8.3 @@ -230,9 +230,10 @@
     8.4    typedef SymbolTable::HashEntry SymbolEntry;
     8.5    typedef CStringTable::HashEntry CStringEntry;
     8.6   private:
     8.7 +  traceid _symbol_id_counter;
     8.8    SymbolTable* _sym_table;
     8.9    CStringTable* _cstring_table;
    8.10 -  traceid _symbol_id_counter;
    8.11 +  CStringTable* _pkg_table;
    8.12  
    8.13    // hashtable(s) callbacks
    8.14    void assign_id(SymbolEntry* entry);
    8.15 @@ -257,6 +258,12 @@
    8.16    traceid mark(const Klass* k);
    8.17    traceid mark(const Symbol* symbol);
    8.18    traceid mark(const char* str, uintptr_t hash);
    8.19 +  traceid markPackage(const char* name, uintptr_t hash);
    8.20 +
    8.21 +  template <typename T>
    8.22 +  void iterate_packages(T& functor) {
    8.23 +    _pkg_table->iterate_entry(functor);
    8.24 +  }
    8.25  
    8.26    const SymbolEntry* map_symbol(const Symbol* symbol) const;
    8.27    const SymbolEntry* map_symbol(uintptr_t hash) const;
    8.28 @@ -334,6 +341,8 @@
    8.29    traceid mark(const char* const str, uintptr_t hash);
    8.30    traceid mark_anonymous_klass_name(const Klass* klass);
    8.31  
    8.32 +  traceid markPackage(const char* const name, uintptr_t hash);
    8.33 +
    8.34    const JfrSymbolId::SymbolEntry* map_symbol(const Symbol* symbol) const;
    8.35    const JfrSymbolId::SymbolEntry* map_symbol(uintptr_t hash) const;
    8.36    const JfrSymbolId::CStringEntry* map_cstring(uintptr_t hash) const;
    8.37 @@ -360,6 +369,11 @@
    8.38    void iterate_cstrings(T& functor) {
    8.39      _symbol_id->iterate_cstrings(functor);
    8.40    }
    8.41 +
    8.42 +  template <typename T>
    8.43 +  void iterate_packages(T& functor) {
    8.44 +    _symbol_id->iterate_packages(functor);
    8.45 +  }
    8.46  };
    8.47  
    8.48  class KlassArtifactRegistrator {
     9.1 --- a/src/share/vm/jfr/recorder/storage/jfrBuffer.cpp	Mon Apr 11 08:51:53 2016 +0200
     9.2 +++ b/src/share/vm/jfr/recorder/storage/jfrBuffer.cpp	Mon Jun 29 21:30:26 2020 +0100
     9.3 @@ -1,5 +1,5 @@
     9.4  /*
     9.5 - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
     9.6 + * Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved.
     9.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     9.8   *
     9.9   * This code is free software; you can redistribute it and/or modify it
    9.10 @@ -137,6 +137,14 @@
    9.11    _identity = NULL;
    9.12  }
    9.13  
    9.14 +bool JfrBuffer::acquired_by(const void* id) const {
    9.15 +  return identity() == id;
    9.16 +}
    9.17 +
    9.18 +bool JfrBuffer::acquired_by_self() const {
    9.19 +  return acquired_by(Thread::current());
    9.20 +}
    9.21 +
    9.22  #ifdef ASSERT
    9.23  static bool validate_to(const JfrBuffer* const to, size_t size) {
    9.24    assert(to != NULL, "invariant");
    9.25 @@ -154,10 +162,6 @@
    9.26    assert(t->top() + size <= t->pos(), "invariant");
    9.27    return true;
    9.28  }
    9.29 -
    9.30 -bool JfrBuffer::acquired_by_self() const {
    9.31 -  return identity() == Thread::current();
    9.32 -}
    9.33  #endif // ASSERT
    9.34  
    9.35  void JfrBuffer::move(JfrBuffer* const to, size_t size) {
    9.36 @@ -184,7 +188,6 @@
    9.37    set_concurrent_top(start());
    9.38  }
    9.39  
    9.40 -// flags
    9.41  enum FLAG {
    9.42    RETIRED = 1,
    9.43    TRANSIENT = 2,
    10.1 --- a/src/share/vm/jfr/recorder/storage/jfrBuffer.hpp	Mon Apr 11 08:51:53 2016 +0200
    10.2 +++ b/src/share/vm/jfr/recorder/storage/jfrBuffer.hpp	Mon Jun 29 21:30:26 2020 +0100
    10.3 @@ -57,7 +57,6 @@
    10.4    u4 _size;
    10.5  
    10.6    const u1* stable_top() const;
    10.7 -  void clear_flags();
    10.8  
    10.9   public:
   10.10    JfrBuffer();
   10.11 @@ -150,6 +149,8 @@
   10.12  
   10.13    void acquire(const void* id);
   10.14    bool try_acquire(const void* id);
   10.15 +  bool acquired_by(const void* id) const;
   10.16 +  bool acquired_by_self() const;
   10.17    void release();
   10.18  
   10.19    void move(JfrBuffer* const to, size_t size);
   10.20 @@ -166,8 +167,6 @@
   10.21    bool retired() const;
   10.22    void set_retired();
   10.23    void clear_retired();
   10.24 -
   10.25 -  debug_only(bool acquired_by_self() const;)
   10.26  };
   10.27  
   10.28  class JfrAgeNode : public JfrBuffer {
    11.1 --- a/src/share/vm/jfr/recorder/storage/jfrMemorySpace.inline.hpp	Mon Apr 11 08:51:53 2016 +0200
    11.2 +++ b/src/share/vm/jfr/recorder/storage/jfrMemorySpace.inline.hpp	Mon Jun 29 21:30:26 2020 +0100
    11.3 @@ -346,19 +346,19 @@
    11.4  template <typename Mspace>
    11.5  inline bool ReleaseOp<Mspace>::process(typename Mspace::Type* t) {
    11.6    assert(t != NULL, "invariant");
    11.7 -  if (t->retired() || t->try_acquire(_thread)) {
    11.8 -    if (t->transient()) {
    11.9 -      if (_release_full) {
   11.10 -        mspace_release_full_critical(t, _mspace);
   11.11 -      } else {
   11.12 -        mspace_release_free_critical(t, _mspace);
   11.13 -      }
   11.14 -      return true;
   11.15 +  // assumes some means of exclusive access to t
   11.16 +  if (t->transient()) {
   11.17 +    if (_release_full) {
   11.18 +      mspace_release_full_critical(t, _mspace);
   11.19 +    } else {
   11.20 +      mspace_release_free_critical(t, _mspace);
   11.21      }
   11.22 -    t->reinitialize();
   11.23 -    assert(t->empty(), "invariant");
   11.24 -    t->release(); // publish
   11.25 +    return true;
   11.26    }
   11.27 +  t->reinitialize();
   11.28 +  assert(t->empty(), "invariant");
   11.29 +  assert(!t->retired(), "invariant");
   11.30 +  t->release(); // publish
   11.31    return true;
   11.32  }
   11.33  
    12.1 --- a/src/share/vm/jfr/recorder/storage/jfrStorage.cpp	Mon Apr 11 08:51:53 2016 +0200
    12.2 +++ b/src/share/vm/jfr/recorder/storage/jfrStorage.cpp	Mon Jun 29 21:30:26 2020 +0100
    12.3 @@ -340,9 +340,9 @@
    12.4  void JfrStorage::register_full(BufferPtr buffer, Thread* thread) {
    12.5    assert(buffer != NULL, "invariant");
    12.6    assert(buffer->retired(), "invariant");
    12.7 +  assert(buffer->acquired_by(thread), "invariant");
    12.8    if (!full_buffer_registration(buffer, _age_mspace, control(), thread)) {
    12.9      handle_registration_failure(buffer);
   12.10 -    buffer->release();
   12.11    }
   12.12    if (control().should_post_buffer_full_message()) {
   12.13      _post_box.post(MSG_FULLBUFFER);
   12.14 @@ -377,8 +377,8 @@
   12.15      }
   12.16    }
   12.17    assert(buffer->empty(), "invariant");
   12.18 +  assert(buffer->identity() != NULL, "invariant");
   12.19    control().increment_dead();
   12.20 -  buffer->release();
   12.21    buffer->set_retired();
   12.22  }
   12.23  
   12.24 @@ -733,13 +733,14 @@
   12.25    Scavenger(JfrStorageControl& control, Mspace* mspace) : _control(control), _mspace(mspace), _count(0), _amount(0) {}
   12.26    bool process(Type* t) {
   12.27      if (t->retired()) {
   12.28 +      assert(t->identity() != NULL, "invariant");
   12.29 +      assert(t->empty(), "invariant");
   12.30        assert(!t->transient(), "invariant");
   12.31        assert(!t->lease(), "invariant");
   12.32 -      assert(t->empty(), "invariant");
   12.33 -      assert(t->identity() == NULL, "invariant");
   12.34        ++_count;
   12.35        _amount += t->total_size();
   12.36        t->clear_retired();
   12.37 +      t->release();
   12.38        _control.decrement_dead();
   12.39        mspace_release_full_critical(t, _mspace);
   12.40      }
    13.1 --- a/src/share/vm/jfr/recorder/storage/jfrStorageUtils.hpp	Mon Apr 11 08:51:53 2016 +0200
    13.2 +++ b/src/share/vm/jfr/recorder/storage/jfrStorageUtils.hpp	Mon Jun 29 21:30:26 2020 +0100
    13.3 @@ -92,7 +92,6 @@
    13.4    size_t processed() const { return ConcurrentWriteOp<Operation>::processed(); }
    13.5  };
    13.6  
    13.7 -
    13.8  template <typename Operation>
    13.9  class MutexedWriteOp {
   13.10   private:
   13.11 @@ -104,6 +103,15 @@
   13.12    size_t processed() const { return _operation.processed(); }
   13.13  };
   13.14  
   13.15 +template <typename Operation>
   13.16 +class ExclusiveOp : private MutexedWriteOp<Operation> {
   13.17 + public:
   13.18 +  typedef typename Operation::Type Type;
   13.19 +  ExclusiveOp(Operation& operation) : MutexedWriteOp<Operation>(operation) {}
   13.20 +  bool process(Type* t);
   13.21 +  size_t processed() const { return MutexedWriteOp<Operation>::processed(); }
   13.22 +};
   13.23 +
   13.24  enum jfr_operation_mode {
   13.25    mutexed = 1,
   13.26    concurrent
    14.1 --- a/src/share/vm/jfr/recorder/storage/jfrStorageUtils.inline.hpp	Mon Apr 11 08:51:53 2016 +0200
    14.2 +++ b/src/share/vm/jfr/recorder/storage/jfrStorageUtils.inline.hpp	Mon Jun 29 21:30:26 2020 +0100
    14.3 @@ -26,6 +26,7 @@
    14.4  #define SHARE_VM_JFR_RECORDER_STORAGE_JFRSTORAGEUTILS_INLINE_HPP
    14.5  
    14.6  #include "jfr/recorder/storage/jfrStorageUtils.hpp"
    14.7 +#include "runtime/thread.inline.hpp"
    14.8  
    14.9  template <typename T>
   14.10  inline bool UnBufferedWriteToChunk<T>::write(T* t, const u1* data, size_t size) {
   14.11 @@ -75,6 +76,28 @@
   14.12    return result;
   14.13  }
   14.14  
   14.15 +template <typename Type>
   14.16 +static void retired_sensitive_acquire(Type* t) {
   14.17 +  assert(t != NULL, "invariant");
   14.18 +  if (t->retired()) {
   14.19 +    return;
   14.20 +  }
   14.21 +  Thread* const thread = Thread::current();
   14.22 +  while (!t->try_acquire(thread)) {
   14.23 +    if (t->retired()) {
   14.24 +      return;
   14.25 +    }
   14.26 +  }
   14.27 +}
   14.28 +
   14.29 +template <typename Operation>
   14.30 +inline bool ExclusiveOp<Operation>::process(typename Operation::Type* t) {
   14.31 +  retired_sensitive_acquire(t);
   14.32 +  assert(t->acquired_by_self() || t->retired(), "invariant");
   14.33 +  // User is required to ensure proper release of the acquisition
   14.34 +  return MutexedWriteOp<Operation>::process(t);
   14.35 +}
   14.36 +
   14.37  template <typename Operation>
   14.38  inline bool DiscardOp<Operation>::process(typename Operation::Type* t) {
   14.39    assert(t != NULL, "invariant");
    15.1 --- a/src/share/vm/jfr/recorder/stringpool/jfrStringPool.cpp	Mon Apr 11 08:51:53 2016 +0200
    15.2 +++ b/src/share/vm/jfr/recorder/stringpool/jfrStringPool.cpp	Mon Jun 29 21:30:26 2020 +0100
    15.3 @@ -1,5 +1,5 @@
    15.4  /*
    15.5 - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
    15.6 + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
    15.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    15.8   *
    15.9   * This code is free software; you can redistribute it and/or modify it
   15.10 @@ -139,93 +139,76 @@
   15.11    return current_epoch;
   15.12  }
   15.13  
   15.14 -class StringPoolWriteOp  {
   15.15 +template <template <typename> class Operation>
   15.16 +class StringPoolOp {
   15.17   public:
   15.18    typedef JfrStringPoolBuffer Type;
   15.19   private:
   15.20 -  UnBufferedWriteToChunk<Type> _writer;
   15.21 +  Operation<Type> _op;
   15.22    Thread* _thread;
   15.23    size_t _strings_processed;
   15.24   public:
   15.25 -  StringPoolWriteOp(JfrChunkWriter& writer, Thread* thread) : _writer(writer), _thread(thread), _strings_processed(0) {}
   15.26 +  StringPoolOp() : _op(), _thread(Thread::current()), _strings_processed(0) {}
   15.27 +  StringPoolOp(JfrChunkWriter& writer, Thread* thread) : _op(writer), _thread(thread), _strings_processed(0) {}
   15.28    bool write(Type* buffer, const u1* data, size_t size) {
   15.29 -    buffer->acquire(_thread); // blocking
   15.30 +    assert(buffer->acquired_by(_thread) || buffer->retired(), "invariant");
   15.31      const uint64_t nof_strings_used = buffer->string_count();
   15.32      assert(nof_strings_used > 0, "invariant");
   15.33      buffer->set_string_top(buffer->string_top() + nof_strings_used);
   15.34      // "size processed" for string pool buffers is the number of processed string elements
   15.35      _strings_processed += nof_strings_used;
   15.36 -    const bool ret = _writer.write(buffer, data, size);
   15.37 -    buffer->release();
   15.38 -    return ret;
   15.39 +    return _op.write(buffer, data, size);
   15.40    }
   15.41    size_t processed() { return _strings_processed; }
   15.42  };
   15.43  
   15.44 -typedef StringPoolWriteOp WriteOperation;
   15.45 -typedef ConcurrentWriteOp<WriteOperation> ConcurrentWriteOperation;
   15.46 +template <typename Type>
   15.47 +class StringPoolDiscarderStub {
   15.48 + public:
   15.49 +  bool write(Type* buffer, const u1* data, size_t size) {
   15.50 +    // stub only, discard happens at higher level
   15.51 +    return true;
   15.52 +  }
   15.53 +};
   15.54 +
   15.55 +typedef StringPoolOp<UnBufferedWriteToChunk> WriteOperation;
   15.56 +typedef StringPoolOp<StringPoolDiscarderStub> DiscardOperation;
   15.57 +typedef ExclusiveOp<WriteOperation> ExclusiveWriteOperation;
   15.58 +typedef ExclusiveOp<DiscardOperation> ExclusiveDiscardOperation;
   15.59 +typedef ReleaseOp<JfrStringPoolMspace> StringPoolReleaseOperation;
   15.60 +typedef CompositeOperation<ExclusiveWriteOperation, StringPoolReleaseOperation> StringPoolWriteOperation;
   15.61 +typedef CompositeOperation<ExclusiveDiscardOperation, StringPoolReleaseOperation> StringPoolDiscardOperation;
   15.62  
   15.63  size_t JfrStringPool::write() {
   15.64    Thread* const thread = Thread::current();
   15.65    WriteOperation wo(_chunkwriter, thread);
   15.66 -  ConcurrentWriteOperation cwo(wo);
   15.67 -  assert(_free_list_mspace->is_full_empty(), "invariant");
   15.68 -  process_free_list(cwo, _free_list_mspace);
   15.69 -  return wo.processed();
   15.70 -}
   15.71 -
   15.72 -typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
   15.73 -typedef ReleaseOp<JfrStringPoolMspace> StringPoolReleaseOperation;
   15.74 -typedef CompositeOperation<MutexedWriteOperation, StringPoolReleaseOperation> StringPoolWriteOperation;
   15.75 -
   15.76 -size_t JfrStringPool::write_at_safepoint() {
   15.77 -  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   15.78 -  Thread* const thread = Thread::current();
   15.79 -  WriteOperation wo(_chunkwriter, thread);
   15.80 -  MutexedWriteOperation mwo(wo);
   15.81 +  ExclusiveWriteOperation ewo(wo);
   15.82    StringPoolReleaseOperation spro(_free_list_mspace, thread, false);
   15.83 -  StringPoolWriteOperation spwo(&mwo, &spro);
   15.84 +  StringPoolWriteOperation spwo(&ewo, &spro);
   15.85    assert(_free_list_mspace->is_full_empty(), "invariant");
   15.86    process_free_list(spwo, _free_list_mspace);
   15.87    return wo.processed();
   15.88  }
   15.89  
   15.90 -class StringPoolBufferDiscarder {
   15.91 - private:
   15.92 -  Thread* _thread;
   15.93 -  size_t _processed;
   15.94 - public:
   15.95 -  typedef JfrStringPoolBuffer Type;
   15.96 -  StringPoolBufferDiscarder() : _thread(Thread::current()), _processed(0) {}
   15.97 -  bool process(Type* buffer) {
   15.98 -    buffer->acquire(_thread); // serialized access
   15.99 -    const u1* const current_top = buffer->top();
  15.100 -    const size_t unflushed_size = buffer->pos() - current_top;
  15.101 -    if (unflushed_size == 0) {
  15.102 -      assert(buffer->string_count() == 0, "invariant");
  15.103 -      buffer->release();
  15.104 -      return true;
  15.105 -    }
  15.106 -    buffer->set_top(current_top + unflushed_size);
  15.107 -    const uint64_t nof_strings_used = buffer->string_count();
  15.108 -    buffer->set_string_top(buffer->string_top() + nof_strings_used);
  15.109 -    // "size processed" for string pool buffers is the number of string elements
  15.110 -    _processed += (size_t)nof_strings_used;
  15.111 -    buffer->release();
  15.112 -    return true;
  15.113 -  }
  15.114 -  size_t processed() const { return _processed; }
  15.115 -};
  15.116 +size_t JfrStringPool::write_at_safepoint() {
  15.117 +  assert(SafepointSynchronize::is_at_safepoint(), "invariant");
  15.118 +  return write();
  15.119 +}
  15.120  
  15.121  size_t JfrStringPool::clear() {
  15.122 -  StringPoolBufferDiscarder discard_operation;
  15.123 +  DiscardOperation discard_operation;
  15.124 +  ExclusiveDiscardOperation edo(discard_operation);
  15.125 +  StringPoolReleaseOperation spro(_free_list_mspace, Thread::current(), false);
  15.126 +  StringPoolDiscardOperation spdo(&edo, &spro);
  15.127    assert(_free_list_mspace->is_full_empty(), "invariant");
  15.128 -  process_free_list(discard_operation, _free_list_mspace);
  15.129 +  process_free_list(spdo, _free_list_mspace);
  15.130    return discard_operation.processed();
  15.131  }
  15.132  
  15.133  void JfrStringPool::register_full(BufferPtr t, Thread* thread) {
  15.134    // nothing here at the moment
  15.135 +  assert(t != NULL, "invariant");
  15.136 +  assert(t->acquired_by(thread), "invariant");
  15.137    assert(t->retired(), "invariant");
  15.138  }
  15.139  
    16.1 --- a/src/share/vm/jfr/recorder/stringpool/jfrStringPoolBuffer.cpp	Mon Apr 11 08:51:53 2016 +0200
    16.2 +++ b/src/share/vm/jfr/recorder/stringpool/jfrStringPoolBuffer.cpp	Mon Jun 29 21:30:26 2020 +0100
    16.3 @@ -1,5 +1,5 @@
    16.4  /*
    16.5 - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
    16.6 + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
    16.7   * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    16.8   *
    16.9   * This code is free software; you can redistribute it and/or modify it
   16.10 @@ -29,11 +29,9 @@
   16.11  
   16.12  void JfrStringPoolBuffer::reinitialize() {
   16.13    assert(acquired_by_self() || retired(), "invariant");
   16.14 -  concurrent_top();
   16.15 -  set_pos((start()));
   16.16    set_string_pos(0);
   16.17    set_string_top(0);
   16.18 -  set_concurrent_top(start());
   16.19 +  JfrBuffer::reinitialize();
   16.20  }
   16.21  
   16.22  uint64_t JfrStringPoolBuffer::string_pos() const {
   16.23 @@ -57,7 +55,7 @@
   16.24  }
   16.25  
   16.26  void JfrStringPoolBuffer::increment(uint64_t value) {
   16.27 -  assert(acquired_by_self() || retired(), "invariant");
   16.28 +  assert(acquired_by_self(), "invariant");
   16.29    ++_string_count_pos;
   16.30  }
   16.31  
    17.1 --- a/src/share/vm/runtime/thread.cpp	Mon Apr 11 08:51:53 2016 +0200
    17.2 +++ b/src/share/vm/runtime/thread.cpp	Mon Jun 29 21:30:26 2020 +0100
    17.3 @@ -3492,15 +3492,14 @@
    17.4    }
    17.5  
    17.6  #if !INCLUDE_JFR
    17.7 -    // if JFR is not enabled at the build time keep the original JvmtiExport location
    17.8 -
    17.9 -    // Always call even when there are not JVMTI environments yet, since environments
   17.10 -    // may be attached late and JVMTI must track phases of VM execution
   17.11 -    JvmtiExport::enter_start_phase();
   17.12 -
   17.13 -    // Notify JVMTI agents that VM has started (JNI is up) - nop if no agents.
   17.14 -    JvmtiExport::post_vm_start();
   17.15 -  }
   17.16 +  // if JFR is not enabled at the build time keep the original JvmtiExport location
   17.17 +
   17.18 +  // Always call even when there are not JVMTI environments yet, since environments
   17.19 +  // may be attached late and JVMTI must track phases of VM execution
   17.20 +  JvmtiExport::enter_start_phase();
   17.21 +
   17.22 +  // Notify JVMTI agents that VM has started (JNI is up) - nop if no agents.
   17.23 +  JvmtiExport::post_vm_start();
   17.24  #endif
   17.25  
   17.26    {

mercurial