src/hotspot/share/jfr/writers/jfrStorageAdapter.hpp
changeset 50113 caf115bb98ad
child 53244 9807daeb47c4
equal deleted inserted replaced
50112:7a2a740815b7 50113:caf115bb98ad
       
     1 /*
       
     2  * Copyright (c) 2016, 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  */
       
    24 
       
    25 #ifndef SHARE_VM_JFR_WRITERS_JFRSTORAGEADAPTER_HPP
       
    26 #define SHARE_VM_JFR_WRITERS_JFRSTORAGEADAPTER_HPP
       
    27 
       
    28 #include "jfr/utilities/jfrAllocation.hpp"
       
    29 
       
    30 class Thread;
       
    31 
       
    32 //
       
    33 // The adapters present writers with a uniform interface over storage.
       
    34 //
       
    35 // Adapter policy
       
    36 //
       
    37 // StorageType* storage();
       
    38 // const u1* start() const;
       
    39 // const u1* pos();
       
    40 // const u1* end() const;
       
    41 // void commit(u1* position);
       
    42 // bool flush(size_t used, size_t requested);
       
    43 // void release();
       
    44 //
       
    45 
       
    46 template <typename Flush>
       
    47 class Adapter {
       
    48  public:
       
    49   typedef typename Flush::Type StorageType;
       
    50   Adapter(StorageType* storage, Thread* thread) : _storage(storage), _thread(thread) {}
       
    51   Adapter(Thread* thread) : _storage(NULL), _thread(thread) {}
       
    52 
       
    53   void set_storage(StorageType* storage) {
       
    54     _storage = storage;
       
    55   }
       
    56 
       
    57   StorageType* storage() {
       
    58     return _storage;
       
    59   }
       
    60 
       
    61   const u1* start() const {
       
    62     assert(_storage != NULL, "invariant");
       
    63     return _storage->start();
       
    64   }
       
    65 
       
    66   u1* pos() {
       
    67     assert(_storage != NULL, "invariant");
       
    68     return _storage->pos();
       
    69   }
       
    70 
       
    71   const u1* end() const {
       
    72     assert(_storage != NULL, "invariant");
       
    73     return _storage->end();
       
    74   }
       
    75 
       
    76   void commit(u1* position) {
       
    77     assert(_storage != NULL, "invariant");
       
    78     _storage->set_pos(position);
       
    79   }
       
    80 
       
    81   bool flush(size_t used, size_t requested) {
       
    82     assert(_thread != NULL, "invariant");
       
    83     Flush f(_storage, used, requested, _thread);
       
    84     _storage = f.result();
       
    85     return _storage != NULL;
       
    86   }
       
    87 
       
    88   void release() {
       
    89     if (_storage != NULL && _storage->lease()) {
       
    90       // This flush call will return the lease
       
    91       // of a temporary storage area.
       
    92       // Since the requested size is 0,
       
    93       // the flush implementation will accomodate
       
    94       // that 'size' request in the
       
    95       // original thread local storage,
       
    96       // by implication restoring the original
       
    97       // in the process of returning a lease.
       
    98       flush(0, 0);
       
    99     }
       
   100   }
       
   101 
       
   102  private:
       
   103   StorageType* _storage;
       
   104   Thread* _thread;
       
   105 };
       
   106 
       
   107 template <size_t DEFAULT_SIZE = K>
       
   108 class MallocAdapter {
       
   109  private:
       
   110   u1* _start;
       
   111   u1* _pos;
       
   112   u1* _end;
       
   113   size_t _initial_size;
       
   114   bool _has_ownership;
       
   115 
       
   116   bool allocate(size_t size);
       
   117   void deallocate();
       
   118 
       
   119  public:
       
   120   typedef u1 StorageType;
       
   121   MallocAdapter(u1* storage, Thread* thread);
       
   122   MallocAdapter(u1* storage, size_t size);
       
   123   MallocAdapter(Thread* thread);
       
   124   ~MallocAdapter();
       
   125 
       
   126   StorageType* storage() { return _start; }
       
   127   const u1* start() const { return _start; }
       
   128   u1* pos() { return _pos; }
       
   129   void commit(u1* position) { _pos = position; }
       
   130   const u1* end() const { return _end; }
       
   131   void release() {}
       
   132   bool flush(size_t used, size_t requested);
       
   133 };
       
   134 
       
   135 template <size_t DEFAULT_SIZE>
       
   136 MallocAdapter<DEFAULT_SIZE>::MallocAdapter(u1* storage, size_t size) :
       
   137   _start(storage),
       
   138   _pos(storage),
       
   139   _end(storage + size),
       
   140   _initial_size(size),
       
   141   _has_ownership(false) {
       
   142 }
       
   143 
       
   144 template <size_t DEFAULT_SIZE>
       
   145 MallocAdapter<DEFAULT_SIZE> ::MallocAdapter(u1* storage, Thread* thread) :
       
   146   _start(storage),
       
   147   _pos(storage),
       
   148   _end(storage),
       
   149   _initial_size(0),
       
   150   _has_ownership(false) {
       
   151 }
       
   152 
       
   153 template <size_t DEFAULT_SIZE>
       
   154 MallocAdapter<DEFAULT_SIZE>::MallocAdapter(Thread* thread) :
       
   155   _start(NULL),
       
   156   _pos(NULL),
       
   157   _end(NULL),
       
   158   _initial_size(DEFAULT_SIZE),
       
   159   _has_ownership(true) {
       
   160   allocate(DEFAULT_SIZE);
       
   161 }
       
   162 
       
   163 template <size_t DEFAULT_SIZE>
       
   164 MallocAdapter<DEFAULT_SIZE>::~MallocAdapter() {
       
   165   if (_has_ownership) {
       
   166     deallocate();
       
   167   }
       
   168 }
       
   169 
       
   170 template <size_t DEFAULT_SIZE>
       
   171 bool MallocAdapter<DEFAULT_SIZE>::allocate(size_t size) {
       
   172   if (NULL == _start) {
       
   173     _start = JfrCHeapObj::new_array<u1>(size);
       
   174     if (_start) {
       
   175       _pos = _start;
       
   176       _end = _start + size;
       
   177       _initial_size = size;
       
   178     }
       
   179   }
       
   180   return _start != NULL;
       
   181 }
       
   182 
       
   183 template <size_t DEFAULT_SIZE>
       
   184 void MallocAdapter<DEFAULT_SIZE>::deallocate() {
       
   185   if (_start != NULL) {
       
   186     JfrCHeapObj::free(_start, (size_t)(_end - _start));
       
   187   }
       
   188 }
       
   189 
       
   190 template <size_t DEFAULT_SIZE>
       
   191 bool MallocAdapter<DEFAULT_SIZE>::flush(size_t used, size_t requested) {
       
   192   if (!_has_ownership) {
       
   193     // can't just realloc a storage that we don't own
       
   194     return false;
       
   195   }
       
   196   assert(_start != NULL, "invariant");
       
   197   assert(used <= (size_t)(_end - _pos), "invariant");
       
   198   assert(_pos + used <= _end, "invariant");
       
   199   const size_t previous_storage_size = _end - _start;
       
   200   const size_t new_storage_size = used + requested + (previous_storage_size * 2);
       
   201   u1* const new_storage = JfrCHeapObj::new_array<u1>(new_storage_size);
       
   202   if (!new_storage) {
       
   203     return false;
       
   204   }
       
   205   const size_t previous_pos_offset = _pos - _start;
       
   206   // migrate in-flight data
       
   207   memcpy(new_storage, _start, previous_pos_offset + used);
       
   208   JfrCHeapObj::free(_start, previous_storage_size);
       
   209   _start = new_storage;
       
   210   _pos = _start + previous_pos_offset;
       
   211   _end = _start + new_storage_size;
       
   212   return true;
       
   213 }
       
   214 
       
   215 class NoOwnershipAdapter {
       
   216  private:
       
   217   u1* _start;
       
   218   u1* _pos;
       
   219   u1* _end;
       
   220   size_t _size;
       
   221 
       
   222  public:
       
   223   typedef u1 StorageType;
       
   224   NoOwnershipAdapter(u1* storage, size_t size) : _start(storage), _pos(storage), _end(storage + size), _size(size) {}
       
   225   NoOwnershipAdapter(u1* storage, Thread* thread) : _start(storage), _pos(storage), _end(storage), _size(0) {
       
   226     ShouldNotCallThis();
       
   227   }
       
   228   NoOwnershipAdapter(Thread* thread) : _start(NULL), _pos(NULL), _end(NULL), _size(0) {
       
   229     ShouldNotCallThis();
       
   230   }
       
   231   StorageType* storage() { return _start; }
       
   232   const u1* start() const { return _start; }
       
   233   u1* pos() { return _pos; }
       
   234   void commit(u1* position) { _pos = position; }
       
   235   const u1* end() const { return _end; }
       
   236   void release() {}
       
   237   bool flush(size_t used, size_t requested) {
       
   238     // don't flush/expand a buffer that is not our own
       
   239     return false;
       
   240   }
       
   241 };
       
   242 
       
   243 #endif // SHARE_VM_JFR_WRITERS_JFRSTORAGEADAPTER_HPP