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 }
|