hotspot/src/share/vm/services/memRecorder.hpp
changeset 25957 100a882dcffa
parent 25944 c8aa7a0bf7d0
parent 25956 99be217ac88d
child 25960 729cd80956ae
equal deleted inserted replaced
25944:c8aa7a0bf7d0 25957:100a882dcffa
     1 /*
       
     2  * Copyright (c) 2012, 2013, 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) throw() {
       
    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) throw() {
       
    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   friend class GenerationData;
       
   207 
       
   208  protected:
       
   209   // the array that holds memory records
       
   210   MemPointerArray*         _pointer_records;
       
   211 
       
   212  private:
       
   213   // used for linked list
       
   214   MemRecorder*             _next;
       
   215   // active recorder can only record a certain generation data
       
   216   unsigned long            _generation;
       
   217 
       
   218  protected:
       
   219   _NOINLINE_ MemRecorder();
       
   220   ~MemRecorder();
       
   221 
       
   222   // record a memory operation
       
   223   bool record(address addr, MEMFLAGS flags, size_t size, jint seq, address caller_pc = 0);
       
   224 
       
   225   // linked list support
       
   226   inline void set_next(MemRecorder* rec) {
       
   227     _next = rec;
       
   228   }
       
   229 
       
   230   inline MemRecorder* next() const {
       
   231     return _next;
       
   232   }
       
   233 
       
   234   // if the recorder is full
       
   235   inline bool is_full() const {
       
   236     assert(_pointer_records != NULL, "just check");
       
   237     return _pointer_records->is_full();
       
   238   }
       
   239 
       
   240   // if running out of memory when initializing recorder's internal
       
   241   // data
       
   242   inline bool out_of_memory() const {
       
   243     return (_pointer_records == NULL ||
       
   244       _pointer_records->out_of_memory());
       
   245   }
       
   246 
       
   247   inline void clear() {
       
   248     assert(_pointer_records != NULL, "Just check");
       
   249     _pointer_records->clear();
       
   250   }
       
   251 
       
   252   SequencedRecordIterator pointer_itr();
       
   253 
       
   254   // return the generation of this recorder which it belongs to
       
   255   unsigned long get_generation() const { return _generation; }
       
   256  protected:
       
   257   // number of MemRecorder instance
       
   258   static volatile jint _instance_count;
       
   259 
       
   260  private:
       
   261   // sorting function, sort records into following order
       
   262   // 1. memory address
       
   263   // 2. allocation type
       
   264   // 3. sequence number
       
   265   static int sort_record_fn(const void* e1, const void* e2);
       
   266 
       
   267   debug_only(void check_dup_seq(jint seq) const;)
       
   268   void set_generation();
       
   269 };
       
   270 
       
   271 #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP