Mon, 29 Jun 2020 21:30:26 +0100
Merge
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 {