1 /* 2 * Copyright (c) 2014, 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_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP 26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP 27 28 #include "memory/allocation.hpp" 29 #include "memory/freeList.hpp" 30 #include "runtime/globals.hpp" 31 32 class CodeBlobClosure; 33 34 class G1CodeRootChunk : public CHeapObj<mtGC> { 35 private: 36 static const int NUM_ENTRIES = 32; 37 public: 38 G1CodeRootChunk* _next; 39 G1CodeRootChunk* _prev; 40 41 nmethod** _top; 42 43 nmethod* _data[NUM_ENTRIES]; 44 45 nmethod** bottom() const { 46 return (nmethod**) &(_data[0]); 47 } 48 49 nmethod** end() const { 50 return (nmethod**) &(_data[NUM_ENTRIES]); 51 } 52 53 public: 54 G1CodeRootChunk(); 55 ~G1CodeRootChunk() {} 56 57 static size_t word_size() { return (size_t)(align_size_up_(sizeof(G1CodeRootChunk), HeapWordSize) / HeapWordSize); } 58 59 // FreeList "interface" methods 60 61 G1CodeRootChunk* next() const { return _next; } 62 G1CodeRootChunk* prev() const { return _prev; } 63 void set_next(G1CodeRootChunk* v) { _next = v; assert(v != this, "Boom");} 64 void set_prev(G1CodeRootChunk* v) { _prev = v; assert(v != this, "Boom");} 65 void clear_next() { set_next(NULL); } 66 void clear_prev() { set_prev(NULL); } 67 68 size_t size() const { return word_size(); } 69 70 void link_next(G1CodeRootChunk* ptr) { set_next(ptr); } 71 void link_prev(G1CodeRootChunk* ptr) { set_prev(ptr); } 72 void link_after(G1CodeRootChunk* ptr) { 73 link_next(ptr); 74 if (ptr != NULL) ptr->link_prev((G1CodeRootChunk*)this); 75 } 76 77 bool is_free() { return true; } 78 79 // New G1CodeRootChunk routines 80 81 void reset(); 82 83 bool is_empty() const { 84 return _top == bottom(); 85 } 86 87 bool is_full() const { 88 return _top == (nmethod**)end(); 89 } 90 91 bool contains(nmethod* method) { 92 nmethod** cur = bottom(); 93 while (cur != _top) { 94 if (*cur == method) return true; 95 cur++; 96 } 97 return false; 98 } 99 100 bool add(nmethod* method) { 101 if (is_full()) return false; 102 *_top = method; 103 _top++; 104 return true; 105 } 106 107 bool remove(nmethod* method) { 108 nmethod** cur = bottom(); 109 while (cur != _top) { 110 if (*cur == method) { 111 memmove(cur, cur + 1, (_top - (cur + 1)) * sizeof(nmethod**)); 112 _top--; 113 return true; 114 } 115 cur++; 116 } 117 return false; 118 } 119 120 void nmethods_do(CodeBlobClosure* blk); 121 122 nmethod* pop() { 123 if (is_empty()) { 124 return NULL; 125 } 126 _top--; 127 return *_top; 128 } 129 }; 130 131 // Manages free chunks. 132 class G1CodeRootChunkManager VALUE_OBJ_CLASS_SPEC { 133 private: 134 // Global free chunk list management 135 FreeList<G1CodeRootChunk> _free_list; 136 // Total number of chunks handed out 137 size_t _num_chunks_handed_out; 138 139 public: 140 G1CodeRootChunkManager(); 141 142 G1CodeRootChunk* new_chunk(); 143 void free_chunk(G1CodeRootChunk* chunk); 144 // Free all elements of the given list. 145 void free_all_chunks(FreeList<G1CodeRootChunk>* list); 146 147 void initialize(); 148 void purge_chunks(size_t keep_ratio); 149 150 size_t static_mem_size(); 151 size_t fl_mem_size(); 152 153 #ifndef PRODUCT 154 size_t num_chunks_handed_out() const; 155 size_t num_free_chunks() const; 156 #endif 157 }; 158 159 // Implements storage for a set of code roots. 160 // All methods that modify the set are not thread-safe except if otherwise noted. 161 class G1CodeRootSet VALUE_OBJ_CLASS_SPEC { 162 private: 163 // Global default free chunk manager instance. 164 static G1CodeRootChunkManager _default_chunk_manager; 165 166 G1CodeRootChunk* new_chunk() { return _manager->new_chunk(); } 167 void free_chunk(G1CodeRootChunk* chunk) { _manager->free_chunk(chunk); } 168 // Free all elements of the given list. 169 void free_all_chunks(FreeList<G1CodeRootChunk>* list) { _manager->free_all_chunks(list); } 170 171 // Return the chunk that contains the given nmethod, NULL otherwise. 172 // Scans the list of chunks backwards, as this method is used to add new 173 // entries, which are typically added in bulk for a single nmethod. 174 G1CodeRootChunk* find(nmethod* method); 175 void free(G1CodeRootChunk* chunk); 176 177 size_t _length; 178 FreeList<G1CodeRootChunk> _list; 179 G1CodeRootChunkManager* _manager; 180 181 public: 182 // If an instance is initialized with a chunk manager of NULL, use the global 183 // default one. 184 G1CodeRootSet(G1CodeRootChunkManager* manager = NULL); 185 ~G1CodeRootSet(); 186 187 static void purge_chunks(size_t keep_ratio); 188 189 static size_t static_mem_size(); 190 static size_t free_chunks_mem_size(); 191 192 // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this 193 // method is likely to be repeatedly called with the same nmethod. 194 void add(nmethod* method); 195 196 void remove(nmethod* method); 197 nmethod* pop(); 198 199 bool contains(nmethod* method); 200 201 void clear(); 202 203 void nmethods_do(CodeBlobClosure* blk) const; 204 205 bool is_empty() { return length() == 0; } 206 207 // Length in elements 208 size_t length() const { return _length; } 209 210 // Memory size in bytes taken by this set. 211 size_t mem_size(); 212 213 static void test() PRODUCT_RETURN; 214 }; 215 216 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP