|
1 /* |
|
2 * Copyright (c) 2019, SAP SE. All rights reserved. |
|
3 * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. |
|
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
|
5 * |
|
6 * This code is free software; you can redistribute it and/or modify it |
|
7 * under the terms of the GNU General Public License version 2 only, as |
|
8 * published by the Free Software Foundation. |
|
9 * |
|
10 * This code is distributed in the hope that it will be useful, but WITHOUT |
|
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
|
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
|
13 * version 2 for more details (a copy is included in the LICENSE file that |
|
14 * accompanied this code). |
|
15 * |
|
16 * You should have received a copy of the GNU General Public License version |
|
17 * 2 along with this work; if not, write to the Free Software Foundation, |
|
18 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
|
19 * |
|
20 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
|
21 * or visit www.oracle.com if you need additional information or have any |
|
22 * questions. |
|
23 * |
|
24 */ |
|
25 #include "precompiled.hpp" |
|
26 |
|
27 #include "memory/metaspace/chunkAllocSequence.hpp" |
|
28 #include "memory/metaspace/chunkLevel.hpp" |
|
29 #include "utilities/globalDefinitions.hpp" |
|
30 |
|
31 namespace metaspace { |
|
32 |
|
33 // A chunk allocation sequence which can be encoded with a simple const array. |
|
34 class ConstantChunkAllocSequence : public ChunkAllocSequence { |
|
35 |
|
36 // integer array specifying chunk level allocation progression. |
|
37 // Last chunk is to be an endlessly repeated allocation. |
|
38 const chklvl_t* const _entries; |
|
39 const int _num_entries; |
|
40 |
|
41 public: |
|
42 |
|
43 ConstantChunkAllocSequence(const chklvl_t* array, int num_entries) |
|
44 : _entries(array) |
|
45 , _num_entries(num_entries) |
|
46 { |
|
47 assert(_num_entries > 0, "must not be empty."); |
|
48 } |
|
49 |
|
50 chklvl_t get_next_chunk_level(int num_allocated) const { |
|
51 if (num_allocated >= _num_entries) { |
|
52 // Caller shall repeat last allocation |
|
53 return _entries[_num_entries - 1]; |
|
54 } |
|
55 return _entries[_num_entries]; |
|
56 } |
|
57 |
|
58 }; |
|
59 |
|
60 // hard-coded chunk allocation sequences for various space types |
|
61 |
|
62 /////////////////////////// |
|
63 // chunk allocation sequences for normal loaders: |
|
64 static const chklvl_t g_sequ_standard_nonclass[] = { |
|
65 chklvl::CHUNK_LEVEL_4K, |
|
66 chklvl::CHUNK_LEVEL_4K, |
|
67 chklvl::CHUNK_LEVEL_4K, |
|
68 chklvl::CHUNK_LEVEL_4K, |
|
69 chklvl::CHUNK_LEVEL_64K |
|
70 -1 // .. repeat last |
|
71 }; |
|
72 |
|
73 static const chklvl_t g_sequ_standard_class[] = { |
|
74 chklvl::CHUNK_LEVEL_4K, |
|
75 chklvl::CHUNK_LEVEL_4K, |
|
76 chklvl::CHUNK_LEVEL_4K, |
|
77 chklvl::CHUNK_LEVEL_4K, |
|
78 chklvl::CHUNK_LEVEL_32K, |
|
79 -1 // .. repeat last |
|
80 }; |
|
81 |
|
82 /////////////////////////// |
|
83 // chunk allocation sequences for reflection/anonymous loaders: |
|
84 // We allocate four smallish chunks before progressing to bigger chunks. |
|
85 static const chklvl_t g_sequ_anon_nonclass[] = { |
|
86 chklvl::CHUNK_LEVEL_1K, |
|
87 chklvl::CHUNK_LEVEL_1K, |
|
88 chklvl::CHUNK_LEVEL_1K, |
|
89 chklvl::CHUNK_LEVEL_1K, |
|
90 chklvl::CHUNK_LEVEL_4K, |
|
91 -1 // .. repeat last |
|
92 }; |
|
93 |
|
94 static const chklvl_t g_sequ_anon_class[] = { |
|
95 chklvl::CHUNK_LEVEL_1K, |
|
96 chklvl::CHUNK_LEVEL_1K, |
|
97 chklvl::CHUNK_LEVEL_1K, |
|
98 chklvl::CHUNK_LEVEL_1K, |
|
99 chklvl::CHUNK_LEVEL_4K, |
|
100 -1 // .. repeat last |
|
101 }; |
|
102 |
|
103 #define DEFINE_CLASS_FOR_ARRAY(what) \ |
|
104 static ConstantChunkAllocSequence g_chunk_alloc_sequence_##what (g_sequ_##what, sizeof(g_sequ_##what)/sizeof(int)); |
|
105 |
|
106 DEFINE_CLASS_FOR_ARRAY(standard_nonclass) |
|
107 DEFINE_CLASS_FOR_ARRAY(standard_class) |
|
108 DEFINE_CLASS_FOR_ARRAY(anon_nonclass) |
|
109 DEFINE_CLASS_FOR_ARRAY(anon_class) |
|
110 |
|
111 |
|
112 class BootLoaderChunkAllocSequence : public ChunkAllocSequence { |
|
113 |
|
114 // For now, this mirrors what the old code did |
|
115 // (see SpaceManager::get_initial_chunk_size() and SpaceManager::calc_chunk_size). |
|
116 |
|
117 // Not sure how much sense this still makes, especially with CDS - by default we |
|
118 // now load JDK classes from CDS and therefore most of the boot loader |
|
119 // chunks remain unoccupied. |
|
120 |
|
121 // Also, InitialBootClassLoaderMetaspaceSize was/is confusing since it only applies |
|
122 // to the non-class chunk. |
|
123 |
|
124 const bool _is_class; |
|
125 |
|
126 static chklvl_t calc_initial_chunk_level(bool is_class) { |
|
127 |
|
128 size_t word_size = 0; |
|
129 if (is_class) { |
|
130 // In the old version first class space chunk for boot loader was always medium class chunk size * 6. |
|
131 word_size = (32 * K * 6) / BytesPerWord; |
|
132 |
|
133 } else { |
|
134 //assert(InitialBootClassLoaderMetaspaceSize < chklvl::MAX_CHUNK_BYTE_SIZE, |
|
135 // "InitialBootClassLoaderMetaspaceSize too large"); |
|
136 word_size = MIN2(InitialBootClassLoaderMetaspaceSize, |
|
137 chklvl::MAX_CHUNK_BYTE_SIZE) / BytesPerWord; |
|
138 } |
|
139 return chklvl::level_fitting_word_size(word_size); |
|
140 } |
|
141 |
|
142 public: |
|
143 |
|
144 BootLoaderChunkAllocSequence(bool is_class) |
|
145 : _is_class(is_class) |
|
146 {} |
|
147 |
|
148 chklvl_t get_next_chunk_level(int num_allocated) const { |
|
149 if (num_allocated == 0) { |
|
150 return calc_initial_chunk_level(_is_class); |
|
151 } |
|
152 // bit arbitrary, but this is what the old code did. Can tweak later if needed. |
|
153 return chklvl::CHUNK_LEVEL_64K; |
|
154 } |
|
155 |
|
156 }; |
|
157 |
|
158 static BootLoaderChunkAllocSequence g_chunk_alloc_sequence_boot_non_class(false); |
|
159 static BootLoaderChunkAllocSequence g_chunk_alloc_sequence_boot_class(true); |
|
160 |
|
161 |
|
162 const ChunkAllocSequence* ChunkAllocSequence::alloc_sequence_by_space_type(MetaspaceType space_type, bool is_class) { |
|
163 |
|
164 if (is_class) { |
|
165 switch(space_type) { |
|
166 case StandardMetaspaceType: return &g_chunk_alloc_sequence_standard_class; |
|
167 case ReflectionMetaspaceType: |
|
168 case UnsafeAnonymousMetaspaceType: return &g_chunk_alloc_sequence_anon_class; |
|
169 case BootMetaspaceType: return &g_chunk_alloc_sequence_boot_non_class; |
|
170 default: ShouldNotReachHere(); |
|
171 } |
|
172 } else { |
|
173 switch(space_type) { |
|
174 case StandardMetaspaceType: return &g_chunk_alloc_sequence_standard_class; |
|
175 case ReflectionMetaspaceType: |
|
176 case UnsafeAnonymousMetaspaceType: return &g_chunk_alloc_sequence_anon_class; |
|
177 case BootMetaspaceType: return &g_chunk_alloc_sequence_boot_class; |
|
178 default: ShouldNotReachHere(); |
|
179 } |
|
180 } |
|
181 |
|
182 return NULL; |
|
183 |
|
184 } |
|
185 |
|
186 |
|
187 |
|
188 } // namespace metaspace |
|
189 |