hotspot/src/share/vm/services/memBaseline.cpp
changeset 14120 7d298141c258
parent 13195 be27e1b6a4b9
child 14484 901d216b74bf
equal deleted inserted replaced
14117:6e2e697e310f 14120:7d298141c258
    38   {mtInternal,   "Internal"},
    38   {mtInternal,   "Internal"},
    39   {mtOther,      "Other"},
    39   {mtOther,      "Other"},
    40   {mtSymbol,     "Symbol"},
    40   {mtSymbol,     "Symbol"},
    41   {mtNMT,        "Memory Tracking"},
    41   {mtNMT,        "Memory Tracking"},
    42   {mtChunk,      "Pooled Free Chunks"},
    42   {mtChunk,      "Pooled Free Chunks"},
       
    43   {mtClassShared,"Shared spaces for classes"},
    43   {mtNone,       "Unknown"}  // It can happen when type tagging records are lagging
    44   {mtNone,       "Unknown"}  // It can happen when type tagging records are lagging
    44                              // behind
    45                              // behind
    45 };
    46 };
    46 
    47 
    47 MemBaseline::MemBaseline() {
    48 MemBaseline::MemBaseline() {
    53     _arena_data[index].set_type(MemType2NameMap[index]._flag);
    54     _arena_data[index].set_type(MemType2NameMap[index]._flag);
    54   }
    55   }
    55 
    56 
    56   _malloc_cs = NULL;
    57   _malloc_cs = NULL;
    57   _vm_cs = NULL;
    58   _vm_cs = NULL;
       
    59   _vm_map = NULL;
    58 
    60 
    59   _number_of_classes = 0;
    61   _number_of_classes = 0;
    60   _number_of_threads = 0;
    62   _number_of_threads = 0;
    61 }
    63 }
    62 
    64 
    68   }
    70   }
    69 
    71 
    70   if (_vm_cs != NULL) {
    72   if (_vm_cs != NULL) {
    71     delete _vm_cs;
    73     delete _vm_cs;
    72     _vm_cs = NULL;
    74     _vm_cs = NULL;
       
    75   }
       
    76 
       
    77   if (_vm_map != NULL) {
       
    78     delete _vm_map;
       
    79     _vm_map = NULL;
    73   }
    80   }
    74 
    81 
    75   reset();
    82   reset();
    76 }
    83 }
    77 
    84 
    83   _total_malloced = 0;
    90   _total_malloced = 0;
    84   _number_of_classes = 0;
    91   _number_of_classes = 0;
    85 
    92 
    86   if (_malloc_cs != NULL) _malloc_cs->clear();
    93   if (_malloc_cs != NULL) _malloc_cs->clear();
    87   if (_vm_cs != NULL) _vm_cs->clear();
    94   if (_vm_cs != NULL) _vm_cs->clear();
       
    95   if (_vm_map != NULL) _vm_map->clear();
    88 
    96 
    89   for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
    97   for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
    90     _malloc_data[index].clear();
    98     _malloc_data[index].clear();
    91     _vm_data[index].clear();
    99     _vm_data[index].clear();
    92     _arena_data[index].clear();
   100     _arena_data[index].clear();
    93   }
   101   }
    94 }
   102 }
    95 
   103 
    96 MemBaseline::~MemBaseline() {
   104 MemBaseline::~MemBaseline() {
    97   if (_malloc_cs != NULL) {
   105   clear();
    98     delete _malloc_cs;
       
    99   }
       
   100 
       
   101   if (_vm_cs != NULL) {
       
   102     delete _vm_cs;
       
   103   }
       
   104 }
   106 }
   105 
   107 
   106 // baseline malloc'd memory records, generate overall summary and summaries by
   108 // baseline malloc'd memory records, generate overall summary and summaries by
   107 // memory types
   109 // memory types
   108 bool MemBaseline::baseline_malloc_summary(const MemPointerArray* malloc_records) {
   110 bool MemBaseline::baseline_malloc_summary(const MemPointerArray* malloc_records) {
   109   MemPointerArrayIteratorImpl mItr((MemPointerArray*)malloc_records);
   111   MemPointerArrayIteratorImpl malloc_itr((MemPointerArray*)malloc_records);
   110   MemPointerRecord* mptr = (MemPointerRecord*)mItr.current();
   112   MemPointerRecord* malloc_ptr = (MemPointerRecord*)malloc_itr.current();
   111   size_t used_arena_size = 0;
   113   size_t used_arena_size = 0;
   112   int index;
   114   int index;
   113   while (mptr != NULL) {
   115   while (malloc_ptr != NULL) {
   114     index = flag2index(FLAGS_TO_MEMORY_TYPE(mptr->flags()));
   116     index = flag2index(FLAGS_TO_MEMORY_TYPE(malloc_ptr->flags()));
   115     size_t size = mptr->size();
   117     size_t size = malloc_ptr->size();
   116     _total_malloced += size;
   118     _total_malloced += size;
   117     _malloc_data[index].inc(size);
   119     _malloc_data[index].inc(size);
   118     if (MemPointerRecord::is_arena_record(mptr->flags())) {
   120     if (MemPointerRecord::is_arena_record(malloc_ptr->flags())) {
   119       // see if arena size record present
   121       // see if arena size record present
   120       MemPointerRecord* next_p = (MemPointerRecordEx*)mItr.peek_next();
   122       MemPointerRecord* next_malloc_ptr = (MemPointerRecordEx*)malloc_itr.peek_next();
   121       if (MemPointerRecord::is_arena_size_record(next_p->flags())) {
   123       if (MemPointerRecord::is_arena_size_record(next_malloc_ptr->flags())) {
   122         assert(next_p->is_size_record_of_arena(mptr), "arena records do not match");
   124         assert(next_malloc_ptr->is_size_record_of_arena(malloc_ptr), "arena records do not match");
   123         size = next_p->size();
   125         size = next_malloc_ptr->size();
   124         _arena_data[index].inc(size);
   126         _arena_data[index].inc(size);
   125         used_arena_size += size;
   127         used_arena_size += size;
   126         mItr.next();
   128         malloc_itr.next();
   127       }
   129       }
   128     }
   130     }
   129     mptr = (MemPointerRecordEx*)mItr.next();
   131     malloc_ptr = (MemPointerRecordEx*)malloc_itr.next();
   130   }
   132   }
   131 
   133 
   132   // substract used arena size to get size of arena chunk in free list
   134   // substract used arena size to get size of arena chunk in free list
   133   index = flag2index(mtChunk);
   135   index = flag2index(mtChunk);
   134   _malloc_data[index].reduce(used_arena_size);
   136   _malloc_data[index].reduce(used_arena_size);
   140 }
   142 }
   141 
   143 
   142 // baseline mmap'd memory records, generate overall summary and summaries by
   144 // baseline mmap'd memory records, generate overall summary and summaries by
   143 // memory types
   145 // memory types
   144 bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) {
   146 bool MemBaseline::baseline_vm_summary(const MemPointerArray* vm_records) {
   145   MemPointerArrayIteratorImpl vItr((MemPointerArray*)vm_records);
   147   MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records);
   146   VMMemRegion* vptr = (VMMemRegion*)vItr.current();
   148   VMMemRegion* vm_ptr = (VMMemRegion*)vm_itr.current();
   147   int index;
   149   int index;
   148   while (vptr != NULL) {
   150   while (vm_ptr != NULL) {
   149     index = flag2index(FLAGS_TO_MEMORY_TYPE(vptr->flags()));
   151     if (vm_ptr->is_reserved_region()) {
   150 
   152       index = flag2index(FLAGS_TO_MEMORY_TYPE(vm_ptr->flags()));
   151     // we use the number of thread stack to count threads
   153     // we use the number of thread stack to count threads
   152     if (IS_MEMORY_TYPE(vptr->flags(), mtThreadStack)) {
   154       if (IS_MEMORY_TYPE(vm_ptr->flags(), mtThreadStack)) {
   153       _number_of_threads ++;
   155       _number_of_threads ++;
   154     }
   156     }
   155     _total_vm_reserved += vptr->reserved_size();
   157       _total_vm_reserved += vm_ptr->size();
   156     _total_vm_committed += vptr->committed_size();
   158       _vm_data[index].inc(vm_ptr->size(), 0);
   157     _vm_data[index].inc(vptr->reserved_size(), vptr->committed_size());
   159     } else {
   158     vptr = (VMMemRegion*)vItr.next();
   160       _total_vm_committed += vm_ptr->size();
       
   161       _vm_data[index].inc(0, vm_ptr->size());
       
   162     }
       
   163     vm_ptr = (VMMemRegion*)vm_itr.next();
   159   }
   164   }
   160   return true;
   165   return true;
   161 }
   166 }
   162 
   167 
   163 // baseline malloc'd memory by callsites, but only the callsites with memory allocation
   168 // baseline malloc'd memory by callsites, but only the callsites with memory allocation
   164 // over 1KB are stored.
   169 // over 1KB are stored.
   165 bool MemBaseline::baseline_malloc_details(const MemPointerArray* malloc_records) {
   170 bool MemBaseline::baseline_malloc_details(const MemPointerArray* malloc_records) {
   166   assert(MemTracker::track_callsite(), "detail tracking is off");
   171   assert(MemTracker::track_callsite(), "detail tracking is off");
   167 
   172 
   168   MemPointerArrayIteratorImpl mItr((MemPointerArray*)malloc_records);
   173   MemPointerArrayIteratorImpl malloc_itr(const_cast<MemPointerArray*>(malloc_records));
   169   MemPointerRecordEx* mptr = (MemPointerRecordEx*)mItr.current();
   174   MemPointerRecordEx* malloc_ptr = (MemPointerRecordEx*)malloc_itr.current();
   170   MallocCallsitePointer mp;
   175   MallocCallsitePointer malloc_callsite;
   171 
   176 
       
   177   // initailize malloc callsite array
   172   if (_malloc_cs == NULL) {
   178   if (_malloc_cs == NULL) {
   173     _malloc_cs = new (std::nothrow) MemPointerArrayImpl<MallocCallsitePointer>(64);
   179     _malloc_cs = new (std::nothrow) MemPointerArrayImpl<MallocCallsitePointer>(64);
   174     // out of native memory
   180     // out of native memory
   175     if (_malloc_cs == NULL) {
   181     if (_malloc_cs == NULL || _malloc_cs->out_of_memory()) {
   176       return false;
   182       return false;
   177     }
   183     }
   178   } else {
   184   } else {
   179     _malloc_cs->clear();
   185     _malloc_cs->clear();
   180   }
   186   }
   181 
   187 
       
   188   MemPointerArray* malloc_data = const_cast<MemPointerArray*>(malloc_records);
       
   189 
       
   190   // sort into callsite pc order. Details are aggregated by callsites
       
   191   malloc_data->sort((FN_SORT)malloc_sort_by_pc);
       
   192   bool ret = true;
       
   193 
   182   // baseline memory that is totaled over 1 KB
   194   // baseline memory that is totaled over 1 KB
   183   while (mptr != NULL) {
   195   while (malloc_ptr != NULL) {
   184     if (!MemPointerRecord::is_arena_size_record(mptr->flags())) {
   196     if (!MemPointerRecord::is_arena_size_record(malloc_ptr->flags())) {
   185       // skip thread stacks
   197       // skip thread stacks
   186       if (!IS_MEMORY_TYPE(mptr->flags(), mtThreadStack)) {
   198       if (!IS_MEMORY_TYPE(malloc_ptr->flags(), mtThreadStack)) {
   187         if (mp.addr() != mptr->pc()) {
   199         if (malloc_callsite.addr() != malloc_ptr->pc()) {
   188           if ((mp.amount()/K) > 0) {
   200           if ((malloc_callsite.amount()/K) > 0) {
   189             if (!_malloc_cs->append(&mp)) {
   201             if (!_malloc_cs->append(&malloc_callsite)) {
       
   202               ret = false;
       
   203               break;
       
   204             }
       
   205           }
       
   206           malloc_callsite = MallocCallsitePointer(malloc_ptr->pc());
       
   207         }
       
   208         malloc_callsite.inc(malloc_ptr->size());
       
   209       }
       
   210     }
       
   211     malloc_ptr = (MemPointerRecordEx*)malloc_itr.next();
       
   212   }
       
   213 
       
   214   // restore to address order. Snapshot malloc data is maintained in memory
       
   215   // address order.
       
   216   malloc_data->sort((FN_SORT)malloc_sort_by_addr);
       
   217 
       
   218   if (!ret) {
   190               return false;
   219               return false;
   191             }
   220             }
   192           }
   221   // deal with last record
   193           mp = MallocCallsitePointer(mptr->pc());
   222   if (malloc_callsite.addr() != 0 && (malloc_callsite.amount()/K) > 0) {
   194         }
   223     if (!_malloc_cs->append(&malloc_callsite)) {
   195         mp.inc(mptr->size());
       
   196       }
       
   197     }
       
   198     mptr = (MemPointerRecordEx*)mItr.next();
       
   199   }
       
   200 
       
   201   if (mp.addr() != 0 && (mp.amount()/K) > 0) {
       
   202     if (!_malloc_cs->append(&mp)) {
       
   203       return false;
   224       return false;
   204     }
   225     }
   205   }
   226   }
   206   return true;
   227   return true;
   207 }
   228 }
   208 
   229 
   209 // baseline mmap'd memory by callsites
   230 // baseline mmap'd memory by callsites
   210 bool MemBaseline::baseline_vm_details(const MemPointerArray* vm_records) {
   231 bool MemBaseline::baseline_vm_details(const MemPointerArray* vm_records) {
   211   assert(MemTracker::track_callsite(), "detail tracking is off");
   232   assert(MemTracker::track_callsite(), "detail tracking is off");
   212 
   233 
   213   VMCallsitePointer vp;
   234   VMCallsitePointer  vm_callsite;
   214   MemPointerArrayIteratorImpl vItr((MemPointerArray*)vm_records);
   235   VMCallsitePointer* cur_callsite = NULL;
   215   VMMemRegionEx* vptr = (VMMemRegionEx*)vItr.current();
   236   MemPointerArrayIteratorImpl vm_itr((MemPointerArray*)vm_records);
   216 
   237   VMMemRegionEx* vm_ptr = (VMMemRegionEx*)vm_itr.current();
       
   238 
       
   239   // initialize virtual memory map array
       
   240   if (_vm_map == NULL) {
       
   241     _vm_map = new (std::nothrow) MemPointerArrayImpl<VMMemRegionEx>(vm_records->length());
       
   242    if (_vm_map == NULL || _vm_map->out_of_memory()) {
       
   243      return false;
       
   244    }
       
   245   } else {
       
   246     _vm_map->clear();
       
   247   }
       
   248 
       
   249   // initialize virtual memory callsite array
   217   if (_vm_cs == NULL) {
   250   if (_vm_cs == NULL) {
   218     _vm_cs = new (std::nothrow) MemPointerArrayImpl<VMCallsitePointer>(64);
   251     _vm_cs = new (std::nothrow) MemPointerArrayImpl<VMCallsitePointer>(64);
   219     if (_vm_cs == NULL) {
   252     if (_vm_cs == NULL || _vm_cs->out_of_memory()) {
   220       return false;
   253       return false;
   221     }
   254     }
   222   } else {
   255   } else {
   223     _vm_cs->clear();
   256     _vm_cs->clear();
   224   }
   257   }
   225 
   258 
   226   while (vptr != NULL) {
   259   // consolidate virtual memory data
   227     if (vp.addr() != vptr->pc()) {
   260   VMMemRegionEx*     reserved_rec = NULL;
   228       if (!_vm_cs->append(&vp)) {
   261   VMMemRegionEx*     committed_rec = NULL;
       
   262 
       
   263   // vm_ptr is coming in increasing base address order
       
   264   while (vm_ptr != NULL) {
       
   265     if (vm_ptr->is_reserved_region()) {
       
   266       // consolidate reserved memory regions for virtual memory map.
       
   267       // The criteria for consolidation is:
       
   268       // 1. two adjacent reserved memory regions
       
   269       // 2. belong to the same memory type
       
   270       // 3. reserved from the same callsite
       
   271       if (reserved_rec == NULL ||
       
   272         reserved_rec->base() + reserved_rec->size() != vm_ptr->addr() ||
       
   273         FLAGS_TO_MEMORY_TYPE(reserved_rec->flags()) != FLAGS_TO_MEMORY_TYPE(vm_ptr->flags()) ||
       
   274         reserved_rec->pc() != vm_ptr->pc()) {
       
   275         if (!_vm_map->append(vm_ptr)) {
   229         return false;
   276         return false;
   230       }
   277       }
   231       vp = VMCallsitePointer(vptr->pc());
   278         // inserted reserved region, we need the pointer to the element in virtual
   232     }
   279         // memory map array.
   233     vp.inc(vptr->size(), vptr->committed_size());
   280         reserved_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1);
   234     vptr = (VMMemRegionEx*)vItr.next();
   281       } else {
   235   }
   282         reserved_rec->expand_region(vm_ptr->addr(), vm_ptr->size());
   236   if (vp.addr() != 0) {
   283     }
   237     if (!_vm_cs->append(&vp)) {
   284 
       
   285       if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) {
   238       return false;
   286       return false;
   239     }
   287     }
   240   }
   288       vm_callsite = VMCallsitePointer(vm_ptr->pc());
       
   289       cur_callsite = &vm_callsite;
       
   290       vm_callsite.inc(vm_ptr->size(), 0);
       
   291     } else {
       
   292       // consolidate committed memory regions for virtual memory map
       
   293       // The criterial is:
       
   294       // 1. two adjacent committed memory regions
       
   295       // 2. committed from the same callsite
       
   296       if (committed_rec == NULL ||
       
   297         committed_rec->base() + committed_rec->size() != vm_ptr->addr() ||
       
   298         committed_rec->pc() != vm_ptr->pc()) {
       
   299         if (!_vm_map->append(vm_ptr)) {
       
   300           return false;
       
   301   }
       
   302         committed_rec = (VMMemRegionEx*)_vm_map->at(_vm_map->length() - 1);
       
   303     } else {
       
   304         committed_rec->expand_region(vm_ptr->addr(), vm_ptr->size());
       
   305       }
       
   306       vm_callsite.inc(0, vm_ptr->size());
       
   307     }
       
   308     vm_ptr = (VMMemRegionEx*)vm_itr.next();
       
   309   }
       
   310   // deal with last record
       
   311   if (cur_callsite != NULL && !_vm_cs->append(cur_callsite)) {
       
   312     return false;
       
   313   }
       
   314 
       
   315   // sort it into callsite pc order. Details are aggregated by callsites
       
   316   _vm_cs->sort((FN_SORT)bl_vm_sort_by_pc);
       
   317 
       
   318   // walk the array to consolidate record by pc
       
   319   MemPointerArrayIteratorImpl itr(_vm_cs);
       
   320   VMCallsitePointer* callsite_rec = (VMCallsitePointer*)itr.current();
       
   321   VMCallsitePointer* next_rec = (VMCallsitePointer*)itr.next();
       
   322   while (next_rec != NULL) {
       
   323     assert(callsite_rec != NULL, "Sanity check");
       
   324     if (next_rec->addr() == callsite_rec->addr()) {
       
   325       callsite_rec->inc(next_rec->reserved_amount(), next_rec->committed_amount());
       
   326       itr.remove();
       
   327       next_rec = (VMCallsitePointer*)itr.current();
       
   328     } else {
       
   329       callsite_rec = next_rec;
       
   330       next_rec = (VMCallsitePointer*)itr.next();
       
   331     }
       
   332   }
       
   333 
   241   return true;
   334   return true;
   242 }
   335 }
   243 
   336 
   244 // baseline a snapshot. If summary_only = false, memory usages aggregated by
   337 // baseline a snapshot. If summary_only = false, memory usages aggregated by
   245 // callsites are also baselined.
   338 // callsites are also baselined.
   249   _baselined = baseline_malloc_summary(snapshot._alloc_ptrs) &&
   342   _baselined = baseline_malloc_summary(snapshot._alloc_ptrs) &&
   250                baseline_vm_summary(snapshot._vm_ptrs);
   343                baseline_vm_summary(snapshot._vm_ptrs);
   251   _number_of_classes = SystemDictionary::number_of_classes();
   344   _number_of_classes = SystemDictionary::number_of_classes();
   252 
   345 
   253   if (!summary_only && MemTracker::track_callsite() && _baselined) {
   346   if (!summary_only && MemTracker::track_callsite() && _baselined) {
   254     ((MemPointerArray*)snapshot._alloc_ptrs)->sort((FN_SORT)malloc_sort_by_pc);
       
   255     ((MemPointerArray*)snapshot._vm_ptrs)->sort((FN_SORT)vm_sort_by_pc);
       
   256     _baselined =  baseline_malloc_details(snapshot._alloc_ptrs) &&
   347     _baselined =  baseline_malloc_details(snapshot._alloc_ptrs) &&
   257       baseline_vm_details(snapshot._vm_ptrs);
   348       baseline_vm_details(snapshot._vm_ptrs);
   258     ((MemPointerArray*)snapshot._alloc_ptrs)->sort((FN_SORT)malloc_sort_by_addr);
       
   259     ((MemPointerArray*)snapshot._vm_ptrs)->sort((FN_SORT)vm_sort_by_addr);
       
   260   }
   349   }
   261   return _baselined;
   350   return _baselined;
   262 }
   351 }
   263 
   352 
   264 
   353 
   276   for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
   365   for (int index = 0; index < NUMBER_OF_MEMORY_TYPE; index ++) {
   277     if (MemType2NameMap[index]._flag == type) {
   366     if (MemType2NameMap[index]._flag == type) {
   278       return MemType2NameMap[index]._name;
   367       return MemType2NameMap[index]._name;
   279     }
   368     }
   280   }
   369   }
   281   assert(false, "no type");
   370   assert(false, err_msg("bad type %x", type));
   282   return NULL;
   371   return NULL;
   283 }
   372 }
   284 
   373 
   285 
   374 
   286 MemBaseline& MemBaseline::operator=(const MemBaseline& other) {
   375 MemBaseline& MemBaseline::operator=(const MemBaseline& other) {
   339   const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1;
   428   const MallocCallsitePointer* mp1 = (const MallocCallsitePointer*)p1;
   340   const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2;
   429   const MallocCallsitePointer* mp2 = (const MallocCallsitePointer*)p2;
   341   return UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
   430   return UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
   342 }
   431 }
   343 
   432 
   344 // sort snapshot mmap'd records in callsite pc order
       
   345 int MemBaseline::vm_sort_by_pc(const void* p1, const void* p2) {
       
   346   assert(MemTracker::track_callsite(),"Just check");
       
   347   const VMMemRegionEx* mp1 = (const VMMemRegionEx*)p1;
       
   348   const VMMemRegionEx* mp2 = (const VMMemRegionEx*)p2;
       
   349   return UNSIGNED_COMPARE(mp1->pc(), mp2->pc());
       
   350 }
       
   351 
   433 
   352 // sort baselined mmap'd records in size (reserved size) order
   434 // sort baselined mmap'd records in size (reserved size) order
   353 int MemBaseline::bl_vm_sort_by_size(const void* p1, const void* p2) {
   435 int MemBaseline::bl_vm_sort_by_size(const void* p1, const void* p2) {
   354   assert(MemTracker::is_on(), "Just check");
   436   assert(MemTracker::is_on(), "Just check");
   355   const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1;
   437   const VMCallsitePointer* mp1 = (const VMCallsitePointer*)p1;
   374   int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
   456   int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
   375   assert(delta != 0, "dup pointer");
   457   assert(delta != 0, "dup pointer");
   376   return delta;
   458   return delta;
   377 }
   459 }
   378 
   460 
   379 // sort snapshot mmap'd records in memory block address order
       
   380 int MemBaseline::vm_sort_by_addr(const void* p1, const void* p2) {
       
   381   assert(MemTracker::is_on(), "Just check");
       
   382   const VMMemRegion* mp1 = (const VMMemRegion*)p1;
       
   383   const VMMemRegion* mp2 = (const VMMemRegion*)p2;
       
   384   int delta = UNSIGNED_COMPARE(mp1->addr(), mp2->addr());
       
   385   assert(delta != 0, "dup pointer");
       
   386   return delta;
       
   387 }