--- a/src/hotspot/share/memory/metaspace/spaceManager.cpp Tue Nov 19 20:01:05 2019 +0100
+++ b/src/hotspot/share/memory/metaspace/spaceManager.cpp Fri Nov 01 10:28:15 2019 +0100
@@ -26,8 +26,10 @@
#include "logging/log.hpp"
#include "logging/logStream.hpp"
+#include "memory/metaspace/blockFreelist.hpp"
#include "memory/metaspace/chunkManager.hpp"
#include "memory/metaspace/internStat.hpp"
+#include "memory/metaspace/leftOverBins.inline.hpp"
#include "memory/metaspace/metachunk.hpp"
#include "memory/metaspace/metaDebug.hpp"
#include "memory/metaspace/metaspaceCommon.hpp"
@@ -157,6 +159,19 @@
_block_freelist->return_block(p, word_size);
}
+
+void SpaceManager::create_lom() {
+ assert(_lom == NULL, "Only call once");
+ _lom = new LeftOverManager();
+}
+
+void SpaceManager::add_allocation_to_lom(MetaWord* p, size_t word_size) {
+ if (_lom == NULL) {
+ _lom = new LeftOverManager(); // Create only on demand
+ }
+ _lom->add_block(p, word_size);
+}
+
SpaceManager::SpaceManager(ChunkManager* chunk_manager,
const ChunkAllocSequence* alloc_sequence,
Mutex* lock,
@@ -167,7 +182,7 @@
_chunk_manager(chunk_manager),
_chunk_alloc_sequence(alloc_sequence),
_chunks(),
- _block_freelist(NULL),
+ _block_freelist(NULL), _lom(NULL),
_total_used_words_counter(total_used_words_counter),
_name(name),
_is_micro_loader(is_micro_loader)
@@ -191,6 +206,7 @@
DEBUG_ONLY(chunk_manager()->verify(true);)
delete _block_freelist;
+ delete _lom;
}
@@ -230,7 +246,13 @@
bool did_hit_limit = false;
MetaWord* ptr = c->allocate(net_remaining_words, &did_hit_limit);
assert(ptr != NULL && did_hit_limit == false, "Should have worked");
- add_allocation_to_block_freelist(ptr, net_remaining_words);
+
+ if (Settings::use_lom()) {
+ add_allocation_to_lom(ptr, net_remaining_words);
+ } else {
+ add_allocation_to_block_freelist(ptr, net_remaining_words);
+ }
+
_total_used_words_counter->increment_by(net_remaining_words);
// After this operation: the current chunk should have (almost) no free committed space left.
@@ -281,6 +303,19 @@
// from the dictionary until it starts to get fat. Is this
// a reasonable policy? Maybe an skinny dictionary is fast enough
// for allocations. Do some profiling. JJJ
+ if (Settings::use_lom()) {
+ if (_lom != NULL) {
+ p = _lom->get_block(raw_word_size);
+ if (p != NULL) {
+ DEBUG_ONLY(InternalStats::inc_num_allocs_from_deallocated_blocks();)
+ log_trace(metaspace)(LOGFMT_SPCMGR ": .. taken from freelist.", LOGFMT_SPCMGR_ARGS);
+ // Note: space in the freeblock dictionary counts as used (see retire_current_chunk()) -
+ // that means that we must not increase the used counter again when allocating from the dictionary.
+ // Therefore we return here.
+ return p;
+ }
+ }
+ } else {
if (_block_freelist != NULL && _block_freelist->total_size() > Settings::allocation_from_dictionary_limit()) {
p = _block_freelist->get_block(raw_word_size);
@@ -294,6 +329,7 @@
}
}
+ }
// 2) Failing that, attempt to allocate from the current chunk. If we hit commit limit, return NULL.
if (p == NULL && !did_hit_limit) {
@@ -405,7 +441,11 @@
return;
}
- add_allocation_to_block_freelist(p, raw_word_size);
+ if (Settings::use_lom()) {
+ add_allocation_to_lom(p, raw_word_size);
+ } else {
+ add_allocation_to_block_freelist(p, raw_word_size);
+ }
DEBUG_ONLY(verify_locked();)
@@ -437,9 +477,18 @@
}
}
- if (block_freelist() != NULL) {
- out->free_blocks_num += block_freelist()->num_blocks();
- out->free_blocks_word_size += block_freelist()->total_size();
+ if (Settings::use_lom()) {
+ if (lom() != NULL) {
+ block_stats_t s;
+ lom()->statistics(&s);
+ out->free_blocks_num += s.num_blocks;
+ out->free_blocks_word_size += s.word_size;
+ }
+ } else {
+ if (block_freelist() != NULL) {
+ out->free_blocks_num += block_freelist()->num_blocks();
+ out->free_blocks_word_size += block_freelist()->total_size();
+ }
}
SOMETIMES(out->verify();)
@@ -456,6 +505,12 @@
_chunks.verify();
+ if (Settings::use_lom()) {
+ if (lom() != NULL) {
+ lom()->verify();
+ }
+ }
+
}
void SpaceManager::verify() const {