--- old/src/share/vm/services/memSnapshot.hpp 2012-11-07 10:54:24.753243000 -0500 +++ new/src/share/vm/services/memSnapshot.hpp 2012-11-07 10:54:23.740581000 -0500 @@ -31,7 +31,6 @@ #include "services/memBaseline.hpp" #include "services/memPtrArray.hpp" - // Snapshot pointer array iterator // The pointer array contains malloc-ed pointers @@ -165,39 +164,56 @@ }; class MallocRecordIterator : public MemPointerArrayIterator { - protected: + private: MemPointerArrayIteratorImpl _itr; + + public: MallocRecordIterator(MemPointerArray* arr) : _itr(arr) { } virtual MemPointer* current() const { - MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); - assert(cur == NULL || !cur->is_vm_pointer(), "seek error"); - MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); - if (next == NULL || next->addr() != cur->addr()) { - return cur; - } else { - assert(!cur->is_vm_pointer(), "Sanity check"); - assert(cur->is_allocation_record() && next->is_deallocation_record(), - "sorting order"); - assert(cur->seq() != next->seq(), "Sanity check"); - return cur->seq() > next->seq() ? cur : next; - } +#ifdef ASSERT + MemPointer* cur_rec = _itr.current(); + if (cur_rec != NULL) { + MemPointer* prev_rec = _itr.peek_prev(); + MemPointer* next_rec = _itr.peek_next(); + assert(prev_rec == NULL || prev_rec->addr() < cur_rec->addr(), "Sorting order"); + assert(next_rec == NULL || next_rec->addr() > cur_rec->addr(), "Sorting order"); + } +#endif + return _itr.current(); } - virtual MemPointer* next() { - MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); - assert(cur == NULL || !cur->is_vm_pointer(), "Sanity check"); - MemPointerRecord* next = (MemPointerRecord*)_itr.next(); - if (next == NULL) { - return NULL; - } - if (cur->addr() == next->addr()) { - next = (MemPointerRecord*)_itr.next(); + MemPointerRecord* next_rec = (MemPointerRecord*)_itr.next(); + // arena size record is a special case, which we have to compare + // sequence number against its associated arena record. + if (next_rec != NULL && next_rec->is_arena_size_record()) { + MemPointerRecord* prev_rec = (MemPointerRecord*)_itr.peek_prev(); + // if there is an associated arena record, it has to be previous + // record because of sorting order + if (prev_rec != NULL && prev_rec->is_arena_record() && + next_rec->is_size_record_of_arena(prev_rec)) { + if (prev_rec->seq() > next_rec->seq()) { + // Skip this arena size record + // Two scenarios: + // - if the arena record is an allocation record, this early + // size record must be leftover by previous arena, + // and the last size record should have size = 0. + // - if the arena record is a deallocation record, this + // size record should be its cleanup record, which should + // also have size = 0. In other world, arena alway reset + // its size before gone (see Arena's destructor) + assert(next_rec->size() == 0, "size not reset"); + return _itr.next(); + } else { + assert(prev_rec->is_allocation_record(), + "Arena size record ahead of allocation record"); + } + } } - return current(); + return next_rec; } MemPointer* peek_next() const { ShouldNotReachHere(); return NULL; } @@ -213,9 +229,12 @@ // still chances seeing duplicated records during promotion. // We want to use the record with higher sequence number, because it has // more accurate callsite pc. -class VMRecordIterator : public MallocRecordIterator { +class VMRecordIterator : public MemPointerArrayIterator { + private: + MemPointerArrayIteratorImpl _itr; + public: - VMRecordIterator(MemPointerArray* arr) : MallocRecordIterator(arr) { + VMRecordIterator(MemPointerArray* arr) : _itr(arr) { MemPointerRecord* cur = (MemPointerRecord*)_itr.current(); MemPointerRecord* next = (MemPointerRecord*)_itr.peek_next(); while (next != NULL) { @@ -256,6 +275,12 @@ return cur; } + MemPointer* peek_next() const { ShouldNotReachHere(); return NULL; } + MemPointer* peek_prev() const { ShouldNotReachHere(); return NULL; } + void remove() { ShouldNotReachHere(); } + bool insert(MemPointer* ptr) { ShouldNotReachHere(); return false; } + bool insert_after(MemPointer* ptr) { ShouldNotReachHere(); return false; } + private: bool is_duplicated_record(MemPointerRecord* p1, MemPointerRecord* p2) const { bool ret = (p1->addr() == p2->addr() && p1->size() == p2->size() && p1->flags() == p2->flags()); @@ -348,8 +373,10 @@ DEBUG_ONLY( void dump_all_vm_pointers();) private: - // copy pointer data from src to dest - void copy_pointer(MemPointerRecord* dest, const MemPointerRecord* src); + // copy sequenced pointer from src to dest + void copy_seq_pointer(MemPointerRecord* dest, const MemPointerRecord* src); + // assign a sequenced pointer to non-sequenced pointer + void assign_pointer(MemPointerRecord*dest, const MemPointerRecord* src); bool promote_malloc_records(MemPointerArrayIterator* itr); bool promote_virtual_memory_records(MemPointerArrayIterator* itr);