1/*
2 * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 *
23 */
24
25#ifndef SHARE_MEMORY_METASPACE_VIRTUALSPACELIST_HPP
26#define SHARE_MEMORY_METASPACE_VIRTUALSPACELIST_HPP
27
28#include "memory/allocation.hpp"
29#include "memory/metaspace/virtualSpaceNode.hpp"
30#include "utilities/globalDefinitions.hpp"
31
32
33namespace metaspace {
34
35class Metachunk;
36class ChunkManager;
37
38// List of VirtualSpaces for metadata allocation.
39class VirtualSpaceList : public CHeapObj<mtClass> {
40 friend class VirtualSpaceNode;
41
42 enum VirtualSpaceSizes {
43 VirtualSpaceSize = 256 * K
44 };
45
46 // Head of the list
47 VirtualSpaceNode* _virtual_space_list;
48 // virtual space currently being used for allocations
49 VirtualSpaceNode* _current_virtual_space;
50
51 // Is this VirtualSpaceList used for the compressed class space
52 bool _is_class;
53
54 // Sum of reserved and committed memory in the virtual spaces
55 size_t _reserved_words;
56 size_t _committed_words;
57
58 // Number of virtual spaces
59 size_t _virtual_space_count;
60
61 // Optimization: we keep an address range to quickly exclude pointers
62 // which are clearly not pointing into metaspace. This is an optimization for
63 // VirtualSpaceList::contains().
64 address _envelope_lo;
65 address _envelope_hi;
66
67 bool is_within_envelope(address p) const {
68 return p >= _envelope_lo && p < _envelope_hi;
69 }
70
71 // Given a node, expand range such that it includes the node.
72 void expand_envelope_to_include_node(const VirtualSpaceNode* node);
73
74 ~VirtualSpaceList();
75
76 VirtualSpaceNode* virtual_space_list() const { return _virtual_space_list; }
77
78 void set_virtual_space_list(VirtualSpaceNode* v) {
79 _virtual_space_list = v;
80 }
81 void set_current_virtual_space(VirtualSpaceNode* v) {
82 _current_virtual_space = v;
83 }
84
85 void link_vs(VirtualSpaceNode* new_entry);
86
87 // Get another virtual space and add it to the list. This
88 // is typically prompted by a failed attempt to allocate a chunk
89 // and is typically followed by the allocation of a chunk.
90 bool create_new_virtual_space(size_t vs_word_size);
91
92 // Chunk up the unused committed space in the current
93 // virtual space and add the chunks to the free list.
94 void retire_current_virtual_space();
95
96 DEBUG_ONLY(bool contains_node(const VirtualSpaceNode* node) const;)
97
98 public:
99 VirtualSpaceList(size_t word_size);
100 VirtualSpaceList(ReservedSpace rs);
101
102 size_t free_bytes();
103
104 Metachunk* get_new_chunk(size_t chunk_word_size,
105 size_t suggested_commit_granularity);
106
107 bool expand_node_by(VirtualSpaceNode* node,
108 size_t min_words,
109 size_t preferred_words);
110
111 bool expand_by(size_t min_words,
112 size_t preferred_words);
113
114 VirtualSpaceNode* current_virtual_space() {
115 return _current_virtual_space;
116 }
117
118 bool is_class() const { return _is_class; }
119
120 bool initialization_succeeded() { return _virtual_space_list != NULL; }
121
122 size_t reserved_words() { return _reserved_words; }
123 size_t reserved_bytes() { return reserved_words() * BytesPerWord; }
124 size_t committed_words() { return _committed_words; }
125 size_t committed_bytes() { return committed_words() * BytesPerWord; }
126
127 void inc_reserved_words(size_t v);
128 void dec_reserved_words(size_t v);
129 void inc_committed_words(size_t v);
130 void dec_committed_words(size_t v);
131 void inc_virtual_space_count();
132 void dec_virtual_space_count();
133
134 VirtualSpaceNode* find_enclosing_space(const void* ptr);
135 bool contains(const void* ptr) { return find_enclosing_space(ptr) != NULL; }
136
137 // Unlink empty VirtualSpaceNodes and free it.
138 void purge(ChunkManager* chunk_manager);
139
140 void print_on(outputStream* st) const { print_on(st, K); }
141 void print_on(outputStream* st, size_t scale) const;
142 void print_map(outputStream* st) const;
143
144 DEBUG_ONLY(void verify(bool slow);)
145
146 class VirtualSpaceListIterator : public StackObj {
147 VirtualSpaceNode* _virtual_spaces;
148 public:
149 VirtualSpaceListIterator(VirtualSpaceNode* virtual_spaces) :
150 _virtual_spaces(virtual_spaces) {}
151
152 bool repeat() {
153 return _virtual_spaces != NULL;
154 }
155
156 VirtualSpaceNode* get_next() {
157 VirtualSpaceNode* result = _virtual_spaces;
158 if (_virtual_spaces != NULL) {
159 _virtual_spaces = _virtual_spaces->next();
160 }
161 return result;
162 }
163 };
164};
165
166} // namespace metaspace
167
168#endif // SHARE_MEMORY_METASPACE_VIRTUALSPACELIST_HPP
169