--- a/src/hotspot/share/memory/metaspace/virtualSpaceList.hpp Tue Sep 10 14:52:53 2019 +0800
+++ b/src/hotspot/share/memory/metaspace/virtualSpaceList.hpp Tue Sep 10 09:24:05 2019 +0200
@@ -1,5 +1,6 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2019 SAP SE. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,143 +27,112 @@
#define SHARE_MEMORY_METASPACE_VIRTUALSPACELIST_HPP
#include "memory/allocation.hpp"
+#include "memory/metaspace/counter.hpp"
+#include "memory/metaspace/commitLimiter.hpp"
#include "memory/metaspace/virtualSpaceNode.hpp"
+#include "memory/virtualspace.hpp"
#include "utilities/globalDefinitions.hpp"
+class outputStream;
namespace metaspace {
class Metachunk;
-class ChunkManager;
+class MetachunkListCluster;
-// List of VirtualSpaces for metadata allocation.
class VirtualSpaceList : public CHeapObj<mtClass> {
- friend class VirtualSpaceNode;
- enum VirtualSpaceSizes {
- VirtualSpaceSize = 256 * K
- };
+ // Name
+ const char* const _name;
- // Head of the list
- VirtualSpaceNode* _virtual_space_list;
- // virtual space currently being used for allocations
- VirtualSpaceNode* _current_virtual_space;
+ // Head of the list.
+ VirtualSpaceNode* _first_node;
- // Is this VirtualSpaceList used for the compressed class space
- bool _is_class;
+ // Number of nodes (kept for statistics only).
+ IntCounter _nodes_counter;
- // Sum of reserved and committed memory in the virtual spaces
- size_t _reserved_words;
- size_t _committed_words;
+ // Whether this list can expand by allocating new nodes.
+ const bool _can_expand;
- // Number of virtual spaces
- size_t _virtual_space_count;
+ // Whether this list can be purged.
+ const bool _can_purge;
- // Optimization: we keep an address range to quickly exclude pointers
- // which are clearly not pointing into metaspace. This is an optimization for
- // VirtualSpaceList::contains().
- address _envelope_lo;
- address _envelope_hi;
+ // Used to check limits before committing memory.
+ CommitLimiter* const _commit_limiter;
- bool is_within_envelope(address p) const {
- return p >= _envelope_lo && p < _envelope_hi;
- }
+ // Statistics
- // Given a node, expand range such that it includes the node.
- void expand_envelope_to_include_node(const VirtualSpaceNode* node);
+ // Holds sum of reserved space, in words, over all list nodes.
+ SizeCounter _reserved_words_counter;
- ~VirtualSpaceList();
-
- VirtualSpaceNode* virtual_space_list() const { return _virtual_space_list; }
+ // Holds sum of committed space, in words, over all list nodes.
+ SizeCounter _committed_words_counter;
- void set_virtual_space_list(VirtualSpaceNode* v) {
- _virtual_space_list = v;
- }
- void set_current_virtual_space(VirtualSpaceNode* v) {
- _current_virtual_space = v;
- }
+ // Create a new node and append it to the list. After
+ // this function, _current_node shall point to a new empty node.
+ // List must be expandable for this to work.
+ void create_new_node();
- void link_vs(VirtualSpaceNode* new_entry);
+public:
- // Get another virtual space and add it to the list. This
- // is typically prompted by a failed attempt to allocate a chunk
- // and is typically followed by the allocation of a chunk.
- bool create_new_virtual_space(size_t vs_word_size);
+ // Create a new, empty, expandable list.
+ VirtualSpaceList(const char* name, CommitLimiter* commit_limiter);
- // Chunk up the unused committed space in the current
- // virtual space and add the chunks to the free list.
- void retire_current_virtual_space();
+ // Create a new list. The list will contain one node only, which uses the given ReservedSpace.
+ // It will be not expandable beyond that first node.
+ VirtualSpaceList(const char* name, ReservedSpace rs, CommitLimiter* commit_limiter);
- DEBUG_ONLY(bool contains_node(const VirtualSpaceNode* node) const;)
+ virtual ~VirtualSpaceList();
- public:
- VirtualSpaceList(size_t word_size);
- VirtualSpaceList(ReservedSpace rs);
-
- size_t free_bytes();
+ // Allocate a root chunk from this list.
+ // Note: this just returns a chunk whose memory is reserved; no memory is committed yet.
+ // Hence, before using this chunk, it must be committed.
+ // Also, no limits are checked, since no committing takes place.
+ Metachunk* allocate_root_chunk();
- Metachunk* get_new_chunk(size_t chunk_word_size,
- size_t suggested_commit_granularity);
-
- bool expand_node_by(VirtualSpaceNode* node,
- size_t min_words,
- size_t preferred_words);
+ // Attempts to purge nodes. This will remove and delete nodes which only contain free chunks.
+ // The free chunks are removed from the freelists before the nodes are deleted.
+ // Return number of purged nodes.
+ int purge(MetachunkListCluster* freelists);
- bool expand_by(size_t min_words,
- size_t preferred_words);
+ //// Statistics ////
- VirtualSpaceNode* current_virtual_space() {
- return _current_virtual_space;
- }
+ // Return sum of reserved words in all nodes.
+ size_t reserved_words() const { return _reserved_words_counter.get(); }
- bool is_class() const { return _is_class; }
-
- bool initialization_succeeded() { return _virtual_space_list != NULL; }
+ // Return sum of committed words in all nodes.
+ size_t committed_words() const { return _committed_words_counter.get(); }
- size_t reserved_words() { return _reserved_words; }
- size_t reserved_bytes() { return reserved_words() * BytesPerWord; }
- size_t committed_words() { return _committed_words; }
- size_t committed_bytes() { return committed_words() * BytesPerWord; }
+ // Return number of nodes in this list.
+ int num_nodes() const { return _nodes_counter.get(); }
- void inc_reserved_words(size_t v);
- void dec_reserved_words(size_t v);
- void inc_committed_words(size_t v);
- void dec_committed_words(size_t v);
- void inc_virtual_space_count();
- void dec_virtual_space_count();
+ //// Debug stuff ////
+ DEBUG_ONLY(void verify(bool slow) const;)
+ DEBUG_ONLY(void verify_locked(bool slow) const;)
- VirtualSpaceNode* find_enclosing_space(const void* ptr);
- bool contains(const void* ptr) { return find_enclosing_space(ptr) != NULL; }
-
- // Unlink empty VirtualSpaceNodes and free it.
- void purge(ChunkManager* chunk_manager);
+ // Print all nodes in this space list.
+ void print_on(outputStream* st) const;
- void print_on(outputStream* st) const { print_on(st, K); }
- void print_on(outputStream* st, size_t scale) const;
- void print_map(outputStream* st) const;
+ // Returns true if this pointer is contained in one of our nodes.
+ bool contains(const MetaWord* p) const;
- DEBUG_ONLY(void verify(bool slow);)
+private:
- class VirtualSpaceListIterator : public StackObj {
- VirtualSpaceNode* _virtual_spaces;
- public:
- VirtualSpaceListIterator(VirtualSpaceNode* virtual_spaces) :
- _virtual_spaces(virtual_spaces) {}
+ static VirtualSpaceList* _vslist_class;
+ static VirtualSpaceList* _vslist_nonclass;
+
+public:
- bool repeat() {
- return _virtual_spaces != NULL;
- }
+ static VirtualSpaceList* vslist_class() { return _vslist_class; }
+ static VirtualSpaceList* vslist_nonclass() { return _vslist_nonclass; }
- VirtualSpaceNode* get_next() {
- VirtualSpaceNode* result = _virtual_spaces;
- if (_virtual_spaces != NULL) {
- _virtual_spaces = _virtual_spaces->next();
- }
- return result;
- }
- };
+ static void set_vslist_class(VirtualSpaceList* vslist_class);
+ static void set_vslist_nonclass(VirtualSpaceList* vslist_class);
+
+
};
} // namespace metaspace
#endif // SHARE_MEMORY_METASPACE_VIRTUALSPACELIST_HPP
+