1 /*
   2  * Copyright (c) 2012, 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_SERVICES_MEM_RECORDER_HPP
  26 #define SHARE_VM_SERVICES_MEM_RECORDER_HPP
  27 
  28 #include "memory/allocation.hpp"
  29 #include "runtime/os.hpp"
  30 #include "services/memPtrArray.hpp"
  31 
  32 class MemSnapshot;
  33 class MemTracker;
  34 class MemTrackWorker;
  35 
  36 // Fixed size memory pointer array implementation
  37 template <class E, int SIZE> class FixedSizeMemPointerArray :
  38   public MemPointerArray {
  39   // This implementation is for memory recorder only
  40   friend class MemRecorder;
  41 
  42  private:
  43   E      _data[SIZE];
  44   int    _size;
  45 
  46  protected:
  47   FixedSizeMemPointerArray(bool init_elements = false):
  48    _size(0){
  49     if (init_elements) {
  50       for (int index = 0; index < SIZE; index ++) {
  51         ::new ((void*)&_data[index]) E();
  52       }
  53     }
  54   }
  55 
  56   void* operator new(size_t size, const std::nothrow_t& nothrow_constant) {
  57     // the instance is part of memRecorder, needs to be tagged with 'otNMTRecorder'
  58     // to avoid recursion
  59     return os::malloc(size, (mtNMT | otNMTRecorder));
  60   }
  61 
  62   void* operator new(size_t size) {
  63     assert(false, "use nothrow version");
  64     return NULL;
  65   }
  66 
  67   void operator delete(void* p) {
  68     os::free(p, (mtNMT | otNMTRecorder));
  69   }
  70 
  71   // instance size
  72   inline size_t instance_size() const {
  73     return sizeof(FixedSizeMemPointerArray<E, SIZE>);
  74   }
  75 
  76   NOT_PRODUCT(int capacity() const { return SIZE; })
  77 
  78  public:
  79   // implementation of public interface
  80   bool out_of_memory() const { return false; }
  81   bool is_empty()      const { return _size == 0; }
  82   bool is_full()             { return length() >= SIZE; }
  83   int  length()        const { return _size; }
  84 
  85   void clear() {
  86     _size = 0;
  87   }
  88 
  89   bool append(MemPointer* ptr) {
  90     if (is_full()) return false;
  91     _data[_size ++] = *(E*)ptr;
  92     return true;
  93   }
  94 
  95   virtual bool insert_at(MemPointer* p, int pos) {
  96     assert(false, "append only");
  97     return false;
  98   }
  99 
 100   virtual bool remove_at(int pos) {
 101     assert(false, "not supported");
 102     return false;
 103   }
 104 
 105   MemPointer* at(int index) const {
 106     assert(index >= 0 && index < length(),
 107       "parameter check");
 108     return ((E*)&_data[index]);
 109   }
 110 
 111   void sort(FN_SORT fn) {
 112     qsort((void*)_data, _size, sizeof(E), fn);
 113   }
 114 
 115   bool shrink() {
 116     return false;
 117   }
 118 };
 119 
 120 
 121 // This iterator requires pre-sorted MemPointerArray, which is sorted by:
 122 //  1. address
 123 //  2. allocation type
 124 //  3. sequence number
 125 // During the array walking, iterator collapses pointers with the same
 126 // address and allocation type, and only returns the one with highest
 127 // sequence number.
 128 //
 129 // This is read-only iterator, update methods are asserted.
 130 class SequencedRecordIterator : public MemPointerArrayIterator {
 131  private:
 132    MemPointerArrayIteratorImpl _itr;
 133    MemPointer*                 _cur;
 134 
 135  public:
 136   SequencedRecordIterator(const MemPointerArray* arr):
 137     _itr(const_cast<MemPointerArray*>(arr)) {
 138     _cur = next_record();
 139   }
 140 
 141   SequencedRecordIterator(const SequencedRecordIterator& itr):
 142     _itr(itr._itr) {
 143     _cur = next_record();
 144   }
 145 
 146   // return the pointer at current position
 147   virtual MemPointer* current() const {
 148     return _cur;
 149   };
 150 
 151   // return the next pointer and advance current position
 152   virtual MemPointer* next() {
 153     _cur = next_record();
 154     return _cur;
 155   }
 156 
 157   // return the next pointer without advancing current position
 158   virtual MemPointer* peek_next() const {
 159     assert(false, "not implemented");
 160     return NULL;
 161 
 162   }
 163   // return the previous pointer without changing current position
 164   virtual MemPointer* peek_prev() const {
 165     assert(false, "not implemented");
 166     return NULL;
 167   }
 168 
 169   // remove the pointer at current position
 170   virtual void remove() {
 171     assert(false, "read-only iterator");
 172   };
 173   // insert the pointer at current position
 174   virtual bool insert(MemPointer* ptr) {
 175     assert(false, "read-only iterator");
 176     return false;
 177   }
 178 
 179   virtual bool insert_after(MemPointer* ptr) {
 180     assert(false, "read-only iterator");
 181     return false;
 182   }
 183  private:
 184   // collapse the 'same kind' of records, and return this 'kind' of
 185   // record with highest sequence number
 186   MemPointer* next_record();
 187 
 188   // Test if the two records are the same kind: the same memory block and allocation
 189   // type.
 190   inline bool same_kind(const MemPointerRecord* p1, const MemPointerRecord* p2) const {
 191     assert(!p1->is_vm_pointer() && !p2->is_vm_pointer(), "malloc pointer only");
 192     return (p1->addr() == p2->addr() &&
 193       (p1->flags() &MemPointerRecord::tag_masks) ==
 194       (p2->flags() & MemPointerRecord::tag_masks));
 195   }
 196 };
 197 
 198 
 199 
 200 #define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512
 201 
 202 class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
 203   friend class MemSnapshot;
 204   friend class MemTracker;
 205   friend class MemTrackWorker;
 206 
 207  protected:
 208   // the array that holds memory records
 209   MemPointerArray*         _pointer_records;
 210 
 211  private:
 212   // used for linked list
 213   MemRecorder*             _next;
 214   // active recorder can only record a certain generation data
 215   debug_only(unsigned long _generation;)
 216 
 217  protected:
 218   _NOINLINE_ MemRecorder();
 219   ~MemRecorder();
 220 
 221   // record a memory operation
 222   bool record(address addr, MEMFLAGS flags, size_t size, address caller_pc = 0);
 223 
 224   // linked list support
 225   inline void set_next(MemRecorder* rec) {
 226     _next = rec;
 227   }
 228 
 229   inline MemRecorder* next() const {
 230     return _next;
 231   }
 232 
 233   // if the recorder is full
 234   inline bool is_full() const {
 235     assert(_pointer_records != NULL, "just check");
 236     return _pointer_records->is_full();
 237   }
 238 
 239   // if running out of memory when initializing recorder's internal
 240   // data
 241   inline bool out_of_memory() const {
 242     return (_pointer_records == NULL ||
 243       _pointer_records->out_of_memory());
 244   }
 245 
 246   inline void clear() {
 247     assert(_pointer_records != NULL, "Just check");
 248     _pointer_records->clear();
 249   }
 250 
 251   SequencedRecordIterator pointer_itr();
 252 
 253  protected:
 254   // number of MemRecorder instance
 255   static volatile jint _instance_count;
 256 
 257  private:
 258   // sorting function, sort records into following order
 259   // 1. memory address
 260   // 2. allocation type
 261   // 3. sequence number
 262   static int sort_record_fn(const void* e1, const void* e2);
 263 
 264   debug_only(void check_dup_seq(jint seq) const;)
 265   debug_only(void set_generation();)
 266 };
 267 
 268 #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP