src/share/vm/services/memSnapshot.hpp

Sat, 29 Sep 2012 06:40:00 -0400

author
coleenp
date
Sat, 29 Sep 2012 06:40:00 -0400
changeset 4142
d8ce2825b193
parent 4053
33143ee07800
child 4193
716c64bda5ba
permissions
-rw-r--r--

8000213: NPG: Should have renamed arrayKlass and typeArrayKlass
Summary: Capitalize these metadata types (and objArrayKlass)
Reviewed-by: stefank, twisti, kvn

     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_SNAPSHOT_HPP
    26 #define SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP
    28 #include "memory/allocation.hpp"
    29 #include "runtime/mutex.hpp"
    30 #include "runtime/mutexLocker.hpp"
    31 #include "services/memBaseline.hpp"
    32 #include "services/memPtrArray.hpp"
    35 // Snapshot pointer array iterator
    37 // The pointer array contains malloc-ed pointers
    38 class MemPointerIterator : public MemPointerArrayIteratorImpl {
    39  public:
    40   MemPointerIterator(MemPointerArray* arr):
    41     MemPointerArrayIteratorImpl(arr) {
    42     assert(arr != NULL, "null array");
    43   }
    45 #ifdef ASSERT
    46   virtual bool is_dup_pointer(const MemPointer* ptr1,
    47     const MemPointer* ptr2) const {
    48     MemPointerRecord* p1 = (MemPointerRecord*)ptr1;
    49     MemPointerRecord* p2 = (MemPointerRecord*)ptr2;
    51     if (p1->addr() != p2->addr()) return false;
    52     if ((p1->flags() & MemPointerRecord::tag_masks) !=
    53         (p2->flags() & MemPointerRecord::tag_masks)) {
    54       return false;
    55     }
    56     // we do see multiple commit/uncommit on the same memory, it is ok
    57     return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc ||
    58            (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release;
    59   }
    61   virtual bool insert(MemPointer* ptr) {
    62     if (_pos > 0) {
    63       MemPointer* p1 = (MemPointer*)ptr;
    64       MemPointer* p2 = (MemPointer*)_array->at(_pos - 1);
    65       assert(!is_dup_pointer(p1, p2),
    66         err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
    67     }
    68      if (_pos < _array->length() -1) {
    69       MemPointer* p1 = (MemPointer*)ptr;
    70       MemPointer* p2 = (MemPointer*)_array->at(_pos + 1);
    71       assert(!is_dup_pointer(p1, p2),
    72         err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
    73      }
    74     return _array->insert_at(ptr, _pos);
    75   }
    77   virtual bool insert_after(MemPointer* ptr) {
    78     if (_pos > 0) {
    79       MemPointer* p1 = (MemPointer*)ptr;
    80       MemPointer* p2 = (MemPointer*)_array->at(_pos - 1);
    81       assert(!is_dup_pointer(p1, p2),
    82         err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
    83     }
    84     if (_pos < _array->length() - 1) {
    85       MemPointer* p1 = (MemPointer*)ptr;
    86       MemPointer* p2 = (MemPointer*)_array->at(_pos + 1);
    88       assert(!is_dup_pointer(p1, p2),
    89         err_msg("duplicated pointer, flag = [%x]", (unsigned int)((MemPointerRecord*)p1)->flags()));
    90      }
    91     if (_array->insert_at(ptr, _pos + 1)) {
    92       _pos ++;
    93       return true;
    94     }
    95     return false;
    96   }
    97 #endif
    99   virtual MemPointer* locate(address addr) {
   100     MemPointer* cur = current();
   101     while (cur != NULL && cur->addr() < addr) {
   102       cur = next();
   103     }
   104     return cur;
   105   }
   106 };
   108 class VMMemPointerIterator : public MemPointerIterator {
   109  public:
   110   VMMemPointerIterator(MemPointerArray* arr):
   111       MemPointerIterator(arr) {
   112   }
   114   // locate an existing record that contains specified address, or
   115   // the record, where the record with specified address, should
   116   // be inserted.
   117   // virtual memory record array is sorted in address order, so
   118   // binary search is performed
   119   virtual MemPointer* locate(address addr) {
   120     int index_low = 0;
   121     int index_high = _array->length();
   122     int index_mid = (index_high + index_low) / 2;
   123     int r = 1;
   124     while (index_low < index_high && (r = compare(index_mid, addr)) != 0) {
   125       if (r > 0) {
   126         index_high = index_mid;
   127       } else {
   128         index_low = index_mid;
   129       }
   130       index_mid = (index_high + index_low) / 2;
   131     }
   132     if (r == 0) {
   133       // update current location
   134       _pos = index_mid;
   135       return _array->at(index_mid);
   136     } else {
   137       return NULL;
   138     }
   139   }
   141 #ifdef ASSERT
   142   virtual bool is_dup_pointer(const MemPointer* ptr1,
   143     const MemPointer* ptr2) const {
   144     VMMemRegion* p1 = (VMMemRegion*)ptr1;
   145     VMMemRegion* p2 = (VMMemRegion*)ptr2;
   147     if (p1->addr() != p2->addr()) return false;
   148     if ((p1->flags() & MemPointerRecord::tag_masks) !=
   149         (p2->flags() & MemPointerRecord::tag_masks)) {
   150       return false;
   151     }
   152     // we do see multiple commit/uncommit on the same memory, it is ok
   153     return (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_alloc ||
   154            (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release;
   155   }
   156 #endif
   157   // compare if an address falls into a memory region,
   158   // return 0, if the address falls into a memory region at specified index
   159   // return 1, if memory region pointed by specified index is higher than the address
   160   // return -1, if memory region pointed by specified index is lower than the address
   161   int compare(int index, address addr) const {
   162     VMMemRegion* r = (VMMemRegion*)_array->at(index);
   163     assert(r->is_reserve_record(), "Sanity check");
   164     if (r->addr() > addr) {
   165       return 1;
   166     } else if (r->addr() + r->reserved_size() <= addr) {
   167       return -1;
   168     } else {
   169       return 0;
   170     }
   171   }
   172 };
   174 class MallocRecordIterator : public MemPointerArrayIterator {
   175  private:
   176   MemPointerArrayIteratorImpl  _itr;
   178  public:
   179   MallocRecordIterator(MemPointerArray* arr) : _itr(arr) {
   180   }
   182   MemPointer* current() const {
   183     MemPointerRecord* cur = (MemPointerRecord*)_itr.current();
   184     assert(cur == NULL || !cur->is_vm_pointer(), "seek error");
   185     MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next();
   186     if (next == NULL || next->addr() != cur->addr()) {
   187       return cur;
   188     } else {
   189       assert(!cur->is_vm_pointer(), "Sanity check");
   190       assert(cur->is_allocation_record() && next->is_deallocation_record(),
   191              "sorting order");
   192       assert(cur->seq() != next->seq(), "Sanity check");
   193       return cur->seq() >  next->seq() ? cur : next;
   194     }
   195   }
   197   MemPointer* next() {
   198     MemPointerRecord* cur = (MemPointerRecord*)_itr.current();
   199     assert(cur == NULL || !cur->is_vm_pointer(), "Sanity check");
   200     MemPointerRecord* next = (MemPointerRecord*)_itr.next();
   201     if (next == NULL) {
   202       return NULL;
   203     }
   204     if (cur->addr() == next->addr()) {
   205       next = (MemPointerRecord*)_itr.next();
   206     }
   207     return current();
   208   }
   210   MemPointer* peek_next() const      { ShouldNotReachHere(); return NULL; }
   211   MemPointer* peek_prev() const      { ShouldNotReachHere(); return NULL; }
   212   void remove()                      { ShouldNotReachHere(); }
   213   bool insert(MemPointer* ptr)       { ShouldNotReachHere(); return false; }
   214   bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; }
   215 };
   217 class StagingArea : public _ValueObj {
   218  private:
   219   MemPointerArray*   _malloc_data;
   220   MemPointerArray*   _vm_data;
   222  public:
   223   StagingArea() : _malloc_data(NULL), _vm_data(NULL) {
   224     init();
   225   }
   227   ~StagingArea() {
   228     if (_malloc_data != NULL) delete _malloc_data;
   229     if (_vm_data != NULL) delete _vm_data;
   230   }
   232   MallocRecordIterator malloc_record_walker() {
   233     return MallocRecordIterator(malloc_data());
   234   }
   236   MemPointerArrayIteratorImpl virtual_memory_record_walker();
   237   bool init();
   238   void clear() {
   239     assert(_malloc_data != NULL && _vm_data != NULL, "Just check");
   240     _malloc_data->shrink();
   241     _malloc_data->clear();
   242     _vm_data->clear();
   243   }
   245   inline MemPointerArray* malloc_data() { return _malloc_data; }
   246   inline MemPointerArray* vm_data()     { return _vm_data; }
   247 };
   249 class MemBaseline;
   250 class MemSnapshot : public CHeapObj<mtNMT> {
   251  private:
   252   // the following two arrays contain records of all known lived memory blocks
   253   // live malloc-ed memory pointers
   254   MemPointerArray*      _alloc_ptrs;
   255   // live virtual memory pointers
   256   MemPointerArray*      _vm_ptrs;
   258   StagingArea           _staging_area;
   260   // the lock to protect this snapshot
   261   Monitor*              _lock;
   263   NOT_PRODUCT(size_t    _untracked_count;)
   264   friend class MemBaseline;
   266  public:
   267   MemSnapshot();
   268   virtual ~MemSnapshot();
   270   // if we are running out of native memory
   271   bool out_of_memory() {
   272     return (_alloc_ptrs == NULL ||
   273       _staging_area.malloc_data() == NULL ||
   274       _staging_area.vm_data() == NULL ||
   275       _vm_ptrs == NULL || _lock == NULL ||
   276       _alloc_ptrs->out_of_memory() ||
   277       _vm_ptrs->out_of_memory());
   278   }
   280   // merge a per-thread memory recorder into staging area
   281   bool merge(MemRecorder* rec);
   282   // promote staged data to snapshot
   283   bool promote();
   286   void wait(long timeout) {
   287     assert(_lock != NULL, "Just check");
   288     MonitorLockerEx locker(_lock);
   289     locker.wait(true, timeout);
   290   }
   292   NOT_PRODUCT(void print_snapshot_stats(outputStream* st);)
   293   NOT_PRODUCT(void check_staging_data();)
   294   NOT_PRODUCT(void check_malloc_pointers();)
   295   NOT_PRODUCT(bool has_allocation_record(address addr);)
   297  private:
   298    // copy pointer data from src to dest
   299    void copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src);
   301    bool promote_malloc_records(MemPointerArrayIterator* itr);
   302    bool promote_virtual_memory_records(MemPointerArrayIterator* itr);
   303 };
   306 #endif // SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP

mercurial