1 | /* |
2 | * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. |
3 | * Copyright (c) 2018, 2019 SAP SE. All rights reserved. |
4 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
5 | * |
6 | * This code is free software; you can redistribute it and/or modify it |
7 | * under the terms of the GNU General Public License version 2 only, as |
8 | * published by the Free Software Foundation. |
9 | * |
10 | * This code is distributed in the hope that it will be useful, but WITHOUT |
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
13 | * version 2 for more details (a copy is included in the LICENSE file that |
14 | * accompanied this code). |
15 | * |
16 | * You should have received a copy of the GNU General Public License version |
17 | * 2 along with this work; if not, write to the Free Software Foundation, |
18 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | * |
20 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
21 | * or visit www.oracle.com if you need additional information or have any |
22 | * questions. |
23 | * |
24 | */ |
25 | |
26 | #ifndef SHARE_CODE_CODEHEAPSTATE_HPP |
27 | #define SHARE_CODE_CODEHEAPSTATE_HPP |
28 | |
29 | #include "memory/heap.hpp" |
30 | #include "utilities/debug.hpp" |
31 | #include "utilities/globalDefinitions.hpp" |
32 | #include "utilities/ostream.hpp" |
33 | |
34 | class CodeHeapState : public CHeapObj<mtCode> { |
35 | |
36 | public: |
37 | enum compType { |
38 | noComp = 0, // must be! due to initialization by memset to zero |
39 | c1, |
40 | c2, |
41 | jvmci, |
42 | lastComp |
43 | }; |
44 | |
45 | enum blobType { |
46 | noType = 0, // must be! due to initialization by memset to zero |
47 | // The nMethod_* values correspond to the CompiledMethod enum values. |
48 | // We can't use the CompiledMethod values 1:1 because we depend on noType == 0. |
49 | nMethod_inconstruction, // under construction. Very soon, the type will transition to "in_use". |
50 | nMethod_inuse, // executable. This is the "normal" state for a nmethod. |
51 | nMethod_notused, // assumed inactive, marked not entrant. Could be revived if necessary. |
52 | nMethod_notentrant, // no new activations allowed, marked for deoptimization. Old activations may still exist. |
53 | // Will transition to "zombie" after all activations are gone. |
54 | nMethod_zombie, // No more activations exist, ready for purge (remove from code cache). |
55 | nMethod_unloaded, // No activations exist, should not be called. Transient state on the way to "zombie". |
56 | nMethod_alive = nMethod_notentrant, // Combined state: nmethod may have activations, thus can't be purged. |
57 | nMethod_dead = nMethod_zombie, // Combined state: nmethod does not have any activations. |
58 | runtimeStub = nMethod_unloaded + 1, |
59 | ricochetStub, |
60 | deoptimizationStub, |
61 | uncommonTrapStub, |
62 | exceptionStub, |
63 | safepointStub, |
64 | adapterBlob, |
65 | mh_adapterBlob, |
66 | bufferBlob, |
67 | lastType |
68 | }; |
69 | |
70 | private: |
71 | static void prepare_StatArray(outputStream* out, size_t nElem, size_t granularity, const char* heapName); |
72 | static void prepare_FreeArray(outputStream* out, unsigned int nElem, const char* heapName); |
73 | static void prepare_TopSizeArray(outputStream* out, unsigned int nElem, const char* heapName); |
74 | static void prepare_SizeDistArray(outputStream* out, unsigned int nElem, const char* heapName); |
75 | static void discard_StatArray(outputStream* out); |
76 | static void discard_FreeArray(outputStream* out); |
77 | static void discard_TopSizeArray(outputStream* out); |
78 | static void discard_SizeDistArray(outputStream* out); |
79 | |
80 | static void update_SizeDistArray(outputStream* out, unsigned int len); |
81 | |
82 | static const char* get_heapName(CodeHeap* heap); |
83 | static unsigned int findHeapIndex(outputStream* out, const char* heapName); |
84 | static void get_HeapStatGlobals(outputStream* out, const char* heapName); |
85 | static void set_HeapStatGlobals(outputStream* out, const char* heapName); |
86 | |
87 | static void printBox(outputStream* out, const char border, const char* text1, const char* text2); |
88 | static void print_blobType_legend(outputStream* out); |
89 | static void print_space_legend(outputStream* out); |
90 | static void print_age_legend(outputStream* out); |
91 | static void print_blobType_single(outputStream *ast, u2 /* blobType */ type); |
92 | static void print_count_single(outputStream *ast, unsigned short count); |
93 | static void print_space_single(outputStream *ast, unsigned short space); |
94 | static void print_age_single(outputStream *ast, unsigned int age); |
95 | static void print_line_delim(outputStream* out, bufferedStream *sst, char* low_bound, unsigned int ix, unsigned int gpl); |
96 | static void print_line_delim(outputStream* out, outputStream *sst, char* low_bound, unsigned int ix, unsigned int gpl); |
97 | static blobType get_cbType(CodeBlob* cb); |
98 | static bool blob_access_is_safe(CodeBlob* this_blob, CodeBlob* prev_blob); |
99 | |
100 | public: |
101 | static void discard(outputStream* out, CodeHeap* heap); |
102 | static void aggregate(outputStream* out, CodeHeap* heap, size_t granularity); |
103 | static void print_usedSpace(outputStream* out, CodeHeap* heap); |
104 | static void print_freeSpace(outputStream* out, CodeHeap* heap); |
105 | static void print_count(outputStream* out, CodeHeap* heap); |
106 | static void print_space(outputStream* out, CodeHeap* heap); |
107 | static void print_age(outputStream* out, CodeHeap* heap); |
108 | static void print_names(outputStream* out, CodeHeap* heap); |
109 | }; |
110 | |
111 | //---------------- |
112 | // StatElement |
113 | //---------------- |
114 | // Each analysis granule is represented by an instance of |
115 | // this StatElement struct. It collects and aggregates all |
116 | // information describing the allocated contents of the granule. |
117 | // Free (unallocated) contents is not considered (see FreeBlk for that). |
118 | // All StatElements of a heap segment are stored in the related StatArray. |
119 | // Current size: 40 bytes + 8 bytes class header. |
120 | class StatElement : public CHeapObj<mtCode> { |
121 | public: |
122 | // A note on ages: The compilation_id easily overflows unsigned short in large systems |
123 | unsigned int t1_age; // oldest compilation_id of tier1 nMethods. |
124 | unsigned int t2_age; // oldest compilation_id of tier2 nMethods. |
125 | unsigned int tx_age; // oldest compilation_id of inactive/not entrant nMethods. |
126 | unsigned short t1_space; // in units of _segment_size to "prevent" overflow |
127 | unsigned short t2_space; // in units of _segment_size to "prevent" overflow |
128 | unsigned short tx_space; // in units of _segment_size to "prevent" overflow |
129 | unsigned short dead_space; // in units of _segment_size to "prevent" overflow |
130 | unsigned short stub_space; // in units of _segment_size to "prevent" overflow |
131 | unsigned short t1_count; |
132 | unsigned short t2_count; |
133 | unsigned short tx_count; |
134 | unsigned short dead_count; |
135 | unsigned short stub_count; |
136 | CompLevel level; // optimization level (see globalDefinitions.hpp) |
137 | //---< replaced the correct enum typing with u2 to save space. |
138 | u2 compiler; // compiler which generated this blob. Type is CodeHeapState::compType |
139 | u2 type; // used only if granularity == segment_size. Type is CodeHeapState::blobType |
140 | }; |
141 | |
142 | //----------- |
143 | // FreeBlk |
144 | //----------- |
145 | // Each free block in the code heap is represented by an instance |
146 | // of this FreeBlk struct. It collects all information we need to |
147 | // know about each free block. |
148 | // All FreeBlks of a heap segment are stored in the related FreeArray. |
149 | struct FreeBlk : public CHeapObj<mtCode> { |
150 | HeapBlock* start; // address of free block |
151 | unsigned int len; // length of free block |
152 | |
153 | unsigned int gap; // gap to next free block |
154 | unsigned int index; // sequential number of free block |
155 | unsigned short n_gapBlocks; // # used blocks in gap |
156 | bool stubs_in_gap; // The occupied space between this and the next free block contains (unmovable) stubs or blobs. |
157 | }; |
158 | |
159 | //-------------- |
160 | // TopSizeBlk |
161 | //-------------- |
162 | // The n largest blocks in the code heap are represented in an instance |
163 | // of this TopSizeBlk struct. It collects all information we need to |
164 | // know about those largest blocks. |
165 | // All TopSizeBlks of a heap segment are stored in the related TopSizeArray. |
166 | struct TopSizeBlk : public CHeapObj<mtCode> { |
167 | HeapBlock* start; // address of block |
168 | unsigned int len; // length of block, in _segment_size units. Will never overflow int. |
169 | |
170 | unsigned int index; // ordering index, 0 is largest block |
171 | // contains array index of next smaller block |
172 | // -1 indicates end of list |
173 | CompLevel level; // optimization level (see globalDefinitions.hpp) |
174 | u2 compiler; // compiler which generated this blob |
175 | u2 type; // blob type |
176 | }; |
177 | |
178 | //--------------------------- |
179 | // SizeDistributionElement |
180 | //--------------------------- |
181 | // During CodeHeap analysis, each allocated code block is associated with a |
182 | // SizeDistributionElement according to its size. Later on, the array of |
183 | // SizeDistributionElements is used to print a size distribution bar graph. |
184 | // All SizeDistributionElements of a heap segment are stored in the related SizeDistributionArray. |
185 | struct SizeDistributionElement : public CHeapObj<mtCode> { |
186 | // Range is [rangeStart..rangeEnd). |
187 | unsigned int rangeStart; // start of length range, in _segment_size units. |
188 | unsigned int rangeEnd; // end of length range, in _segment_size units. |
189 | unsigned int lenSum; // length of block, in _segment_size units. Will never overflow int. |
190 | |
191 | unsigned int count; // number of blocks assigned to this range. |
192 | }; |
193 | |
194 | //---------------- |
195 | // CodeHeapStat |
196 | //---------------- |
197 | // Because we have to deal with multiple CodeHeaps, we need to |
198 | // collect "global" information in a segment-specific way as well. |
199 | // Thats what the CodeHeapStat and CodeHeapStatArray are used for. |
200 | // Before a heap segment is processed, the contents of the CodeHeapStat |
201 | // element is copied to the global variables (get_HeapStatGlobals). |
202 | // When processing is done, the possibly modified global variables are |
203 | // copied back (set_HeapStatGlobals) to the CodeHeapStat element. |
204 | struct CodeHeapStat { |
205 | StatElement* StatArray; |
206 | struct FreeBlk* FreeArray; |
207 | struct TopSizeBlk* TopSizeArray; |
208 | struct SizeDistributionElement* SizeDistributionArray; |
209 | const char* heapName; |
210 | size_t segment_size; |
211 | // StatElement data |
212 | size_t alloc_granules; |
213 | size_t granule_size; |
214 | bool segment_granules; |
215 | unsigned int nBlocks_t1; |
216 | unsigned int nBlocks_t2; |
217 | unsigned int nBlocks_alive; |
218 | unsigned int nBlocks_dead; |
219 | unsigned int nBlocks_inconstr; |
220 | unsigned int nBlocks_unloaded; |
221 | unsigned int nBlocks_stub; |
222 | // FreeBlk data |
223 | unsigned int alloc_freeBlocks; |
224 | // UsedBlk data |
225 | unsigned int alloc_topSizeBlocks; |
226 | unsigned int used_topSizeBlocks; |
227 | // method hotness data. Temperature range is [-reset_val..+reset_val] |
228 | int avgTemp; |
229 | int maxTemp; |
230 | int minTemp; |
231 | }; |
232 | |
233 | #endif // SHARE_CODE_CODEHEAPSTATE_HPP |
234 | |