src/share/vm/services/memRecorder.hpp

Thu, 28 Jun 2012 17:03:16 -0400

author
zgu
date
Thu, 28 Jun 2012 17:03:16 -0400
changeset 3900
d2a62e0f25eb
child 3935
7e5976e66c62
permissions
-rw-r--r--

6995781: Native Memory Tracking (Phase 1)
7151532: DCmd for hotspot native memory tracking
Summary: Implementation of native memory tracking phase 1, which tracks VM native memory usage, and related DCmd
Reviewed-by: acorn, coleenp, fparain

     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  */
    25 #ifndef SHARE_VM_SERVICES_MEM_RECORDER_HPP
    26 #define SHARE_VM_SERVICES_MEM_RECORDER_HPP
    28 #include "memory/allocation.hpp"
    29 #include "runtime/os.hpp"
    30 #include "services/memPtrArray.hpp"
    32 class MemSnapshot;
    33 class MemTracker;
    34 class MemTrackWorker;
    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;
    42  private:
    43   E      _data[SIZE];
    44   int    _size;
    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   }
    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   }
    62   void* operator new(size_t size) {
    63     assert(false, "use nothrow version");
    64     return NULL;
    65   }
    67   void operator delete(void* p) {
    68     os::free(p, (mtNMT | otNMTRecorder));
    69   }
    71   // instance size
    72   inline size_t instance_size() const {
    73     return sizeof(FixedSizeMemPointerArray<E, SIZE>);
    74   }
    76   debug_only(int capacity() const { return SIZE; })
    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; }
    85   void clear() {
    86     _size = 0;
    87   }
    89   bool append(MemPointer* ptr) {
    90     if (is_full()) return false;
    91     _data[_size ++] = *(E*)ptr;
    92     return true;
    93   }
    95   virtual bool insert_at(MemPointer* p, int pos) {
    96     assert(false, "append only");
    97     return false;
    98   }
   100   virtual bool remove_at(int pos) {
   101     assert(false, "not supported");
   102     return false;
   103   }
   105   MemPointer* at(int index) const {
   106     assert(index >= 0 && index < length(),
   107       "parameter check");
   108     return ((E*)&_data[index]);
   109   }
   111   void sort(FN_SORT fn) {
   112     qsort((void*)_data, _size, sizeof(E), fn);
   113   }
   115   bool shrink() {
   116     return false;
   117   }
   118 };
   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;
   135  public:
   136   SequencedRecordIterator(const MemPointerArray* arr):
   137     _itr(const_cast<MemPointerArray*>(arr)) {
   138     _cur = next_record();
   139   }
   141   SequencedRecordIterator(const SequencedRecordIterator& itr):
   142     _itr(itr._itr) {
   143     _cur = next_record();
   144   }
   146   // return the pointer at current position
   147   virtual MemPointer* current() const {
   148     return _cur;
   149   };
   151   // return the next pointer and advance current position
   152   virtual MemPointer* next() {
   153     _cur = next_record();
   154     return _cur;
   155   }
   157   // return the next pointer without advancing current position
   158   virtual MemPointer* peek_next() const {
   159     assert(false, "not implemented");
   160     return NULL;
   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   }
   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   }
   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();
   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     return (p1->addr() == p2->addr() &&
   192       (p1->flags() &MemPointerRecord::tag_masks) ==
   193       (p2->flags() & MemPointerRecord::tag_masks));
   194   }
   195 };
   199 #define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512
   201 class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
   202   friend class MemSnapshot;
   203   friend class MemTracker;
   204   friend class MemTrackWorker;
   206  protected:
   207   // the array that holds memory records
   208   MemPointerArray*         _pointer_records;
   210  private:
   211   // used for linked list
   212   MemRecorder*             _next;
   213   // active recorder can only record a certain generation data
   214   debug_only(unsigned long _generation;)
   216  protected:
   217   _NOINLINE_ MemRecorder();
   218   ~MemRecorder();
   220   // record a memory operation
   221   bool record(address addr, MEMFLAGS flags, size_t size, address caller_pc = 0);
   223   // linked list support
   224   inline void set_next(MemRecorder* rec) {
   225     _next = rec;
   226   }
   228   inline MemRecorder* next() const {
   229     return _next;
   230   }
   232   // if the recorder is full
   233   inline bool is_full() const {
   234     assert(_pointer_records != NULL, "just check");
   235     return _pointer_records->is_full();
   236   }
   238   // if running out of memory when initializing recorder's internal
   239   // data
   240   inline bool out_of_memory() const {
   241     return (_pointer_records == NULL ||
   242       _pointer_records->out_of_memory());
   243   }
   245   inline void clear() {
   246     assert(_pointer_records != NULL, "Just check");
   247     _pointer_records->clear();
   248   }
   250   SequencedRecordIterator pointer_itr();
   252  public:
   253   // number of MemRecorder instance
   254   debug_only(static volatile jint _instance_count;)
   256  private:
   257   // sorting function, sort records into following order
   258   // 1. memory address
   259   // 2. allocation type
   260   // 3. sequence number
   261   static int sort_record_fn(const void* e1, const void* e2);
   263   debug_only(void check_dup_seq(jint seq) const;)
   264   debug_only(void set_generation();)
   265 };
   267 #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP

mercurial