src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp

Wed, 16 Apr 2014 10:14:50 +0200

author
tschatzl
date
Wed, 16 Apr 2014 10:14:50 +0200
changeset 6925
82693fb204a5
parent 0
f90c822e73f8
child 6932
828056cf311f
permissions
-rw-r--r--

8038930: G1CodeRootSet::test fails with assert(_num_chunks_handed_out == 0) failed: No elements must have been handed out yet
Summary: The test incorrectly assumed that it had been started with no other previous compilation activity. Fix this by allowing multiple code root free chunk lists, and use one separate from the global one to perform the test.
Reviewed-by: brutisso

     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  */
    25 #ifndef SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP
    26 #define SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP
    28 #include "memory/allocation.hpp"
    29 #include "memory/freeList.hpp"
    30 #include "runtime/globals.hpp"
    32 class CodeBlobClosure;
    34 class G1CodeRootChunk : public CHeapObj<mtGC> {
    35  private:
    36   static const int NUM_ENTRIES = 32;
    37  public:
    38   G1CodeRootChunk*     _next;
    39   G1CodeRootChunk*     _prev;
    41   nmethod** _top;
    43   nmethod* _data[NUM_ENTRIES];
    45   nmethod** bottom() const {
    46     return (nmethod**) &(_data[0]);
    47   }
    49   nmethod** end() const {
    50     return (nmethod**) &(_data[NUM_ENTRIES]);
    51   }
    53  public:
    54   G1CodeRootChunk();
    55   ~G1CodeRootChunk() {}
    57   static size_t word_size() { return (size_t)(align_size_up_(sizeof(G1CodeRootChunk), HeapWordSize) / HeapWordSize); }
    59   // FreeList "interface" methods
    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); }
    68   size_t size() const { return word_size(); }
    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   }
    77   bool is_free()                 { return true; }
    79   // New G1CodeRootChunk routines
    81   void reset();
    83   bool is_empty() const {
    84     return _top == bottom();
    85   }
    87   bool is_full() const {
    88     return _top == (nmethod**)end();
    89   }
    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   }
   100   bool add(nmethod* method) {
   101     if (is_full()) return false;
   102     *_top = method;
   103     _top++;
   104     return true;
   105   }
   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   }
   120   void nmethods_do(CodeBlobClosure* blk);
   122   nmethod* pop() {
   123     if (is_empty()) {
   124       return NULL;
   125     }
   126     _top--;
   127     return *_top;
   128   }
   129 };
   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;
   139  public:
   140   G1CodeRootChunkManager();
   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);
   147   void initialize();
   148   void purge_chunks(size_t keep_ratio);
   150   size_t static_mem_size();
   151   size_t fl_mem_size();
   153 #ifndef PRODUCT
   154   size_t num_chunks_handed_out() const;
   155   size_t num_free_chunks() const;
   156 #endif
   157 };
   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;
   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); }
   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);
   177   size_t _length;
   178   FreeList<G1CodeRootChunk> _list;
   179   G1CodeRootChunkManager* _manager;
   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();
   187   static void purge_chunks(size_t keep_ratio);
   189   static size_t static_mem_size();
   190   static size_t free_chunks_mem_size();
   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);
   196   void remove(nmethod* method);
   197   nmethod* pop();
   199   bool contains(nmethod* method);
   201   void clear();
   203   void nmethods_do(CodeBlobClosure* blk) const;
   205   bool is_empty() { return length() == 0; }
   207   // Length in elements
   208   size_t length() const { return _length; }
   210   // Memory size in bytes taken by this set.
   211   size_t mem_size();
   213   static void test() PRODUCT_RETURN;
   214 };
   216 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP

mercurial