Mercurial > hg > graal-jvmci-8
comparison src/share/vm/classfile/dictionary.hpp @ 12837:82af7d7a0128
8003420: NPG: make new GC root for pd_set
Summary: Move protection domain oops from system dictionary entries into a seperate set; the system dictionary references entries in that set now. This allows fast iteration during non-classunloading garbage collection. Implementation based on initial prototype from Ioi Lam (iklam).
Reviewed-by: coleenp, iklam
author | tschatzl |
---|---|
date | Wed, 09 Oct 2013 10:57:01 +0200 |
parents | 43083e670adf |
children | aa6f2ea19d8f |
comparison
equal
deleted
inserted
replaced
12836:b4d8a3d4db73 | 12837:82af7d7a0128 |
---|---|
1 /* | 1 /* |
2 * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. | 2 * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. |
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
4 * | 4 * |
5 * This code is free software; you can redistribute it and/or modify it | 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 | 6 * under the terms of the GNU General Public License version 2 only, as |
7 * published by the Free Software Foundation. | 7 * published by the Free Software Foundation. |
25 #ifndef SHARE_VM_CLASSFILE_DICTIONARY_HPP | 25 #ifndef SHARE_VM_CLASSFILE_DICTIONARY_HPP |
26 #define SHARE_VM_CLASSFILE_DICTIONARY_HPP | 26 #define SHARE_VM_CLASSFILE_DICTIONARY_HPP |
27 | 27 |
28 #include "classfile/systemDictionary.hpp" | 28 #include "classfile/systemDictionary.hpp" |
29 #include "oops/instanceKlass.hpp" | 29 #include "oops/instanceKlass.hpp" |
30 #include "oops/oop.hpp" | 30 #include "oops/oop.inline.hpp" |
31 #include "utilities/hashtable.hpp" | 31 #include "utilities/hashtable.hpp" |
32 | 32 |
33 class DictionaryEntry; | 33 class DictionaryEntry; |
34 class PSPromotionManager; | 34 class PSPromotionManager; |
35 class ProtectionDomainCacheTable; | |
36 class ProtectionDomainCacheEntry; | |
37 class BoolObjectClosure; | |
35 | 38 |
36 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 39 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
37 // The data structure for the system dictionary (and the shared system | 40 // The data structure for the system dictionary (and the shared system |
38 // dictionary). | 41 // dictionary). |
39 | 42 |
43 // current iteration index. | 46 // current iteration index. |
44 static int _current_class_index; | 47 static int _current_class_index; |
45 // pointer to the current hash table entry. | 48 // pointer to the current hash table entry. |
46 static DictionaryEntry* _current_class_entry; | 49 static DictionaryEntry* _current_class_entry; |
47 | 50 |
51 ProtectionDomainCacheTable* _pd_cache_table; | |
52 | |
48 DictionaryEntry* get_entry(int index, unsigned int hash, | 53 DictionaryEntry* get_entry(int index, unsigned int hash, |
49 Symbol* name, ClassLoaderData* loader_data); | 54 Symbol* name, ClassLoaderData* loader_data); |
50 | 55 |
51 DictionaryEntry* bucket(int i) { | 56 DictionaryEntry* bucket(int i) { |
52 return (DictionaryEntry*)Hashtable<Klass*, mtClass>::bucket(i); | 57 return (DictionaryEntry*)Hashtable<Klass*, mtClass>::bucket(i); |
91 void classes_do(void f(Klass*, TRAPS), TRAPS); | 96 void classes_do(void f(Klass*, TRAPS), TRAPS); |
92 void classes_do(void f(Klass*, ClassLoaderData*)); | 97 void classes_do(void f(Klass*, ClassLoaderData*)); |
93 | 98 |
94 void methods_do(void f(Method*)); | 99 void methods_do(void f(Method*)); |
95 | 100 |
101 void unlink(BoolObjectClosure* is_alive); | |
96 | 102 |
97 // Classes loaded by the bootstrap loader are always strongly reachable. | 103 // Classes loaded by the bootstrap loader are always strongly reachable. |
98 // If we're not doing class unloading, all classes are strongly reachable. | 104 // If we're not doing class unloading, all classes are strongly reachable. |
99 static bool is_strongly_reachable(ClassLoaderData* loader_data, Klass* klass) { | 105 static bool is_strongly_reachable(ClassLoaderData* loader_data, Klass* klass) { |
100 assert (klass != NULL, "should have non-null klass"); | 106 assert (klass != NULL, "should have non-null klass"); |
116 Handle protection_domain, TRAPS); | 122 Handle protection_domain, TRAPS); |
117 | 123 |
118 // Sharing support | 124 // Sharing support |
119 void reorder_dictionary(); | 125 void reorder_dictionary(); |
120 | 126 |
127 ProtectionDomainCacheEntry* cache_get(oop protection_domain); | |
121 | 128 |
122 #ifndef PRODUCT | 129 #ifndef PRODUCT |
123 void print(); | 130 void print(); |
124 #endif | 131 #endif |
125 void verify(); | 132 void verify(); |
126 }; | 133 }; |
127 | 134 |
128 // The following classes can be in dictionary.cpp, but we need these | 135 // The following classes can be in dictionary.cpp, but we need these |
129 // to be in header file so that SA's vmStructs can access. | 136 // to be in header file so that SA's vmStructs can access them. |
137 class ProtectionDomainCacheEntry : public HashtableEntry<oop, mtClass> { | |
138 friend class VMStructs; | |
139 private: | |
140 // Flag indicating whether this protection domain entry is strongly reachable. | |
141 // Used during iterating over the system dictionary to remember oops that need | |
142 // to be updated. | |
143 bool _strongly_reachable; | |
144 public: | |
145 oop protection_domain() { return literal(); } | |
146 | |
147 void init() { | |
148 _strongly_reachable = false; | |
149 } | |
150 | |
151 ProtectionDomainCacheEntry* next() { | |
152 return (ProtectionDomainCacheEntry*)HashtableEntry<oop, mtClass>::next(); | |
153 } | |
154 | |
155 ProtectionDomainCacheEntry** next_addr() { | |
156 return (ProtectionDomainCacheEntry**)HashtableEntry<oop, mtClass>::next_addr(); | |
157 } | |
158 | |
159 void oops_do(OopClosure* f) { | |
160 f->do_oop(literal_addr()); | |
161 } | |
162 | |
163 void set_strongly_reachable() { _strongly_reachable = true; } | |
164 bool is_strongly_reachable() { return _strongly_reachable; } | |
165 void reset_strongly_reachable() { _strongly_reachable = false; } | |
166 | |
167 void print() PRODUCT_RETURN; | |
168 void verify(); | |
169 }; | |
170 | |
171 // The ProtectionDomainCacheTable contains all protection domain oops. The system | |
172 // dictionary entries reference its entries instead of having references to oops | |
173 // directly. | |
174 // This is used to speed up system dictionary iteration: the oops in the | |
175 // protection domain are the only ones referring the Java heap. So when there is | |
176 // need to update these, instead of going over every entry of the system dictionary, | |
177 // we only need to iterate over this set. | |
178 // The amount of different protection domains used is typically magnitudes smaller | |
179 // than the number of system dictionary entries (loaded classes). | |
180 class ProtectionDomainCacheTable : public Hashtable<oop, mtClass> { | |
181 friend class VMStructs; | |
182 private: | |
183 ProtectionDomainCacheEntry* bucket(int i) { | |
184 return (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::bucket(i); | |
185 } | |
186 | |
187 // The following method is not MT-safe and must be done under lock. | |
188 ProtectionDomainCacheEntry** bucket_addr(int i) { | |
189 return (ProtectionDomainCacheEntry**) Hashtable<oop, mtClass>::bucket_addr(i); | |
190 } | |
191 | |
192 ProtectionDomainCacheEntry* new_entry(unsigned int hash, oop protection_domain) { | |
193 ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::new_entry(hash, protection_domain); | |
194 entry->init(); | |
195 return entry; | |
196 } | |
197 | |
198 static unsigned int compute_hash(oop protection_domain) { | |
199 return (unsigned int)(protection_domain->identity_hash()); | |
200 } | |
201 | |
202 int index_for(oop protection_domain) { | |
203 return hash_to_index(compute_hash(protection_domain)); | |
204 } | |
205 | |
206 ProtectionDomainCacheEntry* add_entry(int index, unsigned int hash, oop protection_domain); | |
207 ProtectionDomainCacheEntry* find_entry(int index, oop protection_domain); | |
208 | |
209 public: | |
210 | |
211 ProtectionDomainCacheTable(int table_size); | |
212 | |
213 ProtectionDomainCacheEntry* get(oop protection_domain); | |
214 void free(ProtectionDomainCacheEntry* entry); | |
215 | |
216 void unlink(BoolObjectClosure* cl); | |
217 | |
218 // GC support | |
219 void oops_do(OopClosure* f); | |
220 void always_strong_oops_do(OopClosure* f); | |
221 | |
222 static uint bucket_size(); | |
223 | |
224 void print() PRODUCT_RETURN; | |
225 void verify(); | |
226 }; | |
227 | |
130 | 228 |
131 class ProtectionDomainEntry :public CHeapObj<mtClass> { | 229 class ProtectionDomainEntry :public CHeapObj<mtClass> { |
132 friend class VMStructs; | 230 friend class VMStructs; |
133 public: | 231 public: |
134 ProtectionDomainEntry* _next; | 232 ProtectionDomainEntry* _next; |
135 oop _protection_domain; | 233 ProtectionDomainCacheEntry* _pd_cache; |
136 | 234 |
137 ProtectionDomainEntry(oop protection_domain, ProtectionDomainEntry* next) { | 235 ProtectionDomainEntry(ProtectionDomainCacheEntry* pd_cache, ProtectionDomainEntry* next) { |
138 _protection_domain = protection_domain; | 236 _pd_cache = pd_cache; |
139 _next = next; | 237 _next = next; |
140 } | 238 } |
141 | 239 |
142 ProtectionDomainEntry* next() { return _next; } | 240 ProtectionDomainEntry* next() { return _next; } |
143 oop protection_domain() { return _protection_domain; } | 241 oop protection_domain() { return _pd_cache->protection_domain(); } |
144 }; | 242 }; |
145 | 243 |
146 // An entry in the system dictionary, this describes a class as | 244 // An entry in the system dictionary, this describes a class as |
147 // { Klass*, loader, protection_domain }. | 245 // { Klass*, loader, protection_domain }. |
148 | 246 |
149 class DictionaryEntry : public HashtableEntry<Klass*, mtClass> { | 247 class DictionaryEntry : public HashtableEntry<Klass*, mtClass> { |
150 friend class VMStructs; | 248 friend class VMStructs; |
151 private: | 249 private: |
152 // Contains the set of approved protection domains that can access | 250 // Contains the set of approved protection domains that can access |
153 // this system dictionary entry. | 251 // this system dictionary entry. |
252 // | |
253 // This protection domain set is a set of tuples: | |
254 // | |
255 // (InstanceKlass C, initiating class loader ICL, Protection Domain PD) | |
256 // | |
257 // [Note that C.protection_domain(), which is stored in the java.lang.Class | |
258 // mirror of C, is NOT the same as PD] | |
259 // | |
260 // If such an entry (C, ICL, PD) exists in the table, it means that | |
261 // it is okay for a class Foo to reference C, where | |
262 // | |
263 // Foo.protection_domain() == PD, and | |
264 // Foo's defining class loader == ICL | |
265 // | |
266 // The usage of the PD set can be seen in SystemDictionary::validate_protection_domain() | |
267 // It is essentially a cache to avoid repeated Java up-calls to | |
268 // ClassLoader.checkPackageAccess(). | |
269 // | |
154 ProtectionDomainEntry* _pd_set; | 270 ProtectionDomainEntry* _pd_set; |
155 ClassLoaderData* _loader_data; | 271 ClassLoaderData* _loader_data; |
156 | 272 |
157 public: | 273 public: |
158 // Tells whether a protection is in the approved set. | 274 // Tells whether a protection is in the approved set. |
159 bool contains_protection_domain(oop protection_domain) const; | 275 bool contains_protection_domain(oop protection_domain) const; |
160 // Adds a protection domain to the approved set. | 276 // Adds a protection domain to the approved set. |
161 void add_protection_domain(oop protection_domain); | 277 void add_protection_domain(Dictionary* dict, oop protection_domain); |
162 | 278 |
163 Klass* klass() const { return (Klass*)literal(); } | 279 Klass* klass() const { return (Klass*)literal(); } |
164 Klass** klass_addr() { return (Klass**)literal_addr(); } | 280 Klass** klass_addr() { return (Klass**)literal_addr(); } |
165 | 281 |
166 DictionaryEntry* next() const { | 282 DictionaryEntry* next() const { |
187 return protection_domain() == NULL | 303 return protection_domain() == NULL |
188 ? true | 304 ? true |
189 : contains_protection_domain(protection_domain()); | 305 : contains_protection_domain(protection_domain()); |
190 } | 306 } |
191 | 307 |
192 | 308 void set_strongly_reachable() { |
193 void protection_domain_set_oops_do(OopClosure* f) { | |
194 for (ProtectionDomainEntry* current = _pd_set; | 309 for (ProtectionDomainEntry* current = _pd_set; |
195 current != NULL; | 310 current != NULL; |
196 current = current->_next) { | 311 current = current->_next) { |
197 f->do_oop(&(current->_protection_domain)); | 312 current->_pd_cache->set_strongly_reachable(); |
198 } | 313 } |
199 } | 314 } |
200 | 315 |
201 void verify_protection_domain_set() { | 316 void verify_protection_domain_set() { |
202 for (ProtectionDomainEntry* current = _pd_set; | 317 for (ProtectionDomainEntry* current = _pd_set; |
203 current != NULL; | 318 current != NULL; |
204 current = current->_next) { | 319 current = current->_next) { |
205 current->_protection_domain->verify(); | 320 current->_pd_cache->protection_domain()->verify(); |
206 } | 321 } |
207 } | 322 } |
208 | 323 |
209 bool equals(Symbol* class_name, ClassLoaderData* loader_data) const { | 324 bool equals(Symbol* class_name, ClassLoaderData* loader_data) const { |
210 Klass* klass = (Klass*)literal(); | 325 Klass* klass = (Klass*)literal(); |