rev 57511 : [mq]: metaspace-improvement
1 /* 2 * Copyright (c) 2012, 2016, 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 26 #include "precompiled.hpp" 27 28 #include "memory/metaspace/chunkLevel.hpp" 29 #include "memory/metaspace/constants.hpp" 30 #include "memory/metaspace/metachunk.hpp" 31 #include "memory/metaspace/metaspaceCommon.hpp" 32 #include "memory/metaspace/virtualSpaceNode.hpp" 33 34 #include "utilities/align.hpp" 35 #include "utilities/copy.hpp" 36 #include "utilities/debug.hpp" 37 38 namespace metaspace { 39 40 // Make sure that the Klass alignment also agree. 41 STATIC_ASSERT(Metachunk::allocation_alignment_bytes == (size_t)KlassAlignmentInBytes); 42 43 void Metachunk::remove_from_list() { 44 if (_prev != NULL) { 45 _prev->set_next(_next); 46 } 47 if (_next != NULL) { 48 _next->set_prev(_prev); 49 } 50 _prev = _next = NULL; 51 } 52 53 // Ensure that chunk is committed up to at least word_size words. 54 bool Metachunk::ensure_committed(size_t new_committed_words) { 55 56 assert(new_committed_words <= word_size(), "too much."); 57 58 if (new_committed_words <= committed_words()) { 59 return true; 60 } 61 62 // Note: we may commit more than the area of our own chunk and that is okay. 63 MetaWord* const commit_top = align_down(base() + committed_words(), constants::commit_granule_words); 64 MetaWord* const new_commit_top = align_up(base() + new_committed_words, constants::commit_granule_words); 65 66 { 67 // Expand lock from here on. 68 MutexLocker cl(MetaspaceExpand_lock, Mutex::_no_safepoint_check_flag); 69 if (!_vsnode->ensure_range_is_committed(commit_top, new_commit_top - commit_top)) { 70 return false; 71 } 72 // Remember how far we have committed. 73 _committed_words = new_commit_top - base(); 74 if (_committed_words > word_size()) { 75 _committed_words = word_size(); 76 } 77 } 78 79 return true; 80 81 } 82 83 84 // Allocate word_size words from this chunk. 85 // 86 // May cause memory to be committed. That may fail if we hit a commit limit. In that case, 87 // NULL is returned and p_did_hit_commit_limit will be set to true. 88 // If the remainder portion of the chunk was too small to hold the allocation, 89 // NULL is returned and p_did_hit_commit_limit will be set to false. 90 MetaWord* Metachunk::allocate(size_t word_size, bool* p_did_hit_commit_limit) { 91 92 size_t request_word_size = align_up(word_size, allocation_alignment_words); 93 94 // Space enough left? 95 if (free_words() < request_word_size) { 96 *p_did_hit_commit_limit = false; 97 return NULL; 98 } 99 100 // Expand committed region if necessary. 101 if (ensure_committed(used_words() + request_word_size) == false) { 102 *p_did_hit_commit_limit = true; 103 return NULL; 104 } 105 106 MetaWord* const p = top(); 107 108 _used_words += request_word_size; 109 110 return p; 111 112 } 113 114 #ifdef ASSERT 115 116 void Metachunk::verify(bool slow) const { 117 118 // Note: only call this on a life Metachunk. 119 chklvl::check_valid_level(level()); 120 121 assert(base() != NULL, "No base ptr"); 122 assert(committed_words() >= used_words(), "Sanity"); 123 assert(word_size() >= committed_words(), "Sanity"); 124 125 // Test base pointer 126 assert(vsnode() != NULL, "No space"); 127 vsnode()->check_pointer(base()); 128 assert(base() != NULL, "Base pointer NULL"); 129 130 // Starting address shall be aligned to chunk size. 131 const size_t required_alignment = word_size() * sizeof(MetaWord); 132 assert_is_aligned(base(), required_alignment); 133 134 // Used words 135 assert(used_words() < word_size(), "oob"); 136 137 // If we are not a root chunk, we shall have a reference to a tree node 138 assert(tree_node_ref() != 0 || level() == chklvl::ROOT_CHUNK_LEVEL, "No parent node."); 139 140 } 141 #endif // ASSERT 142 143 144 #ifdef ASSERT 145 146 bool MetachunkList::contains(const Metachunk* c) const { 147 for (Metachunk* c2 = first(); c2 != NULL; c2 = c2->next()) { 148 if (c == c2) { 149 return true; 150 } 151 } 152 return false; 153 } 154 155 void MetachunkList::verify(bool slow) const { 156 int num = 0; 157 for (Metachunk* c = first(); c != NULL; c = c->next()) { 158 num ++; 159 if (slow) { 160 c->verify(false); 161 } 162 _num.check(num); 163 } 164 } 165 166 #endif // ASSERT 167 168 } // namespace metaspace 169 --- EOF ---