1.1 --- a/src/share/vm/services/memSnapshot.hpp Thu Oct 18 13:09:47 2012 -0400 1.2 +++ b/src/share/vm/services/memSnapshot.hpp Fri Oct 19 21:40:07 2012 -0400 1.3 @@ -111,33 +111,41 @@ 1.4 MemPointerIterator(arr) { 1.5 } 1.6 1.7 - // locate an existing record that contains specified address, or 1.8 - // the record, where the record with specified address, should 1.9 - // be inserted. 1.10 - // virtual memory record array is sorted in address order, so 1.11 - // binary search is performed 1.12 + // locate an existing reserved memory region that contains specified address, 1.13 + // or the reserved region just above this address, where the incoming 1.14 + // reserved region should be inserted. 1.15 virtual MemPointer* locate(address addr) { 1.16 - int index_low = 0; 1.17 - int index_high = _array->length(); 1.18 - int index_mid = (index_high + index_low) / 2; 1.19 - int r = 1; 1.20 - while (index_low < index_high && (r = compare(index_mid, addr)) != 0) { 1.21 - if (r > 0) { 1.22 - index_high = index_mid; 1.23 - } else { 1.24 - index_low = index_mid; 1.25 + reset(); 1.26 + VMMemRegion* reg = (VMMemRegion*)current(); 1.27 + while (reg != NULL) { 1.28 + if (reg->is_reserved_region()) { 1.29 + if (reg->contains_address(addr) || addr < reg->base()) { 1.30 + return reg; 1.31 } 1.32 - index_mid = (index_high + index_low) / 2; 1.33 } 1.34 - if (r == 0) { 1.35 - // update current location 1.36 - _pos = index_mid; 1.37 - return _array->at(index_mid); 1.38 - } else { 1.39 + reg = (VMMemRegion*)next(); 1.40 + } 1.41 return NULL; 1.42 } 1.43 - } 1.44 1.45 + // following methods update virtual memory in the context 1.46 + // of 'current' position, which is properly positioned by 1.47 + // callers via locate method. 1.48 + bool add_reserved_region(MemPointerRecord* rec); 1.49 + bool add_committed_region(MemPointerRecord* rec); 1.50 + bool remove_uncommitted_region(MemPointerRecord* rec); 1.51 + bool remove_released_region(MemPointerRecord* rec); 1.52 + 1.53 + // split a reserved region to create a new memory region with specified base and size 1.54 + bool split_reserved_region(VMMemRegion* rgn, address new_rgn_addr, size_t new_rgn_size); 1.55 + private: 1.56 + bool insert_record(MemPointerRecord* rec); 1.57 + bool insert_record_after(MemPointerRecord* rec); 1.58 + 1.59 + bool insert_reserved_region(MemPointerRecord* rec); 1.60 + 1.61 + // reset current position 1.62 + inline void reset() { _pos = 0; } 1.63 #ifdef ASSERT 1.64 virtual bool is_dup_pointer(const MemPointer* ptr1, 1.65 const MemPointer* ptr2) const { 1.66 @@ -154,32 +162,17 @@ 1.67 (p1->flags() & MemPointerRecord::tag_masks) == MemPointerRecord::tag_release; 1.68 } 1.69 #endif 1.70 - // compare if an address falls into a memory region, 1.71 - // return 0, if the address falls into a memory region at specified index 1.72 - // return 1, if memory region pointed by specified index is higher than the address 1.73 - // return -1, if memory region pointed by specified index is lower than the address 1.74 - int compare(int index, address addr) const { 1.75 - VMMemRegion* r = (VMMemRegion*)_array->at(index); 1.76 - assert(r->is_reserve_record(), "Sanity check"); 1.77 - if (r->addr() > addr) { 1.78 - return 1; 1.79 - } else if (r->addr() + r->reserved_size() <= addr) { 1.80 - return -1; 1.81 - } else { 1.82 - return 0; 1.83 - } 1.84 - } 1.85 }; 1.86 1.87 class MallocRecordIterator : public MemPointerArrayIterator { 1.88 - private: 1.89 + protected: 1.90 MemPointerArrayIteratorImpl _itr; 1.91 1.92 public: 1.93 MallocRecordIterator(MemPointerArray* arr) : _itr(arr) { 1.94 } 1.95 1.96 - MemPointer* current() const { 1.97 + virtual MemPointer* current() const { 1.98 MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); 1.99 assert(cur == NULL || !cur->is_vm_pointer(), "seek error"); 1.100 MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); 1.101 @@ -194,7 +187,7 @@ 1.102 } 1.103 } 1.104 1.105 - MemPointer* next() { 1.106 + virtual MemPointer* next() { 1.107 MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); 1.108 assert(cur == NULL || !cur->is_vm_pointer(), "Sanity check"); 1.109 MemPointerRecord* next = (MemPointerRecord*)_itr.next(); 1.110 @@ -214,6 +207,63 @@ 1.111 bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; } 1.112 }; 1.113 1.114 +// collapse duplicated records. Eliminating duplicated records here, is much 1.115 +// cheaper than during promotion phase. However, it does have limitation - it 1.116 +// can only eliminate duplicated records within the generation, there are 1.117 +// still chances seeing duplicated records during promotion. 1.118 +// We want to use the record with higher sequence number, because it has 1.119 +// more accurate callsite pc. 1.120 +class VMRecordIterator : public MallocRecordIterator { 1.121 + public: 1.122 + VMRecordIterator(MemPointerArray* arr) : MallocRecordIterator(arr) { 1.123 + MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); 1.124 + MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); 1.125 + while (next != NULL) { 1.126 + assert(cur != NULL, "Sanity check"); 1.127 + assert(((SeqMemPointerRecord*)next)->seq() > ((SeqMemPointerRecord*)cur)->seq(), 1.128 + "pre-sort order"); 1.129 + 1.130 + if (is_duplicated_record(cur, next)) { 1.131 + _itr.next(); 1.132 + next = (MemPointerRecord*)_itr.peek_next(); 1.133 + } else { 1.134 + break; 1.135 + } 1.136 + } 1.137 + } 1.138 + 1.139 + virtual MemPointer* current() const { 1.140 + return _itr.current(); 1.141 + } 1.142 + 1.143 + // get next record, but skip the duplicated records 1.144 + virtual MemPointer* next() { 1.145 + MemPointerRecord* cur = (MemPointerRecord*)_itr.next(); 1.146 + MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); 1.147 + while (next != NULL) { 1.148 + assert(cur != NULL, "Sanity check"); 1.149 + assert(((SeqMemPointerRecord*)next)->seq() > ((SeqMemPointerRecord*)cur)->seq(), 1.150 + "pre-sort order"); 1.151 + 1.152 + if (is_duplicated_record(cur, next)) { 1.153 + _itr.next(); 1.154 + cur = next; 1.155 + next = (MemPointerRecord*)_itr.peek_next(); 1.156 + } else { 1.157 + break; 1.158 + } 1.159 + } 1.160 + return cur; 1.161 + } 1.162 + 1.163 + private: 1.164 + bool is_duplicated_record(MemPointerRecord* p1, MemPointerRecord* p2) const { 1.165 + bool ret = (p1->addr() == p2->addr() && p1->size() == p2->size() && p1->flags() == p2->flags()); 1.166 + assert(!(ret && FLAGS_TO_MEMORY_TYPE(p1->flags()) == mtThreadStack), "dup on stack record"); 1.167 + return ret; 1.168 + } 1.169 +}; 1.170 + 1.171 class StagingArea : public _ValueObj { 1.172 private: 1.173 MemPointerArray* _malloc_data; 1.174 @@ -233,7 +283,8 @@ 1.175 return MallocRecordIterator(malloc_data()); 1.176 } 1.177 1.178 - MemPointerArrayIteratorImpl virtual_memory_record_walker(); 1.179 + VMRecordIterator virtual_memory_record_walker(); 1.180 + 1.181 bool init(); 1.182 void clear() { 1.183 assert(_malloc_data != NULL && _vm_data != NULL, "Just check"); 1.184 @@ -293,6 +344,8 @@ 1.185 NOT_PRODUCT(void check_staging_data();) 1.186 NOT_PRODUCT(void check_malloc_pointers();) 1.187 NOT_PRODUCT(bool has_allocation_record(address addr);) 1.188 + // dump all virtual memory pointers in snapshot 1.189 + DEBUG_ONLY( void dump_all_vm_pointers();) 1.190 1.191 private: 1.192 // copy pointer data from src to dest 1.193 @@ -302,5 +355,4 @@ 1.194 bool promote_virtual_memory_records(MemPointerArrayIterator* itr); 1.195 }; 1.196 1.197 - 1.198 #endif // SHARE_VM_SERVICES_MEM_SNAPSHOT_HPP