comparison src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.hpp @ 17753:191174b49bec

8035406: Improve data structure for Code Cache remembered sets Summary: Change the code cache remembered sets data structure from a GrowableArray to a chunked list of nmethods. This makes the data structure more amenable to parallelization, and decreases freeing time. Reviewed-by: mgerdin, brutisso
author tschatzl
date Mon, 24 Mar 2014 15:30:14 +0100
parents
children 82693fb204a5
comparison
equal deleted inserted replaced
17750:f53edbc2b728 17753:191174b49bec
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 // Implements storage for a set of code roots.
132 // All methods that modify the set are not thread-safe except if otherwise noted.
133 class G1CodeRootSet VALUE_OBJ_CLASS_SPEC {
134 private:
135 // Global free chunk list management
136 static FreeList<G1CodeRootChunk> _free_list;
137 // Total number of chunks handed out
138 static size_t _num_chunks_handed_out;
139
140 static G1CodeRootChunk* new_chunk();
141 static void free_chunk(G1CodeRootChunk* chunk);
142 // Free all elements of the given list.
143 static void free_all_chunks(FreeList<G1CodeRootChunk>* list);
144
145 // Return the chunk that contains the given nmethod, NULL otherwise.
146 // Scans the list of chunks backwards, as this method is used to add new
147 // entries, which are typically added in bulk for a single nmethod.
148 G1CodeRootChunk* find(nmethod* method);
149 void free(G1CodeRootChunk* chunk);
150
151 size_t _length;
152 FreeList<G1CodeRootChunk> _list;
153
154 public:
155 G1CodeRootSet();
156 ~G1CodeRootSet();
157
158 static void initialize();
159 static void purge_chunks(size_t keep_ratio);
160
161 static size_t static_mem_size();
162 static size_t fl_mem_size();
163
164 // Search for the code blob from the recently allocated ones to find duplicates more quickly, as this
165 // method is likely to be repeatedly called with the same nmethod.
166 void add(nmethod* method);
167
168 void remove(nmethod* method);
169 nmethod* pop();
170
171 bool contains(nmethod* method);
172
173 void clear();
174
175 void nmethods_do(CodeBlobClosure* blk) const;
176
177 bool is_empty() { return length() == 0; }
178
179 // Length in elements
180 size_t length() const { return _length; }
181
182 // Memory size in bytes taken by this set.
183 size_t mem_size();
184
185 static void test() PRODUCT_RETURN;
186 };
187
188 #endif // SHARE_VM_GC_IMPLEMENTATION_G1_G1CODECACHEREMSET_HPP