aoqi@0: /* aoqi@0: * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: * aoqi@0: */ aoqi@0: aoqi@0: #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP aoqi@0: #define SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP aoqi@0: aoqi@0: #include "memory/allocation.hpp" aoqi@0: #include "memory/freeList.hpp" aoqi@0: #include "runtime/globals.hpp" aoqi@0: aoqi@0: class CodeBlobClosure; aoqi@0: aoqi@0: class G1CodeRootChunk : public CHeapObj { aoqi@0: private: aoqi@0: static const int NUM_ENTRIES = 32; aoqi@0: public: aoqi@0: G1CodeRootChunk* _next; aoqi@0: G1CodeRootChunk* _prev; aoqi@0: aoqi@0: nmethod** _top; aoqi@0: aoqi@0: nmethod* _data[NUM_ENTRIES]; aoqi@0: aoqi@0: nmethod** bottom() const { aoqi@0: return (nmethod**) &(_data[0]); aoqi@0: } aoqi@0: aoqi@0: nmethod** end() const { aoqi@0: return (nmethod**) &(_data[NUM_ENTRIES]); aoqi@0: } aoqi@0: aoqi@0: public: aoqi@0: G1CodeRootChunk(); aoqi@0: ~G1CodeRootChunk() {} aoqi@0: aoqi@0: static size_t word_size() { return (size_t)(align_size_up_(sizeof(G1CodeRootChunk), HeapWordSize) / HeapWordSize); } aoqi@0: aoqi@0: // FreeList "interface" methods aoqi@0: aoqi@0: G1CodeRootChunk* next() const { return _next; } aoqi@0: G1CodeRootChunk* prev() const { return _prev; } aoqi@0: void set_next(G1CodeRootChunk* v) { _next = v; assert(v != this, "Boom");} aoqi@0: void set_prev(G1CodeRootChunk* v) { _prev = v; assert(v != this, "Boom");} aoqi@0: void clear_next() { set_next(NULL); } aoqi@0: void clear_prev() { set_prev(NULL); } aoqi@0: aoqi@0: size_t size() const { return word_size(); } aoqi@0: aoqi@0: void link_next(G1CodeRootChunk* ptr) { set_next(ptr); } aoqi@0: void link_prev(G1CodeRootChunk* ptr) { set_prev(ptr); } aoqi@0: void link_after(G1CodeRootChunk* ptr) { aoqi@0: link_next(ptr); aoqi@0: if (ptr != NULL) ptr->link_prev((G1CodeRootChunk*)this); aoqi@0: } aoqi@0: aoqi@0: bool is_free() { return true; } aoqi@0: aoqi@0: // New G1CodeRootChunk routines aoqi@0: aoqi@0: void reset(); aoqi@0: aoqi@0: bool is_empty() const { aoqi@0: return _top == bottom(); aoqi@0: } aoqi@0: aoqi@0: bool is_full() const { aoqi@0: return _top == (nmethod**)end(); aoqi@0: } aoqi@0: aoqi@0: bool contains(nmethod* method) { aoqi@0: nmethod** cur = bottom(); aoqi@0: while (cur != _top) { aoqi@0: if (*cur == method) return true; aoqi@0: cur++; aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: bool add(nmethod* method) { aoqi@0: if (is_full()) return false; aoqi@0: *_top = method; aoqi@0: _top++; aoqi@0: return true; aoqi@0: } aoqi@0: aoqi@0: bool remove(nmethod* method) { aoqi@0: nmethod** cur = bottom(); aoqi@0: while (cur != _top) { aoqi@0: if (*cur == method) { aoqi@0: memmove(cur, cur + 1, (_top - (cur + 1)) * sizeof(nmethod**)); aoqi@0: _top--; aoqi@0: return true; aoqi@0: } aoqi@0: cur++; aoqi@0: } aoqi@0: return false; aoqi@0: } aoqi@0: aoqi@0: void nmethods_do(CodeBlobClosure* blk); aoqi@0: aoqi@0: nmethod* pop() { aoqi@0: if (is_empty()) { aoqi@0: return NULL; aoqi@0: } aoqi@0: _top--; aoqi@0: return *_top; aoqi@0: } aoqi@0: }; aoqi@0: aoqi@0: // Implements storage for a set of code roots. aoqi@0: // All methods that modify the set are not thread-safe except if otherwise noted. aoqi@0: class G1CodeRootSet VALUE_OBJ_CLASS_SPEC { aoqi@0: private: aoqi@0: // Global free chunk list management aoqi@0: static FreeList _free_list; aoqi@0: // Total number of chunks handed out aoqi@0: static size_t _num_chunks_handed_out; aoqi@0: aoqi@0: static G1CodeRootChunk* new_chunk(); aoqi@0: static void free_chunk(G1CodeRootChunk* chunk); aoqi@0: // Free all elements of the given list. aoqi@0: static void free_all_chunks(FreeList* list); aoqi@0: aoqi@0: // Return the chunk that contains the given nmethod, NULL otherwise. aoqi@0: // Scans the list of chunks backwards, as this method is used to add new aoqi@0: // entries, which are typically added in bulk for a single nmethod. aoqi@0: G1CodeRootChunk* find(nmethod* method); aoqi@0: void free(G1CodeRootChunk* chunk); aoqi@0: aoqi@0: size_t _length; aoqi@0: FreeList _list; aoqi@0: aoqi@0: public: aoqi@0: G1CodeRootSet(); aoqi@0: ~G1CodeRootSet(); aoqi@0: aoqi@0: static void initialize(); aoqi@0: static void purge_chunks(size_t keep_ratio); aoqi@0: aoqi@0: static size_t static_mem_size(); aoqi@0: static size_t fl_mem_size(); aoqi@0: aoqi@0: // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this aoqi@0: // method is likely to be repeatedly called with the same nmethod. aoqi@0: void add(nmethod* method); aoqi@0: aoqi@0: void remove(nmethod* method); aoqi@0: nmethod* pop(); aoqi@0: aoqi@0: bool contains(nmethod* method); aoqi@0: aoqi@0: void clear(); aoqi@0: aoqi@0: void nmethods_do(CodeBlobClosure* blk) const; aoqi@0: aoqi@0: bool is_empty() { return length() == 0; } aoqi@0: aoqi@0: // Length in elements aoqi@0: size_t length() const { return _length; } aoqi@0: aoqi@0: // Memory size in bytes taken by this set. aoqi@0: size_t mem_size(); aoqi@0: aoqi@0: static void test() PRODUCT_RETURN; aoqi@0: }; aoqi@0: aoqi@0: #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP