42 #include "utilities/debug.hpp" |
42 #include "utilities/debug.hpp" |
43 #include "utilities/globalDefinitions.hpp" |
43 #include "utilities/globalDefinitions.hpp" |
44 |
44 |
45 namespace metaspace { |
45 namespace metaspace { |
46 |
46 |
|
47 #define LOGFMT_SPCMGR "SpcMgr @" PTR_FORMAT " (%s)" |
|
48 #define LOGFMT_SPCMGR_ARGS p2i(this), this->_name |
|
49 |
|
50 |
47 // Given a net allocation word size, return the raw word size |
51 // Given a net allocation word size, return the raw word size |
48 // we need to actually allocate in order to: |
52 // we need to actually allocate in order to: |
49 // 1) be able to deallocate the allocation - deallocated blocks are stored either in SmallBlocks |
53 // 1) be able to deallocate the allocation - deallocated blocks are stored either in SmallBlocks |
50 // (an array of short lists) or, beyond a certain size, in a dictionary tree. |
54 // (an array of short lists) or, beyond a certain size, in a dictionary tree. |
51 // For that to work the allocated block must be at least three words. |
55 // For that to work the allocated block must be at least three words. |
106 |
110 |
107 if (pref_level > min_level) { |
111 if (pref_level > min_level) { |
108 pref_level = min_level; |
112 pref_level = min_level; |
109 } |
113 } |
110 |
114 |
111 log_trace(metaspace)("SpaceManager %s: requested word size_ " SIZE_FORMAT ", num chunks so far: %d, preferred level: " |
115 log_trace(metaspace)(LOGFMT_SPCMGR ": requested word size_ " SIZE_FORMAT ", num chunks so far: %d, preferred level: " |
112 CHKLVL_FORMAT ", min level: " CHKLVL_FORMAT ".", |
116 CHKLVL_FORMAT ", min level: " CHKLVL_FORMAT ".", |
113 _name, requested_word_size, _chunks.size(), pref_level, min_level); |
117 LOGFMT_SPCMGR_ARGS, requested_word_size, _chunks.size(), pref_level, min_level); |
114 |
118 |
115 Metachunk* c = _chunk_manager->get_chunk(min_level, pref_level); |
119 Metachunk* c = _chunk_manager->get_chunk(min_level, pref_level); |
116 if (c == NULL) { |
120 if (c == NULL) { |
117 log_debug(metaspace)("SpaceManager %s: failed to allocate new chunk for requested word size " SIZE_FORMAT ".", |
121 log_debug(metaspace)(LOGFMT_SPCMGR ": failed to allocate new chunk for requested word size " SIZE_FORMAT ".", |
118 _name, requested_word_size); |
122 LOGFMT_SPCMGR_ARGS, requested_word_size); |
119 return false; |
123 return false; |
120 } |
124 } |
121 |
125 |
122 assert(c->is_in_use(), "Wrong chunk state."); |
126 assert(c->is_in_use(), "Wrong chunk state."); |
123 assert(c->level() <= min_level && c->level() >= pref_level, "Sanity"); |
127 assert(c->level() <= min_level && c->level() >= pref_level, "Sanity"); |
124 |
128 |
125 _chunks.add(c); |
129 _chunks.add(c); |
126 |
130 |
127 log_debug(metaspace)("SpaceManager %s: allocated new chunk " METACHUNK_FORMAT " for requested word size " SIZE_FORMAT ".", |
131 log_debug(metaspace)(LOGFMT_SPCMGR ": allocated new chunk " METACHUNK_FORMAT " for requested word size " SIZE_FORMAT ".", |
128 _name, METACHUNK_FORMAT_ARGS(c), requested_word_size); |
132 LOGFMT_SPCMGR_ARGS, METACHUNK_FORMAT_ARGS(c), requested_word_size); |
129 |
133 |
130 // Workaround for JDK-8233019: never return space allocated at a 32bit aligned address |
134 // Workaround for JDK-8233019: never return space allocated at a 32bit aligned address |
131 if (Settings::do_not_return_32bit_aligned_addresses() && |
135 if (Settings::do_not_return_32bit_aligned_addresses() && |
132 (((intptr_t)c->base()) & 0xFFFFFFFF) == 0) |
136 (((intptr_t)c->base()) & 0xFFFFFFFF) == 0) |
133 { |
137 { |
193 assert_lock_strong(lock()); |
197 assert_lock_strong(lock()); |
194 |
198 |
195 Metachunk* c = current_chunk(); |
199 Metachunk* c = current_chunk(); |
196 assert(c != NULL, "Sanity"); |
200 assert(c != NULL, "Sanity"); |
197 |
201 |
198 log_debug(metaspace)("SpaceManager %s: retiring chunk " METACHUNK_FULL_FORMAT ".", |
|
199 _name, METACHUNK_FULL_FORMAT_ARGS(c)); |
|
200 |
|
201 // Side note: |
202 // Side note: |
202 // In theory it could happen that we are asked to retire a completely empty chunk. This may be the |
203 // In theory it could happen that we are asked to retire a completely empty chunk. This may be the |
203 // result of rolled back allocations (see deallocate in place) and a lot of luck. |
204 // result of rolled back allocations (see deallocate in place) and a lot of luck. |
204 // But since these cases should be exceedingly rare, we do not handle them special in order to keep |
205 // But since these cases should be exceedingly rare, we do not handle them special in order to keep |
205 // the code simple. |
206 // the code simple. |
206 |
207 |
207 size_t raw_remaining_words = c->free_below_committed_words(); |
208 size_t raw_remaining_words = c->free_below_committed_words(); |
208 size_t net_remaining_words = get_net_allocation_word_size(raw_remaining_words); |
209 size_t net_remaining_words = get_net_allocation_word_size(raw_remaining_words); |
209 if (net_remaining_words > 0) { |
210 if (net_remaining_words > 0) { |
|
211 |
|
212 log_debug(metaspace)(LOGFMT_SPCMGR " @" PTR_FORMAT " : retiring chunk " METACHUNK_FULL_FORMAT ".", |
|
213 LOGFMT_SPCMGR_ARGS, p2i(this), METACHUNK_FULL_FORMAT_ARGS(c)); |
|
214 |
210 bool did_hit_limit = false; |
215 bool did_hit_limit = false; |
211 MetaWord* ptr = c->allocate(net_remaining_words, &did_hit_limit); |
216 MetaWord* ptr = c->allocate(net_remaining_words, &did_hit_limit); |
212 assert(ptr != NULL && did_hit_limit == false, "Should have worked"); |
217 assert(ptr != NULL && did_hit_limit == false, "Should have worked"); |
213 add_allocation_to_block_freelist(ptr, net_remaining_words); |
218 add_allocation_to_block_freelist(ptr, net_remaining_words); |
214 _total_used_words_counter->increment_by(net_remaining_words); |
219 _total_used_words_counter->increment_by(net_remaining_words); |
215 } |
220 |
216 |
221 // After this operation: the current chunk should have (almost) no free committed space left. |
217 // After this operation: the current chunk should have (almost) no free committed space left. |
222 assert(current_chunk()->free_below_committed_words() <= highest_possible_delta_between_raw_and_net_size, |
218 assert(current_chunk()->free_below_committed_words() <= highest_possible_delta_between_raw_and_net_size, |
223 "Chunk retiring did not work (current chunk " METACHUNK_FULL_FORMAT ").", |
219 "Chunk retiring did not work (current chunk " METACHUNK_FULL_FORMAT ").", |
224 METACHUNK_FULL_FORMAT_ARGS(current_chunk())); |
220 METACHUNK_FULL_FORMAT_ARGS(current_chunk())); |
225 |
221 |
226 DEBUG_ONLY(verify_locked();) |
222 DEBUG_ONLY(verify_locked();) |
227 |
|
228 } |
223 |
229 |
224 } |
230 } |
225 |
231 |
226 // Allocate memory from Metaspace. |
232 // Allocate memory from Metaspace. |
227 // 1) Attempt to allocate from the dictionary of deallocated blocks. |
233 // 1) Attempt to allocate from the dictionary of deallocated blocks. |
233 |
239 |
234 MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag); |
240 MutexLocker cl(lock(), Mutex::_no_safepoint_check_flag); |
235 |
241 |
236 const size_t raw_word_size = get_raw_allocation_word_size(requested_word_size); |
242 const size_t raw_word_size = get_raw_allocation_word_size(requested_word_size); |
237 |
243 |
238 log_trace(metaspace)("SpaceManager %s: requested " SIZE_FORMAT " words, " |
244 log_debug(metaspace)(LOGFMT_SPCMGR ": requested " SIZE_FORMAT " words, " |
239 "raw word size: " SIZE_FORMAT ".", |
245 "raw word size: " SIZE_FORMAT ".", |
240 _name, requested_word_size, raw_word_size); |
246 LOGFMT_SPCMGR_ARGS, requested_word_size, raw_word_size); |
241 |
247 |
242 MetaWord* p = NULL; |
248 MetaWord* p = NULL; |
243 |
249 |
244 bool did_hit_limit = false; |
250 bool did_hit_limit = false; |
245 |
251 |
262 if (_block_freelist != NULL && _block_freelist->total_size() > Settings::allocation_from_dictionary_limit()) { |
268 if (_block_freelist != NULL && _block_freelist->total_size() > Settings::allocation_from_dictionary_limit()) { |
263 p = _block_freelist->get_block(raw_word_size); |
269 p = _block_freelist->get_block(raw_word_size); |
264 |
270 |
265 if (p != NULL) { |
271 if (p != NULL) { |
266 DEBUG_ONLY(InternalStats::inc_num_allocs_from_deallocated_blocks();) |
272 DEBUG_ONLY(InternalStats::inc_num_allocs_from_deallocated_blocks();) |
267 log_trace(metaspace)("SpaceManager %s: .. taken from freelist.", _name); |
273 log_trace(metaspace)(LOGFMT_SPCMGR ": .. taken from freelist.", LOGFMT_SPCMGR_ARGS); |
268 // Note: space in the freeblock dictionary counts as used (see retire_current_chunk()) - |
274 // Note: space in the freeblock dictionary counts as used (see retire_current_chunk()) - |
269 // that means that we must not increase the used counter again when allocating from the dictionary. |
275 // that means that we must not increase the used counter again when allocating from the dictionary. |
270 // Therefore we return here. |
276 // Therefore we return here. |
271 return p; |
277 return p; |
272 } |
278 } |
274 } |
280 } |
275 |
281 |
276 // 2) Failing that, attempt to allocate from the current chunk. If we hit commit limit, return NULL. |
282 // 2) Failing that, attempt to allocate from the current chunk. If we hit commit limit, return NULL. |
277 if (p == NULL && !did_hit_limit) { |
283 if (p == NULL && !did_hit_limit) { |
278 p = current_chunk()->allocate(raw_word_size, &did_hit_limit); |
284 p = current_chunk()->allocate(raw_word_size, &did_hit_limit); |
279 log_trace(metaspace)("SpaceManager %s: .. taken from current chunk.", _name); |
285 log_trace(metaspace)(LOGFMT_SPCMGR ": .. taken from current chunk.", LOGFMT_SPCMGR_ARGS); |
280 } |
286 } |
281 |
287 |
282 // 3) Failing that because the remaining chunk space is too small for the requested size |
288 // 3) Failing that because the remaining chunk space is too small for the requested size |
283 // (and not because commit limit), attempt to enlarge the chunk in place. |
289 // (and not because commit limit), attempt to enlarge the chunk in place. |
284 if (p == NULL && !did_hit_limit) { |
290 if (p == NULL && !did_hit_limit) { |
334 if (allocate_new_current_chunk(raw_word_size) == false) { |
340 if (allocate_new_current_chunk(raw_word_size) == false) { |
335 did_hit_limit = true; |
341 did_hit_limit = true; |
336 } else { |
342 } else { |
337 assert(current_chunk() != NULL && current_chunk()->free_words() >= raw_word_size, "Sanity"); |
343 assert(current_chunk() != NULL && current_chunk()->free_words() >= raw_word_size, "Sanity"); |
338 p = current_chunk()->allocate(raw_word_size, &did_hit_limit); |
344 p = current_chunk()->allocate(raw_word_size, &did_hit_limit); |
339 log_trace(metaspace)("SpaceManager %s: .. allocated new chunk " CHKLVL_FORMAT " and taken from that.", |
345 log_trace(metaspace)(LOGFMT_SPCMGR ": .. allocated new chunk " CHKLVL_FORMAT " and taken from that.", |
340 _name, current_chunk()->level()); |
346 LOGFMT_SPCMGR_ARGS, current_chunk()->level()); |
341 } |
347 } |
342 |
348 |
343 } |
349 } |
344 |
350 |
345 assert(p != NULL || (p == NULL && did_hit_limit), "Sanity"); |
351 assert(p != NULL || (p == NULL && did_hit_limit), "Sanity"); |
366 assert_lock_strong(lock()); |
372 assert_lock_strong(lock()); |
367 |
373 |
368 // Allocations and deallocations are in raw_word_size |
374 // Allocations and deallocations are in raw_word_size |
369 size_t raw_word_size = get_raw_allocation_word_size(word_size); |
375 size_t raw_word_size = get_raw_allocation_word_size(word_size); |
370 |
376 |
371 log_debug(metaspace)("SpaceManager %s: deallocating " PTR_FORMAT |
377 log_debug(metaspace)(LOGFMT_SPCMGR ": deallocating " PTR_FORMAT |
372 ", word size: " SIZE_FORMAT ", raw size: " SIZE_FORMAT ".", |
378 ", word size: " SIZE_FORMAT ", raw size: " SIZE_FORMAT ".", |
373 _name, p2i(p), word_size, raw_word_size); |
379 LOGFMT_SPCMGR_ARGS, p2i(p), word_size, raw_word_size); |
374 |
380 |
375 assert(current_chunk() != NULL, "SpaceManager is empty."); |
381 assert(current_chunk() != NULL, "SpaceManager is empty."); |
376 |
382 |
377 assert(is_valid_area(p, word_size), |
383 assert(is_valid_area(p, word_size), |
378 "Pointer range not part of this SpaceManager and cannot be deallocated: (" PTR_FORMAT ".." PTR_FORMAT ").", |
384 "Pointer range not part of this SpaceManager and cannot be deallocated: (" PTR_FORMAT ".." PTR_FORMAT ").", |
379 p2i(p), p2i(p + word_size)); |
385 p2i(p), p2i(p + word_size)); |
380 |
386 |
381 // If this allocation has just been allocated from the current chunk, it may still be on the top of the |
387 // If this allocation has just been allocated from the current chunk, it may still be on the top of the |
382 // current chunk. In that case, just roll back the allocation. |
388 // current chunk. In that case, just roll back the allocation. |
383 if (current_chunk()->attempt_rollback_allocation(p, raw_word_size)) { |
389 if (current_chunk()->attempt_rollback_allocation(p, raw_word_size)) { |
384 log_trace(metaspace)("SpaceManager %s: ... rollback succeeded.", _name); |
390 log_trace(metaspace)(LOGFMT_SPCMGR ": ... rollback succeeded.", LOGFMT_SPCMGR_ARGS); |
385 return; |
391 return; |
386 } |
392 } |
387 |
393 |
388 add_allocation_to_block_freelist(p, raw_word_size); |
394 add_allocation_to_block_freelist(p, raw_word_size); |
389 |
395 |