1.1 --- a/src/share/vm/services/memSnapshot.hpp Tue Sep 04 16:20:28 2012 -0700 1.2 +++ b/src/share/vm/services/memSnapshot.hpp Tue Sep 11 20:53:17 2012 -0400 1.3 @@ -111,37 +111,31 @@ 1.4 MemPointerIterator(arr) { 1.5 } 1.6 1.7 - // locate an exiting record that contains specified address, or 1.8 + // locate an existing record that contains specified address, or 1.9 // the record, where the record with specified address, should 1.10 - // be inserted 1.11 + // be inserted. 1.12 + // virtual memory record array is sorted in address order, so 1.13 + // binary search is performed 1.14 virtual MemPointer* locate(address addr) { 1.15 - VMMemRegion* cur = (VMMemRegion*)current(); 1.16 - VMMemRegion* next_p; 1.17 - 1.18 - while (cur != NULL) { 1.19 - if (cur->base() > addr) { 1.20 - return cur; 1.21 + int index_low = 0; 1.22 + int index_high = _array->length(); 1.23 + int index_mid = (index_high + index_low) / 2; 1.24 + int r = 1; 1.25 + while (index_low < index_high && (r = compare(index_mid, addr)) != 0) { 1.26 + if (r > 0) { 1.27 + index_high = index_mid; 1.28 } else { 1.29 - // find nearest existing range that has base address <= addr 1.30 - next_p = (VMMemRegion*)peek_next(); 1.31 - if (next_p != NULL && next_p->base() <= addr) { 1.32 - cur = (VMMemRegion*)next(); 1.33 - continue; 1.34 - } 1.35 + index_low = index_mid; 1.36 } 1.37 - 1.38 - if (cur->is_reserve_record() && 1.39 - cur->base() <= addr && 1.40 - (cur->base() + cur->size() > addr)) { 1.41 - return cur; 1.42 - } else if (cur->is_commit_record() && 1.43 - cur->base() <= addr && 1.44 - (cur->base() + cur->committed_size() > addr)) { 1.45 - return cur; 1.46 - } 1.47 - cur = (VMMemRegion*)next(); 1.48 + index_mid = (index_high + index_low) / 2; 1.49 } 1.50 - return NULL; 1.51 + if (r == 0) { 1.52 + // update current location 1.53 + _pos = index_mid; 1.54 + return _array->at(index_mid); 1.55 + } else { 1.56 + return NULL; 1.57 + } 1.58 } 1.59 1.60 #ifdef ASSERT 1.61 @@ -160,75 +154,99 @@ 1.62 (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release; 1.63 } 1.64 #endif 1.65 + // compare if an address falls into a memory region, 1.66 + // return 0, if the address falls into a memory region at specified index 1.67 + // return 1, if memory region pointed by specified index is higher than the address 1.68 + // return -1, if memory region pointed by specified index is lower than the address 1.69 + int compare(int index, address addr) const { 1.70 + VMMemRegion* r = (VMMemRegion*)_array->at(index); 1.71 + assert(r->is_reserve_record(), "Sanity check"); 1.72 + if (r->addr() > addr) { 1.73 + return 1; 1.74 + } else if (r->addr() + r->reserved_size() <= addr) { 1.75 + return -1; 1.76 + } else { 1.77 + return 0; 1.78 + } 1.79 + } 1.80 }; 1.81 1.82 -class StagingWalker : public MemPointerArrayIterator { 1.83 +class MallocRecordIterator : public MemPointerArrayIterator { 1.84 private: 1.85 MemPointerArrayIteratorImpl _itr; 1.86 - bool _is_vm_record; 1.87 - bool _end_of_array; 1.88 - VMMemRegionEx _vm_record; 1.89 - MemPointerRecordEx _malloc_record; 1.90 1.91 public: 1.92 - StagingWalker(MemPointerArray* arr): _itr(arr) { 1.93 - _end_of_array = false; 1.94 - next(); 1.95 + MallocRecordIterator(MemPointerArray* arr) : _itr(arr) { 1.96 } 1.97 1.98 - // return the pointer at current position 1.99 MemPointer* current() const { 1.100 - if (_end_of_array) { 1.101 - return NULL; 1.102 - } 1.103 - if (is_vm_record()) { 1.104 - return (MemPointer*)&_vm_record; 1.105 + MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); 1.106 + assert(cur == NULL || !cur->is_vm_pointer(), "seek error"); 1.107 + MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); 1.108 + if (next == NULL || next->addr() != cur->addr()) { 1.109 + return cur; 1.110 } else { 1.111 - return (MemPointer*)&_malloc_record; 1.112 + assert(!cur->is_vm_pointer(), "Sanity check"); 1.113 + assert(cur->is_allocation_record() && next->is_deallocation_record(), 1.114 + "sorting order"); 1.115 + assert(cur->seq() != next->seq(), "Sanity check"); 1.116 + return cur->seq() > next->seq() ? cur : next; 1.117 } 1.118 } 1.119 1.120 - // return the next pointer and advance current position 1.121 - MemPointer* next(); 1.122 - 1.123 - // type of 'current' record 1.124 - bool is_vm_record() const { 1.125 - return _is_vm_record; 1.126 + MemPointer* next() { 1.127 + MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); 1.128 + assert(cur == NULL || !cur->is_vm_pointer(), "Sanity check"); 1.129 + MemPointerRecord* next = (MemPointerRecord*)_itr.next(); 1.130 + if (next == NULL) { 1.131 + return NULL; 1.132 + } 1.133 + if (cur->addr() == next->addr()) { 1.134 + next = (MemPointerRecord*)_itr.next(); 1.135 + } 1.136 + return current(); 1.137 } 1.138 1.139 - // return the next poinger without advancing current position 1.140 - MemPointer* peek_next() const { 1.141 - assert(false, "not supported"); 1.142 - return NULL; 1.143 + MemPointer* peek_next() const { ShouldNotReachHere(); return NULL; } 1.144 + MemPointer* peek_prev() const { ShouldNotReachHere(); return NULL; } 1.145 + void remove() { ShouldNotReachHere(); } 1.146 + bool insert(MemPointer* ptr) { ShouldNotReachHere(); return false; } 1.147 + bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; } 1.148 +}; 1.149 + 1.150 +class StagingArea : public _ValueObj { 1.151 + private: 1.152 + MemPointerArray* _malloc_data; 1.153 + MemPointerArray* _vm_data; 1.154 + 1.155 + public: 1.156 + StagingArea() : _malloc_data(NULL), _vm_data(NULL) { 1.157 + init(); 1.158 } 1.159 1.160 - MemPointer* peek_prev() const { 1.161 - assert(false, "not supported"); 1.162 - return NULL; 1.163 - } 1.164 - // remove the pointer at current position 1.165 - void remove() { 1.166 - assert(false, "not supported"); 1.167 + ~StagingArea() { 1.168 + if (_malloc_data != NULL) delete _malloc_data; 1.169 + if (_vm_data != NULL) delete _vm_data; 1.170 } 1.171 1.172 - // insert the pointer at current position 1.173 - bool insert(MemPointer* ptr) { 1.174 - assert(false, "not supported"); 1.175 - return false; 1.176 + MallocRecordIterator malloc_record_walker() { 1.177 + return MallocRecordIterator(malloc_data()); 1.178 } 1.179 1.180 - bool insert_after(MemPointer* ptr) { 1.181 - assert(false, "not supported"); 1.182 - return false; 1.183 + MemPointerArrayIteratorImpl virtual_memory_record_walker(); 1.184 + bool init(); 1.185 + void clear() { 1.186 + assert(_malloc_data != NULL && _vm_data != NULL, "Just check"); 1.187 + _malloc_data->shrink(); 1.188 + _malloc_data->clear(); 1.189 + _vm_data->clear(); 1.190 } 1.191 1.192 - private: 1.193 - // consolidate all records referring to this vm region 1.194 - bool consolidate_vm_records(VMMemRegionEx* vm_rec); 1.195 + inline MemPointerArray* malloc_data() { return _malloc_data; } 1.196 + inline MemPointerArray* vm_data() { return _vm_data; } 1.197 }; 1.198 1.199 class MemBaseline; 1.200 - 1.201 class MemSnapshot : public CHeapObj<mtNMT> { 1.202 private: 1.203 // the following two arrays contain records of all known lived memory blocks 1.204 @@ -237,9 +255,7 @@ 1.205 // live virtual memory pointers 1.206 MemPointerArray* _vm_ptrs; 1.207 1.208 - // stagging a generation's data, before 1.209 - // it can be prompted to snapshot 1.210 - MemPointerArray* _staging_area; 1.211 + StagingArea _staging_area; 1.212 1.213 // the lock to protect this snapshot 1.214 Monitor* _lock; 1.215 @@ -252,18 +268,19 @@ 1.216 virtual ~MemSnapshot(); 1.217 1.218 // if we are running out of native memory 1.219 - bool out_of_memory() const { 1.220 - return (_alloc_ptrs == NULL || _staging_area == NULL || 1.221 + bool out_of_memory() { 1.222 + return (_alloc_ptrs == NULL || 1.223 + _staging_area.malloc_data() == NULL || 1.224 + _staging_area.vm_data() == NULL || 1.225 _vm_ptrs == NULL || _lock == NULL || 1.226 _alloc_ptrs->out_of_memory() || 1.227 - _staging_area->out_of_memory() || 1.228 _vm_ptrs->out_of_memory()); 1.229 } 1.230 1.231 // merge a per-thread memory recorder into staging area 1.232 bool merge(MemRecorder* rec); 1.233 // promote staged data to snapshot 1.234 - void promote(); 1.235 + bool promote(); 1.236 1.237 1.238 void wait(long timeout) { 1.239 @@ -280,6 +297,9 @@ 1.240 private: 1.241 // copy pointer data from src to dest 1.242 void copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src); 1.243 + 1.244 + bool promote_malloc_records(MemPointerArrayIterator* itr); 1.245 + bool promote_virtual_memory_records(MemPointerArrayIterator* itr); 1.246 }; 1.247 1.248