src/hotspot/share/jfr/recorder/stringpool/jfrStringPool.cpp
changeset 54964 ec7d6d8effc7
parent 50714 2230bb152a9f
child 58154 060d9d139109
child 58863 c16ac7a2eba4
equal deleted inserted replaced
54963:a5f5e680ea32 54964:ec7d6d8effc7
     1 /*
     1 /*
     2  * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     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
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     7  * published by the Free Software Foundation.
   138     writer.inc_nof_strings();
   138     writer.inc_nof_strings();
   139   }
   139   }
   140   return current_epoch;
   140   return current_epoch;
   141 }
   141 }
   142 
   142 
   143 class StringPoolWriteOp  {
   143 template <template <typename> class Operation>
       
   144 class StringPoolOp {
   144  public:
   145  public:
   145   typedef JfrStringPoolBuffer Type;
   146   typedef JfrStringPoolBuffer Type;
   146  private:
   147  private:
   147   UnBufferedWriteToChunk<Type> _writer;
   148   Operation<Type> _op;
   148   Thread* _thread;
   149   Thread* _thread;
   149   size_t _strings_processed;
   150   size_t _strings_processed;
   150  public:
   151  public:
   151   StringPoolWriteOp(JfrChunkWriter& writer, Thread* thread) : _writer(writer), _thread(thread), _strings_processed(0) {}
   152   StringPoolOp() : _op(), _thread(Thread::current()), _strings_processed(0) {}
       
   153   StringPoolOp(JfrChunkWriter& writer, Thread* thread) : _op(writer), _thread(thread), _strings_processed(0) {}
   152   bool write(Type* buffer, const u1* data, size_t size) {
   154   bool write(Type* buffer, const u1* data, size_t size) {
   153     buffer->acquire(_thread); // blocking
   155     assert(buffer->acquired_by(_thread) || buffer->retired(), "invariant");
   154     const uint64_t nof_strings_used = buffer->string_count();
   156     const uint64_t nof_strings_used = buffer->string_count();
   155     assert(nof_strings_used > 0, "invariant");
   157     assert(nof_strings_used > 0, "invariant");
   156     buffer->set_string_top(buffer->string_top() + nof_strings_used);
   158     buffer->set_string_top(buffer->string_top() + nof_strings_used);
   157     // "size processed" for string pool buffers is the number of processed string elements
   159     // "size processed" for string pool buffers is the number of processed string elements
   158     _strings_processed += nof_strings_used;
   160     _strings_processed += nof_strings_used;
   159     const bool ret = _writer.write(buffer, data, size);
   161     return _op.write(buffer, data, size);
   160     buffer->release();
       
   161     return ret;
       
   162   }
   162   }
   163   size_t processed() { return _strings_processed; }
   163   size_t processed() { return _strings_processed; }
   164 };
   164 };
   165 
   165 
   166 typedef StringPoolWriteOp WriteOperation;
   166 template <typename Type>
   167 typedef ConcurrentWriteOp<WriteOperation> ConcurrentWriteOperation;
   167 class StringPoolDiscarderStub {
       
   168  public:
       
   169   bool write(Type* buffer, const u1* data, size_t size) {
       
   170     // stub only, discard happens at higher level
       
   171     return true;
       
   172   }
       
   173 };
       
   174 
       
   175 typedef StringPoolOp<UnBufferedWriteToChunk> WriteOperation;
       
   176 typedef StringPoolOp<StringPoolDiscarderStub> DiscardOperation;
       
   177 typedef ExclusiveOp<WriteOperation> ExclusiveWriteOperation;
       
   178 typedef ExclusiveOp<DiscardOperation> ExclusiveDiscardOperation;
       
   179 typedef ReleaseOp<JfrStringPoolMspace> StringPoolReleaseOperation;
       
   180 typedef CompositeOperation<ExclusiveWriteOperation, StringPoolReleaseOperation> StringPoolWriteOperation;
       
   181 typedef CompositeOperation<ExclusiveDiscardOperation, StringPoolReleaseOperation> StringPoolDiscardOperation;
   168 
   182 
   169 size_t JfrStringPool::write() {
   183 size_t JfrStringPool::write() {
   170   Thread* const thread = Thread::current();
   184   Thread* const thread = Thread::current();
   171   WriteOperation wo(_chunkwriter, thread);
   185   WriteOperation wo(_chunkwriter, thread);
   172   ConcurrentWriteOperation cwo(wo);
   186   ExclusiveWriteOperation ewo(wo);
   173   assert(_free_list_mspace->is_full_empty(), "invariant");
       
   174   process_free_list(cwo, _free_list_mspace);
       
   175   return wo.processed();
       
   176 }
       
   177 
       
   178 typedef MutexedWriteOp<WriteOperation> MutexedWriteOperation;
       
   179 typedef ReleaseOp<JfrStringPoolMspace> StringPoolReleaseOperation;
       
   180 typedef CompositeOperation<MutexedWriteOperation, StringPoolReleaseOperation> StringPoolWriteOperation;
       
   181 
       
   182 size_t JfrStringPool::write_at_safepoint() {
       
   183   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
       
   184   Thread* const thread = Thread::current();
       
   185   WriteOperation wo(_chunkwriter, thread);
       
   186   MutexedWriteOperation mwo(wo);
       
   187   StringPoolReleaseOperation spro(_free_list_mspace, thread, false);
   187   StringPoolReleaseOperation spro(_free_list_mspace, thread, false);
   188   StringPoolWriteOperation spwo(&mwo, &spro);
   188   StringPoolWriteOperation spwo(&ewo, &spro);
   189   assert(_free_list_mspace->is_full_empty(), "invariant");
   189   assert(_free_list_mspace->is_full_empty(), "invariant");
   190   process_free_list(spwo, _free_list_mspace);
   190   process_free_list(spwo, _free_list_mspace);
   191   return wo.processed();
   191   return wo.processed();
   192 }
   192 }
   193 
   193 
   194 class StringPoolBufferDiscarder {
   194 size_t JfrStringPool::write_at_safepoint() {
   195  private:
   195   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
   196   Thread* _thread;
   196   return write();
   197   size_t _processed;
   197 }
   198  public:
       
   199   typedef JfrStringPoolBuffer Type;
       
   200   StringPoolBufferDiscarder() : _thread(Thread::current()), _processed(0) {}
       
   201   bool process(Type* buffer) {
       
   202     buffer->acquire(_thread); // serialized access
       
   203     const u1* const current_top = buffer->top();
       
   204     const size_t unflushed_size = buffer->pos() - current_top;
       
   205     if (unflushed_size == 0) {
       
   206       assert(buffer->string_count() == 0, "invariant");
       
   207       buffer->release();
       
   208       return true;
       
   209     }
       
   210     buffer->set_top(current_top + unflushed_size);
       
   211     const uint64_t nof_strings_used = buffer->string_count();
       
   212     buffer->set_string_top(buffer->string_top() + nof_strings_used);
       
   213     // "size processed" for string pool buffers is the number of string elements
       
   214     _processed += (size_t)nof_strings_used;
       
   215     buffer->release();
       
   216     return true;
       
   217   }
       
   218   size_t processed() const { return _processed; }
       
   219 };
       
   220 
   198 
   221 size_t JfrStringPool::clear() {
   199 size_t JfrStringPool::clear() {
   222   StringPoolBufferDiscarder discard_operation;
   200   DiscardOperation discard_operation;
       
   201   ExclusiveDiscardOperation edo(discard_operation);
       
   202   StringPoolReleaseOperation spro(_free_list_mspace, Thread::current(), false);
       
   203   StringPoolDiscardOperation spdo(&edo, &spro);
   223   assert(_free_list_mspace->is_full_empty(), "invariant");
   204   assert(_free_list_mspace->is_full_empty(), "invariant");
   224   process_free_list(discard_operation, _free_list_mspace);
   205   process_free_list(spdo, _free_list_mspace);
   225   return discard_operation.processed();
   206   return discard_operation.processed();
   226 }
   207 }
   227 
   208 
   228 void JfrStringPool::register_full(BufferPtr t, Thread* thread) {
   209 void JfrStringPool::register_full(BufferPtr t, Thread* thread) {
   229   // nothing here at the moment
   210   // nothing here at the moment
       
   211   assert(t != NULL, "invariant");
       
   212   assert(t->acquired_by(thread), "invariant");
   230   assert(t->retired(), "invariant");
   213   assert(t->retired(), "invariant");
   231 }
   214 }
   232 
   215 
   233 void JfrStringPool::lock() {
   216 void JfrStringPool::lock() {
   234   assert(!_lock->owned_by_self(), "invariant");
   217   assert(!_lock->owned_by_self(), "invariant");