Mercurial > hg > graal-jvmci-8
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 |