src/share/vm/services/memRecorder.hpp

Fri, 19 Oct 2012 21:40:07 -0400

author
zgu
date
Fri, 19 Oct 2012 21:40:07 -0400
changeset 4193
716c64bda5ba
parent 3994
e5bf1c79ed5b
child 4400
ecd24264898b
permissions
-rw-r--r--

7199092: NMT: NMT needs to deal overlapped virtual memory ranges
Summary: Enhanced virtual memory tracking to track committed regions as well as reserved regions, so NMT now can generate virtual memory map.
Reviewed-by: acorn, coleenp

     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   NOT_PRODUCT(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     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 };
   200 #define DEFAULT_RECORDER_PTR_ARRAY_SIZE 512
   202 class MemRecorder : public CHeapObj<mtNMT|otNMTRecorder> {
   203   friend class MemSnapshot;
   204   friend class MemTracker;
   205   friend class MemTrackWorker;
   207  protected:
   208   // the array that holds memory records
   209   MemPointerArray*         _pointer_records;
   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;)
   217  protected:
   218   _NOINLINE_ MemRecorder();
   219   ~MemRecorder();
   221   // record a memory operation
   222   bool record(address addr, MEMFLAGS flags, size_t size, address caller_pc = 0);
   224   // linked list support
   225   inline void set_next(MemRecorder* rec) {
   226     _next = rec;
   227   }
   229   inline MemRecorder* next() const {
   230     return _next;
   231   }
   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   }
   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   }
   246   inline void clear() {
   247     assert(_pointer_records != NULL, "Just check");
   248     _pointer_records->clear();
   249   }
   251   SequencedRecordIterator pointer_itr();
   253  protected:
   254   // number of MemRecorder instance
   255   static volatile jint _instance_count;
   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);
   264   debug_only(void check_dup_seq(jint seq) const;)
   265   debug_only(void set_generation();)
   266 };
   268 #endif // SHARE_VM_SERVICES_MEM_RECORDER_HPP

mercurial