1 /* 2 * Copyright (c) 2018, 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 #include "precompiled.hpp" 25 26 #include "memory/metaspace/chunkAllocSequence.hpp" 27 #include "memory/metaspace/chunkLevel.hpp" 28 #include "utilities/globalDefinitions.hpp" 29 30 namespace metaspace { 31 32 33 34 35 // A chunk allocation sequence which can be encoded with a simple const array. 36 class ConstantChunkAllocSequence : public ChunkAllocSequence { 37 38 // integer array specifying chunk level allocation progression. 39 // Last chunk is to be an endlessly repeated allocation. 40 const chklvl_t* const _entries; 41 const int _num_entries; 42 43 public: 44 45 ConstantChunkAllocSequence(const chklvl_t* array, int num_entries) 46 : _entries(array) 47 , _num_entries(num_entries) 48 { 49 assert(_num_entries > 0, "must not be empty."); 50 } 51 52 chklvl_t get_next_chunk_level(int num_allocated) const { 53 if (num_allocated >= _num_entries) { 54 // Caller shall repeat last allocation 55 return _entries[_num_entries - 1]; 56 } 57 return _entries[_num_entries]; 58 } 59 60 }; 61 62 // hard-coded chunk allocation sequences for various space types 63 64 /////////////////////////// 65 // chunk allocation sequences for normal loaders: 66 static const chklvl_t g_sequ_standard_nonclass[] = { 67 chklvl::CHUNK_LEVEL_4K, 68 chklvl::CHUNK_LEVEL_4K, 69 chklvl::CHUNK_LEVEL_4K, 70 chklvl::CHUNK_LEVEL_4K, 71 chklvl::CHUNK_LEVEL_64K 72 -1 // .. repeat last 73 }; 74 75 static const chklvl_t g_sequ_standard_class[] = { 76 chklvl::CHUNK_LEVEL_4K, 77 chklvl::CHUNK_LEVEL_4K, 78 chklvl::CHUNK_LEVEL_4K, 79 chklvl::CHUNK_LEVEL_4K, 80 chklvl::CHUNK_LEVEL_32K, 81 -1 // .. repeat last 82 }; 83 84 /////////////////////////// 85 // chunk allocation sequences for reflection/anonymous loaders: 86 // We allocate four smallish chunks before progressing to bigger chunks. 87 static const chklvl_t g_sequ_anon_nonclass[] = { 88 chklvl::CHUNK_LEVEL_1K, 89 chklvl::CHUNK_LEVEL_1K, 90 chklvl::CHUNK_LEVEL_1K, 91 chklvl::CHUNK_LEVEL_1K, 92 chklvl::CHUNK_LEVEL_4K, 93 -1 // .. repeat last 94 }; 95 96 static const chklvl_t g_sequ_anon_class[] = { 97 chklvl::CHUNK_LEVEL_1K, 98 chklvl::CHUNK_LEVEL_1K, 99 chklvl::CHUNK_LEVEL_1K, 100 chklvl::CHUNK_LEVEL_1K, 101 chklvl::CHUNK_LEVEL_4K, 102 -1 // .. repeat last 103 }; 104 105 #define DEFINE_CLASS_FOR_ARRAY(what) \ 106 static ConstantChunkAllocSequence g_chunk_alloc_sequence_##what (g_sequ_##what, sizeof(g_sequ_##what)/sizeof(int)); 107 108 DEFINE_CLASS_FOR_ARRAY(standard_nonclass) 109 DEFINE_CLASS_FOR_ARRAY(standard_class) 110 DEFINE_CLASS_FOR_ARRAY(anon_nonclass) 111 DEFINE_CLASS_FOR_ARRAY(anon_class) 112 113 114 class BootLoaderChunkAllocSequence : public ChunkAllocSequence { 115 116 // For now, this mirrors what the old code did 117 // (see SpaceManager::get_initial_chunk_size() and SpaceManager::calc_chunk_size). 118 119 // Not sure how much sense this still makes, especially with CDS - by default we 120 // now load JDK classes from CDS and therefore most of the boot loader 121 // chunks remain unoccupied. 122 123 // Also, InitialBootClassLoaderMetaspaceSize was/is confusing since it only applies 124 // to the non-class chunk. 125 126 const bool _is_class; 127 128 static chklvl_t calc_initial_chunk_level(bool is_class) { 129 130 size_t word_size = 0; 131 if (is_class) { 132 // In the old version first class space chunk for boot loader was always medium class chunk size * 6. 133 word_size = (32 * K * 6) / BytesPerWord; 134 135 } else { 136 //assert(InitialBootClassLoaderMetaspaceSize < chklvl::MAX_CHUNK_BYTE_SIZE, 137 // "InitialBootClassLoaderMetaspaceSize too large"); 138 word_size = MIN2(InitialBootClassLoaderMetaspaceSize, 139 chklvl::MAX_CHUNK_BYTE_SIZE) / BytesPerWord; 140 } 141 return chklvl::level_fitting_word_size(word_size); 142 } 143 144 public: 145 146 BootLoaderChunkAllocSequence(bool is_class) 147 : _is_class(is_class) 148 {} 149 150 chklvl_t get_next_chunk_level(int num_allocated) const { 151 if (num_allocated == 0) { 152 return calc_initial_chunk_level(_is_class); 153 } 154 // bit arbitrary, but this is what the old code did. Can tweak later if needed. 155 return chklvl::CHUNK_LEVEL_64K; 156 } 157 158 }; 159 160 static BootLoaderChunkAllocSequence g_chunk_alloc_sequence_boot_non_class(false); 161 static BootLoaderChunkAllocSequence g_chunk_alloc_sequence_boot_class(true); 162 163 164 const ChunkAllocSequence* ChunkAllocSequence::alloc_sequence_by_space_type(MetaspaceType space_type, bool is_class) { 165 166 if (is_class) { 167 switch(space_type) { 168 case StandardMetaspaceType: return &g_chunk_alloc_sequence_standard_class; 169 case ReflectionMetaspaceType: 170 case UnsafeAnonymousMetaspaceType: return &g_chunk_alloc_sequence_anon_class; 171 case BootMetaspaceType: return &g_chunk_alloc_sequence_boot_non_class; 172 default: ShouldNotReachHere(); 173 } 174 } else { 175 switch(space_type) { 176 case StandardMetaspaceType: return &g_chunk_alloc_sequence_standard_class; 177 case ReflectionMetaspaceType: 178 case UnsafeAnonymousMetaspaceType: return &g_chunk_alloc_sequence_anon_class; 179 case BootMetaspaceType: return &g_chunk_alloc_sequence_boot_class; 180 default: ShouldNotReachHere(); 181 } 182 } 183 184 return NULL; 185 186 } 187 188 189 190 } // namespace metaspace 191