< prev index next >

src/hotspot/share/code/codeHeapState.cpp

Print this page




 100     _sstbuf->print("%s", termString);                     \
 101     _outbuf->print("%s", _sstbuf->as_string());           \
 102     _sstbuf->reset();
 103 
 104 #define STRINGSTREAM_FLUSH_LOCKED(termString)             \
 105     { ttyLocker ttyl;/* keep this output block together */\
 106       STRINGSTREAM_FLUSH(termString)                      \
 107     }
 108 #else
 109 #define STRINGSTREAM_DECL(_anyst, _outst)                 \
 110     outputStream*  _outbuf = _outst;                      \
 111     outputStream*  _anyst  = _outst;   /* any stream. Use this to just print - no buffer flush.  */
 112 
 113 #define STRINGSTREAM_FLUSH(termString)                    \
 114     _outbuf->print("%s", termString);
 115 
 116 #define STRINGSTREAM_FLUSH_LOCKED(termString)             \
 117     _outbuf->print("%s", termString);
 118 #endif
 119 
 120 const char  blobTypeChar[] = {' ', 'N', 'I', 'X', 'Z', 'U', 'R', '?', 'D', 'T', 'E', 'S', 'A', 'M', 'B', 'L' };
 121 const char* blobTypeName[] = {"noType"

 122                              ,     "nMethod (active)"
 123                              ,          "nMethod (inactive)"
 124                              ,               "nMethod (deopt)"
 125                              ,                    "nMethod (zombie)"
 126                              ,                         "nMethod (unloaded)"
 127                              ,                              "runtime stub"
 128                              ,                                   "ricochet stub"
 129                              ,                                        "deopt stub"
 130                              ,                                             "uncommon trap stub"
 131                              ,                                                  "exception stub"
 132                              ,                                                       "safepoint stub"
 133                              ,                                                            "adapter blob"
 134                              ,                                                                 "MH adapter blob"
 135                              ,                                                                      "buffer blob"
 136                              ,                                                                           "lastType"
 137                              };
 138 const char* compTypeName[] = { "none", "c1", "c2", "jvmci" };
 139 
 140 // Be prepared for ten different CodeHeap segments. Should be enough for a few years.
 141 const  unsigned int        nSizeDistElements = 31;  // logarithmic range growth, max size: 2**32
 142 const  unsigned int        maxTopSizeBlocks  = 50;
 143 const  unsigned int        tsbStopper        = 2 * maxTopSizeBlocks;
 144 const  unsigned int        maxHeaps          = 10;
 145 static unsigned int        nHeaps            = 0;
 146 static struct CodeHeapStat CodeHeapStatArray[maxHeaps];
 147 
 148 // static struct StatElement *StatArray      = NULL;
 149 static StatElement* StatArray             = NULL;
 150 static int          log2_seg_size         = 0;
 151 static size_t       seg_size              = 0;
 152 static size_t       alloc_granules        = 0;
 153 static size_t       granule_size          = 0;
 154 static bool         segment_granules      = false;
 155 static unsigned int nBlocks_t1            = 0;  // counting "in_use" nmethods only.
 156 static unsigned int nBlocks_t2            = 0;  // counting "in_use" nmethods only.
 157 static unsigned int nBlocks_alive         = 0;  // counting "not_used" and "not_entrant" nmethods only.
 158 static unsigned int nBlocks_dead          = 0;  // counting "zombie" and "unloaded" methods only.
 159 static unsigned int nBlocks_unloaded      = 0;  // counting "unloaded" nmethods only. This is a transien state.

 160 static unsigned int nBlocks_stub          = 0;
 161 
 162 static struct FreeBlk*          FreeArray = NULL;
 163 static unsigned int      alloc_freeBlocks = 0;
 164 
 165 static struct TopSizeBlk*    TopSizeArray = NULL;
 166 static unsigned int   alloc_topSizeBlocks = 0;
 167 static unsigned int    used_topSizeBlocks = 0;
 168 
 169 static struct SizeDistributionElement*  SizeDistributionArray = NULL;
 170 
 171 // nMethod temperature (hotness) indicators.
 172 static int                     avgTemp    = 0;
 173 static int                     maxTemp    = 0;
 174 static int                     minTemp    = 0;
 175 
 176 static unsigned int  latest_compilation_id   = 0;
 177 static volatile bool initialization_complete = false;
 178 
 179 const char* CodeHeapState::get_heapName(CodeHeap* heap) {


 209   } else {
 210     nHeaps = 1;
 211     CodeHeapStatArray[0].heapName = heapName;
 212     return 0; // This is the default index if CodeCache is not segmented.
 213   }
 214 }
 215 
 216 void CodeHeapState::get_HeapStatGlobals(outputStream* out, const char* heapName) {
 217   unsigned int ix = findHeapIndex(out, heapName);
 218   if (ix < maxHeaps) {
 219     StatArray             = CodeHeapStatArray[ix].StatArray;
 220     seg_size              = CodeHeapStatArray[ix].segment_size;
 221     log2_seg_size         = seg_size == 0 ? 0 : exact_log2(seg_size);
 222     alloc_granules        = CodeHeapStatArray[ix].alloc_granules;
 223     granule_size          = CodeHeapStatArray[ix].granule_size;
 224     segment_granules      = CodeHeapStatArray[ix].segment_granules;
 225     nBlocks_t1            = CodeHeapStatArray[ix].nBlocks_t1;
 226     nBlocks_t2            = CodeHeapStatArray[ix].nBlocks_t2;
 227     nBlocks_alive         = CodeHeapStatArray[ix].nBlocks_alive;
 228     nBlocks_dead          = CodeHeapStatArray[ix].nBlocks_dead;

 229     nBlocks_unloaded      = CodeHeapStatArray[ix].nBlocks_unloaded;
 230     nBlocks_stub          = CodeHeapStatArray[ix].nBlocks_stub;
 231     FreeArray             = CodeHeapStatArray[ix].FreeArray;
 232     alloc_freeBlocks      = CodeHeapStatArray[ix].alloc_freeBlocks;
 233     TopSizeArray          = CodeHeapStatArray[ix].TopSizeArray;
 234     alloc_topSizeBlocks   = CodeHeapStatArray[ix].alloc_topSizeBlocks;
 235     used_topSizeBlocks    = CodeHeapStatArray[ix].used_topSizeBlocks;
 236     SizeDistributionArray = CodeHeapStatArray[ix].SizeDistributionArray;
 237     avgTemp               = CodeHeapStatArray[ix].avgTemp;
 238     maxTemp               = CodeHeapStatArray[ix].maxTemp;
 239     minTemp               = CodeHeapStatArray[ix].minTemp;
 240   } else {
 241     StatArray             = NULL;
 242     seg_size              = 0;
 243     log2_seg_size         = 0;
 244     alloc_granules        = 0;
 245     granule_size          = 0;
 246     segment_granules      = false;
 247     nBlocks_t1            = 0;
 248     nBlocks_t2            = 0;
 249     nBlocks_alive         = 0;
 250     nBlocks_dead          = 0;

 251     nBlocks_unloaded      = 0;
 252     nBlocks_stub          = 0;
 253     FreeArray             = NULL;
 254     alloc_freeBlocks      = 0;
 255     TopSizeArray          = NULL;
 256     alloc_topSizeBlocks   = 0;
 257     used_topSizeBlocks    = 0;
 258     SizeDistributionArray = NULL;
 259     avgTemp               = 0;
 260     maxTemp               = 0;
 261     minTemp               = 0;
 262   }
 263 }
 264 
 265 void CodeHeapState::set_HeapStatGlobals(outputStream* out, const char* heapName) {
 266   unsigned int ix = findHeapIndex(out, heapName);
 267   if (ix < maxHeaps) {
 268     CodeHeapStatArray[ix].StatArray             = StatArray;
 269     CodeHeapStatArray[ix].segment_size          = seg_size;
 270     CodeHeapStatArray[ix].alloc_granules        = alloc_granules;
 271     CodeHeapStatArray[ix].granule_size          = granule_size;
 272     CodeHeapStatArray[ix].segment_granules      = segment_granules;
 273     CodeHeapStatArray[ix].nBlocks_t1            = nBlocks_t1;
 274     CodeHeapStatArray[ix].nBlocks_t2            = nBlocks_t2;
 275     CodeHeapStatArray[ix].nBlocks_alive         = nBlocks_alive;
 276     CodeHeapStatArray[ix].nBlocks_dead          = nBlocks_dead;

 277     CodeHeapStatArray[ix].nBlocks_unloaded      = nBlocks_unloaded;
 278     CodeHeapStatArray[ix].nBlocks_stub          = nBlocks_stub;
 279     CodeHeapStatArray[ix].FreeArray             = FreeArray;
 280     CodeHeapStatArray[ix].alloc_freeBlocks      = alloc_freeBlocks;
 281     CodeHeapStatArray[ix].TopSizeArray          = TopSizeArray;
 282     CodeHeapStatArray[ix].alloc_topSizeBlocks   = alloc_topSizeBlocks;
 283     CodeHeapStatArray[ix].used_topSizeBlocks    = used_topSizeBlocks;
 284     CodeHeapStatArray[ix].SizeDistributionArray = SizeDistributionArray;
 285     CodeHeapStatArray[ix].avgTemp               = avgTemp;
 286     CodeHeapStatArray[ix].maxTemp               = maxTemp;
 287     CodeHeapStatArray[ix].minTemp               = minTemp;
 288   }
 289 }
 290 
 291 //---<  get a new statistics array  >---
 292 void CodeHeapState::prepare_StatArray(outputStream* out, size_t nElem, size_t granularity, const char* heapName) {
 293   if (StatArray == NULL) {
 294     StatArray      = new StatElement[nElem];
 295     //---<  reset some counts  >---
 296     alloc_granules = nElem;


 537                 "   Subsequent print functions create their output based on this snapshot.\n"
 538                 "   The CodeHeap is a living thing, and every effort has been made for the\n"
 539                 "   collected data to be consistent. Only the method names and signatures\n"
 540                 "   are retrieved at print time. That may lead to rare cases where the\n"
 541                 "   name of a method is no longer available, e.g. because it was unloaded.\n");
 542   ast->print_cr("   CodeHeap committed size " SIZE_FORMAT "K (" SIZE_FORMAT "M), reserved size " SIZE_FORMAT "K (" SIZE_FORMAT "M), %d%% occupied.",
 543                 size/(size_t)K, size/(size_t)M, res_size/(size_t)K, res_size/(size_t)M, (unsigned int)(100.0*size/res_size));
 544   ast->print_cr("   CodeHeap allocation segment size is " SIZE_FORMAT " bytes. This is the smallest possible granularity.", seg_size);
 545   ast->print_cr("   CodeHeap (committed part) is mapped to " SIZE_FORMAT " granules of size " SIZE_FORMAT " bytes.", granules, granularity);
 546   ast->print_cr("   Each granule takes " SIZE_FORMAT " bytes of C heap, that is " SIZE_FORMAT "K in total for statistics data.", sizeof(StatElement), (sizeof(StatElement)*granules)/(size_t)K);
 547   ast->print_cr("   The number of granules is limited to %dk, requiring a granules size of at least %d bytes for a 1GB heap.", (unsigned int)(max_granules/K), (unsigned int)(G/max_granules));
 548   STRINGSTREAM_FLUSH("\n")
 549 
 550 
 551   while (!done) {
 552     //---<  reset counters with every aggregation  >---
 553     nBlocks_t1       = 0;
 554     nBlocks_t2       = 0;
 555     nBlocks_alive    = 0;
 556     nBlocks_dead     = 0;

 557     nBlocks_unloaded = 0;
 558     nBlocks_stub     = 0;
 559 
 560     nBlocks_free     = 0;
 561     nBlocks_used     = 0;
 562     nBlocks_zomb     = 0;
 563     nBlocks_disconn  = 0;
 564     nBlocks_notentr  = 0;
 565 
 566     //---<  discard old arrays if size does not match  >---
 567     if (granules != alloc_granules) {
 568       discard_StatArray(out);
 569       discard_TopSizeArray(out);
 570     }
 571 
 572     //---<  allocate arrays if they don't yet exist, initialize  >---
 573     prepare_StatArray(out, granules, granularity, heapName);
 574     if (StatArray == NULL) {
 575       set_HeapStatGlobals(out, heapName);
 576       return;
 577     }
 578     prepare_TopSizeArray(out, maxTopSizeBlocks, heapName);
 579     prepare_SizeDistArray(out, nSizeDistElements, heapName);
 580 
 581     latest_compilation_id = CompileBroker::get_compilation_id();
 582     unsigned int highest_compilation_id = 0;
 583     size_t       usedSpace     = 0;
 584     size_t       t1Space       = 0;
 585     size_t       t2Space       = 0;
 586     size_t       aliveSpace    = 0;
 587     size_t       disconnSpace  = 0;
 588     size_t       notentrSpace  = 0;
 589     size_t       deadSpace     = 0;

 590     size_t       unloadedSpace = 0;
 591     size_t       stubSpace     = 0;
 592     size_t       freeSpace     = 0;
 593     size_t       maxFreeSize   = 0;
 594     HeapBlock*   maxFreeBlock  = NULL;
 595     bool         insane        = false;
 596 
 597     int64_t hotnessAccumulator = 0;
 598     unsigned int n_methods     = 0;
 599     avgTemp       = 0;
 600     minTemp       = (int)(res_size > M ? (res_size/M)*2 : 1);
 601     maxTemp       = -minTemp;
 602 
 603     for (HeapBlock *h = heap->first_block(); h != NULL && !insane; h = heap->next_block(h)) {
 604       unsigned int hb_len     = (unsigned int)h->length();  // despite being size_t, length can never overflow an unsigned int.
 605       size_t       hb_bytelen = ((size_t)hb_len)<<log2_seg_size;
 606       unsigned int ix_beg     = (unsigned int)(((char*)h-low_bound)/granule_size);
 607       unsigned int ix_end     = (unsigned int)(((char*)h-low_bound+(hb_bytelen-1))/granule_size);
 608       unsigned int compile_id = 0;
 609       CompLevel    comp_lvl   = CompLevel_none;


 675               case nMethod_notused:
 676                 nBlocks_alive++;
 677                 nBlocks_disconn++;
 678                 aliveSpace     += hb_bytelen;
 679                 disconnSpace   += hb_bytelen;
 680                 break;
 681               case nMethod_notentrant:  // equivalent to nMethod_alive
 682                 nBlocks_alive++;
 683                 nBlocks_notentr++;
 684                 aliveSpace     += hb_bytelen;
 685                 notentrSpace   += hb_bytelen;
 686                 break;
 687               case nMethod_unloaded:
 688                 nBlocks_unloaded++;
 689                 unloadedSpace  += hb_bytelen;
 690                 break;
 691               case nMethod_dead:
 692                 nBlocks_dead++;
 693                 deadSpace      += hb_bytelen;
 694                 break;




 695               default:
 696                 break;
 697             }
 698           }
 699 
 700           //------------------------------------------
 701           //---<  register block in TopSizeArray  >---
 702           //------------------------------------------
 703           if (alloc_topSizeBlocks > 0) {
 704             if (used_topSizeBlocks == 0) {
 705               TopSizeArray[0].start    = h;
 706               TopSizeArray[0].len      = hb_len;
 707               TopSizeArray[0].index    = tsbStopper;
 708               TopSizeArray[0].compiler = cType;
 709               TopSizeArray[0].level    = comp_lvl;
 710               TopSizeArray[0].type     = cbType;
 711               currMax    = hb_len;
 712               currMin    = hb_len;
 713               currMin_ix = 0;
 714               used_topSizeBlocks++;


 829           StatArray[ix_beg].type = cbType;
 830           switch (cbType) {
 831             case nMethod_inuse:
 832               highest_compilation_id = (highest_compilation_id >= compile_id) ? highest_compilation_id : compile_id;
 833               if (comp_lvl < CompLevel_full_optimization) {
 834                 nBlocks_t1++;
 835                 t1Space   += hb_bytelen;
 836                 StatArray[ix_beg].t1_count++;
 837                 StatArray[ix_beg].t1_space += (unsigned short)hb_len;
 838                 StatArray[ix_beg].t1_age    = StatArray[ix_beg].t1_age < compile_id ? compile_id : StatArray[ix_beg].t1_age;
 839               } else {
 840                 nBlocks_t2++;
 841                 t2Space   += hb_bytelen;
 842                 StatArray[ix_beg].t2_count++;
 843                 StatArray[ix_beg].t2_space += (unsigned short)hb_len;
 844                 StatArray[ix_beg].t2_age    = StatArray[ix_beg].t2_age < compile_id ? compile_id : StatArray[ix_beg].t2_age;
 845               }
 846               StatArray[ix_beg].level     = comp_lvl;
 847               StatArray[ix_beg].compiler  = cType;
 848               break;

 849             case nMethod_alive:
 850               StatArray[ix_beg].tx_count++;
 851               StatArray[ix_beg].tx_space += (unsigned short)hb_len;
 852               StatArray[ix_beg].tx_age    = StatArray[ix_beg].tx_age < compile_id ? compile_id : StatArray[ix_beg].tx_age;
 853               StatArray[ix_beg].level     = comp_lvl;
 854               StatArray[ix_beg].compiler  = cType;
 855               break;
 856             case nMethod_dead:
 857             case nMethod_unloaded:
 858               StatArray[ix_beg].dead_count++;
 859               StatArray[ix_beg].dead_space += (unsigned short)hb_len;
 860               break;
 861             default:
 862               // must be a stub, if it's not a dead or alive nMethod
 863               nBlocks_stub++;
 864               stubSpace   += hb_bytelen;
 865               StatArray[ix_beg].stub_count++;
 866               StatArray[ix_beg].stub_space += (unsigned short)hb_len;
 867               break;
 868           }


 885 
 886                 StatArray[ix_end].t1_count++;
 887                 StatArray[ix_end].t1_space += (unsigned short)end_space;
 888                 StatArray[ix_end].t1_age    = StatArray[ix_end].t1_age < compile_id ? compile_id : StatArray[ix_end].t1_age;
 889               } else {
 890                 nBlocks_t2++;
 891                 t2Space   += hb_bytelen;
 892                 StatArray[ix_beg].t2_count++;
 893                 StatArray[ix_beg].t2_space += (unsigned short)beg_space;
 894                 StatArray[ix_beg].t2_age    = StatArray[ix_beg].t2_age < compile_id ? compile_id : StatArray[ix_beg].t2_age;
 895 
 896                 StatArray[ix_end].t2_count++;
 897                 StatArray[ix_end].t2_space += (unsigned short)end_space;
 898                 StatArray[ix_end].t2_age    = StatArray[ix_end].t2_age < compile_id ? compile_id : StatArray[ix_end].t2_age;
 899               }
 900               StatArray[ix_beg].level     = comp_lvl;
 901               StatArray[ix_beg].compiler  = cType;
 902               StatArray[ix_end].level     = comp_lvl;
 903               StatArray[ix_end].compiler  = cType;
 904               break;

 905             case nMethod_alive:
 906               StatArray[ix_beg].tx_count++;
 907               StatArray[ix_beg].tx_space += (unsigned short)beg_space;
 908               StatArray[ix_beg].tx_age    = StatArray[ix_beg].tx_age < compile_id ? compile_id : StatArray[ix_beg].tx_age;
 909 
 910               StatArray[ix_end].tx_count++;
 911               StatArray[ix_end].tx_space += (unsigned short)end_space;
 912               StatArray[ix_end].tx_age    = StatArray[ix_end].tx_age < compile_id ? compile_id : StatArray[ix_end].tx_age;
 913 
 914               StatArray[ix_beg].level     = comp_lvl;
 915               StatArray[ix_beg].compiler  = cType;
 916               StatArray[ix_end].level     = comp_lvl;
 917               StatArray[ix_end].compiler  = cType;
 918               break;
 919             case nMethod_dead:
 920             case nMethod_unloaded:
 921               StatArray[ix_beg].dead_count++;
 922               StatArray[ix_beg].dead_space += (unsigned short)beg_space;
 923               StatArray[ix_end].dead_count++;
 924               StatArray[ix_end].dead_space += (unsigned short)end_space;


 932               StatArray[ix_end].stub_count++;
 933               StatArray[ix_end].stub_space += (unsigned short)end_space;
 934               break;
 935           }
 936           for (unsigned int ix = ix_beg+1; ix < ix_end; ix++) {
 937             StatArray[ix].type = cbType;
 938             switch (cbType) {
 939               case nMethod_inuse:
 940                 if (comp_lvl < CompLevel_full_optimization) {
 941                   StatArray[ix].t1_count++;
 942                   StatArray[ix].t1_space += (unsigned short)(granule_size>>log2_seg_size);
 943                   StatArray[ix].t1_age    = StatArray[ix].t1_age < compile_id ? compile_id : StatArray[ix].t1_age;
 944                 } else {
 945                   StatArray[ix].t2_count++;
 946                   StatArray[ix].t2_space += (unsigned short)(granule_size>>log2_seg_size);
 947                   StatArray[ix].t2_age    = StatArray[ix].t2_age < compile_id ? compile_id : StatArray[ix].t2_age;
 948                 }
 949                 StatArray[ix].level     = comp_lvl;
 950                 StatArray[ix].compiler  = cType;
 951                 break;

 952               case nMethod_alive:
 953                 StatArray[ix].tx_count++;
 954                 StatArray[ix].tx_space += (unsigned short)(granule_size>>log2_seg_size);
 955                 StatArray[ix].tx_age    = StatArray[ix].tx_age < compile_id ? compile_id : StatArray[ix].tx_age;
 956                 StatArray[ix].level     = comp_lvl;
 957                 StatArray[ix].compiler  = cType;
 958                 break;
 959               case nMethod_dead:
 960               case nMethod_unloaded:
 961                 StatArray[ix].dead_count++;
 962                 StatArray[ix].dead_space += (unsigned short)(granule_size>>log2_seg_size);
 963                 break;
 964               default:
 965                 // must be a stub, if it's not a dead or alive nMethod
 966                 StatArray[ix].stub_count++;
 967                 StatArray[ix].stub_space += (unsigned short)(granule_size>>log2_seg_size);
 968                 break;
 969             }
 970           }
 971         }
 972       }
 973     }
 974     if (n_methods > 0) {
 975       avgTemp = hotnessAccumulator/n_methods;
 976     } else {
 977       avgTemp = 0;
 978     }
 979     done = true;
 980 
 981     if (!insane) {
 982       // There is a risk for this block (because it contains many print statements) to get
 983       // interspersed with print data from other threads. We take this risk intentionally.
 984       // Getting stalled waiting for tty_lock while holding the CodeCache_lock is not desirable.
 985       printBox(ast, '-', "Global CodeHeap statistics for segment ", heapName);
 986       ast->print_cr("freeSpace        = " SIZE_FORMAT_W(8) "k, nBlocks_free     = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", freeSpace/(size_t)K,     nBlocks_free,     (100.0*freeSpace)/size,     (100.0*freeSpace)/res_size);
 987       ast->print_cr("usedSpace        = " SIZE_FORMAT_W(8) "k, nBlocks_used     = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", usedSpace/(size_t)K,     nBlocks_used,     (100.0*usedSpace)/size,     (100.0*usedSpace)/res_size);
 988       ast->print_cr("  Tier1 Space    = " SIZE_FORMAT_W(8) "k, nBlocks_t1       = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", t1Space/(size_t)K,       nBlocks_t1,       (100.0*t1Space)/size,       (100.0*t1Space)/res_size);
 989       ast->print_cr("  Tier2 Space    = " SIZE_FORMAT_W(8) "k, nBlocks_t2       = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", t2Space/(size_t)K,       nBlocks_t2,       (100.0*t2Space)/size,       (100.0*t2Space)/res_size);
 990       ast->print_cr("  Alive Space    = " SIZE_FORMAT_W(8) "k, nBlocks_alive    = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", aliveSpace/(size_t)K,    nBlocks_alive,    (100.0*aliveSpace)/size,    (100.0*aliveSpace)/res_size);
 991       ast->print_cr("    disconnected = " SIZE_FORMAT_W(8) "k, nBlocks_disconn  = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", disconnSpace/(size_t)K,  nBlocks_disconn,  (100.0*disconnSpace)/size,  (100.0*disconnSpace)/res_size);
 992       ast->print_cr("    not entrant  = " SIZE_FORMAT_W(8) "k, nBlocks_notentr  = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", notentrSpace/(size_t)K,  nBlocks_notentr,  (100.0*notentrSpace)/size,  (100.0*notentrSpace)/res_size);

 993       ast->print_cr("  unloadedSpace  = " SIZE_FORMAT_W(8) "k, nBlocks_unloaded = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", unloadedSpace/(size_t)K, nBlocks_unloaded, (100.0*unloadedSpace)/size, (100.0*unloadedSpace)/res_size);
 994       ast->print_cr("  deadSpace      = " SIZE_FORMAT_W(8) "k, nBlocks_dead     = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", deadSpace/(size_t)K,     nBlocks_dead,     (100.0*deadSpace)/size,     (100.0*deadSpace)/res_size);
 995       ast->print_cr("  stubSpace      = " SIZE_FORMAT_W(8) "k, nBlocks_stub     = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", stubSpace/(size_t)K,     nBlocks_stub,     (100.0*stubSpace)/size,     (100.0*stubSpace)/res_size);
 996       ast->print_cr("ZombieBlocks     = %8d. These are HeapBlocks which could not be identified as CodeBlobs.", nBlocks_zomb);
 997       ast->cr();
 998       ast->print_cr("Segment start          = " INTPTR_FORMAT ", used space      = " SIZE_FORMAT_W(8)"k", p2i(low_bound), size/K);
 999       ast->print_cr("Segment end (used)     = " INTPTR_FORMAT ", remaining space = " SIZE_FORMAT_W(8)"k", p2i(low_bound) + size, (res_size - size)/K);
1000       ast->print_cr("Segment end (reserved) = " INTPTR_FORMAT ", reserved space  = " SIZE_FORMAT_W(8)"k", p2i(low_bound) + res_size, res_size/K);
1001       ast->cr();
1002       ast->print_cr("latest allocated compilation id = %d", latest_compilation_id);
1003       ast->print_cr("highest observed compilation id = %d", highest_compilation_id);
1004       ast->print_cr("Building TopSizeList iterations = %ld", total_iterations);
1005       ast->cr();
1006 
1007       int             reset_val = NMethodSweeper::hotness_counter_reset_val();
1008       double reverse_free_ratio = (res_size > size) ? (double)res_size/(double)(res_size-size) : (double)res_size;
1009       printBox(ast, '-', "Method hotness information at time of this analysis", NULL);
1010       ast->print_cr("Highest possible method temperature:          %12d", reset_val);
1011       ast->print_cr("Threshold for method to be considered 'cold': %12.3f", -reset_val + reverse_free_ratio * NmethodSweepActivity);


1012       ast->print_cr("min. hotness = %6d", minTemp);
1013       ast->print_cr("avg. hotness = %6d", avgTemp);
1014       ast->print_cr("max. hotness = %6d", maxTemp);




1015       STRINGSTREAM_FLUSH("\n")
1016 
1017       // This loop is intentionally printing directly to "out".
1018       out->print("Verifying collected data...");
1019       size_t granule_segs = granule_size>>log2_seg_size;
1020       for (unsigned int ix = 0; ix < granules; ix++) {
1021         if (StatArray[ix].t1_count   > granule_segs) {
1022           out->print_cr("t1_count[%d]   = %d", ix, StatArray[ix].t1_count);
1023         }
1024         if (StatArray[ix].t2_count   > granule_segs) {
1025           out->print_cr("t2_count[%d]   = %d", ix, StatArray[ix].t2_count);
1026         }



1027         if (StatArray[ix].stub_count > granule_segs) {
1028           out->print_cr("stub_count[%d] = %d", ix, StatArray[ix].stub_count);
1029         }
1030         if (StatArray[ix].dead_count > granule_segs) {
1031           out->print_cr("dead_count[%d] = %d", ix, StatArray[ix].dead_count);
1032         }
1033         if (StatArray[ix].t1_space   > granule_segs) {
1034           out->print_cr("t1_space[%d]   = %d", ix, StatArray[ix].t1_space);
1035         }
1036         if (StatArray[ix].t2_space   > granule_segs) {
1037           out->print_cr("t2_space[%d]   = %d", ix, StatArray[ix].t2_space);
1038         }



1039         if (StatArray[ix].stub_space > granule_segs) {
1040           out->print_cr("stub_space[%d] = %d", ix, StatArray[ix].stub_space);
1041         }
1042         if (StatArray[ix].dead_space > granule_segs) {
1043           out->print_cr("dead_space[%d] = %d", ix, StatArray[ix].dead_space);
1044         }
1045         //   this cast is awful! I need it because NT/Intel reports a signed/unsigned mismatch.
1046         if ((size_t)(StatArray[ix].t1_count+StatArray[ix].t2_count+StatArray[ix].stub_count+StatArray[ix].dead_count) > granule_segs) {
1047           out->print_cr("t1_count[%d] = %d, t2_count[%d] = %d, stub_count[%d] = %d", ix, StatArray[ix].t1_count, ix, StatArray[ix].t2_count, ix, StatArray[ix].stub_count);
1048         }
1049         if ((size_t)(StatArray[ix].t1_space+StatArray[ix].t2_space+StatArray[ix].stub_space+StatArray[ix].dead_space) > granule_segs) {
1050           out->print_cr("t1_space[%d] = %d, t2_space[%d] = %d, stub_space[%d] = %d", ix, StatArray[ix].t1_space, ix, StatArray[ix].t2_space, ix, StatArray[ix].stub_space);
1051         }
1052       }
1053 
1054       // This loop is intentionally printing directly to "out".
1055       if (used_topSizeBlocks > 0) {
1056         unsigned int j = 0;
1057         if (TopSizeArray[0].len != currMax) {
1058           out->print_cr("currMax(%d) differs from TopSizeArray[0].len(%d)", currMax, TopSizeArray[0].len);
1059         }
1060         for (unsigned int i = 0; (TopSizeArray[i].index != tsbStopper) && (j++ < alloc_topSizeBlocks); i = TopSizeArray[i].index) {
1061           if (TopSizeArray[i].len < TopSizeArray[TopSizeArray[i].index].len) {
1062             out->print_cr("sort error at index %d: %d !>= %d", i, TopSizeArray[i].len, TopSizeArray[TopSizeArray[i].index].len);
1063           }
1064         }
1065         if (j >= alloc_topSizeBlocks) {
1066           out->print_cr("Possible loop in TopSizeArray chaining!\n  allocBlocks = %d, usedBlocks = %d", alloc_topSizeBlocks, used_topSizeBlocks);
1067           for (unsigned int i = 0; i < alloc_topSizeBlocks; i++) {
1068             out->print_cr("  TopSizeArray[%d].index = %d, len = %d", i, TopSizeArray[i].index, TopSizeArray[i].len);
1069           }
1070         }


1114       if (ix < alloc_freeBlocks) { // don't index out of bounds if _freelist has more blocks than anticipated
1115         FreeArray[ix].start = cur;
1116         FreeArray[ix].len   = (unsigned int)(cur->length()<<log2_seg_size);
1117         FreeArray[ix].index = ix;
1118       }
1119       cur  = cur->link();
1120       ix++;
1121     }
1122     if (ix != alloc_freeBlocks) {
1123       ast->print_cr("Free block count mismatch. Expected %d free blocks, but found %d.", alloc_freeBlocks, ix);
1124       ast->print_cr("I will update the counter and retry data collection");
1125       STRINGSTREAM_FLUSH("\n")
1126       nBlocks_free = ix;
1127       continue;
1128     }
1129     done = true;
1130   }
1131 
1132   if (!done || (nBlocks_free == 0)) {
1133     if (nBlocks_free == 0) {
1134       printBox(ast, '-', "no free blocks found in", heapName);
1135     } else if (!done) {
1136       ast->print_cr("Free block count mismatch could not be resolved.");
1137       ast->print_cr("Try to run \"aggregate\" function to update counters");
1138     }
1139     STRINGSTREAM_FLUSH("")
1140 
1141     //---< discard old array and update global values  >---
1142     discard_FreeArray(out);
1143     set_HeapStatGlobals(out, heapName);
1144     return;
1145   }
1146 
1147   //---<  calculate and fill remaining fields  >---
1148   if (FreeArray != NULL) {
1149     // This loop is intentionally printing directly to "out".
1150     for (unsigned int ix = 0; ix < alloc_freeBlocks-1; ix++) {
1151       size_t lenSum = 0;
1152       FreeArray[ix].gap = (unsigned int)((address)FreeArray[ix+1].start - ((address)FreeArray[ix].start + FreeArray[ix].len));
1153       for (HeapBlock *h = heap->next_block(FreeArray[ix].start); (h != NULL) && (h != FreeArray[ix+1].start); h = heap->next_block(h)) {
1154         CodeBlob *cb  = (CodeBlob*)(heap->find_start(h));


1246 
1247         //---<  print size, name, and signature (for nMethods)  >---
1248         if ((nm != NULL) && (nm->method() != NULL)) {
1249           ResourceMark rm;
1250           //---<  nMethod size in hex  >---
1251           unsigned int total_size = nm->total_size();
1252           ast->print(PTR32_FORMAT, total_size);
1253           ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K);
1254           ast->fill_to(51);
1255           ast->print("  %c", blobTypeChar[TopSizeArray[i].type]);
1256           //---<  compiler information  >---
1257           ast->fill_to(56);
1258           ast->print("%5s %3d", compTypeName[TopSizeArray[i].compiler], TopSizeArray[i].level);
1259           //---<  method temperature  >---
1260           ast->fill_to(67);
1261           ast->print("%5d", nm->hotness_counter());
1262           //---<  name and signature  >---
1263           ast->fill_to(67+6);
1264           if (nm->is_in_use())      {blob_name = nm->method()->name_and_sig_as_C_string(); }
1265           if (nm->is_not_entrant()) {blob_name = nm->method()->name_and_sig_as_C_string(); }
1266           if (nm->is_zombie())      {ast->print("%14s", " zombie method"); }

1267           ast->print("%s", blob_name);
1268         } else {
1269           //---<  block size in hex  >---
1270           ast->print(PTR32_FORMAT, (unsigned int)(TopSizeArray[i].len<<log2_seg_size));
1271           ast->print("(" SIZE_FORMAT_W(4) "K)", (TopSizeArray[i].len<<log2_seg_size)/K);
1272           //---<  no compiler information  >---
1273           ast->fill_to(56);
1274           //---<  name and signature  >---
1275           ast->fill_to(67+6);
1276           ast->print("%s", blob_name);
1277         }
1278         STRINGSTREAM_FLUSH_LOCKED("\n")
1279       }
1280       if (used_topSizeBlocks != printed_topSizeBlocks) {
1281         ast->print_cr("used blocks: %d, printed blocks: %d", used_topSizeBlocks, printed_topSizeBlocks);
1282         STRINGSTREAM_FLUSH("")
1283         for (unsigned int i = 0; i < alloc_topSizeBlocks; i++) {
1284           ast->print_cr("  TopSizeArray[%d].index = %d, len = %d", i, TopSizeArray[i].index, TopSizeArray[i].len);
1285           STRINGSTREAM_FLUSH("")
1286         }


1640       STRINGSTREAM_FLUSH_LOCKED("")
1641 
1642       granules_per_line = 128;
1643       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
1644         print_line_delim(out, ast, low_bound, ix, granules_per_line);
1645         if (segment_granules && StatArray[ix].t2_count > 0) {
1646           print_blobType_single(ast, StatArray[ix].type);
1647         } else {
1648           print_count_single(ast, StatArray[ix].t2_count);
1649         }
1650       }
1651       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
1652     } else {
1653       ast->print("No Tier2 nMethods found in CodeHeap.");
1654       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
1655     }
1656   }
1657 
1658   {
1659     if (nBlocks_alive > 0) {
1660       printBox(ast, '-', "not_used/not_entrant nMethod count only, 0x1..0xf. '*' indicates >= 16 blocks, ' ' indicates empty", NULL);
1661       STRINGSTREAM_FLUSH_LOCKED("")
1662 
1663       granules_per_line = 128;
1664       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
1665         print_line_delim(out, ast, low_bound, ix, granules_per_line);
1666         if (segment_granules && StatArray[ix].tx_count > 0) {
1667           print_blobType_single(ast, StatArray[ix].type);
1668         } else {
1669           print_count_single(ast, StatArray[ix].tx_count);
1670         }
1671       }
1672       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
1673     } else {
1674       ast->print("No not_used/not_entrant nMethods found in CodeHeap.");
1675       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
1676     }
1677   }
1678 
1679   {
1680     if (nBlocks_stub > 0) {


1829       STRINGSTREAM_FLUSH_LOCKED("")
1830 
1831       granules_per_line = 128;
1832       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
1833         print_line_delim(out, ast, low_bound, ix, granules_per_line);
1834         if (segment_granules && StatArray[ix].t2_space > 0) {
1835           print_blobType_single(ast, StatArray[ix].type);
1836         } else {
1837           print_space_single(ast, StatArray[ix].t2_space);
1838         }
1839       }
1840       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
1841     } else {
1842       ast->print("No Tier2 nMethods found in CodeHeap.");
1843       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
1844     }
1845   }
1846 
1847   {
1848     if (nBlocks_alive > 0) {
1849       printBox(ast, '-', "not_used/not_entrant space consumption. ' ' indicates empty, '*' indicates full", NULL);
1850 
1851       granules_per_line = 128;
1852       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
1853         print_line_delim(out, ast, low_bound, ix, granules_per_line);
1854         if (segment_granules && StatArray[ix].tx_space > 0) {
1855           print_blobType_single(ast, StatArray[ix].type);
1856         } else {
1857           print_space_single(ast, StatArray[ix].tx_space);
1858         }
1859       }
1860       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
1861     } else {
1862       ast->print("No Tier2 nMethods found in CodeHeap.");
1863       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
1864     }
1865   }
1866 
1867   {
1868     if (nBlocks_stub > 0) {
1869       printBox(ast, '-', "Stub and Blob space consumption. ' ' indicates empty, '*' indicates full", NULL);


1999 
2000   {
2001     if (nBlocks_t2 > 0) {
2002       printBox(ast, '-', "Tier2 age distribution. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL);
2003       STRINGSTREAM_FLUSH_LOCKED("")
2004 
2005       granules_per_line = 128;
2006       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
2007         print_line_delim(out, ast, low_bound, ix, granules_per_line);
2008         print_age_single(ast, StatArray[ix].t2_age);
2009       }
2010       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
2011     } else {
2012       ast->print("No Tier2 nMethods found in CodeHeap.");
2013       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
2014     }
2015   }
2016 
2017   {
2018     if (nBlocks_alive > 0) {
2019       printBox(ast, '-', "not_used/not_entrant age distribution. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL);
2020       STRINGSTREAM_FLUSH_LOCKED("")
2021 
2022       granules_per_line = 128;
2023       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
2024         print_line_delim(out, ast, low_bound, ix, granules_per_line);
2025         print_age_single(ast, StatArray[ix].tx_age);
2026       }
2027       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
2028     } else {
2029       ast->print("No Tier2 nMethods found in CodeHeap.");
2030       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
2031     }
2032   }
2033 
2034   {
2035     if (!segment_granules) { // Prevent totally redundant printouts
2036       printBox(ast, '-', "age distribution by tier <a1>:<a2>. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL);
2037       STRINGSTREAM_FLUSH_LOCKED("")
2038 
2039       granules_per_line = 32;


2129         //---<  print table header for new print range  >---
2130         if (!name_in_addr_range) {
2131           name_in_addr_range = true;
2132           ast->fill_to(51);
2133           ast->print("%9s", "compiler");
2134           ast->fill_to(61);
2135           ast->print_cr("%6s", "method");
2136           ast->print_cr("%18s %13s %17s %9s  %5s %18s  %s", "Addr(module)      ", "offset", "size", " type lvl", " temp", "blobType          ", "Name");
2137           STRINGSTREAM_FLUSH_LOCKED("")
2138         }
2139 
2140         //---<  print line prefix (address and offset from CodeHeap start)  >---
2141         ast->print(INTPTR_FORMAT, p2i(this_blob));
2142         ast->fill_to(19);
2143         ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound));
2144         ast->fill_to(33);
2145 
2146         // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
2147         nmethod*    nm     = this_blob->as_nmethod_or_null();
2148         Method*     method = (nm == NULL) ? NULL : nm->method();  // may be uninitialized, i.e. != NULL, but invalid
2149         if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) &&
2150             is_readable_pointer(method) && is_readable_pointer(method->constants())) {
2151           ResourceMark rm;
2152           //---<  collect all data to locals as quickly as possible  >---
2153           unsigned int total_size = nm->total_size();
2154           int          hotness    = nm->hotness_counter();
2155           bool         get_name   = (cbType == nMethod_inuse) || (cbType == nMethod_notused);
2156           //---<  nMethod size in hex  >---
2157           ast->print(PTR32_FORMAT, total_size);
2158           ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K);
2159           //---<  compiler information  >---
2160           ast->fill_to(51);
2161           ast->print("%5s %3d", compTypeName[StatArray[ix].compiler], StatArray[ix].level);
2162           //---<  method temperature  >---
2163           ast->fill_to(62);
2164           ast->print("%5d", hotness);
2165           //---<  name and signature  >---
2166           ast->fill_to(62+6);
2167           ast->print("%s", blobTypeName[cbType]);
2168           ast->fill_to(82+6);
2169           if (cbType == nMethod_dead) {


2341 
2342     ast->print(INTPTR_FORMAT, p2i(low_bound + ix*granule_size));
2343     ast->fill_to(19);
2344     ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size));
2345   }
2346 }
2347 
2348 CodeHeapState::blobType CodeHeapState::get_cbType(CodeBlob* cb) {
2349   if ((cb != NULL) && is_readable_pointer(cb)) {
2350     if (cb->is_runtime_stub())                return runtimeStub;
2351     if (cb->is_deoptimization_stub())         return deoptimizationStub;
2352     if (cb->is_uncommon_trap_stub())          return uncommonTrapStub;
2353     if (cb->is_exception_stub())              return exceptionStub;
2354     if (cb->is_safepoint_stub())              return safepointStub;
2355     if (cb->is_adapter_blob())                return adapterBlob;
2356     if (cb->is_method_handles_adapter_blob()) return mh_adapterBlob;
2357     if (cb->is_buffer_blob())                 return bufferBlob;
2358 
2359     nmethod*  nm = cb->as_nmethod_or_null();
2360     if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb.

2361       if (nm->is_zombie())        return nMethod_dead;
2362       if (nm->is_unloaded())      return nMethod_unloaded;

2363       if (nm->is_alive() && !(nm->is_not_entrant()))   return nMethod_notused;
2364       if (nm->is_alive())         return nMethod_alive;
2365       if (nm->is_in_use())        return nMethod_inuse;
2366       return nMethod_dead;
2367     }
2368   }
2369   return noType;
2370 }
2371 
2372 // Check if pointer can be read from (4-byte read access).
2373 // Helps to prove validity of a not-NULL pointer.
2374 // Returns true in very early stages of VM life when stub is not yet generated.
2375 #define SAFEFETCH_DEFAULT true
2376 bool CodeHeapState::is_readable_pointer(const void* p) {
2377   if (!CanUseSafeFetch32()) {
2378     return SAFEFETCH_DEFAULT;
2379   }
2380   int* const aligned = (int*) align_down((intptr_t)p, 4);
2381   int cafebabe = 0xcafebabe;  // tester value 1
2382   int deadbeef = 0xdeadbeef;  // tester value 2
2383   return (SafeFetch32(aligned, cafebabe) != cafebabe) || (SafeFetch32(aligned, deadbeef) != deadbeef);
2384 }


 100     _sstbuf->print("%s", termString);                     \
 101     _outbuf->print("%s", _sstbuf->as_string());           \
 102     _sstbuf->reset();
 103 
 104 #define STRINGSTREAM_FLUSH_LOCKED(termString)             \
 105     { ttyLocker ttyl;/* keep this output block together */\
 106       STRINGSTREAM_FLUSH(termString)                      \
 107     }
 108 #else
 109 #define STRINGSTREAM_DECL(_anyst, _outst)                 \
 110     outputStream*  _outbuf = _outst;                      \
 111     outputStream*  _anyst  = _outst;   /* any stream. Use this to just print - no buffer flush.  */
 112 
 113 #define STRINGSTREAM_FLUSH(termString)                    \
 114     _outbuf->print("%s", termString);
 115 
 116 #define STRINGSTREAM_FLUSH_LOCKED(termString)             \
 117     _outbuf->print("%s", termString);
 118 #endif
 119 
 120 const char  blobTypeChar[] = {' ', 'C', 'N', 'I', 'X', 'Z', 'U', 'R', '?', 'D', 'T', 'E', 'S', 'A', 'M', 'B', 'L' };
 121 const char* blobTypeName[] = {"noType"
 122                              ,     "nMethod (under construction)"
 123                              ,          "nMethod (active)"
 124                              ,               "nMethod (inactive)"
 125                              ,                    "nMethod (deopt)"
 126                              ,                         "nMethod (zombie)"
 127                              ,                              "nMethod (unloaded)"
 128                              ,                                   "runtime stub"
 129                              ,                                        "ricochet stub"
 130                              ,                                             "deopt stub"
 131                              ,                                                  "uncommon trap stub"
 132                              ,                                                       "exception stub"
 133                              ,                                                            "safepoint stub"
 134                              ,                                                                 "adapter blob"
 135                              ,                                                                      "MH adapter blob"
 136                              ,                                                                           "buffer blob"
 137                              ,                                                                                "lastType"
 138                              };
 139 const char* compTypeName[] = { "none", "c1", "c2", "jvmci" };
 140 
 141 // Be prepared for ten different CodeHeap segments. Should be enough for a few years.
 142 const  unsigned int        nSizeDistElements = 31;  // logarithmic range growth, max size: 2**32
 143 const  unsigned int        maxTopSizeBlocks  = 50;
 144 const  unsigned int        tsbStopper        = 2 * maxTopSizeBlocks;
 145 const  unsigned int        maxHeaps          = 10;
 146 static unsigned int        nHeaps            = 0;
 147 static struct CodeHeapStat CodeHeapStatArray[maxHeaps];
 148 
 149 // static struct StatElement *StatArray      = NULL;
 150 static StatElement* StatArray             = NULL;
 151 static int          log2_seg_size         = 0;
 152 static size_t       seg_size              = 0;
 153 static size_t       alloc_granules        = 0;
 154 static size_t       granule_size          = 0;
 155 static bool         segment_granules      = false;
 156 static unsigned int nBlocks_t1            = 0;  // counting "in_use" nmethods only.
 157 static unsigned int nBlocks_t2            = 0;  // counting "in_use" nmethods only.
 158 static unsigned int nBlocks_alive         = 0;  // counting "not_used" and "not_entrant" nmethods only.
 159 static unsigned int nBlocks_dead          = 0;  // counting "zombie" and "unloaded" methods only.
 160 static unsigned int nBlocks_inconstr      = 0;  // counting "inconstruction" nmethods only. This is a transient state.
 161 static unsigned int nBlocks_unloaded      = 0;  // counting "unloaded" nmethods only. This is a transient state.
 162 static unsigned int nBlocks_stub          = 0;
 163 
 164 static struct FreeBlk*          FreeArray = NULL;
 165 static unsigned int      alloc_freeBlocks = 0;
 166 
 167 static struct TopSizeBlk*    TopSizeArray = NULL;
 168 static unsigned int   alloc_topSizeBlocks = 0;
 169 static unsigned int    used_topSizeBlocks = 0;
 170 
 171 static struct SizeDistributionElement*  SizeDistributionArray = NULL;
 172 
 173 // nMethod temperature (hotness) indicators.
 174 static int                     avgTemp    = 0;
 175 static int                     maxTemp    = 0;
 176 static int                     minTemp    = 0;
 177 
 178 static unsigned int  latest_compilation_id   = 0;
 179 static volatile bool initialization_complete = false;
 180 
 181 const char* CodeHeapState::get_heapName(CodeHeap* heap) {


 211   } else {
 212     nHeaps = 1;
 213     CodeHeapStatArray[0].heapName = heapName;
 214     return 0; // This is the default index if CodeCache is not segmented.
 215   }
 216 }
 217 
 218 void CodeHeapState::get_HeapStatGlobals(outputStream* out, const char* heapName) {
 219   unsigned int ix = findHeapIndex(out, heapName);
 220   if (ix < maxHeaps) {
 221     StatArray             = CodeHeapStatArray[ix].StatArray;
 222     seg_size              = CodeHeapStatArray[ix].segment_size;
 223     log2_seg_size         = seg_size == 0 ? 0 : exact_log2(seg_size);
 224     alloc_granules        = CodeHeapStatArray[ix].alloc_granules;
 225     granule_size          = CodeHeapStatArray[ix].granule_size;
 226     segment_granules      = CodeHeapStatArray[ix].segment_granules;
 227     nBlocks_t1            = CodeHeapStatArray[ix].nBlocks_t1;
 228     nBlocks_t2            = CodeHeapStatArray[ix].nBlocks_t2;
 229     nBlocks_alive         = CodeHeapStatArray[ix].nBlocks_alive;
 230     nBlocks_dead          = CodeHeapStatArray[ix].nBlocks_dead;
 231     nBlocks_inconstr      = CodeHeapStatArray[ix].nBlocks_inconstr;
 232     nBlocks_unloaded      = CodeHeapStatArray[ix].nBlocks_unloaded;
 233     nBlocks_stub          = CodeHeapStatArray[ix].nBlocks_stub;
 234     FreeArray             = CodeHeapStatArray[ix].FreeArray;
 235     alloc_freeBlocks      = CodeHeapStatArray[ix].alloc_freeBlocks;
 236     TopSizeArray          = CodeHeapStatArray[ix].TopSizeArray;
 237     alloc_topSizeBlocks   = CodeHeapStatArray[ix].alloc_topSizeBlocks;
 238     used_topSizeBlocks    = CodeHeapStatArray[ix].used_topSizeBlocks;
 239     SizeDistributionArray = CodeHeapStatArray[ix].SizeDistributionArray;
 240     avgTemp               = CodeHeapStatArray[ix].avgTemp;
 241     maxTemp               = CodeHeapStatArray[ix].maxTemp;
 242     minTemp               = CodeHeapStatArray[ix].minTemp;
 243   } else {
 244     StatArray             = NULL;
 245     seg_size              = 0;
 246     log2_seg_size         = 0;
 247     alloc_granules        = 0;
 248     granule_size          = 0;
 249     segment_granules      = false;
 250     nBlocks_t1            = 0;
 251     nBlocks_t2            = 0;
 252     nBlocks_alive         = 0;
 253     nBlocks_dead          = 0;
 254     nBlocks_inconstr      = 0;
 255     nBlocks_unloaded      = 0;
 256     nBlocks_stub          = 0;
 257     FreeArray             = NULL;
 258     alloc_freeBlocks      = 0;
 259     TopSizeArray          = NULL;
 260     alloc_topSizeBlocks   = 0;
 261     used_topSizeBlocks    = 0;
 262     SizeDistributionArray = NULL;
 263     avgTemp               = 0;
 264     maxTemp               = 0;
 265     minTemp               = 0;
 266   }
 267 }
 268 
 269 void CodeHeapState::set_HeapStatGlobals(outputStream* out, const char* heapName) {
 270   unsigned int ix = findHeapIndex(out, heapName);
 271   if (ix < maxHeaps) {
 272     CodeHeapStatArray[ix].StatArray             = StatArray;
 273     CodeHeapStatArray[ix].segment_size          = seg_size;
 274     CodeHeapStatArray[ix].alloc_granules        = alloc_granules;
 275     CodeHeapStatArray[ix].granule_size          = granule_size;
 276     CodeHeapStatArray[ix].segment_granules      = segment_granules;
 277     CodeHeapStatArray[ix].nBlocks_t1            = nBlocks_t1;
 278     CodeHeapStatArray[ix].nBlocks_t2            = nBlocks_t2;
 279     CodeHeapStatArray[ix].nBlocks_alive         = nBlocks_alive;
 280     CodeHeapStatArray[ix].nBlocks_dead          = nBlocks_dead;
 281     CodeHeapStatArray[ix].nBlocks_inconstr      = nBlocks_inconstr;
 282     CodeHeapStatArray[ix].nBlocks_unloaded      = nBlocks_unloaded;
 283     CodeHeapStatArray[ix].nBlocks_stub          = nBlocks_stub;
 284     CodeHeapStatArray[ix].FreeArray             = FreeArray;
 285     CodeHeapStatArray[ix].alloc_freeBlocks      = alloc_freeBlocks;
 286     CodeHeapStatArray[ix].TopSizeArray          = TopSizeArray;
 287     CodeHeapStatArray[ix].alloc_topSizeBlocks   = alloc_topSizeBlocks;
 288     CodeHeapStatArray[ix].used_topSizeBlocks    = used_topSizeBlocks;
 289     CodeHeapStatArray[ix].SizeDistributionArray = SizeDistributionArray;
 290     CodeHeapStatArray[ix].avgTemp               = avgTemp;
 291     CodeHeapStatArray[ix].maxTemp               = maxTemp;
 292     CodeHeapStatArray[ix].minTemp               = minTemp;
 293   }
 294 }
 295 
 296 //---<  get a new statistics array  >---
 297 void CodeHeapState::prepare_StatArray(outputStream* out, size_t nElem, size_t granularity, const char* heapName) {
 298   if (StatArray == NULL) {
 299     StatArray      = new StatElement[nElem];
 300     //---<  reset some counts  >---
 301     alloc_granules = nElem;


 542                 "   Subsequent print functions create their output based on this snapshot.\n"
 543                 "   The CodeHeap is a living thing, and every effort has been made for the\n"
 544                 "   collected data to be consistent. Only the method names and signatures\n"
 545                 "   are retrieved at print time. That may lead to rare cases where the\n"
 546                 "   name of a method is no longer available, e.g. because it was unloaded.\n");
 547   ast->print_cr("   CodeHeap committed size " SIZE_FORMAT "K (" SIZE_FORMAT "M), reserved size " SIZE_FORMAT "K (" SIZE_FORMAT "M), %d%% occupied.",
 548                 size/(size_t)K, size/(size_t)M, res_size/(size_t)K, res_size/(size_t)M, (unsigned int)(100.0*size/res_size));
 549   ast->print_cr("   CodeHeap allocation segment size is " SIZE_FORMAT " bytes. This is the smallest possible granularity.", seg_size);
 550   ast->print_cr("   CodeHeap (committed part) is mapped to " SIZE_FORMAT " granules of size " SIZE_FORMAT " bytes.", granules, granularity);
 551   ast->print_cr("   Each granule takes " SIZE_FORMAT " bytes of C heap, that is " SIZE_FORMAT "K in total for statistics data.", sizeof(StatElement), (sizeof(StatElement)*granules)/(size_t)K);
 552   ast->print_cr("   The number of granules is limited to %dk, requiring a granules size of at least %d bytes for a 1GB heap.", (unsigned int)(max_granules/K), (unsigned int)(G/max_granules));
 553   STRINGSTREAM_FLUSH("\n")
 554 
 555 
 556   while (!done) {
 557     //---<  reset counters with every aggregation  >---
 558     nBlocks_t1       = 0;
 559     nBlocks_t2       = 0;
 560     nBlocks_alive    = 0;
 561     nBlocks_dead     = 0;
 562     nBlocks_inconstr = 0;
 563     nBlocks_unloaded = 0;
 564     nBlocks_stub     = 0;
 565 
 566     nBlocks_free     = 0;
 567     nBlocks_used     = 0;
 568     nBlocks_zomb     = 0;
 569     nBlocks_disconn  = 0;
 570     nBlocks_notentr  = 0;
 571 
 572     //---<  discard old arrays if size does not match  >---
 573     if (granules != alloc_granules) {
 574       discard_StatArray(out);
 575       discard_TopSizeArray(out);
 576     }
 577 
 578     //---<  allocate arrays if they don't yet exist, initialize  >---
 579     prepare_StatArray(out, granules, granularity, heapName);
 580     if (StatArray == NULL) {
 581       set_HeapStatGlobals(out, heapName);
 582       return;
 583     }
 584     prepare_TopSizeArray(out, maxTopSizeBlocks, heapName);
 585     prepare_SizeDistArray(out, nSizeDistElements, heapName);
 586 
 587     latest_compilation_id = CompileBroker::get_compilation_id();
 588     unsigned int highest_compilation_id = 0;
 589     size_t       usedSpace     = 0;
 590     size_t       t1Space       = 0;
 591     size_t       t2Space       = 0;
 592     size_t       aliveSpace    = 0;
 593     size_t       disconnSpace  = 0;
 594     size_t       notentrSpace  = 0;
 595     size_t       deadSpace     = 0;
 596     size_t       inconstrSpace = 0;
 597     size_t       unloadedSpace = 0;
 598     size_t       stubSpace     = 0;
 599     size_t       freeSpace     = 0;
 600     size_t       maxFreeSize   = 0;
 601     HeapBlock*   maxFreeBlock  = NULL;
 602     bool         insane        = false;
 603 
 604     int64_t hotnessAccumulator = 0;
 605     unsigned int n_methods     = 0;
 606     avgTemp       = 0;
 607     minTemp       = (int)(res_size > M ? (res_size/M)*2 : 1);
 608     maxTemp       = -minTemp;
 609 
 610     for (HeapBlock *h = heap->first_block(); h != NULL && !insane; h = heap->next_block(h)) {
 611       unsigned int hb_len     = (unsigned int)h->length();  // despite being size_t, length can never overflow an unsigned int.
 612       size_t       hb_bytelen = ((size_t)hb_len)<<log2_seg_size;
 613       unsigned int ix_beg     = (unsigned int)(((char*)h-low_bound)/granule_size);
 614       unsigned int ix_end     = (unsigned int)(((char*)h-low_bound+(hb_bytelen-1))/granule_size);
 615       unsigned int compile_id = 0;
 616       CompLevel    comp_lvl   = CompLevel_none;


 682               case nMethod_notused:
 683                 nBlocks_alive++;
 684                 nBlocks_disconn++;
 685                 aliveSpace     += hb_bytelen;
 686                 disconnSpace   += hb_bytelen;
 687                 break;
 688               case nMethod_notentrant:  // equivalent to nMethod_alive
 689                 nBlocks_alive++;
 690                 nBlocks_notentr++;
 691                 aliveSpace     += hb_bytelen;
 692                 notentrSpace   += hb_bytelen;
 693                 break;
 694               case nMethod_unloaded:
 695                 nBlocks_unloaded++;
 696                 unloadedSpace  += hb_bytelen;
 697                 break;
 698               case nMethod_dead:
 699                 nBlocks_dead++;
 700                 deadSpace      += hb_bytelen;
 701                 break;
 702               case nMethod_inconstruction:
 703                 nBlocks_inconstr++;
 704                 inconstrSpace  += hb_bytelen;
 705                 break;
 706               default:
 707                 break;
 708             }
 709           }
 710 
 711           //------------------------------------------
 712           //---<  register block in TopSizeArray  >---
 713           //------------------------------------------
 714           if (alloc_topSizeBlocks > 0) {
 715             if (used_topSizeBlocks == 0) {
 716               TopSizeArray[0].start    = h;
 717               TopSizeArray[0].len      = hb_len;
 718               TopSizeArray[0].index    = tsbStopper;
 719               TopSizeArray[0].compiler = cType;
 720               TopSizeArray[0].level    = comp_lvl;
 721               TopSizeArray[0].type     = cbType;
 722               currMax    = hb_len;
 723               currMin    = hb_len;
 724               currMin_ix = 0;
 725               used_topSizeBlocks++;


 840           StatArray[ix_beg].type = cbType;
 841           switch (cbType) {
 842             case nMethod_inuse:
 843               highest_compilation_id = (highest_compilation_id >= compile_id) ? highest_compilation_id : compile_id;
 844               if (comp_lvl < CompLevel_full_optimization) {
 845                 nBlocks_t1++;
 846                 t1Space   += hb_bytelen;
 847                 StatArray[ix_beg].t1_count++;
 848                 StatArray[ix_beg].t1_space += (unsigned short)hb_len;
 849                 StatArray[ix_beg].t1_age    = StatArray[ix_beg].t1_age < compile_id ? compile_id : StatArray[ix_beg].t1_age;
 850               } else {
 851                 nBlocks_t2++;
 852                 t2Space   += hb_bytelen;
 853                 StatArray[ix_beg].t2_count++;
 854                 StatArray[ix_beg].t2_space += (unsigned short)hb_len;
 855                 StatArray[ix_beg].t2_age    = StatArray[ix_beg].t2_age < compile_id ? compile_id : StatArray[ix_beg].t2_age;
 856               }
 857               StatArray[ix_beg].level     = comp_lvl;
 858               StatArray[ix_beg].compiler  = cType;
 859               break;
 860             case nMethod_inconstruction: // let's count "in construction" nmethods here.
 861             case nMethod_alive:
 862               StatArray[ix_beg].tx_count++;
 863               StatArray[ix_beg].tx_space += (unsigned short)hb_len;
 864               StatArray[ix_beg].tx_age    = StatArray[ix_beg].tx_age < compile_id ? compile_id : StatArray[ix_beg].tx_age;
 865               StatArray[ix_beg].level     = comp_lvl;
 866               StatArray[ix_beg].compiler  = cType;
 867               break;
 868             case nMethod_dead:
 869             case nMethod_unloaded:
 870               StatArray[ix_beg].dead_count++;
 871               StatArray[ix_beg].dead_space += (unsigned short)hb_len;
 872               break;
 873             default:
 874               // must be a stub, if it's not a dead or alive nMethod
 875               nBlocks_stub++;
 876               stubSpace   += hb_bytelen;
 877               StatArray[ix_beg].stub_count++;
 878               StatArray[ix_beg].stub_space += (unsigned short)hb_len;
 879               break;
 880           }


 897 
 898                 StatArray[ix_end].t1_count++;
 899                 StatArray[ix_end].t1_space += (unsigned short)end_space;
 900                 StatArray[ix_end].t1_age    = StatArray[ix_end].t1_age < compile_id ? compile_id : StatArray[ix_end].t1_age;
 901               } else {
 902                 nBlocks_t2++;
 903                 t2Space   += hb_bytelen;
 904                 StatArray[ix_beg].t2_count++;
 905                 StatArray[ix_beg].t2_space += (unsigned short)beg_space;
 906                 StatArray[ix_beg].t2_age    = StatArray[ix_beg].t2_age < compile_id ? compile_id : StatArray[ix_beg].t2_age;
 907 
 908                 StatArray[ix_end].t2_count++;
 909                 StatArray[ix_end].t2_space += (unsigned short)end_space;
 910                 StatArray[ix_end].t2_age    = StatArray[ix_end].t2_age < compile_id ? compile_id : StatArray[ix_end].t2_age;
 911               }
 912               StatArray[ix_beg].level     = comp_lvl;
 913               StatArray[ix_beg].compiler  = cType;
 914               StatArray[ix_end].level     = comp_lvl;
 915               StatArray[ix_end].compiler  = cType;
 916               break;
 917             case nMethod_inconstruction: // let's count "in construction" nmethods here.
 918             case nMethod_alive:
 919               StatArray[ix_beg].tx_count++;
 920               StatArray[ix_beg].tx_space += (unsigned short)beg_space;
 921               StatArray[ix_beg].tx_age    = StatArray[ix_beg].tx_age < compile_id ? compile_id : StatArray[ix_beg].tx_age;
 922 
 923               StatArray[ix_end].tx_count++;
 924               StatArray[ix_end].tx_space += (unsigned short)end_space;
 925               StatArray[ix_end].tx_age    = StatArray[ix_end].tx_age < compile_id ? compile_id : StatArray[ix_end].tx_age;
 926 
 927               StatArray[ix_beg].level     = comp_lvl;
 928               StatArray[ix_beg].compiler  = cType;
 929               StatArray[ix_end].level     = comp_lvl;
 930               StatArray[ix_end].compiler  = cType;
 931               break;
 932             case nMethod_dead:
 933             case nMethod_unloaded:
 934               StatArray[ix_beg].dead_count++;
 935               StatArray[ix_beg].dead_space += (unsigned short)beg_space;
 936               StatArray[ix_end].dead_count++;
 937               StatArray[ix_end].dead_space += (unsigned short)end_space;


 945               StatArray[ix_end].stub_count++;
 946               StatArray[ix_end].stub_space += (unsigned short)end_space;
 947               break;
 948           }
 949           for (unsigned int ix = ix_beg+1; ix < ix_end; ix++) {
 950             StatArray[ix].type = cbType;
 951             switch (cbType) {
 952               case nMethod_inuse:
 953                 if (comp_lvl < CompLevel_full_optimization) {
 954                   StatArray[ix].t1_count++;
 955                   StatArray[ix].t1_space += (unsigned short)(granule_size>>log2_seg_size);
 956                   StatArray[ix].t1_age    = StatArray[ix].t1_age < compile_id ? compile_id : StatArray[ix].t1_age;
 957                 } else {
 958                   StatArray[ix].t2_count++;
 959                   StatArray[ix].t2_space += (unsigned short)(granule_size>>log2_seg_size);
 960                   StatArray[ix].t2_age    = StatArray[ix].t2_age < compile_id ? compile_id : StatArray[ix].t2_age;
 961                 }
 962                 StatArray[ix].level     = comp_lvl;
 963                 StatArray[ix].compiler  = cType;
 964                 break;
 965               case nMethod_inconstruction: // let's count "in construction" nmethods here.
 966               case nMethod_alive:
 967                 StatArray[ix].tx_count++;
 968                 StatArray[ix].tx_space += (unsigned short)(granule_size>>log2_seg_size);
 969                 StatArray[ix].tx_age    = StatArray[ix].tx_age < compile_id ? compile_id : StatArray[ix].tx_age;
 970                 StatArray[ix].level     = comp_lvl;
 971                 StatArray[ix].compiler  = cType;
 972                 break;
 973               case nMethod_dead:
 974               case nMethod_unloaded:
 975                 StatArray[ix].dead_count++;
 976                 StatArray[ix].dead_space += (unsigned short)(granule_size>>log2_seg_size);
 977                 break;
 978               default:
 979                 // must be a stub, if it's not a dead or alive nMethod
 980                 StatArray[ix].stub_count++;
 981                 StatArray[ix].stub_space += (unsigned short)(granule_size>>log2_seg_size);
 982                 break;
 983             }
 984           }
 985         }
 986       }
 987     }





 988     done = true;
 989 
 990     if (!insane) {
 991       // There is a risk for this block (because it contains many print statements) to get
 992       // interspersed with print data from other threads. We take this risk intentionally.
 993       // Getting stalled waiting for tty_lock while holding the CodeCache_lock is not desirable.
 994       printBox(ast, '-', "Global CodeHeap statistics for segment ", heapName);
 995       ast->print_cr("freeSpace        = " SIZE_FORMAT_W(8) "k, nBlocks_free     = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", freeSpace/(size_t)K,     nBlocks_free,     (100.0*freeSpace)/size,     (100.0*freeSpace)/res_size);
 996       ast->print_cr("usedSpace        = " SIZE_FORMAT_W(8) "k, nBlocks_used     = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", usedSpace/(size_t)K,     nBlocks_used,     (100.0*usedSpace)/size,     (100.0*usedSpace)/res_size);
 997       ast->print_cr("  Tier1 Space    = " SIZE_FORMAT_W(8) "k, nBlocks_t1       = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", t1Space/(size_t)K,       nBlocks_t1,       (100.0*t1Space)/size,       (100.0*t1Space)/res_size);
 998       ast->print_cr("  Tier2 Space    = " SIZE_FORMAT_W(8) "k, nBlocks_t2       = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", t2Space/(size_t)K,       nBlocks_t2,       (100.0*t2Space)/size,       (100.0*t2Space)/res_size);
 999       ast->print_cr("  Alive Space    = " SIZE_FORMAT_W(8) "k, nBlocks_alive    = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", aliveSpace/(size_t)K,    nBlocks_alive,    (100.0*aliveSpace)/size,    (100.0*aliveSpace)/res_size);
1000       ast->print_cr("    disconnected = " SIZE_FORMAT_W(8) "k, nBlocks_disconn  = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", disconnSpace/(size_t)K,  nBlocks_disconn,  (100.0*disconnSpace)/size,  (100.0*disconnSpace)/res_size);
1001       ast->print_cr("    not entrant  = " SIZE_FORMAT_W(8) "k, nBlocks_notentr  = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", notentrSpace/(size_t)K,  nBlocks_notentr,  (100.0*notentrSpace)/size,  (100.0*notentrSpace)/res_size);
1002       ast->print_cr("  inconstrSpace  = " SIZE_FORMAT_W(8) "k, nBlocks_inconstr = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", inconstrSpace/(size_t)K, nBlocks_inconstr, (100.0*inconstrSpace)/size, (100.0*inconstrSpace)/res_size);
1003       ast->print_cr("  unloadedSpace  = " SIZE_FORMAT_W(8) "k, nBlocks_unloaded = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", unloadedSpace/(size_t)K, nBlocks_unloaded, (100.0*unloadedSpace)/size, (100.0*unloadedSpace)/res_size);
1004       ast->print_cr("  deadSpace      = " SIZE_FORMAT_W(8) "k, nBlocks_dead     = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", deadSpace/(size_t)K,     nBlocks_dead,     (100.0*deadSpace)/size,     (100.0*deadSpace)/res_size);
1005       ast->print_cr("  stubSpace      = " SIZE_FORMAT_W(8) "k, nBlocks_stub     = %6d, %10.3f%% of capacity, %10.3f%% of max_capacity", stubSpace/(size_t)K,     nBlocks_stub,     (100.0*stubSpace)/size,     (100.0*stubSpace)/res_size);
1006       ast->print_cr("ZombieBlocks     = %8d. These are HeapBlocks which could not be identified as CodeBlobs.", nBlocks_zomb);
1007       ast->cr();
1008       ast->print_cr("Segment start          = " INTPTR_FORMAT ", used space      = " SIZE_FORMAT_W(8)"k", p2i(low_bound), size/K);
1009       ast->print_cr("Segment end (used)     = " INTPTR_FORMAT ", remaining space = " SIZE_FORMAT_W(8)"k", p2i(low_bound) + size, (res_size - size)/K);
1010       ast->print_cr("Segment end (reserved) = " INTPTR_FORMAT ", reserved space  = " SIZE_FORMAT_W(8)"k", p2i(low_bound) + res_size, res_size/K);
1011       ast->cr();
1012       ast->print_cr("latest allocated compilation id = %d", latest_compilation_id);
1013       ast->print_cr("highest observed compilation id = %d", highest_compilation_id);
1014       ast->print_cr("Building TopSizeList iterations = %ld", total_iterations);
1015       ast->cr();
1016 
1017       int             reset_val = NMethodSweeper::hotness_counter_reset_val();
1018       double reverse_free_ratio = (res_size > size) ? (double)res_size/(double)(res_size-size) : (double)res_size;
1019       printBox(ast, '-', "Method hotness information at time of this analysis", NULL);
1020       ast->print_cr("Highest possible method temperature:          %12d", reset_val);
1021       ast->print_cr("Threshold for method to be considered 'cold': %12.3f", -reset_val + reverse_free_ratio * NmethodSweepActivity);
1022       if (n_methods > 0) {
1023         avgTemp = hotnessAccumulator/n_methods;
1024         ast->print_cr("min. hotness = %6d", minTemp);
1025         ast->print_cr("avg. hotness = %6d", avgTemp);
1026         ast->print_cr("max. hotness = %6d", maxTemp);
1027       } else {
1028         avgTemp = 0;
1029         ast->print_cr("No hotness data available");
1030       }
1031       STRINGSTREAM_FLUSH("\n")
1032 
1033       // This loop is intentionally printing directly to "out".
1034       out->print("Verifying collected data...");
1035       size_t granule_segs = granule_size>>log2_seg_size;
1036       for (unsigned int ix = 0; ix < granules; ix++) {
1037         if (StatArray[ix].t1_count   > granule_segs) {
1038           out->print_cr("t1_count[%d]   = %d", ix, StatArray[ix].t1_count);
1039         }
1040         if (StatArray[ix].t2_count   > granule_segs) {
1041           out->print_cr("t2_count[%d]   = %d", ix, StatArray[ix].t2_count);
1042         }
1043         if (StatArray[ix].tx_count   > granule_segs) {
1044           out->print_cr("tx_count[%d]   = %d", ix, StatArray[ix].tx_count);
1045         }
1046         if (StatArray[ix].stub_count > granule_segs) {
1047           out->print_cr("stub_count[%d] = %d", ix, StatArray[ix].stub_count);
1048         }
1049         if (StatArray[ix].dead_count > granule_segs) {
1050           out->print_cr("dead_count[%d] = %d", ix, StatArray[ix].dead_count);
1051         }
1052         if (StatArray[ix].t1_space   > granule_segs) {
1053           out->print_cr("t1_space[%d]   = %d", ix, StatArray[ix].t1_space);
1054         }
1055         if (StatArray[ix].t2_space   > granule_segs) {
1056           out->print_cr("t2_space[%d]   = %d", ix, StatArray[ix].t2_space);
1057         }
1058         if (StatArray[ix].tx_space   > granule_segs) {
1059           out->print_cr("tx_space[%d]   = %d", ix, StatArray[ix].tx_space);
1060         }
1061         if (StatArray[ix].stub_space > granule_segs) {
1062           out->print_cr("stub_space[%d] = %d", ix, StatArray[ix].stub_space);
1063         }
1064         if (StatArray[ix].dead_space > granule_segs) {
1065           out->print_cr("dead_space[%d] = %d", ix, StatArray[ix].dead_space);
1066         }
1067         //   this cast is awful! I need it because NT/Intel reports a signed/unsigned mismatch.
1068         if ((size_t)(StatArray[ix].t1_count+StatArray[ix].t2_count+StatArray[ix].tx_count+StatArray[ix].stub_count+StatArray[ix].dead_count) > granule_segs) {
1069           out->print_cr("t1_count[%d] = %d, t2_count[%d] = %d, tx_count[%d] = %d, stub_count[%d] = %d", ix, StatArray[ix].t1_count, ix, StatArray[ix].t2_count, ix, StatArray[ix].tx_count, ix, StatArray[ix].stub_count);
1070         }
1071         if ((size_t)(StatArray[ix].t1_space+StatArray[ix].t2_space+StatArray[ix].tx_space+StatArray[ix].stub_space+StatArray[ix].dead_space) > granule_segs) {
1072           out->print_cr("t1_space[%d] = %d, t2_space[%d] = %d, tx_space[%d] = %d, stub_space[%d] = %d", ix, StatArray[ix].t1_space, ix, StatArray[ix].t2_space, ix, StatArray[ix].tx_space, ix, StatArray[ix].stub_space);
1073         }
1074       }
1075 
1076       // This loop is intentionally printing directly to "out".
1077       if (used_topSizeBlocks > 0) {
1078         unsigned int j = 0;
1079         if (TopSizeArray[0].len != currMax) {
1080           out->print_cr("currMax(%d) differs from TopSizeArray[0].len(%d)", currMax, TopSizeArray[0].len);
1081         }
1082         for (unsigned int i = 0; (TopSizeArray[i].index != tsbStopper) && (j++ < alloc_topSizeBlocks); i = TopSizeArray[i].index) {
1083           if (TopSizeArray[i].len < TopSizeArray[TopSizeArray[i].index].len) {
1084             out->print_cr("sort error at index %d: %d !>= %d", i, TopSizeArray[i].len, TopSizeArray[TopSizeArray[i].index].len);
1085           }
1086         }
1087         if (j >= alloc_topSizeBlocks) {
1088           out->print_cr("Possible loop in TopSizeArray chaining!\n  allocBlocks = %d, usedBlocks = %d", alloc_topSizeBlocks, used_topSizeBlocks);
1089           for (unsigned int i = 0; i < alloc_topSizeBlocks; i++) {
1090             out->print_cr("  TopSizeArray[%d].index = %d, len = %d", i, TopSizeArray[i].index, TopSizeArray[i].len);
1091           }
1092         }


1136       if (ix < alloc_freeBlocks) { // don't index out of bounds if _freelist has more blocks than anticipated
1137         FreeArray[ix].start = cur;
1138         FreeArray[ix].len   = (unsigned int)(cur->length()<<log2_seg_size);
1139         FreeArray[ix].index = ix;
1140       }
1141       cur  = cur->link();
1142       ix++;
1143     }
1144     if (ix != alloc_freeBlocks) {
1145       ast->print_cr("Free block count mismatch. Expected %d free blocks, but found %d.", alloc_freeBlocks, ix);
1146       ast->print_cr("I will update the counter and retry data collection");
1147       STRINGSTREAM_FLUSH("\n")
1148       nBlocks_free = ix;
1149       continue;
1150     }
1151     done = true;
1152   }
1153 
1154   if (!done || (nBlocks_free == 0)) {
1155     if (nBlocks_free == 0) {
1156       printBox(ast, '-', "no free blocks found in ", heapName);
1157     } else if (!done) {
1158       ast->print_cr("Free block count mismatch could not be resolved.");
1159       ast->print_cr("Try to run \"aggregate\" function to update counters");
1160     }
1161     STRINGSTREAM_FLUSH("")
1162 
1163     //---< discard old array and update global values  >---
1164     discard_FreeArray(out);
1165     set_HeapStatGlobals(out, heapName);
1166     return;
1167   }
1168 
1169   //---<  calculate and fill remaining fields  >---
1170   if (FreeArray != NULL) {
1171     // This loop is intentionally printing directly to "out".
1172     for (unsigned int ix = 0; ix < alloc_freeBlocks-1; ix++) {
1173       size_t lenSum = 0;
1174       FreeArray[ix].gap = (unsigned int)((address)FreeArray[ix+1].start - ((address)FreeArray[ix].start + FreeArray[ix].len));
1175       for (HeapBlock *h = heap->next_block(FreeArray[ix].start); (h != NULL) && (h != FreeArray[ix+1].start); h = heap->next_block(h)) {
1176         CodeBlob *cb  = (CodeBlob*)(heap->find_start(h));


1268 
1269         //---<  print size, name, and signature (for nMethods)  >---
1270         if ((nm != NULL) && (nm->method() != NULL)) {
1271           ResourceMark rm;
1272           //---<  nMethod size in hex  >---
1273           unsigned int total_size = nm->total_size();
1274           ast->print(PTR32_FORMAT, total_size);
1275           ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K);
1276           ast->fill_to(51);
1277           ast->print("  %c", blobTypeChar[TopSizeArray[i].type]);
1278           //---<  compiler information  >---
1279           ast->fill_to(56);
1280           ast->print("%5s %3d", compTypeName[TopSizeArray[i].compiler], TopSizeArray[i].level);
1281           //---<  method temperature  >---
1282           ast->fill_to(67);
1283           ast->print("%5d", nm->hotness_counter());
1284           //---<  name and signature  >---
1285           ast->fill_to(67+6);
1286           if (nm->is_in_use())        {blob_name = nm->method()->name_and_sig_as_C_string(); }
1287           if (nm->is_not_entrant())   {blob_name = nm->method()->name_and_sig_as_C_string(); }
1288           if (nm->is_not_installed()) {ast->print("%s", " not (yet) installed method "); }
1289           if (nm->is_zombie())        {ast->print("%s", " zombie method "); }
1290           ast->print("%s", blob_name);
1291         } else {
1292           //---<  block size in hex  >---
1293           ast->print(PTR32_FORMAT, (unsigned int)(TopSizeArray[i].len<<log2_seg_size));
1294           ast->print("(" SIZE_FORMAT_W(4) "K)", (TopSizeArray[i].len<<log2_seg_size)/K);
1295           //---<  no compiler information  >---
1296           ast->fill_to(56);
1297           //---<  name and signature  >---
1298           ast->fill_to(67+6);
1299           ast->print("%s", blob_name);
1300         }
1301         STRINGSTREAM_FLUSH_LOCKED("\n")
1302       }
1303       if (used_topSizeBlocks != printed_topSizeBlocks) {
1304         ast->print_cr("used blocks: %d, printed blocks: %d", used_topSizeBlocks, printed_topSizeBlocks);
1305         STRINGSTREAM_FLUSH("")
1306         for (unsigned int i = 0; i < alloc_topSizeBlocks; i++) {
1307           ast->print_cr("  TopSizeArray[%d].index = %d, len = %d", i, TopSizeArray[i].index, TopSizeArray[i].len);
1308           STRINGSTREAM_FLUSH("")
1309         }


1663       STRINGSTREAM_FLUSH_LOCKED("")
1664 
1665       granules_per_line = 128;
1666       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
1667         print_line_delim(out, ast, low_bound, ix, granules_per_line);
1668         if (segment_granules && StatArray[ix].t2_count > 0) {
1669           print_blobType_single(ast, StatArray[ix].type);
1670         } else {
1671           print_count_single(ast, StatArray[ix].t2_count);
1672         }
1673       }
1674       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
1675     } else {
1676       ast->print("No Tier2 nMethods found in CodeHeap.");
1677       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
1678     }
1679   }
1680 
1681   {
1682     if (nBlocks_alive > 0) {
1683       printBox(ast, '-', "not_used/not_entrant/not_installed nMethod count only, 0x1..0xf. '*' indicates >= 16 blocks, ' ' indicates empty", NULL);
1684       STRINGSTREAM_FLUSH_LOCKED("")
1685 
1686       granules_per_line = 128;
1687       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
1688         print_line_delim(out, ast, low_bound, ix, granules_per_line);
1689         if (segment_granules && StatArray[ix].tx_count > 0) {
1690           print_blobType_single(ast, StatArray[ix].type);
1691         } else {
1692           print_count_single(ast, StatArray[ix].tx_count);
1693         }
1694       }
1695       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
1696     } else {
1697       ast->print("No not_used/not_entrant nMethods found in CodeHeap.");
1698       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
1699     }
1700   }
1701 
1702   {
1703     if (nBlocks_stub > 0) {


1852       STRINGSTREAM_FLUSH_LOCKED("")
1853 
1854       granules_per_line = 128;
1855       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
1856         print_line_delim(out, ast, low_bound, ix, granules_per_line);
1857         if (segment_granules && StatArray[ix].t2_space > 0) {
1858           print_blobType_single(ast, StatArray[ix].type);
1859         } else {
1860           print_space_single(ast, StatArray[ix].t2_space);
1861         }
1862       }
1863       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
1864     } else {
1865       ast->print("No Tier2 nMethods found in CodeHeap.");
1866       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
1867     }
1868   }
1869 
1870   {
1871     if (nBlocks_alive > 0) {
1872       printBox(ast, '-', "not_used/not_entrant/not_installed space consumption. ' ' indicates empty, '*' indicates full", NULL);
1873 
1874       granules_per_line = 128;
1875       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
1876         print_line_delim(out, ast, low_bound, ix, granules_per_line);
1877         if (segment_granules && StatArray[ix].tx_space > 0) {
1878           print_blobType_single(ast, StatArray[ix].type);
1879         } else {
1880           print_space_single(ast, StatArray[ix].tx_space);
1881         }
1882       }
1883       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
1884     } else {
1885       ast->print("No Tier2 nMethods found in CodeHeap.");
1886       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
1887     }
1888   }
1889 
1890   {
1891     if (nBlocks_stub > 0) {
1892       printBox(ast, '-', "Stub and Blob space consumption. ' ' indicates empty, '*' indicates full", NULL);


2022 
2023   {
2024     if (nBlocks_t2 > 0) {
2025       printBox(ast, '-', "Tier2 age distribution. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL);
2026       STRINGSTREAM_FLUSH_LOCKED("")
2027 
2028       granules_per_line = 128;
2029       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
2030         print_line_delim(out, ast, low_bound, ix, granules_per_line);
2031         print_age_single(ast, StatArray[ix].t2_age);
2032       }
2033       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
2034     } else {
2035       ast->print("No Tier2 nMethods found in CodeHeap.");
2036       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
2037     }
2038   }
2039 
2040   {
2041     if (nBlocks_alive > 0) {
2042       printBox(ast, '-', "not_used/not_entrant/not_installed age distribution. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL);
2043       STRINGSTREAM_FLUSH_LOCKED("")
2044 
2045       granules_per_line = 128;
2046       for (unsigned int ix = 0; ix < alloc_granules; ix++) {
2047         print_line_delim(out, ast, low_bound, ix, granules_per_line);
2048         print_age_single(ast, StatArray[ix].tx_age);
2049       }
2050       STRINGSTREAM_FLUSH_LOCKED("|\n\n\n")
2051     } else {
2052       ast->print("No Tier2 nMethods found in CodeHeap.");
2053       STRINGSTREAM_FLUSH_LOCKED("\n\n\n")
2054     }
2055   }
2056 
2057   {
2058     if (!segment_granules) { // Prevent totally redundant printouts
2059       printBox(ast, '-', "age distribution by tier <a1>:<a2>. '0' indicates youngest 1/256, '8': oldest half, ' ': no age information", NULL);
2060       STRINGSTREAM_FLUSH_LOCKED("")
2061 
2062       granules_per_line = 32;


2152         //---<  print table header for new print range  >---
2153         if (!name_in_addr_range) {
2154           name_in_addr_range = true;
2155           ast->fill_to(51);
2156           ast->print("%9s", "compiler");
2157           ast->fill_to(61);
2158           ast->print_cr("%6s", "method");
2159           ast->print_cr("%18s %13s %17s %9s  %5s %18s  %s", "Addr(module)      ", "offset", "size", " type lvl", " temp", "blobType          ", "Name");
2160           STRINGSTREAM_FLUSH_LOCKED("")
2161         }
2162 
2163         //---<  print line prefix (address and offset from CodeHeap start)  >---
2164         ast->print(INTPTR_FORMAT, p2i(this_blob));
2165         ast->fill_to(19);
2166         ast->print("(+" PTR32_FORMAT ")", (unsigned int)((char*)this_blob-low_bound));
2167         ast->fill_to(33);
2168 
2169         // this_blob->as_nmethod_or_null() is safe. Inlined, maybe invisible on stack.
2170         nmethod*    nm     = this_blob->as_nmethod_or_null();
2171         Method*     method = (nm == NULL) ? NULL : nm->method();  // may be uninitialized, i.e. != NULL, but invalid
2172         if ((nm != NULL) && (method != NULL) && (cbType != nMethod_dead) && (cbType != nMethod_inconstruction) &&
2173             is_readable_pointer(method) && is_readable_pointer(method->constants())) {
2174           ResourceMark rm;
2175           //---<  collect all data to locals as quickly as possible  >---
2176           unsigned int total_size = nm->total_size();
2177           int          hotness    = nm->hotness_counter();
2178           bool         get_name   = (cbType == nMethod_inuse) || (cbType == nMethod_notused);
2179           //---<  nMethod size in hex  >---
2180           ast->print(PTR32_FORMAT, total_size);
2181           ast->print("(" SIZE_FORMAT_W(4) "K)", total_size/K);
2182           //---<  compiler information  >---
2183           ast->fill_to(51);
2184           ast->print("%5s %3d", compTypeName[StatArray[ix].compiler], StatArray[ix].level);
2185           //---<  method temperature  >---
2186           ast->fill_to(62);
2187           ast->print("%5d", hotness);
2188           //---<  name and signature  >---
2189           ast->fill_to(62+6);
2190           ast->print("%s", blobTypeName[cbType]);
2191           ast->fill_to(82+6);
2192           if (cbType == nMethod_dead) {


2364 
2365     ast->print(INTPTR_FORMAT, p2i(low_bound + ix*granule_size));
2366     ast->fill_to(19);
2367     ast->print("(+" PTR32_FORMAT "): |", (unsigned int)(ix*granule_size));
2368   }
2369 }
2370 
2371 CodeHeapState::blobType CodeHeapState::get_cbType(CodeBlob* cb) {
2372   if ((cb != NULL) && is_readable_pointer(cb)) {
2373     if (cb->is_runtime_stub())                return runtimeStub;
2374     if (cb->is_deoptimization_stub())         return deoptimizationStub;
2375     if (cb->is_uncommon_trap_stub())          return uncommonTrapStub;
2376     if (cb->is_exception_stub())              return exceptionStub;
2377     if (cb->is_safepoint_stub())              return safepointStub;
2378     if (cb->is_adapter_blob())                return adapterBlob;
2379     if (cb->is_method_handles_adapter_blob()) return mh_adapterBlob;
2380     if (cb->is_buffer_blob())                 return bufferBlob;
2381 
2382     nmethod*  nm = cb->as_nmethod_or_null();
2383     if (nm != NULL) { // no is_readable check required, nm = (nmethod*)cb.
2384       if (nm->is_not_installed()) return nMethod_inconstruction;
2385       if (nm->is_zombie())        return nMethod_dead;
2386       if (nm->is_unloaded())      return nMethod_unloaded;
2387       if (nm->is_in_use())        return nMethod_inuse;
2388       if (nm->is_alive() && !(nm->is_not_entrant()))   return nMethod_notused;
2389       if (nm->is_alive())         return nMethod_alive;

2390       return nMethod_dead;
2391     }
2392   }
2393   return noType;
2394 }
2395 
2396 // Check if pointer can be read from (4-byte read access).
2397 // Helps to prove validity of a not-NULL pointer.
2398 // Returns true in very early stages of VM life when stub is not yet generated.
2399 #define SAFEFETCH_DEFAULT true
2400 bool CodeHeapState::is_readable_pointer(const void* p) {
2401   if (!CanUseSafeFetch32()) {
2402     return SAFEFETCH_DEFAULT;
2403   }
2404   int* const aligned = (int*) align_down((intptr_t)p, 4);
2405   int cafebabe = 0xcafebabe;  // tester value 1
2406   int deadbeef = 0xdeadbeef;  // tester value 2
2407   return (SafeFetch32(aligned, cafebabe) != cafebabe) || (SafeFetch32(aligned, deadbeef) != deadbeef);
2408 }
< prev index next >