23 */ |
24 */ |
24 |
25 |
25 #ifndef SHARE_MEMORY_METASPACE_VIRTUALSPACENODE_HPP |
26 #ifndef SHARE_MEMORY_METASPACE_VIRTUALSPACENODE_HPP |
26 #define SHARE_MEMORY_METASPACE_VIRTUALSPACENODE_HPP |
27 #define SHARE_MEMORY_METASPACE_VIRTUALSPACENODE_HPP |
27 |
28 |
|
29 |
|
30 #include <memory/metaspace/settings.hpp> |
|
31 #include "memory/allocation.hpp" |
|
32 #include "memory/metaspace/counter.hpp" |
|
33 #include "memory/metaspace/commitMask.hpp" |
|
34 #include "memory/metaspace/rootChunkArea.hpp" |
28 #include "memory/virtualspace.hpp" |
35 #include "memory/virtualspace.hpp" |
29 #include "memory/memRegion.hpp" |
36 #include "memory/memRegion.hpp" |
30 #include "utilities/debug.hpp" |
37 #include "utilities/debug.hpp" |
|
38 #include "utilities/bitMap.hpp" |
31 #include "utilities/globalDefinitions.hpp" |
39 #include "utilities/globalDefinitions.hpp" |
32 |
40 |
|
41 |
33 class outputStream; |
42 class outputStream; |
34 |
43 |
35 namespace metaspace { |
44 namespace metaspace { |
36 |
45 |
37 class Metachunk; |
46 class CommitLimiter; |
38 class ChunkManager; |
47 class MetachunkListCluster; |
39 class OccupancyMap; |
48 |
40 |
49 // VirtualSpaceNode manage a single address range of the Metaspace. |
41 // A VirtualSpaceList node. |
50 // |
|
51 // That address range may contain interleaved committed and uncommitted |
|
52 // regions. It keeps track of which regions have committed and offers |
|
53 // functions to commit and uncommit regions. |
|
54 // |
|
55 // It allocates and hands out memory ranges, starting at the bottom. |
|
56 // |
|
57 // Address range must be aligned to root chunk size. |
|
58 // |
42 class VirtualSpaceNode : public CHeapObj<mtClass> { |
59 class VirtualSpaceNode : public CHeapObj<mtClass> { |
43 friend class VirtualSpaceList; |
|
44 |
60 |
45 // Link to next VirtualSpaceNode |
61 // Link to next VirtualSpaceNode |
46 VirtualSpaceNode* _next; |
62 VirtualSpaceNode* _next; |
47 |
63 |
48 // Whether this node is contained in class or metaspace. |
|
49 const bool _is_class; |
|
50 |
|
51 // total in the VirtualSpace |
|
52 ReservedSpace _rs; |
64 ReservedSpace _rs; |
53 VirtualSpace _virtual_space; |
65 |
54 MetaWord* _top; |
66 // Start pointer of the area. |
55 // count of chunks contained in this VirtualSpace |
67 MetaWord* const _base; |
56 uintx _container_count; |
68 |
57 |
69 // Size, in words, of the whole node |
58 OccupancyMap* _occupancy_map; |
70 const size_t _word_size; |
59 |
71 |
60 // Convenience functions to access the _virtual_space |
72 // Size, in words, of the range of this node which has been handed out in |
61 char* low() const { return virtual_space()->low(); } |
73 // the form of chunks. |
62 char* high() const { return virtual_space()->high(); } |
74 size_t _used_words; |
63 char* low_boundary() const { return virtual_space()->low_boundary(); } |
75 |
64 char* high_boundary() const { return virtual_space()->high_boundary(); } |
76 // The bitmap describing the commit state of the region: |
65 |
77 // Each bit covers a region of 64K (see constants::commit_granule_size). |
66 // The first Metachunk will be allocated at the bottom of the |
78 CommitMask _commit_mask; |
67 // VirtualSpace |
79 |
68 Metachunk* first_chunk() { return (Metachunk*) bottom(); } |
80 // An array/LUT of RootChunkArea objects. Each one describes |
69 |
81 // fragmentation inside a root chunk. |
70 // Committed but unused space in the virtual space |
82 RootChunkAreaLUT _root_chunk_area_lut; |
71 size_t free_words_in_vs() const; |
83 |
72 |
84 // Limiter object to ask before expanding the committed size of this node. |
73 // True if this node belongs to class metaspace. |
85 CommitLimiter* const _commit_limiter; |
74 bool is_class() const { return _is_class; } |
86 |
75 |
87 // Points to outside size counters which we are to increase/decrease when we commit/uncommit |
76 // Helper function for take_from_committed: allocate padding chunks |
88 // space from this node. |
77 // until top is at the given address. |
89 SizeCounter* const _total_reserved_words_counter; |
78 void allocate_padding_chunks_until_top_is_at(MetaWord* target_top); |
90 SizeCounter* const _total_committed_words_counter; |
79 |
91 |
80 public: |
92 // For debug and tracing purposes |
81 |
93 const int _node_id; |
82 VirtualSpaceNode(bool is_class, size_t byte_size); |
94 |
83 VirtualSpaceNode(bool is_class, ReservedSpace rs) : |
95 /// committing, uncommitting /// |
84 _next(NULL), _is_class(is_class), _rs(rs), _top(NULL), _container_count(0), _occupancy_map(NULL) {} |
96 |
|
97 // Given a pointer into this node, calculate the start of the commit granule |
|
98 // the pointer points into. |
|
99 MetaWord* calc_start_of_granule(MetaWord* p) const { |
|
100 DEBUG_ONLY(check_pointer(p)); |
|
101 return align_down(p, Settings::commit_granule_bytes()); |
|
102 } |
|
103 |
|
104 // Given an address range, ensure it is committed. |
|
105 // |
|
106 // The range has to be aligned to granule size. |
|
107 // |
|
108 // Function will: |
|
109 // - check how many granules in that region are uncommitted; If all are committed, it |
|
110 // returns true immediately. |
|
111 // - check if committing those uncommitted granules would bring us over the commit limit |
|
112 // (GC threshold, MaxMetaspaceSize). If true, it returns false. |
|
113 // - commit the memory. |
|
114 // - mark the range as committed in the commit mask |
|
115 // |
|
116 // Returns true if success, false if it did hit a commit limit. |
|
117 bool commit_range(MetaWord* p, size_t word_size); |
|
118 |
|
119 //// creation //// |
|
120 |
|
121 // Create a new empty node spanning the given reserved space. |
|
122 VirtualSpaceNode(int node_id, |
|
123 ReservedSpace rs, |
|
124 CommitLimiter* limiter, |
|
125 SizeCounter* reserve_counter, |
|
126 SizeCounter* commit_counter); |
|
127 |
|
128 MetaWord* base() const { return _base; } |
|
129 |
|
130 public: |
|
131 |
|
132 // Create a node of a given size |
|
133 static VirtualSpaceNode* create_node(int node_id, |
|
134 size_t word_size, |
|
135 CommitLimiter* limiter, |
|
136 SizeCounter* reserve_words_counter, |
|
137 SizeCounter* commit_words_counter); |
|
138 |
|
139 // Create a node over an existing space |
|
140 static VirtualSpaceNode* create_node(int node_id, |
|
141 ReservedSpace rs, |
|
142 CommitLimiter* limiter, |
|
143 SizeCounter* reserve_words_counter, |
|
144 SizeCounter* commit_words_counter); |
|
145 |
85 ~VirtualSpaceNode(); |
146 ~VirtualSpaceNode(); |
86 |
147 |
87 // Convenience functions for logical bottom and end |
148 |
88 MetaWord* bottom() const { return (MetaWord*) _virtual_space.low(); } |
149 // Reserved size of the whole node. |
89 MetaWord* end() const { return (MetaWord*) _virtual_space.high(); } |
150 size_t word_size() const { return _word_size; } |
90 |
151 |
91 const OccupancyMap* occupancy_map() const { return _occupancy_map; } |
152 //// Chunk allocation, splitting, merging ///// |
92 OccupancyMap* occupancy_map() { return _occupancy_map; } |
153 |
93 |
154 // Allocate a root chunk from this node. Will fail and return NULL |
94 bool contains(const void* ptr) { return ptr >= low() && ptr < high(); } |
155 // if the node is full. |
95 |
156 // Note: this just returns a chunk whose memory is reserved; no memory is committed yet. |
96 size_t reserved_words() const { return _virtual_space.reserved_size() / BytesPerWord; } |
157 // Hence, before using this chunk, it must be committed. |
97 size_t committed_words() const { return _virtual_space.actual_committed_size() / BytesPerWord; } |
158 // Also, no limits are checked, since no committing takes place. |
98 |
159 Metachunk* allocate_root_chunk(); |
99 bool is_pre_committed() const { return _virtual_space.special(); } |
160 |
100 |
161 // Given a chunk c, split it recursively until you get a chunk of the given target_level. |
101 // address of next available space in _virtual_space; |
162 // |
102 // Accessors |
163 // The original chunk must not be part of a freelist. |
103 VirtualSpaceNode* next() { return _next; } |
164 // |
104 void set_next(VirtualSpaceNode* v) { _next = v; } |
165 // Returns pointer to the result chunk; the splitted-off chunks are added as |
105 |
166 // free chunks to the freelists. |
106 void set_top(MetaWord* v) { _top = v; } |
167 // |
107 |
168 // Returns NULL if chunk cannot be split at least once. |
108 // Accessors |
169 Metachunk* split(chklvl_t target_level, Metachunk* c, MetachunkListCluster* freelists); |
109 VirtualSpace* virtual_space() const { return (VirtualSpace*) &_virtual_space; } |
170 |
110 |
171 // Given a chunk, attempt to merge it recursively with its neighboring chunks. |
111 // Returns true if "word_size" is available in the VirtualSpace |
172 // |
112 bool is_available(size_t word_size) { return word_size <= pointer_delta(end(), _top, sizeof(MetaWord)); } |
173 // If successful (merged at least once), returns address of |
113 |
174 // the merged chunk; NULL otherwise. |
114 MetaWord* top() const { return _top; } |
175 // |
115 void inc_top(size_t word_size) { _top += word_size; } |
176 // The merged chunks are removed from the freelists. |
116 |
177 // |
117 uintx container_count() { return _container_count; } |
178 // !!! Please note that if this method returns a non-NULL value, the |
118 void inc_container_count(); |
179 // original chunk will be invalid and should not be accessed anymore! !!! |
119 void dec_container_count(); |
180 Metachunk* merge(Metachunk* c, MetachunkListCluster* freelists); |
120 |
181 |
121 // used and capacity in this single entry in the list |
182 // Given a chunk c, which must be "in use" and must not be a root chunk, attempt to |
122 size_t used_words_in_vs() const; |
183 // enlarge it in place by claiming its trailing buddy. |
123 size_t capacity_words_in_vs() const; |
184 // |
124 |
185 // This will only work if c is the leader of the buddy pair and the trailing buddy is free. |
125 bool initialize(); |
186 // |
126 |
187 // If successful, the follower chunk will be removed from the freelists, the leader chunk c will |
127 // get space from the virtual space |
188 // double in size (level decreased by one). |
128 Metachunk* take_from_committed(size_t chunk_word_size); |
189 // |
129 |
190 // On success, true is returned, false otherwise. |
130 // Allocate a chunk from the virtual space and return it. |
191 bool attempt_enlarge_chunk(Metachunk* c, MetachunkListCluster* freelists); |
131 Metachunk* get_chunk_vs(size_t chunk_word_size); |
192 |
132 |
193 // Attempts to purge the node: |
133 // Expands the committed space by at least min_words words. |
194 // |
134 bool expand_by(size_t min_words, size_t preferred_words); |
195 // If all chunks living in this node are free, they will all be removed from their freelists |
135 |
196 // and deletes the node. |
136 // In preparation for deleting this node, remove all the chunks |
197 // |
137 // in the node from any freelist. |
198 // Returns true if the node has been deleted, false if not. |
138 void purge(ChunkManager* chunk_manager); |
199 // !! If this returns true, do not access the node from this point on. !! |
139 |
200 bool attempt_purge(MetachunkListCluster* freelists); |
140 // If an allocation doesn't fit in the current node a new node is created. |
201 |
141 // Allocate chunks out of the remaining committed space in this node |
202 // Attempts to uncommit free areas according to the rules set in settings. |
142 // to avoid wasting that memory. |
203 // Returns number of words uncommitted. |
143 // This always adds up because all the chunk sizes are multiples of |
204 size_t uncommit_free_areas(); |
144 // the smallest chunk size. |
205 |
145 void retire(ChunkManager* chunk_manager); |
206 /// misc ///// |
146 |
207 |
147 void print_on(outputStream* st) const { print_on(st, K); } |
208 // Returns size, in words, of the used space in this node alone. |
148 void print_on(outputStream* st, size_t scale) const; |
209 // (Notes: |
149 void print_map(outputStream* st, bool is_class) const; |
210 // - This is the space handed out to the ChunkManager, so it is "used" from the viewpoint of this node, |
150 |
211 // but not necessarily used for Metadata. |
151 // Debug support |
212 // - This may or may not be committed memory. |
152 DEBUG_ONLY(void mangle();) |
213 size_t used_words() const { return _used_words; } |
153 // Verify counters and basic structure. Slow mode: verify all chunks in depth and occupancy map. |
214 |
154 DEBUG_ONLY(void verify(bool slow);) |
215 // Returns size, in words, of how much space is left in this node alone. |
155 // Verify that all free chunks in this node are ideally merged |
216 size_t free_words() const { return _word_size - _used_words; } |
156 // (there should not be multiple small chunks where a large chunk could exist.) |
217 |
157 DEBUG_ONLY(void verify_free_chunks_are_ideally_merged();) |
218 // Returns size, in words, of committed space in this node alone. |
|
219 // Note: iterates over commit mask and hence may be a tad expensive on large nodes. |
|
220 size_t committed_words() const; |
|
221 |
|
222 //// Committing/uncommitting memory ///// |
|
223 |
|
224 // Given an address range, ensure it is committed. |
|
225 // |
|
226 // The range does not have to be aligned to granule size. However, the function will always commit |
|
227 // whole granules. |
|
228 // |
|
229 // Function will: |
|
230 // - check how many granules in that region are uncommitted; If all are committed, it |
|
231 // returns true immediately. |
|
232 // - check if committing those uncommitted granules would bring us over the commit limit |
|
233 // (GC threshold, MaxMetaspaceSize). If true, it returns false. |
|
234 // - commit the memory. |
|
235 // - mark the range as committed in the commit mask |
|
236 // |
|
237 // Returns true if success, false if it did hit a commit limit. |
|
238 bool ensure_range_is_committed(MetaWord* p, size_t word_size); |
|
239 |
|
240 // Given an address range (which has to be aligned to commit granule size): |
|
241 // - uncommit it |
|
242 // - mark it as uncommitted in the commit mask |
|
243 void uncommit_range(MetaWord* p, size_t word_size); |
|
244 |
|
245 //// List stuff //// |
|
246 VirtualSpaceNode* next() const { return _next; } |
|
247 void set_next(VirtualSpaceNode* vsn) { _next = vsn; } |
|
248 |
|
249 |
|
250 /// Debug stuff //// |
|
251 |
|
252 // Print a description about this node. |
|
253 void print_on(outputStream* st) const; |
|
254 |
|
255 // Verify counters and basic structure. Slow mode: verify all chunks in depth |
|
256 bool contains(const MetaWord* p) const { |
|
257 return p >= _base && p < _base + _used_words; |
|
258 } |
|
259 |
|
260 #ifdef ASSERT |
|
261 void check_pointer(const MetaWord* p) const { |
|
262 assert(contains(p), "invalid pointer"); |
|
263 } |
|
264 void verify(bool slow) const; |
|
265 #endif |
158 |
266 |
159 }; |
267 }; |
160 |
268 |
|
269 |
161 } // namespace metaspace |
270 } // namespace metaspace |
162 |
271 |
163 #endif // SHARE_MEMORY_METASPACE_VIRTUALSPACENODE_HPP |
272 #endif // SHARE_MEMORY_METASPACE_VIRTUALSPACENODE_HPP |